Contributing#

Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.

You can contribute in many ways:

Types of Contributions#

Report Bugs#

Report bugs at usnistgov/module-utilities#issues.

If you are reporting a bug, please include:

  • Your operating system name and version.

  • Any details about your local setup that might be helpful in troubleshooting.

  • Detailed steps to reproduce the bug.

Fix Bugs#

Look through the GitHub issues for bugs. Anything tagged with “bug” and “help wanted” is open to whoever wants to implement it.

Implement Features#

Look through the GitHub issues for features. Anything tagged with “enhancement” and “help wanted” is open to whoever wants to implement it.

Write Documentation#

module-utilities could always use more documentation, whether as part of the official module-utilities docs, in docstrings, or even on the web in blog posts, articles, and such.

Submit Feedback#

The best way to send feedback is to file an issue at usnistgov/module-utilities#issues.

If you are proposing a feature:

  • Explain in detail how it would work.

  • Keep the scope as narrow as possible, to make it easier to implement.

  • Remember that this is a volunteer-driven project, and that contributions are welcome!

Get Started#

Environment setup#

This project uses a host of tools to (hopefully) make development easier. We recommend installing some of these tools system wide. For this, we recommend using either pipx or condax. We mostly use conda/condax, but the choice is yours. For conda, we recommend actually using mamba. Alternatively, you can setup conda to use the faster mamba solver. See here for details.

Additional tools are:

These are setup using the following:

condax/pipx install pre-commit
condax/pipx install cruft
condax/pipx install commitizen # optional
pipx install scriv
pipx install pyproject2conda # optional
condax/pipx install cogapp # optional

if using pipx, nox can be installed with:

pipx install nox
pipx inject nox ruamel.yaml
pipx inject nox noxopt

If using condax, you’ll need to use:

condax install nox
condax inject nox ruamel.yaml
conda activate ~/.condax/nox
pip install noxopt

Getting the repo#

Ready to contribute? Here’s how to set up module-utilities for local development.

  • Fork the module-utilities repo on GitHub.

  • Clone your fork locally:

    git clone git@github.com:your_name_here/module-utilities.git
    

    If the repo includes submodules, you can add them either with the initial close using:

    git clone --recursive-submodules git@github.com:your_name_here/module-utilities.git
    

    or after the clone using

    cd module-utilities
    git submodule update --init --recursive
    
  • Create development environment. There are two options to create the development environment.

    • The recommended method is to use nox. First you’ll need to create the environment files using:

      nox -e pyproject2conda
      

      Then run:

      nox -e dev
      

      This create a development environment located at .nox/dev.

    • Alternatively, you can create centrally located conda environmentment using the command:

      conda/mamba env create -n {env-name} -f environment/dev.yaml
      
      pip install -e . --no-deps
      
  • Initiate pre-commit with:

    pre-commit install
    

    To update the recipe, periodically run:

    pre-commit autoupdate
    

    If recipes change over time, you can clean up old installs with:

    pre-commit gc
    
  • Create a branch for local development:

    git checkout -b name-of-your-bugfix-or-feature
    

    Now you can make your changes locally. Alternatively, we recommend using git-flow.

  • When you’re done making changes, check that your changes pass the pre-commit checks: tests.

    pre-commit run [--all-files]
    

    To run tests, use:

    pytest
    

    To test against multiple python versions, use nox:

    nox -s test
    

    Additionally, you should run the following:

    make pre-commit-lint-markdown
    make pre-commit-codespell
    
  • Create changelog fragment. See scriv for more info.

    scriv create --edit
    
  • Commit your changes and push your branch to GitHub:

    git add .
    git commit -m "Your detailed description of your changes."
    git push origin name-of-your-bugfix-or-feature
    

    Note that the pre-commit hooks will force the commit message to be in the conventional style. To assist this, you may want to commit using commitizen.

    cz commit
    
  • Submit a pull request through the GitHub website.

Dependency management#

We use pyproject2conda to handle conda environment.yaml files. This extracts the dependencies from pyproject.toml. See pyproject2conda for info. To make the environment.yaml files, run:

