Development and Testing¶
This guide covers development practices, testing, and contribution guidelines for pyclif.
Development Setup¶
Requirements¶
- Python 3.10 or higher
- uv for dependency management
- Git for version control
Setting up the Environment¶
-
Clone the repository:
-
Install dependencies:
-
Activate the virtual environment (optional — uv run handles this automatically):
Project Structure¶
pyclif/
├── src/pyclif/ # Main package
│ ├── __init__.py # Public API exports
│ └── core/ # Core functionality
│ ├── __init__.py # Core exports
│ ├── callbacks.py # Click callbacks (meta storage)
│ ├── classes.py # PyclifOption, PyclifGroup, CustomConfigOption
│ ├── context.py # BaseContext
│ ├── decorators.py # @app_group, @group, @command, @option
│ ├── rich_help_config.py # Rich-click help configuration
│ ├── logging/ # Rich logging system
│ └── mixins/ # Feature mixins (cli, output, response, rich)
│ └── output/ # Response, CliTable, ExceptionTable
├── tests/ # Test files (mirror src/ layout)
├── docs/ # Documentation
├── pyproject.toml # Project configuration
└── README.md # Main project README
Testing¶
The project uses pytest with comprehensive test coverage.
Running Tests¶
# All tests
uv run python -m pytest tests/ -v
# Specific test file
uv run python -m pytest tests/core/log/test_verbosity_default.py -v
# With coverage
uv run python -m pytest tests/ --cov=pyclif --cov-report=html
Test Categories¶
- Unit tests: Test individual components in isolation
- Integration tests: Test decorator interactions and CLI flows
- Configuration tests: Test
CustomConfigOptionfunctionality - Logging tests: Test verbosity, file logging, Rich formatting
- Tox compatibility tests: Marked
@pytest.mark.tox— multi-version checks
Writing Tests¶
import pytest
from click.testing import CliRunner
from pyclif import app_group, command, option
@app_group()
def test_cli():
"""Test CLI application."""
pass
@test_cli.command()
@option("--name", required=True, help="Name parameter")
def hello(name):
"""Test hello command."""
print(f"Hello {name}!")
def test_hello_command():
runner = CliRunner()
result = runner.invoke(test_cli, ["hello", "--name", "Test"])
assert result.exit_code == 0
assert "Hello Test!" in result.output
def test_missing_required_option():
runner = CliRunner()
result = runner.invoke(test_cli, ["hello"])
assert result.exit_code != 0
assert "Missing option" in result.output
Testing Configuration Files¶
def test_config_file_loading():
runner = CliRunner()
with runner.isolated_filesystem():
with open("test_config.toml", "w") as f:
f.write('[hello]\nname = "From Config"\n')
result = runner.invoke(test_cli, ["--config", "test_config.toml", "hello"])
assert result.exit_code == 0
assert "Hello From Config!" in result.output
Code Quality¶
Linting and Formatting¶
Code Style Summary¶
- Type hints: PEP 585 built-in generics (
list[str],dict[str, Any]), nevertyping.List/Dict/Optional - Docstrings: Google style, required on all public classes, methods, and functions
- Naming:
snake_casefor functions/modules,PascalCasefor classes,_single_underscorefor private - Imports: PEP 8 order — stdlib → third-party → local; relative imports preferred inside the package
See CLAUDE.md for the full style reference.
Testing Across Python Versions¶
pyclif supports Python 3.10, 3.11, 3.12, and 3.13. Use tox to test across all versions:
# Test all supported versions
uv run tox
# Test a specific version
uv run tox -e py310
uv run tox -e py313
Note: always use uv run tox rather than tox directly, so the project venv's tox (with the tox-uv plugin)
is used.
tox Configuration¶
[tool.tox]
env_list = ["py310", "py311", "py312", "py313"]
isolated_build = true
[tool.tox.env_run_base]
runner = "uv-venv-lock-runner"
package = "editable"
extras = ["dev"]
commands = [
["python", "-m", "pytest", "tests/", "-v"],
["pyclif", "--help"],
]
Contributing¶
Workflow¶
- Fork the repository on GitHub
- Create a feature branch:
- Make changes and add tests
- Run tests:
- Run quality checks:
- Commit:
- Push and open a Pull Request on GitHub
Commit Message Convention¶
pyclif uses conventional commits with emoji prefixes:
| Prefix | Type |
|---|---|
| ✨ | feat |
| 🐛 | fix |
| 📝 | docs |
| 🧪 | test |
| ♻️ | refactor |
| 🎨 | style |
| 🚀 | release |
Release Process¶
Versions are managed with bump-my-version. Version is synced across pyproject.toml, README.md, and
src/pyclif/__init__.py.
# Bump patch version (1.0.0 → 1.0.1)
uv run bump-my-version bump patch
# Bump minor version (1.0.0 → 1.1.0)
uv run bump-my-version bump minor