Coding standards
Guide to coding standards for Q-CTRL projects
Hierarchy of standards
Standards for coding style MUST be obtained from the following hierarchy in the order specified:
Third-party
“Third-party” refers to the third-party software you are using and the corresponding Third-party coding standards. For example, if you are using Django, you MUST use the Django coding style. If any of the following conditions hold then you MUST move to Language:
- You are not using third-party software
- The third-party software does not specify a coding standard
- The coding standard does not specify a rule (for example how to name variables)
Language
“Language” refers to the language you are using and the corresponding language coding standards. For example, if you are using Python, you MUST use the PEP 8 – Style Guide for Python Code. If any of the following conditions hold then you MUST move to First-party:
- The language does not specify a coding standard
- The coding standard does not specify a rule (for example how to name variables)
First-party
“First-party” refers to the First-party coding standards. These standards are developed by Q-CTRL and exist to specify standards that are not defined in the coding standards of the third-party software or language you are using.
Third-party coding standards
Third-party | Style | Docstrings | Testing | Linting |
---|---|---|---|---|
Django | Django coding style | numpydoc[++] | pytest | Pylint or Ruff |
Protocol Buffers | Buf Style Guide | N/A | N/A | buf lint |
React | Q-CTRL ESLint Config | TSDoc | Jest, Testing Library, and Playwright | ESLint and Prettier |
Terraform | Terraform Style Guide | N/A | N/A | terraform fmt |
Language coding standards
Language | Style | Docstrings | Testing | Linting |
---|---|---|---|---|
Cython | PEP 8 | numpydoc[++] | pytest | (Pylint, Black, isort) or Ruff |
Go | Effective Go | Godoc | go test | go vet and Staticcheck |
GraphQL | GraphQL Rules | CommonMark | N/A | graphql-schema-linter |
HTML | Prettier | N/A | Playwright | Prettier |
JavaScript | Q-CTRL ESLint Config | JSDoc | Jest, Testing Library, and Playwright | ESLint and Prettier |
Markdown | N/A | N/A | N/A | markdownlint |
Python | PEP 8 | numpydoc[++] | pytest | (Pylint, Black, isort) or Ruff |
Rust | rustfmt | rustdoc | cargo test | Clippy |
TypeScript | Q-CTRL ESLint Config | TSDoc | Jest, Testing Library, and Playwright | ESLint and Prettier |
YAML | Home Assistant YAML Style Guide | N/A | N/A | yamllint |
First-party coding standards
Variable naming
Unless prescribed otherwise by the framework or language (as described above), use the following rules when naming variables:
- Spell variable names out in full using American English spelling (for example
optimized_pulse
oroptimizedPulse
and NOTop
). - For variable names that are more than three words, use an acronym (for example
cpmg
and NOTcarr_purcell_meiboom_gill
orcarrPurcellMeiboomGill
). - For variable names that describe how many of an object there are, use
<object>_count
or<object>Count
(for examplepulse_count
orpulseCount
and NOTnumber_of_pulses
,numberOfPulses
,pulses_count
, orpulsesCount
). - Capitalize only the first letter of acronyms in camelCase or PascalCase names (for example
QctrlApiException
ortensorPwc
and NOTQCTRLAPIException
ortensorPWC
).
OIDC authentication provider
We currently use Keycloak for our OpenId Connect (OIDC) authentication. As OIDC is a standard for authentication and Keycloak is only our current provider all variables required for use related to OIDC should be prefixed with OIDC_
. Avoid KEYCLOAK_
unless you feel there is a valid reason for bringing that prefix back into use, in which case bring it up for discussion.
Docstrings
numpydoc
The numpydoc standard is unclear, unopinionated, or inconsistent in a small number of cases. We therefore adopt the following additional standards.
-
For docstrings that fit on a single line, the opening and closing triple quotes should be on the same line as the content, as follows:
"""An example docstring that fits on a single line."""
For docstrings that span multiple lines, place the opening and closing triple quotes of on their own lines, with no blank lines separating them from the contents, as follows:
""" An example docstring. Optional additional paragraphs that go into more detail. """
- Use single backticks when referring to a module, function, class, method, parameter, variable, or attribute thereof; otherwise use double backticks (for example
`np.array`
,`int`
,`parameter_1`
,`CustomClass.attribute`
,`CustomClass.method`
, `value_1*value_2
,
function().result
, or
List[int]
`). Do not use backticks for literals such as 3.2, “string”, True, or None. -
We adopt the following on top of numpydoc’s style for parameter types, as is too simple for some complex types:
- We use Python 3.9 (or later) syntax to represent lists or tuples.
- If a parameter has requirements on its shape or data type, we include that information in parentheses.
- The word “optional” at the end of a type indicates that a parameter has a default value. If a parameter is nullable we add “or None” to its type.
Below are a few examples of how we might represent some types.
hamiltonian : Pwc or SparsePwc noise_operators : list[np.ndarray or Tensor or Stf] or None, optional lindblad_terms : list[tuple[float, np.ndarray or sp.sparse.spmatrix]] cost : Tensor(scalar, real) verbose : bool, optional sample_times : np.ndarray(1D, real)