This repository follows a set of standard development practices for modern Python packages.
- Clone the repository:
git clone https://github.com/talmolab/sleap-io && cd sleap-io
- Install the package in development mode:
With
conda
(recommended):Or without conda:conda env create -f environment.yml && conda activate sleap-io
pip install -e .[dev]
- Test that things are working:
pytest tests
To reinstall the environment from scratch using conda
:
conda env remove -n sleap-io && conda env create -f environment.yml
We also recommend setting up black
to run automatically in your IDE.
A good way to do this without messing up your global environment is to use a tool like pipx
:
pip install pipx
pipx ensurepath
pipx install black
This will make black
available everywhere (such as VSCode), but will not be dependent on your conda base
environment.
Once you're set up, follow these steps to make a change:
- If you don't have push access to the repository, start by making a fork of the repository.
- Switch to the
main
branch andgit pull
to fetch the latest changes. - Create a new branch named
<username>/<feature_name>
with a descriptive title for the change. For example:talmo/nwb_support
ortalmo/update_dependencies
. - Push as many commits as you want. Descriptive commit messages and titles are optional but recommended.
- Open a Pull Request of your new branch against
main
with a description of your changes. Feel free to create a "Draft" pull request to work on it incrementally. - Once the tests pass, request a review from a core developer and make any changes requested.
- Once approved, perform a squash merge against
main
to incorporate your changes.
This repository employs continuous integration via GitHub Actions to enforce code quality.
See the .github/workflows
folder for how our checks are implemented.
This package uses setuptools
as a packaging and distribution system.
Our build system is configured in two places:
pyproject.toml
which defines the basic build system configuration. This probably won't need to be changed.setup.cfg
which contains the declarative configuration of the package and its dependencies.
If new dependencies need to be introduced (or if versions need to be fenced), specify these in setup.cfg
in the install_requires
section. For development-only dependencies (i.e., packages that are not needed for distribution), add them to the [options.extras_require]
→ dev
section. These dependencies will only be installed when specifying the dev
extras like: pip install -e .[dev]
or pip install sleap-io[dev]
.
Best practices for adding dependencies include:
- Use permissive version ranges so that the package remains future- and backward-compatible without requiring new releases.
- Don't pin to a single specific versions of dependencies unless absolutely necessary, and consider using platform-specific specifiers.
For more reference see:
- Configuring setuptools using
setup.cfg
files - Setuptools Keywords
- PEP 508 - Dependency specification for Python Software Packages
Note: We use conda
as a preferred method for defining and managing environments, but this is not required. A recommended development environment is defined in environment.yml
.
Testing is done via pytest
.
Tests should be created in the tests/
subfolder following the convention test_{MODULE_NAME}.py
which mimicks the main module organization.
It is highly recommended checking out other existing tests for reference on how these are structured.
All tests must pass before a PR can be merged.
Tests will be run on every commit across multiple operating systems and Python versions (see .github/workflows/ci.yml
).
We check for coverage by parsing the outputs from pytest
and uploading to Codecov.
All changes should aim to increase or maintain test coverage.
The following steps are based on this guide.
- If you already have an environment installed,
pip install -e ."[dev]"
to make sure you have the latest dev tools (namelypytest-watch
). - Install the Coverage Gutters extension in VS Code.
- Open a terminal,
conda activate sleap-io
and then runptw
to automatically run tests. This will generate a newlcov.info
file when it's done. - Enable the coverage gutters by using Ctrl/Cmd+Shift+P, then Coverage Gutters: Display Coverage.
To standardize formatting conventions, we use black
.
It's highly recommended to set this up in your local environment so your code is auto-formatted before pushing commits.
Adherence to the black
code style is automatically checked on push (see .github/workflows/lint.yml
).
We require that all non-test code follow the Google Python Style Guide conventions. This is checked via pydocstyle
.
For example, a method might be documented as:
def load_tracks(filepath: str) -> np.ndarray:
"""Load the tracks from a SLEAP Analysis HDF5 file.
Args:
filepath: Path to a SLEAP Analysis HDF5 file.
Returns:
The loaded tracks as a `np.ndarray` of shape `(n_tracks, n_frames, n_nodes, 2)`
and dtype `float32`.
Raises:
ValueError: If the file does not contain a `/tracks` dataset.
See also: save_tracks
"""
with h5py.File(filepath, "r") as f:
if "tracks" not in f:
raise ValueError(
"The file does not contain a /tracks dataset. "
"This may not have been generated by SLEAP."
)
tracks = f["tracks"][:]
return tracks.astype("float32")
Notes:
- The first line should fit within the 88 character limit, be on the same line as the initial
"""
, and should use imperative tense (e.g., "Load X..." not "Loads X..."). - Use backticks (`) when possible to enable auto-linking for documentation.
- Always document shapes and data types when describing inputs/outputs that are arrays.
Adherence to the docstring conventions is automatically checked on push (see .github/workflows/ci.yml
).
This package follows standard semver version practices, i.e.:
{MAJOR}.{MINOR}.{PATCH}
For alpha/pre-releases, append a{NUM}
to the version.
Valid examples:
0.0.1
0.1.10a2
The PyPI-compatible package settings are in pyproject.toml
.
The version number is set in sleap_io/version.py
in the __version__
variable. This is read automatically by setuptools during installation and build.
To manually build (e.g., locally):
python -m build --wheel
To trigger an automated build (via the .github/workflows/build.yml
action), publish a Release.
- Install
sleap-io
with thedev
dependencies (e.g.,pip install -e ".[dev]"
). This is the default when installing from source via conda (conda env create -f environment.yml
). - Build and tag a new version of the docs:
mike deploy --update-aliases 0.1.4 latest
- Preview live changes locally with:
mike serve
- Manually push a specific version with:
mike deploy --push --update-aliases --allow-empty 0.1.4 latest