Contributing to Backoff-Utils¶
As a general rule of thumb, the Backoff-Utils apply PEP 8 styling, with some important differences.
The Backoff-Utils is meant to be a “beautiful” and “usable” library. That means that it should offer an idiomatic API that:
- works out of the box as intended,
- minimizes “bootstrapping” to produce meaningful output, and
- does not force users to understand how it does what it does.
In other words:
Users should simply be able to drive the car without looking at the engine.
Do not terminate lines with semicolons.
Line length should have a maximum of approximately 90 characters. If in doubt, make a longer line or break the line between clear concepts.
Each class should be contained in its own file.
If a file runs longer than 2,000 lines…it should probably be refactored and split.
All imports should occur at the top of the file.
Do not use single-line conditions:
# GOOD if x: do_something() # BAD if x: do_something()
When testing if an object has a value, be sure to use
if x is None:or
if x is not None. Do not confuse this with
if not x:.
if x:construction for testing truthiness, and
if not x:for testing falsiness. This is different from testing:
if x is True:
if x is False:
if x is None:
As of right now, because we feel that it negatively impacts readability and is less-widely used in the community, we are not using type annotations.
VariableName. Should be a noun that describes what information is contained in the variable. If a
bool, preface with
has_or similar question-word that can be answered with a yes-or-no.
functionName. Should be an imperative that describes what the function does (e.g.
Functions at the module level can only be aware of objects either at a higher scope or singletons (which effectively have a higher scope).
Functions and methods can use one positional argument (other than
cls) without a default value. Any other arguments must be keyword arguments with default value given.
def do_some_function(argument): # rest of function... def do_some_function(first_arg, second_arg = None, third_arg = True): # rest of function ...
Functions and methods that accept values should start by validating their input, throwing exceptions as appropriate.
When defining a class, define all attributes in
When defining a class, start by defining its attributes and methods as private using a single-underscore prefix. Then, only once they’re implemented, decide if they should be public.
Don’t be afraid of the private attribute/public property/public setter pattern:
class SomeClass(object): def __init__(*args, **kwargs): self._private_attribute = None @property def private_attribute(self): # custom logic which may override the default return return self._private_attribute @setter.private_attribute def private_attribute(self, value): # custom logic that creates modified_value self._private_attribute = modified_value
Separate a function or method’s final (or default)
returnfrom the rest of the code with a blank line (except for single-line functions/methods).
We are very big believers in documentation (maybe you can tell). To document the Backoff-Utils we rely on several tools:
Sphinx  is used to organize the library’s documentation into this lovely
readable format (which will also be published to ReadTheDocs ). This
documentation is written in reStructuredText  files which are stored in
To build the HTML documentation locally:
- In a terminal, navigate to
When built locally, the HTML output of the documentation will be available at
By design, Backoff-Utils are designed to rely on minimal dependencies. The only dependency they have outside of the Python standard library is:
validator-collection which provides for robust validation functionality.
This library in turn has one external dependency when installed under Python 2.7:
- regex which is a drop-in replacement for
Python’s (buggy) standard
- regex which is a drop-in replacement for Python’s (buggy) standard
In order to prepare your local development environment, you should:
- Fork the Git repository.
- Clone your forked repository.
- Set up a virtual environment (optional).
- Install dependencies:
backoff-utils/ $ pip install -r requirements.txt
And you should be good to go!
Check for open issues or create a new issue to start a discussion around a bug or feature idea.
If you’ve added a new feature, we recommend you:
- create local unit tests to verify that your feature works as expected, and
- run local unit tests before you submit the pull request to make sure nothing else got broken by accident.
For more information about the Backoff-Utils testing approach please see: Testing Backoff-Utils
After you have made changes that you think are ready to be included in the main library, submit a pull request on Github and one of our developers will review your changes. If they’re ready (meaning they’re well documented, pass unit tests, etc.) then they’ll be merged back into the main repository and slated for inclusion in the next release.
In order to build documentation locally, you can do so from the command line using:
backoff-utils/ $ cd docs backoff-utils/docs $ make html
When the build process has finished, the HTML documentation will be locally available at:
Built documentation (the HTML) is not included in the project’s Git repository. If you need local documentation, you’ll need to build it.