nox -s pyproject2conda -- [--pyproject2conda-force]

Where the option in brackets is optional.

Pull Request Guidelines#

Before you submit a pull request, check that it meets these guidelines:

  • The pull request should include tests.

  • If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in CHANGELOG.md. You should use scriv for this.

  • The pull request should work for Python 3.8, 3.9, 3.10.

ipykernel#

The environments created by nox dev and docs will try to add meaningful display names for ipykernel (assuming you’re using nb_conda_kernels)

Building the docs#

We use nox to isolate the documentation build. Specific tasks can be run with

nox -s docs -- -d [commands]

where commands can be one of:

  • clean : remove old doc build

  • build/html : build html documentation

  • spelling : check spelling

  • linkcheck : check the links

  • symlink : rebuild symlinks from examples to docs/examples

  • release : make pages branch for documentation hosting (using ghp-import)

  • livehtml : Live documentation updates

  • open : open the documentation in a web browser

Testing with nox#

The basic command is:

nox -s test -- [--test-opts] [--no-cov]

where you can pass in additional pytest options (properly escaped) via --test-opts. For example:

nox -s test -- --test-opts "'-v'"
# or
nox -s test -- --test-opts "\-v"

Building distribution for conda#

For the most part, we use grayskull to create the conda recipe. However, I’ve had issues getting it to play nice with pyproject.toml for some of the ‘extra’ variables. So, we use grayskull to build the majority of the recipe, and append the file .recipe-append.yaml. For some edge cases (install name different from package name, etc), you’ll need to manually edit this file to create the final recipe.

The basic command is:

nox -s dist-conda -- -c [command]

Where command is one of:

  • clean

  • recipe : create recipe via grayskull

  • build : build the distribution

To upload the recipe, you’ll need to run an external command like:

nox -s dist-conda -- --dist-conda-run "anaconda upload PATH-TO-TARBALL"

Building distribution for pypi#

The basic command is:

nox -s dist-pypi -- -p [command]

where command is one of:

  • clean : clean out old distribution

  • build : build distribution (if specify only this, clean will be called first)

  • testrelease : upload to testpypi

  • release : upload to pypi

Testing pypi or conda installs#

Run:

nox -s testdist-pypi -- --version [version]

to test a specific version from pypi and

nox -s testdist-conda -- --version [version]

to to likewise from conda.

Type checking#

Run:

nox -s typing -- -m [commands] [options]

Package version#

Versioning is handled with setuptools_scm.The package version is set by the git tag. For convenience, you can override the version with nox setting --version .... This is useful for updating the docs, etc.

We use the write_to option to setuptools_scm. This stores the current version in _version.py. Note that if you build the package (or, build docs with the --version flag), this will overwrite information in _version.py in the src directory. To refresh the version, run:

make version-scm

This scheme avoids having to install setuptools-scm (and setuptools) in each environment.

Notes on nox#

One downside of using tox with this particular workflow is the need for multiple scripts/makefiles, while with nox, most everything is self contained in the file noxfile.py. nox also is allows for a mix of conda and virtualenv environments.

We use a mix of conda environments and virtualenv with nox. For example, for building the distribution, we use virtualenv, while for development, the default is to create a conda environment. To facilitate this, we need to let virtualenv know where different python interpreters are. I’ve had trouble mixing pyenv with conda. Instead, I use conda to create multiple invironments to hold different python version:

$ for version in 3.8 3.9 3.10 3.11; do
    conda create -n test-${version} python=${version}
  done

To tell nox where these environments live, create the file .noxconfig.toml with the following:

[nox.python]
paths = ["~/.conda/envs/test-3.*/bin"]

where ~/.conda/envs should be replaced by whatever prefix you have setup on your machine. The noxfile.py will add this to the search path for python versions when creating virtualenvs. The file .noxconfig.toml should not be tracked by git. There is also an example file .noxconfig.example.toml to get you started.

Serving the documentation#

To view to documentation with js headers/footers, you’ll need to serve them:

python -m http.server -d docs/_build/html

Then open the address localhost:8000 in a webbrowser.