Developer Notes¶
Contributing¶
Contributions to symmray are very welcome, whether they are bug reports,
documentation fixes, examples, tests, or new features. If you are planning a
larger change, opening an issue first is often the easiest way to check the
approach before spending too much time on implementation.
Please also read the
symmray Code of Conduct.
Things to check if new functionality is added:
Ensure functions are unit tested. Heavy use of
@pytest.mark.parametrizeover symmetry types (Z2,ZN,U1,Z2Z2,U1U1), shapes, and seeds is the standard pattern. After any mutating op, callx.check()for internal consistency — it is a no-op unlessSYMMRAY_DEBUG=1is set (thetestandpytestpixi tasks set it automatically).New method names must not collide across the MRO of any user-facing class. The single-definition MRO rule is enforced by
tests/test_no_method_overrides.py(only__init__is allow-listed). When backend-specific delegation is needed, use_<method>_<mixin>helpers (e.g._copy_abelian,_transpose_abelian).Ensure functions have NumPy-style docstrings.
Ensure code is formatted and linted with
pixi run lint.Add to
symmray/__init__.pyand"__all__"if appropriate.Heavy dependencies (numpy, …) must be imported inside functions, not at module top, to keep the import graph lean.
Add to
docs/changelog.mdand elsewhere in docs if appropriate
AI Policy¶
Please treat the numpy AI policy as a rough guide.
Development Setup¶
symmray uses pixi to manage development environments and
reproducible tasks. The environments and tasks are defined in pyproject.toml,
which is the source of truth for the commands below.
After cloning the repository, install the pixi environments from the project root:
git clone https://github.com/jcmgray/symmray.git
cd symmray
pixi install
You can then run project tasks with pixi run .... For example, to run a
short Python command inside the default test environment:
pixi run -e testpymid python -c "import symmray as sr; print(sr.__version__)"
Running the Tests¶
Testing symmray is handled by pixi tasks. The most common commands are:
pixi run -e testpymid test # full suite with coverage, matches CI
The test task expands to:
SYMMRAY_DEBUG=1 pytest tests/ \
--cov=symmray \
--cov-report=xml \
--verbose \
--durations=10
For a narrower check, use the pytest task (which also sets SYMMRAY_DEBUG=1)
and forward arguments after --:
pixi run pytest -- tests/test_sparse/test_xxx.py -v
pixi run pytest -- tests/ -k "test_tensordot" -v
To run the full suite in a specific environment, use -e:
pixi run -e testpyold test
pixi run -e testpymid test
pixi run -e testpynew test
If you invoke pytest directly (without pixi), set SYMMRAY_DEBUG=1 yourself to
enable check() calls throughout the library.
Formatting the Code¶
symmray uses ruff to format imports and
code style. Use the predefined pixi tasks rather than running the tools
directly:
pixi run lint
pixi run format
The format-all task also runs notebook cleanup with squeaky:
pixi run format-all
Building the Docs Locally¶
The documentation dependencies are managed by pixi. To build, clean, and serve the docs locally, use:
pixi run docs
pixi run docs-clean
pixi run docs-serve
The local server hosts the built docs at http://localhost:8000/. The
generated HTML is in docs/_build/html/.
On ReadTheDocs, the build is driven by .readthedocs.yml and uses the
dedicated readthedocs pixi task.
Minting a Release¶
symmray uses
hatch-vcs to derive the version
from git tags, and GitHub Actions
to publish to PyPI. To mint a new
release:
Make sure all the tests are passing on CI.
git tagthe release with the nextvX.Y.Z.Push the tag to GitHub:
git push --tags. The release workflow will build the sdist and wheel and upload them to the PyPI test server.If the test-pypi build looks good, create a GitHub release from the tag. Publishing the release triggers the same workflow to upload to the PyPI production server.
The
conda-forge/symmray-feedstockrepo should automatically pick up the new PyPI release and build a new conda package; the recipe should only need to be manually updated if there are, for example, new dependencies.
Alternate manual release steps (after tagging):
Remove any old builds:
rm -rf dist/*Build the sdist and wheel:
python -m buildUpload using twine:
twine upload dist/*