We welcome contributions to E3FP! These notes are designed to help developers
E3FP’s code should be readable. To ensure this, we rigorously follow the
PEP8 style conventions and PEP257 docstring conventions, which maximize
readability of the code and ease of future development. You may check your
code for conformation to these conventions with the pycodestyle and
pydocstyle utilities, respectively. Where the code is necessarily
complicated, inline comments should reorient the reader.
Utility Methods and Classes
Three sets of utility methods and classes are provided:
e3fp.fingerprint.util. These provide general and
often-used functionality in their corresponding packages. Additionally, they
provide E3FP-specific errors and exceptions.
Warnings and Errors
By default, warnings in Python are silent. We therefore provide a warning base
e3fp.util.E3FPWarning that is not silent by default. We provide several
warns when a deprecated method is called or class is instantiated.
warns when a method, module version, or combination of parameters is known
to be inefficient.
If possible, the warning message should advise on a more efficient
E3FP-specific errors should inherit
e3fp.util.E3FPError base class. Several
fingerprinting-specific errors are defined in
Whenever changing the interface or behavior of a user-facing method or class,
it is proper to deprecate it for at least one release, so that the users have
time to update their scripts accordingly. A deprecated method should providing
e3fp.util.E3FPDeprecationWarning, notifying the user in which release to
expect the method or class to be removed, and updating the documentation
accordingly. This functionality is automated with the
decorator, as shown in this example:
>>> import sys
>>> sys.stderr = sys.stdout
>>> from e3fp.util import deprecated
>>> @deprecated("1.1", remove_version="1.3", msg="Function no longer needed.")
... def deprecated_method():
... """A method to demonstrate method deprecation."""
...: E3FPDeprecationWarning: Function `my_function` was deprecated in 1.1 and will be removed in 1.3. Function no longer needed.
In the api documentation, the method will appear as:
Deprecated in e3fp 1.1.
deprecated_method will be removed in e3fp 1.3. Function no longer needed.
A method to demonstrate method deprecation.
If no remove_version is specified, then the remove version defaults to the
next release after deprecation. For example, if the method was deprecated in
1.1, it is by default marked for removal in 1.2.
Before contributing code to E3FP, it is advisable for major modifications to
submit an issue to the
issue tracker to enable other
developers to contribute to the design of the code and to reduce the amount of
work necessary to conform the code to E3FP’s standards. After writing the code,
create a pull request. This is best even if you have push access to the
E3FP repo, as it enables the test suite to be run on the new code prior to
merging it with the remaining code base.
The standard in E3FP is to commit a test for new functionality simultaneously
with the new functionality or within the same pull request. While this slows
development, it prevents building a large backlog of untested methods and
These should ideally be unit tests, though for some complicated
functionalities, such as fingerprinting, integration tests are also
necessary. For these complicated functions, specific units may still be
unittest.mock. For example,
unittest.mock.patch() may be used to force a high level method to
produce a specific output. For examples, see the fingeprinting tests.
E3FP uses GitHub Actions for continuous integration. This ensures that each commit
and pull request passes all tests on a variety of a systems and for all
supported versions of Python. Additionally, GitHub Actions updates code coverage on
Codecov and tests all usage examples in the documentation using
In general, it is best to document the rationale and basic usage of a module,
class, or method in its docstring instead of in a separate documentation file.
See, for example, the docstring for
We use a variety of tools to ensure that our documentation is always
up-to-date. The official documentation is hosted on ReadtheDocs and is
automatically generated when new code is committed to the repository.
E3FP uses NumPy’s docstring conventions for all docstrings. These are
parsed by Sphinx using Napoleon. All usage examples must be fully
functional, as these are tested using
The purpose of a docstring is to explain the purpose of a class/method, any
relevant implementation details, its parameters, its attributes, its outputs,
and its usage. The goal is clarity. For self-evident methods with descriptive
variables, a simple one- ine summary is all that is needed. For complicated use
cases, often involving other methods/classes, it is better to document the
usage elsewhere in the documentation.