Skip to content

Contributing to BatteryProc

Thank you for your interest in contributing to BatteryProc! This guide covers development setup, code standards, and the pull request process.

Quick Start for Contributors

# 1. Clone and set up
git clone https://github.com/nickbashian/batteryproc.git
cd batteryproc
conda env create -f environment-simple.yml
conda activate batteryproc

# 2. Install in editable mode with dev tools
pip install -e .
pip install -r requirements-dev.txt

# 3. Verify everything works
batteryproc --help
pytest

Development Environment Setup

conda env create -f environment-simple.yml
conda activate batteryproc
pip install -e .
pip install -r requirements-dev.txt

To update the environment later:

conda env update -f environment-simple.yml --prune

Option B: venv (No Conda)

# macOS/Linux
python3.11 -m venv .venv
source .venv/bin/activate

# Windows PowerShell
py -3.11 -m venv .venv
.venv\Scripts\Activate.ps1

Then install:

pip install -e .
pip install -r requirements-dev.txt

IDE Setup

Configure your IDE to use the Python interpreter from your environment:

  • VS Code: Command Palette → "Python: Select Interpreter" → select the batteryproc Conda env or .venv
  • PyCharm: Settings → Project Interpreter → select the environment

Validation Commands

Run these before every commit and pull request. All must pass in CI.

# 1. Linting
ruff check .

# 2. Code formatting
black --check .

# 3. Type checking
mypy batteryproc

# 4. Test suite (~2 minutes)
pytest

# Or with coverage
pytest --cov=batteryproc --cov-report=xml

You can also auto-fix formatting and lint issues:

black .                 # Apply formatting
ruff check . --fix      # Auto-fix lint issues

Pre-commit Hooks (Optional)

Pre-commit hooks run these checks automatically before each commit:

pre-commit install            # One-time setup
pre-commit run --all-files    # Manual run

Code Style Guidelines

  1. PEP 8 compliance with 100-character line length.
  2. Black for formatting, Ruff for linting (replaces flake8, isort).
  3. NumPy-style docstrings for all public functions:
def function_name(param1: str, param2: int) -> float:
    """Brief description of function.

    Parameters
    ----------
    param1 : str
        Description of param1.
    param2 : int
        Description of param2.

    Returns
    -------
    float
        Description of return value.
    """
  1. Type hints are required in all new and modified code.

Typing Policy

BatteryProc enforces static typing in tiers:

  • Typed-core (strict) — Modules in the first [[tool.mypy.overrides]] block of pyproject.toml must satisfy disallow_untyped_defs = true. Currently includes: api, batteryproc_types, cli, formulas, metrics (and the metrics.* package submodules), parsers, plots (and the plots.* package submodules), processing, and utils.
  • Missing third-party stubs — there is no global ignore_missing_imports; missing-stub ignores are scoped per-module to only the third-party packages that genuinely lack type information (currently seaborn.* and scipy.*). Any other untyped import surfaces as a mypy error.
  • Legacy (cleanup lane) — Modules with ignore_errors = true (currently batteryproc.colours). Promote by finishing type annotations and moving to the typed-core list.

When adding a new public module:

  1. Add complete type hints.
  2. Add the module to the typed-core override in pyproject.toml.
  3. Run mypy batteryproc --no-incremental to confirm it's clean.

Testing

  • Write tests using pytest in the tests/ directory, mirroring the module structure.
  • Use pytest-mock for mocking (installed via requirements-dev.txt).
  • Close all matplotlib figures in plotting tests.
  • Prefer parametrized tests over loops.
  • CI tests on Python 3.10 and 3.11.

Branching and Pull Request Process

  1. Branch from dev — create feature branches from the dev branch.
  2. Make your changes — keep commits small and focused.
  3. Run validation — ruff check ., black --check ., mypy batteryproc, pytest.
  4. Submit a PR targeting dev — include a clear description of what changed and why.

Never merge directly to main

The main branch is for stable releases only. All work goes through dev.

Commit Messages

Use imperative mood: "Add efficiency calculation" not "Added efficiency calculation".


Continuous Integration

GitHub Actions runs on every push to main/dev and on all pull requests:

  1. Code quality: Black formatting, Ruff linting, mypy type checking
  2. Tests: Full test suite with coverage on Python 3.10 and 3.11
  3. Docs: MkDocs build verification

Local Documentation Preview

mkdocs serve

This runs a local dev server with live reload at http://localhost:8000.


Issue Reporting

Bug Reports

Please include:

  • Clear description of the issue
  • Steps to reproduce
  • Expected vs. actual behaviour
  • OS, Python version, BatteryProc version
  • Sample input files if applicable
  • Complete error messages and stack traces

Feature Requests

Please include:

  • The problem you're trying to solve
  • Your proposed solution
  • Alternatives you've considered
  • Concrete usage examples

Code Structure

batteryproc/
├── api.py              # Public programmatic API
├── cli.py              # CLI entry point and orchestration
├── parsers.py          # Parser registry and format handlers
├── metrics/            # Metric computation package (capacity, energy,
│                       #   cycle_detection, averaging, bad_cell; re-exported
│                       #   via metrics/__init__.py)
├── formulas.py         # Pure math functions (stateless)
├── plots/              # Visualization package (builders.py + _style.py styling
│                       #   component; re-exported via plots/__init__.py)
├── utils.py            # Cross-cutting utilities
├── colours.py          # Color palettes and style tokens
├── errors.py           # Domain exception types
├── batteryproc_types.py # Shared dataclasses and type aliases
├── _version.py         # Single source of truth for __version__
├── csv_export.py       # CSV export functions
└── config/             # YAML configuration files

Line Endings Policy

All text files use Unix (LF) line endings, enforced via .editorconfig, .gitattributes, and a pre-commit hook.


Contributors

  • Nicholas Bashian — Lead Developer, Project Maintainer
  • Scott Mitchell — Core Contributor, Testing and Documentation

Want to be listed here? Make a meaningful contribution and we'll add you!