Skip to content

Development Guide

Set up Shellsmith for local development, testing, linting, and documentation.

Want to propose a fix, improve the CLI, or update the docs? This guide gets you started.


Setup

Follow these steps to set up your development environment:

Clone the repository:

git clone https://github.com/SmartFactory-KL/shellsmith

Navigate into the project folder:

cd shellsmith

Create a virtual environment:

python -m venv .venv

Activate the virtual environment:

source .venv/bin/activate
.venv\Scripts\activate

Install the package in editable mode with test and documentation dependencies:

pip install -e .[test,docs]

Testing

Start the BaSyx test environment (if needed):

docker compose up -d

Run the test suite with coverage:

pytest --cov

Generate an HTML coverage report:

pytest --cov --cov-report=html

Then open htmlcov/index.html in your browser.


Code Style

We use Ruff for linting and formatting, and mypy for static type checking:

Check code:

ruff check
What is being checked?

Ruff is configured to enforce modern Python code standards:

The following linting rules are enabled:

  • Type hints (ANN)
  • Common bugs (B)
  • Comprehension style (C4)
  • Docstring style (D)
  • PEP8 errors (E) and warnings (W)
  • Unused/undefined code (F)
  • Imports (I)
  • Naming conventions (N)
  • Pylint compatibility (PL)
  • Simplifications (SIM)
  • Modernization (UP)

Additional rules and ignores are set in pyproject.toml.

[tool.ruff]
target-version = "py310"

[tool.ruff.lint]
select = [
    "ANN",  # flake8-annotations
    "B",    # flake8-bugbear
    "C4",   # flake8-comprehensions
    "D",    # pydocstyle
    "E",    # pycodestyle errors
    "F",    # pyflakes
    "I",    # isort
    "N",    # pep8-naming
    "PL",   # pylint
    "SIM",  # flake8-simplify
    "UP",   # pyupgrade
    "W",    # pycodestyle warnings
]

[tool.ruff.lint.pydocstyle]
convention = "google"

Auto-fix issues:

ruff check --fix

Format code:

ruff format

Run static type checks:

mypy src

Docs

We use Material for MkDocs for documentation.

Serve the documentation locally:

mkdocs serve

Note

Documentation lives in the docs/ folder and uses Markdown with Material features.

Then open http://localhost:8000

Build the static site:

mkdocs build

Releasing

Create a release tag

Write release notes in a UTF-8 text file, then create an annotated tag (e.g. v0.4.0):

git tag -a v0.4.0 -F RELEASE-v0.4.0.txt

Push the tag (e.g. v0.4.0) to the remote:

git push origin v0.4.0

Note

You can also push all local tags at once:

git push origin --tags

Note

With hatch-vcs, the package version is derived automatically from Git.

Build the distribution

Use Hatch to build sdist and wheel:

hatch build

Artifacts are written to dist/.

Note

If you see leftovers from previous builds, clean first:

rm -rf dist build *.egg-info    

Verify the package

Run Twine checks on the built files:

twine check dist/*

Upload to TestPyPI

Try the upload on TestPyPI:

twine upload --repository testpypi dist/*
Configure API tokens

Twine asks for an API token when uploading the distributions. You can either provide it directly after running the command or you can configure your API tokens in a .pypirc at $HOME/.pypirc

[distutils]
index-servers =
    pypi
    testpypi

[pypi]
username = __token__
password = <PyPI token>

[testpypi]
username = __token__
password = <TestPyPI token>

Test install (e.g. shellsmith==0.4.0) with --no-deps in another virtual environment:

pip install --index-url https://test.pypi.org/simple/ --no-deps shellsmith==0.4.0

Note

The --no-deps tells pip to only install the built wheel or sdist and skips dependency resolution

Upload to PyPI

Publish to the main index:

twine upload dist/*