Skip to content

Latest commit

 

History

History
263 lines (202 loc) · 12.5 KB

CONTRIBUTING.md

File metadata and controls

263 lines (202 loc) · 12.5 KB

Contributing

Installation and Development

Clone from github:

git clone [email protected]:CitrineInformatics/citrine-python

Create a virtual environment using Python >= 3.8. One option is to use conda, but it is not required.

conda create -n <environment_name> python=3.8
conda activate <environment_name>

Then install requirements.

pip install -U -r requirements.txt
pip install -U -r test_requirements.txt
pip install --no-deps -e .

Note that if you use python setup.py install it will not install the libraries in "test_requirements.txt". Although not necessary for using citrine-python, these libraries are important for development.

If using a conda environment, you can now launch a Jupyter notebook from the environment with jupyter notebook. The resulting notebook will have access to the citrine-python library and all its dependencies.

Changes to citrine-python must pass all tests, follow style guidelines, and maintain 100% test coverage. We use flake8 as a linter. To run the linter on the "src/" directory:

flake8 src

Running tests

We use pytest to run tests and use the associated library pytest-cov to check coverage. See the PyTest documentation for more information.

Command line

To run all tests and output a report of the coverage of the "src/" directory:

pytest tests/ --cov=src/

It is not uncommon to have path issues when running pytest from the command line. Ensure that your $PATH variable contains the directory with the citrine-python repo.

Logging

A number of our Python modules use Python's built-in logging module, which supports several log levels:

  • FATAL - indicates a very serious (probably irrecoverable) failure has occurred
  • ERROR - indicates an error, which by default will not be handled has occurred
  • WARNING - indicates that something unusual is happening, often precedes failures
  • INFO - informational output unrelated to problems
  • DEBUG - verbose information output that may assist the developer while debugging
  • NOTSET - currently unused in Citrine code, typically extremely verbose output describing the details of every operation being performed

As set, a logging level will return any logs at the set level and above, e.g., WARNING includes itself, ERROR, and FATAL. By default, the log level is set to WARNING. However, it may be preferable to set the log level to ERROR if your program's output should be particularly concise and/or only produce actionable information. When debugging issues, increasing the verbosity to DEBUG may be helpful, particularly if seeking assistance from the Citrine team.

To set your log level, add

import logging
logging.root.setLevel(level=logging.DEBUG)

with the desired log level to your script.

Fine-grained log level control

In some scenarios, you may wish to increase or decrease the verbosity of a particular logger. For instance

from gemd.entity.dict_serializable import logger
import logging
logger.setLevel(logging.ERROR)

will silence warnings about receiving superfluous data in responses from Citrine APIs, while still allowing other loggers to produce output of WARNING level and lower.

Another example:

from citrine._session import logger
import logging
logger.setLevel(logging.DEBUG)

will enable DEBUG level output in the for all activity relating to HTTP requests to Citrine APIs.

In general, all log output originating from Citrine source code will include the module from which log output originates. By convention loggers are named logger, so importing logger from the originating module will locate the correct instance. The log line

INFO:citrine._session:200 GET /projects/fc568490-224a-4070-807f-1427c4f4dcd8

is an example of output from the logger in the previous example.

Dependencies

Dependencies are tracked in multiple places:

  • requirements files (requirements.txt and test_requirements.txt)
  • setup.py

The setup.py file only contains libraries that are necessary for users to run citrine-python. If you add a dependency that is necessary to run the repo, it is crucial that you add it to setup.py.

The requirements files additionally contain dependencies for testing/development. Please keep it up to date whenever you add or change dependencies.

Coding Style

The citrine-python library follows PEP8, with the following exceptions:

  • Maximum line length is 99 characters for code and 119 characters for docstrings
  • Several docstring rules are relaxed (see tox.ini for a list of the ignored rules)

Type hints are strongly encouraged.

Positional arguments are strongly discouraged for methods with multiple arguments. Keywords should be required for almost all arguments. The only exception is that the first argument should be a positional argument if and only if the following are all true:

  • It is required
  • Its identity is obvious
  • It is consistent (all similar methods have the same first argument)

Unique identifiers are always denoted uid unless the object being referenced and the object doing the referencing have different types. If object of type "Foo" has a method that accepts the id of an object of type "Bar", it is denoted bar_id.

Docstrings must follow Numpy style so that Sphinx can parse them to make the docs.

For additional (non-binding) inspiration, check out the Google Python Style Guide.

PR Submission

Features should be developed in a branch with a descriptive name and the pull request (PR) submitted into the main branch. Every PR to main should increment the version number following semantic versioning. In order to be merged, a PR must be approved by one authorized user and the build must pass. A passing build requires the following:

  • All tests pass
  • The linter finds no violations of PEP8 style
  • Every line of code is executed by a test (100% coverage)
  • The version, as found in src/citrine/__version__.py, has increased

