Skip to content

Commit 24add9e

Browse files
authored
v0.4.0 (#4)
Features: - Add async context manager support (async with Timer()) - Add async function decorator support (@Timer on async functions) - Add async generator function support - Maintain full backward compatibility with existing synchronous code Improvements: - Update GitHub Actions to use latest actions (v6) and Python 3.11 - Integrate Codecov for automated coverage reporting - Add Python 3.14 support to CI test matrix - Fix test dependency installation to use pyproject.toml - Update pre-commit config to be flexible on Python version - Switch to pyenforce hook and resolve all linting issues - Enhance type hints and protocol definitions - Expand test suite with comprehensive async test coverage - Update README with async usage examples - Update shields.io badges
1 parent c1efb4a commit 24add9e

12 files changed

Lines changed: 721 additions & 199 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
---
12
name: Continuous Integration
23

4+
# yamllint disable-line rule:truthy
35
on:
46
pull_request:
57
branches: [main]
@@ -14,12 +16,12 @@ jobs:
1416
runs-on: ubuntu-latest
1517
steps:
1618
- name: Checkout code
17-
uses: actions/checkout@v5
19+
uses: actions/checkout@v6
1820

19-
- name: Set up Python 3.12
20-
uses: actions/setup-python@v5
21+
- name: Set up Python 3.11
22+
uses: actions/setup-python@v6
2123
with:
22-
python-version: '3.12'
24+
python-version: '3.11'
2325

2426
- name: Run pre-commit hooks
2527
uses: pre-commit/action@v3.0.1
@@ -29,33 +31,44 @@ jobs:
2931
needs: lint
3032
strategy:
3133
matrix:
32-
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
34+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
3335
steps:
3436
- name: Checkout code
35-
uses: actions/checkout@v5
37+
uses: actions/checkout@v6
3638

3739
- name: Set up Python ${{ matrix.python-version }}
38-
uses: actions/setup-python@v5
40+
uses: actions/setup-python@v6
3941
with:
4042
python-version: ${{ matrix.python-version }}
4143

4244
- name: Install test dependencies
43-
run: pip install pytest
45+
run: pip install -e ".[dev]"
4446

45-
- name: Run tests
46-
run: python -m pytest
47+
- 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
54+
55+
- name: Upload coverage reports to Codecov
56+
uses: codecov/codecov-action@v5
57+
with:
58+
token: ${{ secrets.CODECOV_TOKEN }}
59+
flags: python${{ matrix.python-version }}
4760

4861
build:
4962
runs-on: ubuntu-latest
5063
needs: test
5164
steps:
5265
- name: Checkout code
53-
uses: actions/checkout@v5
66+
uses: actions/checkout@v6
5467

55-
- name: Set up Python 3.12
56-
uses: actions/setup-python@v5
68+
- name: Set up Python 3.11
69+
uses: actions/setup-python@v6
5770
with:
58-
python-version: '3.12'
71+
python-version: '3.11'
5972

6073
- name: Install build dependencies
6174
run: pip install build twine

.github/workflows/release.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ jobs:
1212
runs-on: ubuntu-latest
1313
steps:
1414
- name: Checkout code
15-
uses: actions/checkout@v5
15+
uses: actions/checkout@v6
1616

17-
- name: Set up Python 3.12
18-
uses: actions/setup-python@v5
17+
- name: Set up Python 3.11
18+
uses: actions/setup-python@v6
1919
with:
20-
python-version: '3.12'
20+
python-version: '3.11'
2121

2222
- name: Install build dependencies
2323
run: pip install build

.pre-commit-config.yaml

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

14-
- repo: https://github.com/adrienverge/yamllint
15-
rev: v1.37.1
16-
hooks:
17-
- id: yamllint
18-
19-
- repo: https://github.com/pycqa/isort
20-
rev: 6.0.1
21-
hooks:
22-
- id: isort
23-
24-
- repo: https://github.com/psf/black
25-
rev: 25.1.0
26-
hooks:
27-
- id: black
28-
29-
- repo: https://github.com/pre-commit/mirrors-mypy
30-
rev: v1.17.1
14+
- repo: https://github.com/HH-MWB/pyenforce
15+
rev: v0.1.0
3116
hooks:
17+
- id: ruff-format
18+
- id: ruff-check
3219
- id: mypy
33-
34-
- repo: https://github.com/pylint-dev/pylint
35-
rev: v3.3.8
36-
hooks:
20+
additional_dependencies:
21+
- ".[mypy]" # Required to re-adds mypy as a dependency
22+
- pytest
3723
- id: pylint
3824
additional_dependencies:
25+
- ".[pylint]" # Required to re-adds Pylint as a dependency
3926
- pytest
27+
- id: bandit
28+
- id: semgrep
29+
- id: vulture
4030

41-
- repo: https://github.com/pycqa/bandit
42-
rev: '1.8.6'
31+
- repo: https://github.com/adrienverge/yamllint
32+
rev: v1.37.1
4333
hooks:
44-
- id: bandit
45-
args: ['-c', 'pyproject.toml']
34+
- id: yamllint

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2019-2025 HH-MWB
3+
Copyright (c) 2019-2026 HH-MWB
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
<p align="center"><strong>TimeRun</strong> - <em>Python library for elapsed time measurement.</em></p>
88

99
<p align="center">
10-
<a href="https://github.com/HH-MWB/timerun/blob/master/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/timerun.svg"></a>
11-
<a href="https://pypi.org/project/timerun/"><img alt="PyPI Latest Release" src="https://img.shields.io/pypi/v/timerun.svg"></a>
12-
<a href="https://pypi.org/project/timerun/"><img alt="Package Status" src="https://img.shields.io/pypi/status/timerun.svg"></a>
13-
<a href="https://github.com/psf/black/"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
14-
<a href="https://pycqa.github.io/isort/"><img alt="Imports: isort" src="https://img.shields.io/badge/%20imports-isort-%231674b1"></a>
10+
<a href="https://pypi.org/project/timerun/"><img alt="Version" src="https://img.shields.io/pypi/v/timerun.svg"></a>
11+
<a href="https://pypi.org/project/timerun/"><img alt="Status" src="https://img.shields.io/pypi/status/timerun.svg"></a>
12+
<a href="https://github.com/HH-MWB/timerun/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/timerun.svg"></a>
13+
<a href="https://codecov.io/gh/HH-MWB/timerun"><img alt="Coverage" src="https://codecov.io/gh/HH-MWB/timerun/branch/main/graph/badge.svg"></a>
14+
<a href="https://pepy.tech/project/timerun"><img alt="Total Downloads" src="https://static.pepy.tech/badge/timerun"></a>
1515
</p>
1616

1717
TimeRun is a simple, yet elegant elapsed time measurement library for [Python](https://www.python.org). It is distributed as a single file module and has no dependencies other than the [Python Standard Library](https://docs.python.org/3/library/).
@@ -45,24 +45,79 @@ pip install git+https://github.com/HH-MWB/timerun.git
4545
### Measure Code Block
4646

4747
```python
48+
>>> import time
4849
>>> from timerun import Timer
4950
>>> with Timer() as timer:
50-
... pass # put your code here
51+
... time.sleep(0.1) # your code here
5152
>>> print(timer.duration)
52-
0:00:00.000000100
53+
0:00:00.100000000
5354
```
5455

5556
### Measure Function
5657

5758
```python
59+
>>> import time
5860
>>> from timerun import Timer
5961
>>> timer = Timer()
6062
>>> @timer
6163
... def func():
62-
... pass # put your code here
64+
... time.sleep(0.1) # your code here
6365
>>> func()
6466
>>> print(timer.duration)
65-
0:00:00.000000100
67+
0:00:00.100000000
68+
```
69+
70+
### Measure Async Function
71+
72+
```python
73+
>>> import asyncio
74+
>>> from timerun import Timer
75+
>>> timer = Timer()
76+
>>> @timer
77+
... async def async_func():
78+
... await asyncio.sleep(0.1) # your code here
79+
>>> asyncio.run(async_func())
80+
>>> print(timer.duration)
81+
0:00:00.100000000
82+
```
83+
84+
### Measure Async Code Block
85+
86+
```python
87+
>>> import asyncio
88+
>>> from timerun import Timer
89+
>>> async def async_code():
90+
... async with Timer() as timer:
91+
... await asyncio.sleep(0.1) # your code here
92+
... print(timer.duration)
93+
>>> asyncio.run(async_code())
94+
0:00:00.100000000
95+
```
96+
97+
### Multiple Measurements
98+
99+
```python
100+
>>> import time
101+
>>> from timerun import Timer
102+
>>> timer = Timer()
103+
>>> with timer:
104+
... time.sleep(0.1) # your code here
105+
>>> with timer:
106+
... time.sleep(0.1) # your code here
107+
>>> print(timer.duration) # Last duration
108+
0:00:00.100000000
109+
>>> print(timer.durations) # All durations
110+
(ElapsedTime(nanoseconds=100000000), ElapsedTime(nanoseconds=100000000))
111+
```
112+
113+
### Advanced Options
114+
115+
```python
116+
>>> from timerun import Timer
117+
>>> # Exclude sleep time from measurements
118+
>>> timer = Timer(count_sleep=False)
119+
>>> # Limit storage to last 10 measurements
120+
>>> timer = Timer(max_len=10)
66121
```
67122

68123
## Contributing
@@ -71,4 +126,4 @@ We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guid
71126

72127
## License
73128

74-
This project is licensed under the MIT License - see the [LICENSE](https://github.com/HH-MWB/timerun/blob/master/LICENSE) file for details.
129+
This project is licensed under the MIT License - see the [LICENSE](https://github.com/HH-MWB/timerun/blob/main/LICENSE) file for details.

pyproject.toml

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ classifiers = [
2828
"Programming Language :: Python :: 3.11",
2929
"Programming Language :: Python :: 3.12",
3030
"Programming Language :: Python :: 3.13",
31+
"Programming Language :: Python :: 3.14",
3132
"Topic :: Software Development :: Libraries :: Python Modules",
3233
"Topic :: System :: Monitoring",
3334
]
3435
dynamic = ["version"]
3536

3637
[project.optional-dependencies]
37-
dev = ["pytest", "pytest-cov"]
38+
dev = ["pytest", "pytest-asyncio", "pytest-cov"]
3839

3940
[project.urls]
4041
Homepage = "https://github.com/HH-MWB/timerun"
@@ -49,19 +50,3 @@ license-files = ["LICENSE"]
4950

5051
[tool.setuptools.dynamic]
5152
version = { attr = "timerun.__version__" }
52-
53-
[tool.bandit]
54-
skips = ["B101"] # Skip assert_used test
55-
56-
[tool.black]
57-
line-length = 79
58-
target-version = [
59-
"py39",
60-
"py310",
61-
"py311",
62-
"py312",
63-
"py313",
64-
]
65-
66-
[tool.isort]
67-
profile = "black"

tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Test suite for timerun."""

0 commit comments

Comments
 (0)