Skip to content

Commit d9b0001

Browse files
authored
v0.5.0 (#5)
Features: - Record both wall-clock and CPU time per run (Measurement with TimeSpan) - Add Measurement (wall_time, cpu_time, metadata) and TimeSpan (start, end, duration) as public types - Context manager yields Measurement; decorator adds measurements deque on callable - Add optional metadata and maxlen (decorator) to Timer Improvements: - Replace pytest with Behave BDD (Gherkin features and step implementations) - Remove ElapsedTime, Stopwatch, count_sleep, custom storage, Timer.duration/durations - Require Python 3.10+; update README Quickstart and docstrings - Update CI and pre-commit for new test suite; stdlib-only, strict typing
1 parent 24add9e commit d9b0001

27 files changed

Lines changed: 1600 additions & 1555 deletions

.github/workflows/ci.yaml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
needs: lint
3232
strategy:
3333
matrix:
34-
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
34+
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
3535
steps:
3636
- name: Checkout code
3737
uses: actions/checkout@v6
@@ -45,12 +45,10 @@ jobs:
4545
run: pip install -e ".[dev]"
4646

4747
- name: Run tests with coverage
48-
run: >-
49-
python -m pytest tests/
50-
--cov=timerun
51-
--cov-branch
52-
--cov-report=xml
53-
--cov-report=term
48+
run: |
49+
coverage run --source=timerun -m behave -f progress
50+
coverage report
51+
coverage xml
5452
5553
- name: Upload coverage reports to Codecov
5654
uses: codecov/codecov-action@v5

.pre-commit-config.yaml

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,39 @@ repos:
1111
- id: check-yaml
1212
- id: check-toml
1313

14-
- repo: https://github.com/HH-MWB/pyenforce
15-
rev: v0.1.0
14+
- repo: https://github.com/astral-sh/ruff-pre-commit
15+
rev: v0.15.1
1616
hooks:
1717
- id: ruff-format
1818
- id: ruff-check
19+
20+
- repo: https://github.com/pre-commit/mirrors-mypy
21+
rev: v1.19.1
22+
hooks:
1923
- id: mypy
20-
additional_dependencies:
21-
- ".[mypy]" # Required to re-adds mypy as a dependency
22-
- pytest
24+
args: ["--scripts-are-modules"]
25+
files: ^timerun\.py$
26+
additional_dependencies: [behave]
27+
28+
- repo: https://github.com/pylint-dev/pylint
29+
rev: v4.0.4
30+
hooks:
2331
- id: pylint
24-
additional_dependencies:
25-
- ".[pylint]" # Required to re-adds Pylint as a dependency
26-
- pytest
32+
additional_dependencies: [behave]
33+
34+
- repo: https://github.com/PyCQA/bandit
35+
rev: 1.9.3
36+
hooks:
2737
- id: bandit
38+
args: ["-c", "pyproject.toml"]
39+
40+
- repo: https://github.com/semgrep/pre-commit
41+
rev: v1.151.0
42+
hooks:
2843
- id: semgrep
29-
- id: vulture
44+
args: ["--config", "p/python", "--error"]
3045

3146
- repo: https://github.com/adrienverge/yamllint
32-
rev: v1.37.1
47+
rev: v1.38.0
3348
hooks:
3449
- id: yamllint

CONTRIBUTING.md

Lines changed: 148 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,119 +1,201 @@
11
# Contributing to TimeRun
22

3-
Thank you for your interest in contributing to TimeRun! This document provides guidelines for contributing to the project.
3+
Thank you for considering contributing to TimeRun. This guide explains how to set up your environment, run tests, and submit changes.
44

5-
## Getting Started
5+
## Table of Contents
6+
7+
- [Code of Conduct](#code-of-conduct)
8+
- [How You Can Help](#how-you-can-help)
9+
- [Development Setup](#development-setup)
10+
- [Testing](#testing)
11+
- [Code Style and Quality](#code-style-and-quality)
12+
- [Project Structure](#project-structure)
13+
- [Pull Request Process](#pull-request-process)
14+
- [Reporting Bugs](#reporting-bugs)
15+
- [License](#license)
16+
17+
## Code of Conduct
18+
19+
Please be respectful and constructive. By participating, you agree to uphold a welcoming environment for everyone.
20+
21+
## How You Can Help
22+
23+
- **Report bugs** — Open an issue with clear steps to reproduce.
24+
- **Suggest features** — Open an issue describing the use case and desired behavior.
25+
- **Submit code** — Fix bugs or add features via pull requests (see [Pull Request Process](#pull-request-process)).
26+
- **Improve docs** — Fix typos, clarify README or docstrings, or add examples.
27+
28+
## Development Setup
629

730
### Prerequisites
831

9-
- Python 3.9 or higher
10-
- Git
32+
- **Python 3.10+**
33+
- **Git**
1134

12-
### Development Setup
35+
### One-time setup
36+
37+
1. **Fork** the repository on GitHub, then clone your fork:
1338

14-
1. Fork the repository on GitHub
15-
2. Clone your fork locally:
1639
```bash
1740
git clone https://github.com/YOUR_USERNAME/timerun.git
1841
cd timerun
1942
```
2043

21-
3. Set up the development environment:
44+
2. **Create and activate a virtual environment** (recommended):
45+
2246
```bash
23-
make init
47+
python3 -m venv .venv
48+
source .venv/bin/activate # Windows: .venv\Scripts\activate
2449
```
2550

26-
4. Activate the virtual environment:
51+
3. **Install the project in editable mode with dev dependencies**:
52+
2753
```bash
28-
source .venv/bin/activate
54+
pip install -e ".[dev]"
2955
```
3056

31-
## Development Workflow
57+
4. **Install and enable pre-commit hooks** (optional but recommended):
3258

33-
### Running Tests
59+
```bash
60+
pip install pre-commit
61+
pre-commit install
62+
```
63+
64+
Or use the convenience target:
65+
66+
```bash
67+
make init
68+
```
69+
70+
Then activate the venv: `source .venv/bin/activate`.
71+
72+
### Verify setup
73+
74+
Run the test suite:
3475

35-
Run the test suite with coverage:
3676
```bash
3777
make test
3878
```
3979

40-
### Code Style
80+
You should see the BDD scenarios run and a coverage report.
81+
82+
## Testing
83+
84+
TimeRun uses **behavior-driven development (BDD)** with [behave](https://behave.readthedocs.io/). All tests are written in Gherkin and live under `features/`.
85+
86+
### Run tests
87+
88+
| Command | Description |
89+
|--------------------|----------------------------------------------------------------|
90+
| `make test` | Run BDD suite with progress + summary + coverage (default) |
91+
| `make test-summary`| Summary and coverage only (minimal output) |
92+
| `make test-verbose`| Full scenario/step output (use when debugging failures) |
93+
| `behave` | Run BDD suite only (no coverage) |
94+
95+
### Run coverage manually
96+
97+
```bash
98+
coverage run --source=timerun -m behave # full output
99+
coverage run --source=timerun -m behave -f progress # progress + summary
100+
coverage run --source=timerun -m behave -f null # summary only
101+
coverage report --show-missing
102+
```
103+
104+
### Adding or changing tests
41105

42-
This project follows these code style guidelines:
43-
- **Black** for code formatting (line length: 79 characters)
44-
- **isort** for import sorting
106+
- **Feature files** — Add or edit `.feature` files in `features/` (e.g. `features/version.feature`). Use standard Gherkin: `Feature`, `Scenario`, `Given`, `When`, `Then`.
107+
- **Step definitions** — Implement steps in Python under `features/steps/`, typically in a `*_steps.py` file. Use `@given`, `@when`, `@then` from `behave`; step functions receive a `context` argument.
108+
- Keep scenarios focused and steps reusable. Add or extend scenarios for new behavior rather than skipping BDD.
109+
110+
## Code Style and Quality
111+
112+
Style and linting are enforced via **pre-commit** (Ruff, mypy, Pylint, and other hooks). After `pre-commit install`, these run automatically on each commit.
113+
114+
### Run checks manually
45115

46-
Pre-commit hooks are installed automatically with `make init` and will run on every commit. You can also run them manually:
47116
```bash
48117
pre-commit run --all-files
49118
```
50119

51-
### Making Changes
120+
### What we expect
52121

53-
1. Create a new branch for your feature or bugfix:
54-
```bash
55-
git checkout -b feature/your-feature-name
56-
```
122+
- **Formatting** — Ruff format (run via pre-commit or `ruff format`).
123+
- **Linting** — Ruff check, Pylint, and other hooks must pass.
124+
- **Types** — Use type hints for public APIs; mypy must pass.
125+
- **Docstrings** — Public functions, classes, and modules should have docstrings.
126+
- **Security** — Bandit and Semgrep run in pre-commit; address any reported issues.
57127

58-
2. Make your changes following the project conventions
59-
3. Add or update tests as needed
60-
4. Ensure all tests pass: `make test`
61-
5. Commit your changes with a clear message
128+
Fixing pre-commit failures before pushing keeps the history clean and CI green.
62129

63-
### Submitting Changes
130+
## Project Structure
64131

65-
1. Push your branch to your fork:
66-
```bash
67-
git push origin feature/your-feature-name
68-
```
132+
```
133+
timerun/
134+
├── timerun.py # Library (single-file by design)
135+
├── features/ # BDD feature files (Gherkin) — behave convention
136+
│ ├── __init__.py # Makes features a package for imports
137+
│ ├── *.feature
138+
│ ├── environment.py # Optional: hooks (before/after scenario, etc.)
139+
│ └── steps/ # Step definitions (flat; all .py files loaded)
140+
│ ├── __init__.py
141+
│ ├── utils.py # Shared constants and helpers (no step decorators)
142+
│ ├── common_steps.py # Shared steps used by multiple features
143+
│ └── *_steps.py # Feature-specific step files
144+
├── pyproject.toml # Project metadata and config
145+
├── Makefile # Commands: init, test, clean, help
146+
├── README.md
147+
├── CONTRIBUTING.md
148+
└── LICENSE
149+
```
69150

70-
2. Create a pull request on GitHub with:
71-
- Clear description of the changes
72-
- Reference to any related issues
73-
- Test coverage for new functionality
151+
- **`timerun.py`** — The only library module; keep it a single file by design.
152+
- **`features/`** — All executable specs; no separate unit test directory. Layout follows [behave](https://behave.readthedocs.io/) convention: step definitions live under `features/steps/` (flat; subdirectories are not searched). Shared logic lives in `features/steps/utils.py`; shared steps (e.g. metadata, wall-time buffer, exception propagation) in `common_steps.py`. Run behave from the project root so `from features.steps.utils import ...` works.
74153

75-
## Project Structure
154+
## Pull Request Process
76155

77-
- `timerun.py` - Main library code (single file module)
78-
- `tests/` - Test suite
79-
- `pyproject.toml` - Project configuration and dependencies
80-
- `Makefile` - Development commands
156+
1. **Create a branch** from `main`:
81157

82-
## Guidelines
158+
```bash
159+
git checkout main
160+
git pull origin main
161+
git checkout -b feature/short-description # or fix/short-description
162+
```
83163

84-
### Code Quality
164+
2. **Make your changes** — Follow [Code Style and Quality](#code-style-and-quality) and add or update BDD scenarios in `features/` for new or changed behavior.
85165

86-
- Maintain 100% test coverage for new code
87-
- Follow existing code patterns and conventions
88-
- Add docstrings for all public functions and classes
89-
- Use type hints consistently
166+
3. **Run the suite and pre-commit**:
90167

91-
### Testing
168+
```bash
169+
make test
170+
pre-commit run --all-files
171+
```
92172

93-
- Write tests for all new functionality
94-
- Use descriptive test names
95-
- Test both success and error cases
96-
- Keep tests focused and independent
173+
4. **Commit** with clear, concise messages. Optionally use conventional style (e.g. `feat: add X`, `fix: correct Y`).
97174

98-
### Documentation
175+
5. **Push** to your fork and open a pull request against `main`:
99176

100-
- Update docstrings for any API changes
101-
- Add examples for new features
102-
- Update README.md if needed
177+
```bash
178+
git push origin feature/short-description
179+
```
103180

104-
## Reporting Issues
181+
6. **Fill out the PR**:
182+
- Describe what changed and why.
183+
- Reference any related issues (e.g. "Fixes #123").
184+
- Confirm tests pass and, for new behavior, that BDD scenarios were added or updated.
105185

106-
When reporting bugs or requesting features:
186+
Maintainers will review and may request changes. Once approved, your PR will be merged.
107187

108-
1. Check existing issues first
109-
2. Use the issue templates if available
110-
3. Provide clear reproduction steps for bugs
111-
4. Include Python version and environment details
188+
## Reporting Bugs
112189

113-
## Questions?
190+
- **Search** existing issues to avoid duplicates.
191+
- **Open an issue** with:
192+
- A short, clear title.
193+
- Steps to reproduce (code or commands).
194+
- Expected vs actual behavior.
195+
- Your environment: OS, Python version (`python --version`), and how you installed TimeRun (pip, editable, etc.).
114196

115-
Feel free to open an issue for questions about contributing or reach out to the maintainers.
197+
For small, obvious fixes you may open a PR directly with a short explanation.
116198

117199
## License
118200

119-
By contributing to TimeRun, you agree that your contributions will be licensed under the MIT License.
201+
Contributions are made under the [MIT License](LICENSE). By submitting a pull request, you agree that your contributions will be licensed under the same terms.

Makefile

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,23 @@ init: ## Set up Python development environment with pre-commit hooks
2222
@echo "Development environment ready! To activate it, run: source $(VENV_DIR)/bin/activate"
2323

2424
.PHONY: test
25-
test: ## Run all tests and display coverage ratio
26-
@"$(VENV_DIR)/bin/pytest" tests/ --cov=timerun --cov-report=term-missing
25+
test: ## Run BDD tests (progress + summary + coverage)
26+
@"$(VENV_DIR)/bin/coverage" run --source=timerun -m behave -f progress
27+
@"$(VENV_DIR)/bin/coverage" report --show-missing
28+
29+
.PHONY: test-summary
30+
test-summary: ## Run BDD tests (summary and coverage only; use 'make test' to see which feature failed)
31+
@"$(VENV_DIR)/bin/coverage" run --source=timerun -m behave -f null
32+
@"$(VENV_DIR)/bin/coverage" report --show-missing
33+
34+
.PHONY: test-verbose
35+
test-verbose: ## Run BDD tests with full scenario/step output (for debugging failures)
36+
@"$(VENV_DIR)/bin/coverage" run --source=timerun -m behave
37+
@"$(VENV_DIR)/bin/coverage" report --show-missing
2738

2839
.PHONY: clean
2940
clean: ## Delete all temporary files including venv
3041
@rm -rf "$(VENV_DIR)" *.egg-info
31-
@rm -rf .mypy_cache .pytest_cache .coverage htmlcov
42+
@rm -rf .mypy_cache .ruff_cache .coverage htmlcov
3243
@find . -name "*.pyc" -delete
3344
@find . -name "__pycache__" -type d -exec rm -rf {} +

0 commit comments

Comments
 (0)