Contributing to SQLAthanor

Note

As a general rule of thumb, SQLAthanor applies PEP 8 styling, with some important differences.

Branch Unit Tests
latest Build Status (Travis CI) Code Coverage Status (Codecov) Documentation Status (ReadTheDocs)
v.0.6 Build Status (Travis CI) Code Coverage Status (Codecov) Documentation Status (ReadTheDocs)
v.0.5 Build Status (Travis CI) Code Coverage Status (Codecov) Documentation Status (ReadTheDocs)
v.0.4 Build Status (Travis CI) Code Coverage Status (Codecov) Documentation Status (ReadTheDocs)
v.0.3 Build Status (Travis CI) Code Coverage Status (Codecov) Documentation Status (ReadTheDocs)
v.0.2 Build Status (Travis CI) Code Coverage Status (Codecov) Documentation Status (ReadTheDocs)
v.0.1 Build Status (Travis CI) Code Coverage Status (Codecov) Documentation Status (ReadTheDocs)
develop Build Status (Travis CI) Code Coverage Status (Codecov) Documentation Status (ReadTheDocs)

Design Philosophy

SQLAthanor 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.

Style Guide

Basic Conventions

  • 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 x: and if not x:.

  • Use the 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.

Naming Conventions

  • variable_name and not variableName or VariableName. Should be a noun that describes what information is contained in the variable. If a bool, preface with is_ or has_ or similar question-word that can be answered with a yes-or-no.
  • function_name and not function_name or functionName. Should be an imperative that describes what the function does (e.g. get_next_page).
  • CONSTANT_NAME and not constant_name or ConstantName.
  • ClassName and not class_name or Class_Name.

Design Conventions

  • 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 self or 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 __init__.

  • 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) return from the rest of the code with a blank line (except for single-line functions/methods).

Documentation Conventions

We are very big believers in documentation (maybe you can tell). To document SQLAthanor we rely on several tools:

Sphinx [1]

Sphinx [1] is used to organize the library’s documentation into this lovely readable format (which is also published to ReadTheDocs [2]). This documentation is written in reStructuredText [3] files which are stored in <project>/docs.

Tip

As a general rule of thumb, we try to apply the ReadTheDocs [2] own Documentation Style Guide [4] to our RST documentation.

Hint

To build the HTML documentation locally:

  1. In a terminal, navigate to <project>/docs.
  2. Execute make html.

When built locally, the HTML output of the documentation will be available at ./docs/_build/index.html.

Docstrings

  • Docstrings are used to document the actual source code itself. When writing docstrings we adhere to the conventions outlined in PEP 257.

Dependencies

Preparing Your Development Environment

In order to prepare your local development environment, you should:

  1. Fork the Git repository.
  2. Clone your forked repository.
  3. Set up a virtual environment (optional).
  4. Install dependencies:
sqlathanor/ $ pip install -r requirements.txt

And you should be good to go!

Ideas and Feature Requests

Check for open issues or create a new issue to start a discussion around a bug or feature idea.

Testing

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.

See also

For more information about the SQLAthanor testing approach please see: Testing SQLAthanor

Submitting Pull Requests

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.

Building Documentation

In order to build documentation locally, you can do so from the command line using:

sqlathanor/ $ cd docs
sqlathanor/docs $ make html

When the build process has finished, the HTML documentation will be locally available at:

sqlathanor/docs/_build/html/index.html

Note

Built documentation (the HTML) is not included in the project’s Git repository. If you need local documentation, you’ll need to build it.