PR descriptions should describe the motivation and context of the code changes in the PR, both for the reviewer and also for future developers. If there's a JIRA ticket or Github issue, the PR should be linked to the ticket/issue to provide that context.

As it can be easy to forget to verify these prior to pushing, it's possible to use git hooks to enforce compliance during normal workflows. Consider editing .git/hooks/pre-commit or .git/hooks/pre-push (or adding them and marking them as executable: chmod +x <file>). For example, you could set your local .git/hooks/pre-commit to be

python $REPO_DIR/scripts/validate_version_bump.py                        || exit 1;
flake8 $REPO_DIR/src                                                          || exit 1;
derp $REPO_DIR/src $REPO_DIR/src/citrine/__version__.py                       || exit 1;
pytest --cov=src --cov-report term-missing:skip-covered --cov-config=tox.ini --no-cov-on-fail --cov-fail-under=100  tests     

to make sure you've incremented the package version, you pass the linter, nothing is deprecated past its major version, and you have complete, passing tests.

Documentation

The documentation for this project is built using Sphinx and can be found here.

Building Documentation

To build the documentation for this project, make sure you've installed all dependencies (core and development). Once done:

cd docs/
make html

You can see the result by opening docs/_build/html/index.html in a web browser.

Autogenerated Docs

Sphinx supports generating documentation from docstrings, which is accomplished automatically during the build step using sphinxcontrib-apidoc. The output of this process is stored in the gitignore'd docs/source/reference directory. It's not stored in source control because it's generated from the current state of the docstrings in the source code.

Custom documentation

One of the outstanding features of sphinx is its support for arbitrarily organized documentation materials such as tutorials, introductions, and other context-providing content. These items should be stored in source control under the docs/source directory in properly formatted .rst files.

Development Status

Classes and methods may be marked as alpha by including [ALPHA] at the start of their docstrings. These methods are intended for development, testing, and experimentation, are not supported, and may change or be removed without notice.

Public Release Notes

When releasing a version of Citrine Python for use by customers through exchanges like PyPI, include release notes in the folloing template format.

vx.x.x is released!

Here is a short overview of the main changes in this release. This is written in a friendly tone, avoids jargon, and conveys enthusiasm! This section should be ~2-3 sentences and highlight the “what” and the “why” of this release. Citrine has a personality, and its personality should come through in both this paragraph and the writing through the release notes.

What’s New

  • DO: Use these bullets to specify new and never before seen features
  • DO: Add a short description of each new feature and its name if it has one
  • DO: Share particularly exciting screenshots or GIFs of new features easily encapsulated in an image format
  • DO: Keep each bullet to 1-3 sentences (3 sentences max, 1-2 ideal), but DO use sub-lists if a new feature requires extra explanation
  • DO: Include links in each bullet to any important public-facing landing pages, docs, blog posts, resources, etc. relevant to the feature being discussed
  • DON’T: Use these bullets to talk about improvements, that’s the next section!
  • DON’T: Use these bullets to talk about bug fixes, that’s later!
  • DON’T: Use these bullets to discuss things still in progress
  • EXAMPLE: Likes have been in development for 6 months and now that they’re here, you can finally let your friends know how much you appreciate their content. Below each post is now a Like button you can click to express your enthusiasm.

Improvements

  • DO: Use these bullets to specify aspects of the product that have a better UI/UX
  • DO: Use these bullets to specify aspects of the product that are faster or more performant
  • DO: Use these bullets to address improvements requested by users
  • DO: Share particularly exciting screenshots or GIFs of improvements easily encapsulated in an image format
  • DO: Keep each bullet to 1-3 sentences (3 sentences max, 1-2 ideal)
  • DON’T: Use these bullets to talk about bug fixes, that’s the next section!
  • DON’T: Use these bullets to discuss things still in progress
  • EXAMPLE: Uploading content to the platform has never been faster. With this release, something that took 30 seconds before now should now use much less time.

Fixes

  • DO: Use these bullets to describe specific bug fixes
  • DO: Explain the before and after of the bug fix
  • DO: Keep each bullet to 1-3 sentences (3 sentences max, 1-2 ideal)
  • DON’T: Use these bullets to talk about general improvements that were not actually bugs
  • EXAMPLE: A bug causing a confusing error message when entering an incorrect password has been fixed. Now, if you type your password incorrectly you’ll get a helpful message and a link to reset your password.

Deprecated

  • DO: Use these bullets to list features that are now deprecated
  • DO: Explain how the deprecated feature will be replaced, if it will, or other key workarounds.
  • DO: Give a very brief explanation for the deprecation.
  • EXAMPLE: As of this release, the /filter endpoint is now deprecated in favor of the new, faster, and more robust /search endpoint.