Skip to content

Commit

Permalink
Ensure template works with pright in strict mode (#184)
Browse files Browse the repository at this point in the history
  • Loading branch information
callumforrester authored Aug 9, 2024
2 parents cbc04ca + 2f9da23 commit 262db8e
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 6 deletions.
17 changes: 17 additions & 0 deletions docs/how-to/strict-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Enable Pyright's Strict Mode

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.

## Configuration

Add the `strict` line to `pyproject.toml` as follows:

```toml
[tool.pyright]
strict = ["src", "tests"]
reportMissingImports = false # Ignore missing stubs in imported modules
```

## Third Party Libraries

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.
12 changes: 9 additions & 3 deletions template/src/{{ package_name }}/__main__.py.jinja
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
from argparse import ArgumentParser
from collections.abc import Sequence

from . import __version__

__all__ = ["main"]


def main(args=None):
def main(args: Sequence[str] | None = None) -> None:
parser = ArgumentParser()
parser.add_argument("-v", "--version", action="version", version=__version__)
args = parser.parse_args(args)
parser.add_argument(
"-v",
"--version",
action="version",
version=__version__,
)
parser.parse_args(args)


# test with: python -m {{package_name}}
Expand Down
12 changes: 9 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from typing import Any

import pytest

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

@pytest.hookimpl(tryfirst=True)
def pytest_exception_interact(call):
raise call.excinfo.value
def pytest_exception_interact(call: pytest.CallInfo[Any]):
if call.excinfo is not None:
raise call.excinfo.value
else:
raise RuntimeError(
f"{call} has no exception data, an unknown error has occurred"
)

@pytest.hookimpl(tryfirst=True)
def pytest_internalerror(excinfo):
def pytest_internalerror(excinfo: pytest.ExceptionInfo[Any]):
raise excinfo.value
14 changes: 14 additions & 0 deletions tests/test_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,17 @@ def __init__(self):
stream.write(code)
with pytest.raises(AssertionError, match="SLF001 Private member accessed: `_bar`"):
run("ruff check")


def test_works_in_pyright_strict_mode(tmp_path: Path):
copy_project(tmp_path)
pyproject_toml = tmp_path / "pyproject.toml"

# Enable strict mode
run_pipe(
f'sed -i \'/\\[tool.pyright\\]/a\\strict = ["src", "tests"]\' {pyproject_toml}'
)

# Ensure pyright is still happy
run = make_venv(tmp_path)
run(f"./venv/bin/pyright {tmp_path}")

0 comments on commit 262db8e

Please sign in to comment.