Coding standards

Guide to coding standards for Q-CTRL projects


Standards for coding style MUST be obtained from the following hierarchy in the order specified:

  1. Third-party
  2. Language
  3. First-party

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:

  1. You are not using third-party software
  2. The third-party software does not specify a coding standard
  3. 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:

  1. The language does not specify a coding standard
  2. The coding standard does not specify a rule (for example how to name variables)

First-party

“First-party” refers to the Q-CTRL coding standards. The Q-CTRL coding standards 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-partyStyleDocstringsTestingLinting
DjangoDjango coding stylenumpydoc[++]pytestPylint
ReactAirbnb React/JSX Style GuideJSDocJest and React Testing LibraryESLint and eslint-config-airbnb

Language coding standards

LanguageStyleDocstringsTestingLinting
GoEffective GoGodocgo testgo vet and Staticcheck
GraphQLGraphQL RulesCommonMark[++]N/Agraphql-schema-linter
HTMLPrettierN/AHTMLProoferN/A
JavaScriptAirbnb JavaScript Style Guide() {JSDocJestESLint and eslint-config-airbnb
MarkdownPrettierN/AN/AMarkdownlint
PythonPEP 8numpydoc[++]pytest, mypyPylint, Black, isort
TypeScriptN/ATSDocJestESLint and eslint-config-airbnb-typescript

Q-CTRL 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 or optimizedPulse and NOT op).
  • For variable names that are more than three words, use an acronym (for example cpmg and NOT carr_purcell_meiboom_gill or carrPurcellMeiboomGill).
  • For variable names that describe how many of an object there are, use <object>_count or <object>Count (for example pulse_count or pulseCount and NOT number_of_pulses, numberOfPulses, pulses_count, or pulsesCount).
  • Capitalize only the first letter of acronyms in camelCase or PascalCase names (for example QctrlApiException or tensorPwc and NOT QCTRLAPIException or tensorPWC).

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

GraphQL

The CommonMark specification is unopinionated and/or inconsistent in a small number of cases. We therefore adopt the following additional standards.

  • Inline math MUST start with `$ and end with $`:
`$E=mc^2$`
  • Block math MUST have the language set to math:
 ```math
 E=mc^2
 ```
  • Footnote referencing MUST use the following syntax:
This is my sentence with a footnote[^1].

[^1]: My reference.

numpydoc

The numpydoc standard is unopinionated and/or inconsistent in a small number of cases. We therefore adopt the following additional standards.

  • Place the leading and final triple quotes of each docstring on their own lines, with no blank lines separating them from the contents, as follows:

    """
    <contents>
    """
    
  • 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.

  • numpydoc’s style for parameter types is too simple for some complex types, in particular involving lists or tuples; we use Python (3.9) syntax to represent them. Moreover, if there are requirements on the dtype or shape of a parameter, we include that information in parentheses. Below are a few examples of how we represent some types.

    hamiltonian : Pwc or SparsePwc
    noise_operators : list[np.ndarray or Tensor or Stf], optional
    lindblad_terms : list[tuple[float, np.ndarray or sp.sparse.spmatrix]]
    tensor : Tensor(scalar, real)
    sample_times : np.ndarray(1D, real), optional
    

numpydoc applied to GraphQL

The documentation for Boulder Opal functions comes from their corresponding GraphQL schemas. Write their docstrings in Markdown format, as required by the GraphQL specification. The documentation infrastructure automatically converts them into the reStructuredText (reST) format required by Python. The following example shows how you can do that for a hypothetical function calculate_object:

extend type Mutation {
    """
    # Description

    Single-line description.

    Extended summary about the functionality of the object.
    It can contain multiple sentences.

    # Warnings

    Text explaining some behavior of the function that the user
    should be aware of, such as possible mistakes a user could
    make that are not described elsewhere.

    # See Also

    function1: Summary of function1, relating it to this function.
    function_whose_name_makes_relationship_obvious

    # Notes

    A more detailed description that can contain references such as
    [external links](www.someurl.com) and paper citations [1]_. It
    can also contain mathematical formulas such as:

    ```math
    H(t) = \Omega(t) \sigma_x,
    ```

    where `$\Omega(t)$` is an inline formula.

    # References

    .. [1] A. Person, Some Journal **22**, 1 (2021).
    """
    calculateObject(objectInput!): objectResult!
}

input objectInput{
    """
    Short description of the parameter. A short description can span
    over multiple lines if necessary.
    """
    parameter: type!
    """Short description of the optional parameter. Defaults to 2."""
    optional_parameter: int=2
}

Note that the sections following “Warnings” have to be placed after “Parameters” and “Returns” according to the numpydoc docstring guide. The documentation infrastructure automatically moves them to their appropriate location in the Python docstring. It also removes the “Description” section and converts the Markdown syntax into reStructuredText (reST).

The next sections explain the contents of each of these parts in more detail.

Single-line description

In this sentence, explain what the function does without repeating the function’s name nor its variables.

Extended summary

Add some sentences with a more detailed description of the functionality, including additional information about the function that is not obvious from its syntax. Leave out any internal implementation details that aren’t relevant to the user.

Warnings

If the user should be aware of situations that might cause unexpected behavior but that don’t necessarily raise errors or warnings, include one or more paragraphs of text about them.

See also

If there are other objects whose documentation contains relevant information about the element, include each of them in a new line, without empty lines between them.

Notes

Add a mathematical description of the theory behind the purpose of the object, including mathematical formulas if necessary. Make sure that your text makes sense on its own, and link to clear explanations of the key concepts if the user is not necessarily familiar with them.

In this section, you can include links to external pages with additional information about the functionality. Make sure that the text of the link is meaningful in itself, and only link to websites that are visible and useful globally. If you cite academic references, you can list them in full form in the References section.

You can also add a description of the algorithm if it’s relevant for the understanding the purpose of the object, and if the algorithm is not proprietary.

References

If you cite academic references in the “Notes” section, add a list of them here.