Development Guide

All contributions to rowan are welcome! Developers are invited to contribute to the framework by pull request to the package repository on github, and all users are welcome to provide contributions in the form of user feedback and bug reports. We recommend discussing new features in form of a proposal on the issue tracker for the appropriate project prior to development.

Design Philosophy and Code Guidelines

The goal of rowan is to provide a flexible, easy-to-use, and scalable approach to dealing with rotation representations. To best serve these goals, rowan operates entirely on NumPy arrays (the de facto standard for efficient multi-dimensional arrays in Python) and supports NumPy broadcasting wherever possible. Use of broadcasting ensures that rowan can take full advantage of NumPy performance, and in general all operations are very fast (benchmarks are included in the code base). Furthermore, to remain lightweight and easy to install, rowan is written in pure Python and has no hard dependencies aside from NumPy.

Code contributions should keep these ideals in mind and adhere to the following guidelines:

  • Use the OneFlow model of development: - Both new features and bug fixes should be developed in branches based on master. - Hotfixes (critical bugs that need to be released fast) should be developed in a branch based on the latest tagged release.
  • All code must be compatible with all supported versions of Python (listed in the package setup.py file).
  • Avoid external dependencies where possible, and avoid introducing any hard dependencies. Soft dependencies are allowed for specific functionality, but such dependencies cannot impede the installation of rowan or the use of any other features.
  • All code should adhere to the source code and documentation conventions discussed below.
  • Create unit tests and integration tests as part of development.
  • Preserve backwards-compatibility whenever possible. Make clear if something must change, and notify package maintainers that merging such changes will require a major release.
  • Enable broadcasting if at all possible. Functions for which broadcasting is not available must be documented as such.

To provide a reasonable balance between a high level of backwards compatibility and a reasonable maintenance burden, rowan has adopted NEP 29 to limit the Python and NumPy versions that will be supported.

Tip

During continuous integration, the code is checked automatically with Flake8. To ensure your code is compliant before committing, you can set up a pre-commit hook using pre-commit (recommended) or use flake8’s built-in hooks installation:

flake8 --install-hook git
git config --bool flake8.strict true

Note

Please see the individual package documentation for detailed guidelines on how to contribute to a specific package.

Source Code Conventions

The rowan package adheres to a relatively strict set of style guidelines. All code in rowan should be formatted using black; a notable consequence of this is that the recommended max line length is 88, not the more common 80. Imports should be formatted using isort. For guidance on the style, see PEP 8 and the Google Python Style Guide, but any ambiguities should be resolved automatically by running black. All code should also follow the principles in PEP 20. In particular, always prefer simple, explicit code where possible, avoiding unnecessary convolution or complicated code that could be written more simply. Avoid writing code in a manner that will be difficult for others to understand.

Tip

Developers should format their code using black and isort locally using the commands:

black --exclude "coxeter/[polytri|bentley_ottman]" coxeter/ tests/
isort -rc coxeter/ tests/

Documentation

API documentation should be written as part of the docstrings of the package in the Google style. There is one notable exception to the guide: class properties should be documented in the getters functions, not as class attributes, to allow for more useful help messages and inheritance of docstrings. Docstrings may be validated using pydocstyle (or using the flake8-docstrings plugin as documented above). The official documentation is generated from the docstrings using Sphinx.

Unit Tests

All code should include a set of unit tests which test for correct behavior. All tests should be placed in the tests folder at the root of the project. These tests should be as simple as possible, testing a single function each, and they should be kept as short as possible. Tests should also be entirely deterministic: if you are using a random set of objects for testing, they should either be generated once and then stored in the tests/files folder, or the random number generator in use should be seeded explicitly (e.g, numpy.random.seed or random.seed). Tests should be written in the style of the standard Python unittest framework. At all times, tests should be executable by simply running python -m unittest discover tests from the root of the project.

Release Guide

To make a new release of rowan, follow the following steps:

  1. Make a new branch off of master based on the expected new version, e.g. release-2.3.1.
  2. Make any final changes as desired on this branch. Push the changes and ensure all tests are passing as expected on the new branch.
  3. Once the branch is completely finalized, run bumpversion with the appropriate type (patch, minor, major) so that the version now matches the version number in the branch name.
  4. Merge the branch back into master, then push master and push tags. The tagged commit will automatically trigger generation of binaries and upload to PyPI and conda-forge.
  5. Delete the release branch both locally and on the remote.