synapse/docs/code_style.md
Quentin Gliech cdd5979129
Some checks failed
Build docker images / build (push) Waiting to run
Deploy the documentation / Calculate variables for GitHub Pages deployment (push) Waiting to run
Deploy the documentation / GitHub Pages (push) Blocked by required conditions
Build release artifacts / Calculate list of debian distros (push) Waiting to run
Build release artifacts / Build .deb packages (push) Blocked by required conditions
Build release artifacts / Build wheels on ${{ matrix.os }} for ${{ matrix.arch }} (aarch64, ${{ startsWith(github.ref, 'refs/pull/') }}, ubuntu-20.04) (push) Waiting to run
Build release artifacts / Build wheels on ${{ matrix.os }} for ${{ matrix.arch }} (x86_64, ${{ startsWith(github.ref, 'refs/pull/') }}, macos-12) (push) Waiting to run
Build release artifacts / Build wheels on ${{ matrix.os }} for ${{ matrix.arch }} (x86_64, ${{ startsWith(github.ref, 'refs/pull/') }}, ubuntu-20.04) (push) Waiting to run
Build release artifacts / Build sdist (push) Waiting to run
Build release artifacts / Attach assets to release (push) Blocked by required conditions
Tests / changes (push) Waiting to run
Tests / check-sampleconfig (push) Blocked by required conditions
Tests / check-schema-delta (push) Blocked by required conditions
Tests / check-lockfile (push) Waiting to run
Tests / lint (push) Blocked by required conditions
Tests / Typechecking (push) Blocked by required conditions
Tests / lint-crlf (push) Waiting to run
Tests / lint-newsfile (push) Waiting to run
Tests / lint-pydantic (push) Blocked by required conditions
Tests / lint-clippy (push) Blocked by required conditions
Tests / lint-clippy-nightly (push) Blocked by required conditions
Tests / complement (monolith, SQLite) (push) Blocked by required conditions
Tests / complement (workers, Postgres) (push) Blocked by required conditions
Tests / cargo-test (push) Blocked by required conditions
Tests / cargo-bench (push) Blocked by required conditions
Tests / tests-done (push) Blocked by required conditions
Tests / lint-rustfmt (push) Blocked by required conditions
Tests / lint-readme (push) Blocked by required conditions
Tests / linting-done (push) Blocked by required conditions
Tests / calculate-test-jobs (push) Blocked by required conditions
Tests / trial (push) Blocked by required conditions
Tests / trial-olddeps (push) Blocked by required conditions
Tests / trial-pypy (all, pypy-3.8) (push) Blocked by required conditions
Tests / sytest (push) Blocked by required conditions
Tests / export-data (push) Blocked by required conditions
Tests / portdb (11, 3.8) (push) Blocked by required conditions
Tests / portdb (15, 3.11) (push) Blocked by required conditions
Tests / complement (monolith, Postgres) (push) Blocked by required conditions
/ Check locked dependencies have sdists (push) Has been cancelled
Replace isort and black with ruff (#17620)
Ruff now has decent parity with black and isort, so this is going to just save us a bunch of time
2024-08-30 10:07:46 +02:00

4.2 KiB

Code Style

Formatting tools

The Synapse codebase uses a number of code formatting tools in order to quickly and automatically check for formatting (and sometimes logical) errors in code.

The necessary tools are:

  • ruff, which can spot common errors and enforce a consistent style; and
  • mypy, a type checker.

See the contributing guide for instructions on how to install the above tools and run the linters.

It's worth noting that modern IDEs and text editors can run these tools automatically on save. It may be worth looking into whether this functionality is supported in your editor for a more convenient development workflow. It is not, however, recommended to run mypy on save as it takes a while and can be very resource intensive.

General rules

  • Naming:
    • Use CamelCase for class and type names
    • Use underscores for function_names and variable_names.
  • Docstrings: should follow the google code style. See the examples in the sphinx documentation.
  • Imports:
    • Imports should be sorted by isort as described above.

    • Prefer to import classes and functions rather than packages or modules.

      Example:

      from synapse.types import UserID
      ...
      user_id = UserID(local, server)
      

      is preferred over:

      from synapse import types
      ...
      user_id = types.UserID(local, server)
      

      (or any other variant).

      This goes against the advice in the Google style guide, but it means that errors in the name are caught early (at import time).

    • Avoid wildcard imports (from synapse.types import *) and relative imports (from .types import UserID).

Configuration code and documentation format

When adding a configuration option to the code, if several settings are grouped into a single dict, ensure that your code correctly handles the top-level option being set to None (as it will be if no sub-options are enabled).

The configuration manual acts as a reference to Synapse's configuration options for server administrators. Remember that many readers will be unfamiliar with YAML and server administration in general, so it is important that when you add a configuration option the documentation be as easy to understand as possible, which includes following a consistent format.

Some guidelines follow:

  • Each option should be listed in the config manual with the following format:

    • The name of the option, prefixed by ###.

    • A comment which describes the default behaviour (i.e. what happens if the setting is omitted), as well as what the effect will be if the setting is changed.

    • An example setting, using backticks to define the code block

      For boolean (on/off) options, convention is that this example should be the opposite to the default. For other options, the example should give some non-default value which is likely to be useful to the reader.

  • There should be a horizontal rule between each option, which can be achieved by adding --- before and after the option.

  • true and false are spelt thus (as opposed to True, etc.)

Example:


modules

Use the module sub-option to add a module under modules to extend functionality. The module setting then has a sub-option, config, which can be used to define some configuration for the module.

Defaults to none.

Example configuration:

modules:
  - module: my_super_module.MySuperClass
    config:
      do_thing: true
  - module: my_other_super_module.SomeClass
    config: {}

Note that the sample configuration is generated from the synapse code and is maintained by a script, scripts-dev/generate_sample_config.sh. Making sure that the output from this script matches the desired format is left as an exercise for the reader!