Developer Notes¶
We welcome contributions to E3FP! These notes are designed to help developers contribute code
Authoring Code¶
Code Formatting¶
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.util
,
e3fp.conformer.util
, and 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
class e3fp.util.E3FPWarning
that is not silent by default. We provide several
general warnings:
E3FPDeprecationWarning
warns when a deprecated method is called or class is instantiated.
See also
E3FPEfficiencyWarning
warns when a method, module version, or combination of parameters is known to be inefficient.
Note
If possible, the warning message should advise on a more efficient approach.
E3FP-specific errors should inherit e3fp.util.E3FPError
base class. Several
fingerprinting-specific errors are defined in e3fp.fingerprint.util
.
Deprecation¶
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
an 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 e3fp.util.deprecated
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."""
... pass
>>> deprecated_method()
...: 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_method
()¶ Note
Deprecated in e3fp 1.1. deprecated_method will be removed in e3fp 1.3. Function no longer needed.
A method to demonstrate method deprecation.
Note
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.
Contributing Code¶
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.
Writing Tests¶
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 classes.
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
tested using 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.
Continuous Integration¶
E3FP uses Travis CI 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, Travis CI updates code coverage on
Coveralls and tests all usage examples in the documentation using doctest
.
Documentation¶
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 e3fp.fingerprint.db.FingerprintDatabase
.
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.
Documenting Code¶
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 doctest
.
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.
Documentation Usage¶
Coming soon.