Skip to content

Commit 544ee3c

Browse files
committed
Adds type hints. Modernizes tooling.
1 parent 5c07e08 commit 544ee3c

File tree

13 files changed

+511
-131
lines changed

13 files changed

+511
-131
lines changed

.github/workflows/python-pr.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@ jobs:
1313
steps:
1414
- uses: actions/checkout@v4
1515

16+
- name: Install uv
17+
uses: astral-sh/setup-uv@v5
18+
1619
- name: Set up Python ${{ matrix.python-version }}
1720
uses: actions/setup-python@v5
1821
with:
1922
python-version: ${{ matrix.python-version }}
2023
allow-prereleases: true
2124

2225
- name: Install dependencies
23-
run: |
24-
python -m pip install --upgrade pip
25-
pip install tox tox-gh-actions
26+
run: uv pip install tox tox-gh-actions tox-uv --system
2627

2728
- name: Test with tox without uploading coverage
2829
run: tox

.github/workflows/python-tox.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,17 @@ jobs:
2727
echo "CODECOV_BRANCH=$(echo ${GITHUB_HEAD_REF} | tr / -)" \
2828
>> $GITHUB_ENV
2929
30+
- name: Install uv
31+
uses: astral-sh/setup-uv@v5
32+
3033
- name: Set up Python ${{ matrix.python-version }}
3134
uses: actions/setup-python@v5
3235
with:
3336
python-version: ${{ matrix.python-version }}
3437
allow-prereleases: true
3538

3639
- name: Install dependencies
37-
run: |
38-
python -m pip install --upgrade pip
39-
pip install tox tox-gh-actions
40+
run: uv pip install tox tox-gh-actions tox-uv --system
4041

4142
- name: Test with tox and upload coverage results
4243
run: tox -- --codecov --codecov-token=${{ secrets.CODECOV_TOKEN }} --junit-xml=junit.xml -o junit_family=legacy

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ __pycache__/
99
# Distribution / packaging
1010
.Python
1111
env/
12+
venv/
13+
.venv/
1214
build/
1315
develop-eggs/
1416
dist/

.pre-commit-config.yaml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v5.0.0
4+
hooks:
5+
- id: trailing-whitespace
6+
exclude: '^(.bumpversion.cfg)$'
7+
- id: mixed-line-ending
8+
- id: check-merge-conflict
9+
- id: check-ast
10+
- id: debug-statements
11+
- repo: https://github.com/Lucas-C/pre-commit-hooks-markup
12+
rev: v1.0.1
13+
hooks:
14+
- id: rst-linter
15+
files: '^[A-Z]+\.rst$'
16+
- repo: https://github.com/seantis/pre-commit-hooks
17+
rev: v1.1.0
18+
hooks:
19+
- id: nocheckin
20+
exclude: .pre-commit-config.yaml
21+
- repo: https://github.com/astral-sh/ruff-pre-commit
22+
rev: v0.11.13
23+
hooks:
24+
- id: ruff
25+
args: [ "--fix" ]
26+
files: '^(src|tests)/.*\.py$'
27+
- repo: https://github.com/pre-commit/mirrors-mypy
28+
rev: v1.16.0
29+
hooks:
30+
- id: mypy
31+
additional_dependencies:
32+
- GitPython
33+
- pytest
34+
- pytest-cov
35+
- types-requests
36+
exclude: '.*'
37+
always_run: true
38+
pass_filenames: false
39+
args: ["-p", "pytest_codecov", "-p", "tests"]
40+

pyproject.toml

