-
Notifications
You must be signed in to change notification settings - Fork 0
Code guidelines
All Python code should where possible follow the PEP 8 - Style Guide for Python Code.
A quick reference is provided below for some of the most commonly used examples:
Packages should support stable Python versions (security and bugfix). Refer to the Python Developer Guide for the current status of Python versions. Package updates should announce the deprecation of Python versions that have reached their end-of-life.
All package imports should be grouped together and contained within a single cell, which is ideally the cell immediately following any cells containing titles, descriptions and licenses. Ideally all lines beginning with import
should come first, with lines beginning with from
second.
All package imports should be grouped together and immediately follow any comments containing titles, descriptions and licenses. Ideally all lines beginning with import
should come first, with lines beginning with from
second.
Names that are visible to the user as public parts of the API should follow conventions that reflect usage rather than implementation.
Python packages should have short, all-lowercase names. The use of underscores is discouraged as per PEP 8, however they can be included only if required to improve readability.
Examples:
mypackage
my_complex_package_name
Module names should be short, all-lowercase, and ideally semantic in nature. Underscores can be used in the module name if it improves readability as per PEP 8.
Examples:
mymodule
my_module
my_more_complex_module
Class names should be short, ideally semantic in nature, and normally use the CapWords convention as per PEP 8.
Example:
MyNewClass
Function names should be lowercase and ideally semantic in nature with words separated by underscores as necessary to improve readability as per PEP 8.
Examples:
my_function
my_more_complex_function
Variable names should be lowercase and ideally semantic in nature, with words separated by underscores as necessary to improve readability as per PEP 8.
Example:
my_variable
my_more_complex_variable
Note: Never use the characters ‘l’ (lowercase letter el), ‘O’ (uppercase letter oh), or ‘I’ (uppercase letter eye) as single character variable names. In some fonts, these characters are indistinguishable from the numerals one and zero. When tempted to use ‘l’ (lowercase letter el), use ‘L’ instead.
All references to ACCESS-NRI within 'code situations' outside of already defined naming conventions (e.g. databases, arrays, dictionaries, lists etc) should use access_nri
. For all 'non-code' examples (e.g. plot titles, script names, docstring descriptions etc), use ACCESS-NRI
.
To define a private attribute or function/method within a given class, prefix the name with a single underscore(_
).
Example:
-
my_function
becomes_my_function
-
my_variable
becomes_my_variable
Note: Python does not have true private functions/methods, so restrictions to attributes or functions/methods prepended with an underscore (_
) are not strictly enforced. The single underscore(_
) is just a convention to denote an attribute or function/method is intended to be private.
Documenting software is very important! Documentation helps both users and developers to understand everything about a given piece of software or code. From more high-level aspects such as what is the purpose of the code, how it is put together and how it is deployed, to more low-level information including installation, troubleshooting and how the code can be implemented and/or extended.
If a line of code does something, describe it with a comment! Comments should be complete sentences and be placed on the line above the line of code they are describing. The first word should be capitalized, unless it is an identifier that begins with a lower case letter (never alter the case of identifiers!). Comments that contradict the code are worse than no comments. Always make a priority of keeping the comments up-to-date when the code changes!
Block comments generally apply to some (or all) code that follows them, and are indented to the same level as that code. Each line of a block comment starts with a # and a single space (unless it is indented text inside the comment). Paragraphs inside a block comment are separated by a line containing a single #.
Use inline comments sparingly.
An inline comment is a comment on the same line as a statement. Inline comments should be separated by at least two spaces from the statement. They should start with a # and a single space.
See PEP 8 - Comments for a full description of good commenting practices.
A docstring (or documentation string) is a string literal that occurs as the first statement in a module, function, class, or method definition. This docstring becomes the __doc__
special attribute of that object. All modules should normally have docstrings, and all functions and classes exported by a module should also have docstrings. A full description of general docstring best practices can be found in the PEP 257 - Docstring Conventions.
Beyond providing code-level information to the user via the __doc__
special attribute, docstrings can (and should) also be used to auto-generate package/API reference documentation. For this task, it is recommended to use Sphinx.
To auto-generate documentation using Sphinx, specific docstring formatting is required (i.e. you cannot use PEP 257 - Docstring Conventions formatting). For this, please use the numpydoc syntax. Documentation should use the sphinx-rtd-theme
found here.
Example Sphinx-compatible numpydoc formatting for a multiline docstring describing a function containing multiple explicit arguments:
def my_function(arg1, arg2, arg3=True):
"""
Clear and concise function description.
Parameters
----------
arg1 : string
Argument 1 description
arg2 : float
Argument 2 description
arg3 : bool, default True
Argument 3 description
Returns
----------
string
Description of returned object
"""
if type(arg1) == str and type(arg2) == float and type(arg3) == bool:
result = 'winning'
else:
result = 'not winning'
return result
Robust and consistent software formatting and testing is a very important phase of the complete development cycle. Routinely evaluating and linting classes, functions and scripts not only ensures that code is working correctly, it also informs code optimisation.
Linting is a 'quality-control' process to check code syntax and highlight issues or inconsistencies (e.g. spelling errors in function or variable names, incorrect indentation etc). This process is often automated in dedicated Python IDE's (e.g. Jupyter, PyCharm etc), so is typically most useful for evaluating *.py files. We recommend using the Flake8 package. In addition to linting, we recommend using the black package as a code formatter.
To evaluate code stability, functionality and performance, unit testing is considered an industry-standard approach.
For testing Python code at ACESS-NRI, it is recommended that unit testing be completed using the pytest framework. A library of pytest examples can be found here.
See coverage.py.
TODO which tool(s) should be used for versioning ACCESS NRI repos?