Developer Guide#
Want to contribute to decent-array? That’s great! This guide contains useful information about development tools, processes, and rules.
Getting Started#
Prerequisites#
Installation for Development#
A compatible C compiler is required to build the mypyc extensions. On Windows, install
Build Tools for Visual Studio 2022 or
C++ Build Tools.
and select the “C++ build tools” workload. On Mac, install Xcode Command Line Tools by running xcode-select --install in the terminal.
On Linux, install the appropriate build tools for your distribution, see the Mypyc documentation for details.
git clone https://github.com/team-decent/decent-array.git
cd decent-array
tox -e dev # create dev env (admin privileges may be needed)
source .tox/dev/bin/activate # activate dev env on Mac/Linux
.\.tox\dev\Scripts\activate # activate dev env on Windows
Optionally install development dependencies with proper gpu support, e.g. for PyTorch and TensorFlow:
tox -e dev-gpu
It is not recommended to use the development environments for regular usage of decent-array, as they contain additional packages that are not needed for that purpose. This may cause performance degradation due to multiple packages competing for resources (e.g. GPU resources).
Tooling#
To make sure all GitHub status checks pass, simply run tox. You can also run individual checks:
tox -e mypy # find typing issues
tox -e ruff # find formatting and style issues
tox -e pytest # run tests
tox -e sphinx # rebuild documentation
tox -m lint # run all linters (ruff + mypy)
Note: Running tox commands can take several minutes and may require admin privileges.
If you have mypy addon installed in your IDE, you can use it to get instant feedback on typing issues while coding.
If mypy fails with KeyError: 'setter_type', delete the .mypy_cache folder in the project root.
Tools can also be used directly (instead of via tox) after activating the dev environment. Useful examples include:
ruff check decent_array --fix # find and fix style issues
ruff format decent_array # format code
mypy decent_array --strict # find typing issues
pytest tests # run tests
sphinx-build -W -E -b html docs/source docs/build/html # rebuild html doc files
To verify that doc changes look good, use an html previewer such as
Live Preview.
If you are running pytest tests while using WSL on Windows and it starts to randomly fail (or if its really slow), restart your WSL instance.
Compiled hot path (mypyc)#
The Array wrapper and the entire
interoperability package are compiled to C extensions with
mypyc at wheel-build time, so end users get the
speed-up automatically when installing from a wheel. During development you can
manage the compiled artifacts with two tox environments:
tox -e mypyc # compile in-place (drops .so files alongside the .py source)
tox -e clean-mypyc # remove compiled .so files so Python loads the .py source again
When both module.py and module.cpython-*.so exist in the same directory, Python
imports the .so. This means edits to a compiled module will not take effect until
either tox -e mypyc is rerun or tox -e clean-mypyc is invoked. A typical
edit-test-edit cycle therefore looks like:
Run
tox -e clean-mypyconce at the start of the session.Edit, run, repeat (Python loads the
.pysource directly — no rebuild needed).When measuring performance, run
tox -e mypycto recompile and re-bench.
Compilation takes ~25 s from a clean state. The build emits a hash-named shared-runtime
file (<hash>__mypyc.cpython-*.so) at the project root that holds helpers used by
every compiled module; it must sit on sys.path because the compiled modules import
it by bare name. The file is gitignored.
Performance tools#
The benchmarks/ directory contains scripts to measure wrapper overhead and
performance of the interoperability layer.
CUTE Design Principles#
CUTE is a set of principles that serve as guidelines for code design. They are meant to help keep the codebase simple and the development fast. To mitigate any conflict, the principles are ordered from most to least important:
Correctness: working code is the top priority.
Understandability: others should easily understand your code, avoid bloat, unnecessary indirection, and fancy abstractions.
Testability: code allows for short and clear tests.
Extendability: code allows for future extension, but avoid premature generalization and keep YAGNI and KISS in mind as trying to predict tomorrow’s requirements can cause more problems than it solves.
Pull Requests#
To give other contributors an opportunity to review and to run GitHub status checks, we use pull requests instead of merging directly to main. The process is detailed below:
Fork the repository.
Create a feature branch.
Make your changes.
Update documentation as needed.
Run
toxto ensure that all checks pass.Submit a pull request.
Doc changes? Click the readthedocs link found in the status checks to verify that everything looks good.
Commit Messages#
To keep the git history easy to follow, encourage well-scoped PRs, and facilitate changelog writing and versioning, we follow certain rules for commit messages when merging pull requests into main. Each message uses this template:
<type>(<scope>): <subject> (#<pr-id>)
<description>
closes #<issue-id>
perf(costs): Cache m_cvx and m_smooth (#105)
Cache the properties m_cvx and m_smooth where applicable. This led to a
75% speed up when running ADMM on a logistic regression problem.
closes #101
- Notes:
See table below for types.
Scope can be a subpackage, module or build tool, e.g. metrics, costs, or sphinx.
Max 72 characters per line.
Capitalize but do not punctuate subject.
Start subject and description with a verb.
Use imperative mood in subject and description.
Description explains what changes and why it changes.
If the PR has a related issue but doesn’t close it, skip the “closes”-keyword and simply reference the issue.
Type |
Description |
|---|---|
feat |
New functionality |
perf |
Performance improvement |
ref |
Refactor |
enh |
Small improvement that doesn’t qualify as feat, perf, or ref, e.g. improved variable naming, additional logging, or prettier plots |
fix |
Bug fix |
test |
Change to tests |
docs |
Update to readme, comments, docstrings, rst files, or sphinx config |
ci |
CI related change, e.g. modifying GitHub checks or tox environments |
meta |
Update to metadata, e.g. project description, version, or .gitignore |
license |
License update |
Inspired by Sentry.
Releases#
Update the version in pyproject.toml using Semantic Versioning.
Merge the change into main with commit message
meta: Bump version to <x>.<y>.<z> (#<pr-id>).Create a new release on GitHub.
Publish to PyPI using
hatch clean && hatch build && hatch publish.