Skip to content

Commit 262db8e

Browse files
Ensure template works with pright in strict mode (#184)
2 parents cbc04ca + 2f9da23 commit 262db8e

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

docs/how-to/strict-mode.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Enable Pyright's Strict Mode
2+
3+
For projects using pyright you can enable strict mode for stricter than normal type checking. See [the docs](https://github.com/microsoft/pyright/blob/main/docs/configuration.md) for a full breakdown. The primary benefits are increased confidence in code that has been more thoroughly analyzed and a shorter development time thanks to fast feedback from the type checker.
4+
5+
## Configuration
6+
7+
Add the `strict` line to `pyproject.toml` as follows:
8+
9+
```toml
10+
[tool.pyright]
11+
strict = ["src", "tests"]
12+
reportMissingImports = false # Ignore missing stubs in imported modules
13+
```
14+
15+
## Third Party Libraries
16+
17+
Strict mode does not usually work well with libraries that do not have [type stubs](https://github.com/microsoft/pyright/blob/main/docs/type-stubs.md), you will likely need a `# type: ignore` on any line that directly uses the library code. This may limit the usefulness of pyright but it can still be worth doing to ensure your own code is internally consistent.

template/src/{{ package_name }}/__main__.py.jinja

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
from argparse import ArgumentParser
2+
from collections.abc import Sequence
23

34
from . import __version__
45

56
__all__ = ["main"]
67

78

8-
def main(args=None):
9+
def main(args: Sequence[str] | None = None) -> None:
910
parser = ArgumentParser()
10-
parser.add_argument("-v", "--version", action="version", version=__version__)
11-
args = parser.parse_args(args)
11+
parser.add_argument(
12+
"-v",
13+
"--version",
14+
action="version",
15+
version=__version__,
16+
)
17+
parser.parse_args(args)
1218

1319

1420
# test with: python -m {{package_name}}

tests/conftest.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
from typing import Any
23

34
import pytest
45

@@ -7,9 +8,14 @@
78
if os.getenv("PYTEST_RAISE", "0") == "1":
89

910
@pytest.hookimpl(tryfirst=True)
10-
def pytest_exception_interact(call):
11-
raise call.excinfo.value
11+
def pytest_exception_interact(call: pytest.CallInfo[Any]):
12+
if call.excinfo is not None:
13+
raise call.excinfo.value
14+
else:
15+
raise RuntimeError(
16+
f"{call} has no exception data, an unknown error has occurred"
17+
)
1218

1319
@pytest.hookimpl(tryfirst=True)
14-
def pytest_internalerror(excinfo):
20+
def pytest_internalerror(excinfo: pytest.ExceptionInfo[Any]):
1521
raise excinfo.value

tests/test_example.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,17 @@ def __init__(self):
149149
stream.write(code)
150150
with pytest.raises(AssertionError, match="SLF001 Private member accessed: `_bar`"):
151151
run("ruff check")
152+
153+
154+
def test_works_in_pyright_strict_mode(tmp_path: Path):
155+
copy_project(tmp_path)
156+
pyproject_toml = tmp_path / "pyproject.toml"
157+
158+
# Enable strict mode
159+
run_pipe(
160+
f'sed -i \'/\\[tool.pyright\\]/a\\strict = ["src", "tests"]\' {pyproject_toml}'
161+
)
162+
163+
# Ensure pyright is still happy
164+
run = make_venv(tmp_path)
165+
run(f"./venv/bin/pyright {tmp_path}")

0 commit comments

Comments
 (0)