Mbed TLS script coding standards
General conventions for scripts
Choice of scripting language
The preferred language for scripts in the Mbed TLS project is Python. Use Python for new scripts that are committed to the project unless there’s a good reason.
Some reasons not to use Python:
A script that only applies to Windows and should ideally work out of the box can be written in cmd.
Some CI code in the
mbedtls-test
repository is written in Groovy, for its Jenkins integration.A script only intended for the Mbed TLS developers, and whose job is mostly to run other programs, can be written in sh.
If you’re extending existing scripts, then obviously keep using the same language.
Throwaway scripts that do ad hoc automated refactoring (e.g. renaming identifiers) are often in Perl, thanks to its convenient text manipulation primitives.
Language versions
Check README.md
for the current minimum supported version of Python and other tools. Note that in addition to the public commitments, at any given time, there may be additional constraints due to the platforms on which we run automated tests.
For scripts that need to be backported, note that long-time support branches may need to support older versions than the development
branch.
Script naming conventions
Use lowercase names.
Use either underscores or hyphens to separate words. Python modules that are imported by other scripts cannot use hyphens.
Perl scripts have a
.pl
extension. Python scripts have a.py
extensions. Sh and bash scripts have a.sh
extension. This helps on Windows.
Invocation conventions
Scripts should be able to run from the root of the Mbed TLS source tree. Support for running from a subdirectory is a plus.
Scripts should run out of the box on a typical Unix-like system if possible. If the script requires some environment variables, try to set sensible defaults.
All scripts should start with a comment that explains the purpose of the script and details of how to use it.
All scripts should print at least a summary explanation of how to invoke the script, including a list of supported options, when invoked with --help
as an argument.
Scripts should follow Unix conventions for options: -x
for single-letter option, --long-option
for options with longer names.
File structure
All executable scripts committed into the repository should have the following structure:
The first line is a shebang line, e.g.
#!/usr/bin/env python3
.A brief description of the file (either as a comment or as a string).
Copyright notice and license indication.
Initialization code.
Auxiliary functions (unless the script is so simple it doesn’t need any).
Code that performs the script’s purpose (this can be as simple as calling a
main
function, or more complex).
Python coding standards
Python version
As of September 2022, Python scripts must be compatible with Python 3.5,
because that’s what’s on parts of the CI, even though we only promise Python 3.6 in README.md
.
Exception: scripts/config.py
must remain compatible with Python 3.4, which is the earliest version that was officially supported at the time of the 2.28.0 release. (This is only a requirement in 2.28, but it’s easiest to keep the development version mostly aligned.) Other scripts in 2.28 are not user-facing and so can require a more recent version.
Directory structure
Non-executable Python modules are in scripts/mbedtls_dev
.
Executable Python scripts in scripts
can use auxiliary modules with from mbedtls_dev import ...
.
Executable Python scripts in tests/scripts
cannot refer to modules in scripts/mbedtls_dev
directly, because we do not assume that PYTHONPATH
contains the Mbed TLS source tree. To use other Python modules from a script in tests/scripts
, use the following idiom:
import scripts_path # pylint: disable=unused-import
from mbedtls_dev import ...
Python imports
We follow the usual convention that imports go at the top of a file (after the docstring and the license comment). Imports are typically ordered as follows:
Standard library, in lexicographic order.
Third-party libraries, if any, in lexicographic order.
Modules from
mbedtls_dev
, in lexicographic order.
Avoid importing individual names from modules, as it can be difficult to figure out which module an unqualified name comes from. However, it’s ok to import names if they’re sufficiently recognizable, for example:
Importing individual modules from
mbedtls_dev
is fine.Importing capitalized type names from
typing
is fine.Importing individual submodules from Cryptodome is fine.
Third-party Python libraries
Avoid bringing in new dependencies, because each dependency adds risk to the project. Only use dependencies if they have a clear advantage.
The minimum supported version of third-party Python libraries is recorded in *.requirements.txt
files in the scripts
directory. As with the Python version, keep in mind that long-time support branches may need to support older versions.
Python language features
The maintainers of Mbed TLS are primarily C programmers, not Python programmers. It’s ok to use fancy language features if they make the code significantly simpler, but don’t necessarily assume that the reader is familiar with them. Make sure that unfamiliar readers can easily look up such fancy features.
Classes, methods and simple inheritance can be used freely.
Avoid metaclasses and nontrivial dynamic class creation. If you use these features, write documentation that’s accessible to non-experts.
Do define special methods if convenient for comparison, context managers, etc. But avoid customizing attribute access.
Use decorators if they have a clear benefit.
Do use generators and list comprehension where warranted.
Python typing
Using type annotations is encouraged. We run mypy to verify static typing.
Avoid complex overloading. It’s generally easier to understand code if it only expects a specific type of data.
Python style conventions
We generally follow PEP 8. For docstrings, we also follow PEP 257.
Python style enforcement
We run Pylint for style enforcement. Pylint is quite opinionated sometimes, so if a rule doesn’t make sense in a specific context, use a Pylint pragma comment to disable it.