Coding tips

Backend development

Prototyping Python code

For quick prototyping or testing certain functionality, the Kadi shell can prove useful:

kadi shell
>>> app           # Imported automatically
<Kadi 'kadi.app'>
>>> dir()         # Get an overview of all automatically imported names

This shell is almost exactly the same as a regular interactive Python shell (or as the Flask shell), except that it ensures that a Flask application context is pushed automatically. Additionally, all database model classes and various other names are imported automatically.

Simulating sending emails

To simulate sending emails without using an actual SMTP server, the following command can be used to simply print the emails on the terminal instead using a debugging SMTP server:

kadi utils smtpd

The development configuration of Kadi4Mat already includes the correct values in order to make use of this debugging server, so no further changes should be necessary.

Adjusting or adding database models

For managing incremental changes to the database schema, potentially including existing data, Alembic is used via Flask-Migrate. These tools enable migration scripts to be generated, each script corresponding to the necessary database revisions, allowing another developer or system administrator to run the script and get the same changes in their database.

When adding a new model or adjusting an existing one, a new migration script has to be created to perform the necessary upgrades (see also migrations). To automatically generate such a script, the following command can be used:

kadi migrations migrate -m "Add some new table"

Note

When adding a new model, it needs to be imported somewhere in order for the tools to find it, as otherwise no changes might be detected. Furthermore, the current database schema always needs to be up to date in accordance to the latest migration script for the command to work.

The resulting code of the migration script should be checked and adjusted accordingly, as not all changes to the models may be detected automatically, such as new check constraints. Additionally, further steps may be necessary to migrate any existing data as well when adjusting existing models. Afterwards, the database can be upgraded by running the following command:

kadi migrations upgrade

When making further changes to a model after applying a newly generated migration script during development, it is usually best to recreate the script rather than creating another one. However, before deleting the old script, make sure to downgrade the database, as otherwise it may end up in an inconsistent state in regards to the revisions:

kadi migrations downgrade

Managing dependencies

All Python dependencies are currently specified via the pyproject.toml file, which lists all direct or major dependencies used in the project. All package versions are pinned in order to ensure installations that are (mostly) deterministic. In order to check for new package versions, the following helper script that is included in the Kadi4Mat source code can be used:

${HOME}/workspace/kadi/bin/check_requirements.py

Especially in case of major updates, any updated dependencies should always be checked for potentially breaking changes beforehand and for any issues that may arise in the application after the update.

Frontend development

Writing frontend code

To process and package all frontend assets, including Vue.js components, into individual JavaScript bundles runnable in a browser context, webpack is used. The main webpack configuration can be found in webpack.config.js, while a few other relevant global settings can be found in kadi/assets/scripts/main.js, which defines the main entry point for webpack. When writing frontend code, it is necessary to run the following in a separate terminal:

kadi assets watch

This way, changes to existing files will be detected and the resulting bundles in kadi/static/dist will be rebuilt automatically. When adding new files, the command might have to be restarted to pick them up, depending on which directory the files reside in. See also assets and static.

Managing dependencies

All frontend dependencies are managed using npm, the package manager of Node.js. The corresponding npm command uses the dependencies and configuration options as specified in the package.json file, so it must always be run somewhere inside the application’s root directory. Additionally, a package-lock.json file is generated automatically each time the package.json file is updated by npm to ensure deterministic installations. In order to install a new dependency, the following command can be used.

npm install <package>

This will add the new dependency to package.json automatically. In order to check all existing dependencies for updates, the following command can be used:

npm outdated

The outdated packages may be shown in different colors, depending on how each package is specified in package.json and on the magnitude of the update in accordance with Semantic Versioning. To apply any updates, one of the following commands can be used:

npm update                  # Automatically update all packages with compatible versions
npm install <package>@x.y.z # Install version x.y.z (e.g. a new major version) of a package

Especially in case of major updates, any updated dependencies should always be checked for potentially breaking changes beforehand and for any issues that may arise in the application after the update.

Security audits

npm offers built-in functionality to check all installed packages and subpackages for known vulnerabilities. As sometimes certain vulnerabilities may not be relevant for various reasons, e.g. false positives or the affected package is only used during development, it is possible to ignore certain vulnerabilities using audit-ci via the audit-ci.json file.

The modified security audit can then be run using the following command. Note that npm needs access to the package.json file, see also the section about managing frontend dependencies.

npm run audit