Contributing

As an open source project, all cihai projects accept contributions through GitHub, GitLab and Codeberg. Below you will find resources on the internals of the project.

Note

This guide applies to all cihai projects, not just the cihai repo.

Cihai projects follow shared Python packaging, testing, and documentation conventions.

To be efficient at debugging, developing, testing, documenting, etc. it helps to familiarize yourself with the tool within, independently if needed.

<cihai-project> can be assumed to be an existing or future cihai project, including cihai, cihai-cli, unihan-etl, unihan-db. See GitHub, GitLab and Codeberg.

Development environment

uv is a required package to develop.

$ git clone https://github.com/cihai/<cihai-project>.git
$ cd <cihai-project>

So if <cihai-project> is [cihai]:

$ git clone https://github.com/cihai/cihai.git
$ cd cihai

Install dependencies

$ uv sync --all-extras --dev

Justfile commands prefixed with watch- will watch files and rerun.

Tests

[pytest] is used for tests.

$ uv run py.test

Rerun on file change

via pytest-watcher (works out of the box):

$ just start

via entr(1) (requires installation):

$ just watch-test

Manual (just the command, please)

$ uv run py.test

or:

$ just test

pytest options

For filename / test names within, examples will be for [cihai], if using a different cihai project check the filename and test names accordingly:

PYTEST_ADDOPTS can be set in the commands below. For more information read docs.pytest.com for the latest documentation.

Verbose:

$ env PYTEST_ADDOPTS="-verbose" just start

Pick a file:

$ env PYTEST_ADDOPTS="tests/test_cihai.py" just start

Drop into test_cihai_version() in tests/test_cihai.py:

$ env PYTEST_ADDOPTS="-s -x -vv tests/test_cihai.py" just start

Drop into test_cihai_version() in tests/test_cihai.py and stop on first error:

$ env PYTEST_ADDOPTS="-s -x -vv tests/test_cihai.py::test_cihai" just start

Drop into pdb on first error:

$ env PYTEST_ADDOPTS="-x -s --pdb" just start

If you have ipython installed:

$ env PYTEST_ADDOPTS="--pdbcls=IPython.terminal.debugger:TerminalPdb" just start
$ just test

You probably didn’t see anything but tests scroll by.

If you found a problem or are trying to write a test, you can file an on the tracker for the relevant cihai project.

Manual invocation

Test only a file:

$ py.test tests/test_cihai.py

will test the tests/test_cihai.py tests.

$ py.test tests/test_cihai.py::test_cihai_version

tests test_cihai_version() inside of tests/test_cihai.py.

Multiple can be separated by spaces:

$ py.test tests/test_{conversion,exc}.py tests/test_config.py::test_configurator

Documentation

sphinx-autobuild will automatically build the docs, watch for file changes and launch a server.

From the project root, start the docs server:

$ just start-docs

From inside docs/, start the docs server:

$ just start

Manual documentation (the hard way)

From inside docs/, build the docs:

$ just html

From inside docs/, start the HTTP server:

$ just serve

From the project root, build the docs:

$ just build-docs

From the project root, serve the built docs:

$ just serve-docs

Rebuild docs on file change with entr(1):

$ just watch-docs

Rebuild docs and run the server from one terminal:

$ just dev-docs

View documentation locally

To find the URL of the preview server, read the terminal, the URL may very depending on the project! An example of what to look for:

[I 220816 14:43:41 server:335] Serving on http://127.0.0.1:8035

Formatting / Linting

ruff

The project uses ruff to handle formatting, sorting imports, and linting.

uv:

$ uv run ruff

If you setup manually:

$ ruff check .
$ just ruff
$ just watch-ruff

requires entr(1).

uv:

$ uv run ruff check . --fix

If you setup manually:

$ ruff check . --fix

ruff format

[ruff format] is used for formatting.

uv:

$ uv run ruff format .

If you setup manually:

$ ruff format .
$ just ruff-format

mypy

mypy is used for static type checking.

uv:

$ uv run mypy .

If you setup manually:

$ mypy .
$ just mypy
$ just watch-mypy

requires entr(1).

Releasing

Since this software used in production projects, we don’t release breaking changes until there’s a major feature release.

Choose what the next version is. Assuming it’s version 0.9.0, it could be:

  • 0.9.0post0: postrelease, if there was a packaging issue

  • 0.9.1: bugfix / security / tweak

  • 0.10.0: breaking changes, new features

Let’s assume we pick 0.9.1

CHANGES: make sure every merged PR since the last release is mentioned, thank contributors where appropriate, and keep the unreleased placeholder at the top. Use deliverable headings with prose so readers see what changed before they see implementation details:

## package-name 0.10.x (unreleased)

### What's new

#### Clear user-facing deliverable (#1)

package-name 0.10.x ships a reader-facing improvement. Explain who benefits,
what changed, and where to read more.

## package-name 0.9.1 (2020-10-12)

package-name 0.9.1 fixes a released bug.

package_name/__init__.py and __about__.py - Set version

$ git commit -m 'Tag v0.9.1'
$ git push

Important: Create and push the tag. Make sure the version is correct and the pyproject.toml and __about__.py match the version being deployed.

$ git tag v0.9.1
$ git push --tags

Automated deployment

CI will automatically push to the PyPI index when a tag is pushed.

Manual deployment

uv handles virtualenv creation, package requirements, versioning, building, and publishing. Therefore there is no setup.py or requirements files.

Update __version__ in __about__.py and pyproject.toml:

$ git commit -m 'Tag v0.1.1'
$ git tag v0.1.1
$ git push
$ git push --tags

GitHub Actions will detect the new git tag, and in its own workflow run uv build and push to PyPI.