Skip to content

Commit 2dfe36f

Browse files
authored
Optionally run tests with mypy nightly (#512)
* CI: option to use mypy nightly * update pre-commit * skip ignores to run on CI * docs
1 parent 5740fe7 commit 2dfe36f

File tree

8 files changed

+78
-9
lines changed

8 files changed

+78
-9
lines changed

.github/pull_request_template.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1+
<!--
2+
Two CI tests are using not yet released versions of pandas ("nightly") and mypy ("mypy_nightly"). It is okay if they fail.
3+
-->
4+
15
- [ ] Closes #xxxx (Replace xxxx with the Github issue number)
26
- [ ] Tests added: Please use `assert_type()` to assert the type of any return value

.github/workflows/test.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,19 @@ jobs:
6666
- uses: actions/checkout@v3
6767

6868
- uses: pre-commit/action@v3.0.0
69+
70+
mypy_nightly:
71+
runs-on: ubuntu-latest
72+
timeout-minutes: 10
73+
74+
steps:
75+
- uses: actions/checkout@v3
76+
77+
- name: Install project dependencies
78+
uses: ./.github/setup
79+
with:
80+
os: ubuntu-latest
81+
python-version: '3.10'
82+
83+
- name: Run mypy tests with mypy nightly
84+
run: poetry run poe mypy --mypy_nightly

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ repos:
77
hooks:
88
- id: black
99
- repo: https://github.com/PyCQA/isort
10-
rev: 5.11.2
10+
rev: 5.11.4
1111
hooks:
1212
- id: isort
1313
- repo: https://github.com/asottile/pyupgrade
@@ -27,7 +27,7 @@ repos:
2727
- id: flake8
2828
name: flake8 (pyi)
2929
additional_dependencies:
30-
- flake8-pyi==22.11.0
30+
- flake8-pyi==23.1.0
3131
types: [pyi]
3232
args: [
3333
--ignore=E301 E302 E305 E402 E501 E701 E704 F401 F811 W503 Y019 Y034 Y037 Y041 Y042,

docs/tests.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ Here are the most important options. Fore more details, please use `poe --help`.
1111
- Run only pytest: `poe pytest`
1212
- Run only pre-commit: `poe style`
1313
- Run tests against the installed stubs (this will install and uninstall the stubs): `poe test_dist`
14-
- Optional: run pytest against pandas nightly (this might fail): `poe pytest --nightly`
15-
- Optional: Run stubtest to compare the installed pandas-stubs against pandas (this will fail): `poe stubtest`. If you have created an allowlist to ignore certain errors: `poe stubtest path_to_the_allow_list`
1614

1715
These tests originally came from https://github.com/VirtusLab/pandas-stubs.
16+
17+
The following tests are **optional**. Some of them are run by the CI but it is okay if they fail.
18+
19+
- Run pytest against pandas nightly: `poe pytest --nightly`
20+
- Use mypy nightly to validate the annotations: `poe mypy --mypy_nightly`
21+
- Run stubtest to compare the installed pandas-stubs against pandas (this will fail): `poe stubtest`. If you have created an allowlist to ignore certain errors: `poe stubtest path_to_the_allow_list`

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ script = "scripts.test.run:style"
9090

9191
[tool.poe.tasks.mypy]
9292
help = "Run mypy on 'tests' (using the local stubs) and on the local stubs"
93-
script = "scripts.test.run:mypy_src"
93+
args = [{name = "mypy_nightly", positional = false, default = false, type = "boolean", required = false, help= "Use mypy nightly (off by default)"}]
94+
script = "scripts.test:mypy_src(mypy_nightly)"
9495

9596
[tool.poe.tasks.mypy_dist]
9697
help = "Run mypy on 'tests' using the installed stubs"

scripts/test/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,8 @@ def stubtest(allowlist: str, check_missing: bool, nightly: bool) -> None:
5151
def pytest(nightly: bool) -> None:
5252
steps = [_step.nightly] if nightly else []
5353
run_job(steps + [_step.pytest])
54+
55+
56+
def mypy_src(mypy_nightly: bool) -> None:
57+
steps = [_step.mypy_nightly] if mypy_nightly else []
58+
run_job(steps + [_step.mypy_src])

scripts/test/_step.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,6 @@
3232
nightly = Step(
3333
name="Install pandas nightly", run=run.nightly_pandas, rollback=run.released_pandas
3434
)
35+
mypy_nightly = Step(
36+
name="Install mypy nightly", run=run.nightly_mypy, rollback=run.released_mypy
37+
)

scripts/test/run.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,49 @@ def nightly_pandas():
9595
subprocess.run(cmd, check=True)
9696

9797

98-
def released_pandas():
99-
# query pandas version
98+
def _get_version_from_pyproject(program: str) -> str:
10099
text = Path("pyproject.toml").read_text()
101100
version_line = next(
102-
line for line in text.splitlines() if line.startswith("pandas = ")
101+
line for line in text.splitlines() if line.startswith(f"{program} = ")
103102
)
104-
version = version_line.split('"')[1]
103+
return version_line.split('"')[1]
104+
105105

106+
def released_pandas():
107+
version = _get_version_from_pyproject("pandas")
106108
cmd = [sys.executable, "-m", "pip", "install", f"pandas=={version}"]
107109
subprocess.run(cmd, check=True)
110+
111+
112+
def nightly_mypy():
113+
cmd = [
114+
sys.executable,
115+
"-m",
116+
"pip",
117+
"install",
118+
"--upgrade",
119+
"git+https://github.com/python/mypy.git",
120+
]
121+
subprocess.run(cmd, check=True)
122+
123+
# ignore unused ignore errors
124+
config_file = Path("pyproject.toml")
125+
config_file.write_text(
126+
config_file.read_text().replace(
127+
"warn_unused_ignores = true", "warn_unused_ignores = false"
128+
)
129+
)
130+
131+
132+
def released_mypy():
133+
version = _get_version_from_pyproject("mypy")
134+
cmd = [sys.executable, "-m", "pip", "install", f"mypy=={version}"]
135+
subprocess.run(cmd, check=True)
136+
137+
# check for unused ignores again
138+
config_file = Path("pyproject.toml")
139+
config_file.write_text(
140+
config_file.read_text().replace(
141+
"warn_unused_ignores = false", "warn_unused_ignores = true"
142+
)
143+
)

0 commit comments

Comments
 (0)