Lines changed: 142 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ authors = [
1616
maintainers = [
1717
{ name = "David Salvisberg", email = "[email protected]" },
1818
]
19-
license = {file = "LICENSE"}
19+
license = { file = "LICENSE" }
2020
classifiers = [
2121
"Framework :: Pytest",
2222
"Development Status :: 4 - Beta",
@@ -53,6 +53,9 @@ Repository = "https://github.com/seantis/pytest-codecov"
5353
[project.entry-points.pytest11]
5454
codecov = "pytest_codecov"
5555

56+
[tool.setuptools.package-data]
57+
pytest_codecov = ["py.typed"]
58+
5659
[tool.setuptools.dynamic]
5760
version = {attr = "pytest_codecov.__version__"}
5861

@@ -66,17 +69,135 @@ source = ["pytest_codecov"]
6669
show_missing = true
6770
precision = 2
6871

72+
[tool.mypy]
73+
python_version = "3.8"
74+
follow_imports = "silent"
75+
namespace_packages = true
76+
explicit_package_bases = true
77+
strict = true
78+
mypy_path = "$MYPY_CONFIG_FILE_DIR/src"
79+
80+
[tool.ruff]
81+
exclude = [
82+
".bzr",
83+
".direnv",
84+
".eggs",
85+
".git",
86+
".git-rewrite",
87+
".hg",
88+
".ipynb_checkpoints",
89+
".mypy_cache",
90+
".nox",
91+
".pants.d",
92+
".pyenv",
93+
".pytest_cache",
94+
".pytype",
95+
".ruff_cache",
96+
".svn",
97+
".tox",
98+
".venv",
99+
".vscode",
100+
"__pypackages__",
101+
"_build",
102+
"buck-out",
103+
"build",
104+
"dist",
105+
"node_modules",
106+
"site-packages",
107+
"venv",
108+
]
109+
src = ["src", "test"]
110+
include = [
111+
"pyproject.toml",
112+
"src/**/*.py",
113+
"tests/**/*.py",
114+
]
115+
line-length = 79
116+
indent-width = 4
117+
target-version = "py38"
118+
119+
[tool.ruff.lint]
120+
select = [
121+
"A005",
122+
"ASYNC",
123+
"B0",
124+
"B904",
125+
"B909",
126+
"C4",
127+
"COM818",
128+
"E",
129+
"F",
130+
"FLY002",
131+
"FURB",
132+
"G010",
133+
"G2",
134+
"I002",
135+
"ISC",
136+
"LOG",
137+
"N",
138+
"PERF",
139+
"PGH004",
140+
"PGH005",
141+
"PIE",
142+
"PT",
143+
"PYI",
144+
"Q",
145+
"RUF",
146+
"S",
147+
"SIM",
148+
"SLOT",
149+
"T",
150+
"UP",
151+
"W",
152+
]
153+
ignore = [
154+
"FURB101",
155+
"FURB103",
156+
]
157+
unfixable = []
158+
preview = true
159+
160+
[tool.ruff.lint.extend-per-file-ignores]
161+
"src/**/*.py" = ["PT"]
162+
"tests/**/*.py" = [
163+
"S",
164+
]
165+
166+
[tool.ruff.lint.isort]
167+
required-imports = ["from __future__ import annotations"]
168+
169+
[tool.ruff.lint.pep8-naming]
170+
extend-ignore-names = []
171+
classmethod-decorators = []
172+
173+
[tool.ruff.lint.flake8-quotes]
174+
avoid-escape = true
175+
docstring-quotes = "double"
176+
inline-quotes = "single"
177+
multiline-quotes = "double"
178+
179+
[tool.ruff.lint.pyupgrade]
180+
keep-runtime-typing = true
181+
182+
[tool.ruff.format]
183+
quote-style = "single"
184+
indent-style = "space"
185+
skip-magic-trailing-comma = false
186+
line-ending = "lf"
187+
docstring-code-format = true
188+
docstring-code-line-length = "dynamic"
189+
69190
[tool.tox]
70191
legacy_tox_ini = """
71192
[tox]
72-
envlist = py38,py39,py310,py311,py312,py313,flake8,report
193+
envlist = py38,py39,py310,py311,py312,py313,mypy,ruff,report
73194
74195
[gh-actions]
75196
python =
76-
3.8: py38,flake8
197+
3.8: py38
77198
3.9: py39
78199
3.10: py310
79-
3.11: py311
200+
3.11: py311,ruff,mypy
80201
3.12: py312
81202
3.13: py313
82203
@@ -94,14 +215,27 @@ legacy_tox_ini = """
94215
.
95216
GitPython
96217
97-
[testenv:flake8]
218+
[testenv:mypy]
219+
basepython = python3.11
220+
deps =
221+
-e{toxinidir}[git]
222+
mypy
223+
types-requests
224+
commands =
225+
mypy -p pytest_codecov -p tests --python-version 3.9
226+
mypy -p pytest_codecov -p tests --python-version 3.10
227+
mypy -p pytest_codecov -p tests --python-version 3.11
228+
mypy -p pytest_codecov -p tests --python-version 3.12
229+
mypy -p pytest_codecov -p tests --python-version 3.13
230+
231+
[testenv:ruff]
98232
skip_install = true
99-
deps = flake8
100-
commands = flake8 src setup.py tests
233+
deps = ruff
234+
commands = ruff check
101235
102236
[testenv:report]
103-
deps = coverage
104237
skip_install = true
238+
deps = coverage
105239
commands =
106240
coverage combine
107241
coverage report

src/pytest_codecov/__init__.py

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
from __future__ import annotations
2+
13
import argparse
24
import os
35
import pytest
46
import re
7+
from typing import TYPE_CHECKING
58

69
import pytest_codecov.git as git
710
import pytest_codecov.codecov as codecov
811

12+
if TYPE_CHECKING:
13+
from coverage import Coverage
14+
from pytest_cov.plugin import CovPlugin # type: ignore[import-untyped]
15+
916

1017
__version__ = '0.7.0'
1118
token_regex = re.compile(
@@ -16,21 +23,24 @@
1623
)
1724

1825

19-
def validate_token(arg):
26+
def validate_token(arg: str) -> str:
2027
if not token_regex.match(arg):
2128
msg = 'Invalid Codecov.io repository token supplied.'
2229
raise argparse.ArgumentTypeError(msg)
2330
return arg
2431

2532

26-
def validate_slug(arg):
33+
def validate_slug(arg: str) -> str:
2734
if not slug_regex.match(arg):
2835
msg = 'Invalid repository slug supplied.'
2936
raise argparse.ArgumentTypeError(msg)
3037
return arg
3138

3239

33-
def pytest_addoption(parser, pluginmanager):
40+
def pytest_addoption(
41+
parser: pytest.Parser,
42+
pluginmanager: pytest.PytestPluginManager
43+
) -> None:
3444
group = parser.getgroup('codecov')
3545
group.addoption(
3646
'--codecov',
@@ -83,20 +93,25 @@ def pytest_addoption(parser, pluginmanager):
8393
action='store_false',
8494
dest='codecov_upload_on_failure',
8595
default=True,
86-
help='Don\'t upload coverage results on test failure'
96+
help="Don't upload coverage results on test failure"
8797
)
8898
group.addoption(
8999
'--codecov-exclude-junit-xml',
90100
action='store_false',
91101
dest='codecov_junit_xml',
92102
default=True,
93-
help='Don\'t upload the junit xml file'
103+
help="Don't upload the junit xml file"
94104
)
95105

96106

97107
class CodecovPlugin:
98108

99-
def upload_report(self, terminalreporter, config, cov):
109+
def upload_report(
110+
self,
111+
terminalreporter: pytest.TerminalReporter,
112+
config: pytest.Config,
113+
cov: Coverage
114+
) -> None:
100115
option = config.option
101116
uploader = codecov.CodecovUploader(
102117
option.codecov_slug,
@@ -105,7 +120,7 @@ def upload_report(self, terminalreporter, config, cov):
105120
token=option.codecov_token,
106121
)
107122
uploader.add_network_files(git.ls_files())
108-
from coverage.misc import CoverageException
123+
from coverage.exceptions import CoverageException
109124
try:
110125
uploader.add_coverage_report(cov)
111126
except CoverageException as exc:
@@ -188,12 +203,20 @@ def upload_report(self, terminalreporter, config, cov):
188203
terminalreporter.write_line(f'ERROR: {error}', red=True, bold=True)
189204

190205
@pytest.hookimpl(trylast=True)
191-
def pytest_terminal_summary(self, terminalreporter, exitstatus, config):
192-
cov_plugin = config.pluginmanager.get_plugin('_cov')
206+
def pytest_terminal_summary(
207+
self,
208+
terminalreporter: pytest.TerminalReporter,
209+
exitstatus: int,
210+
config: pytest.Config
211+
) -> None:
212+
cov_plugin: CovPlugin | None = config.pluginmanager.get_plugin('_cov')
213+
if cov_plugin is None:
214+
return
215+
193216
if cov_plugin.cov_controller is None:
194217
return
195218

196-
cov = cov_plugin.cov_controller.cov
219+
cov: Coverage | None = cov_plugin.cov_controller.cov
197220
if cov is None:
198221
return
199222

@@ -203,7 +226,7 @@ def pytest_terminal_summary(self, terminalreporter, exitstatus, config):
203226
self.upload_report(terminalreporter, config, cov)
204227

205228

206-
def pytest_configure(config): # pragma: no cover
229+
def pytest_configure(config: pytest.Config) -> None: # pragma: no cover
207230
# NOTE: Don't report codecov results on worker nodes
208231
if hasattr(config, 'workerinput'):
209232
return

0 commit comments

Comments
 (0)