Skip to content

Commit 4355a33

Browse files
authored
Add pyright support (#125)
* attempt setting up pyright * fix cookiecutter * add tests for typechecking config * add some comments * fix formatting
1 parent 5354d43 commit 4355a33

File tree

10 files changed

+84
-13
lines changed

10 files changed

+84
-13
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ This is a modern Cookiecutter template that can be used to initiate a Python pro
1515
- [Poetry](https://python-poetry.org/) for dependency management
1616
- CI/CD with [GitHub Actions](https://github.com/features/actions)
1717
- Pre-commit hooks with [pre-commit](https://pre-commit.com/)
18-
- Code quality with [ruff](https://github.com/charliermarsh/ruff), [mypy](https://mypy.readthedocs.io/en/stable/), [deptry](https://github.com/fpgmaas/deptry/) and [prettier](https://prettier.io/)
18+
- Code quality with [ruff](https://github.com/charliermarsh/ruff), [mypy](https://mypy.readthedocs.io/en/stable/) or [pyright](https://github.com/microsoft/pyright), [deptry](https://github.com/fpgmaas/deptry/) and [prettier](https://prettier.io/)
1919
- Publishing to [PyPI](https://pypi.org) or [Artifactory](https://jfrog.com/artifactory) by creating a new release on GitHub
2020
- Testing and coverage with [pytest](https://docs.pytest.org/en/7.1.x/) and [codecov](https://about.codecov.io/)
2121
- Documentation with [MkDocs](https://www.mkdocs.org/)

cookiecutter.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"project_description": "This is a template repository for Python projects that use Poetry for their dependency management.",
88
"include_github_actions": ["y", "n"],
99
"publish_to": ["pypi", "artifactory", "none"],
10+
"typechecking": ["mypy", "pyright"],
1011
"deptry": ["y", "n"],
1112
"mkdocs": ["y", "n"],
1213
"codecov": ["y", "n"],

docs/features/linting.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,13 @@ ignore = [
6464
"tests/*" = ["S101"]
6565
```
6666

67-
# mypy
67+
# Typechecking
6868

69-
[mypy](https://mypy.readthedocs.io/en/stable/) is used for static type checking, and it's configuration and can be edited in `pyproject.toml`.
69+
Two typechecking options are available, `mypy` or `pyright`.
70+
71+
## mypy
72+
73+
[mypy](https://mypy.readthedocs.io/en/stable/) can be used for static type checking, and its configuration and can be edited in `pyproject.toml`.
7074

7175
```toml
7276
[tool.mypy]
@@ -84,9 +88,21 @@ exclude = [
8488
]
8589
```
8690

91+
## pyright
92+
93+
[pyright](https://github.com/microsoft/pyright) can be used for static type checking, and its configuration and can be edited in `pyproject.toml`:
94+
95+
```toml
96+
[tool.pyright]
97+
include = ['{{cookiecutter.project_slug}}']
98+
typeCheckingMode = "strict"
99+
venvPath = "."
100+
venv = ".venv"
101+
```
102+
87103
# deptry
88104

89-
[deptry](https://github.com/fpgmaas/deptry) is used to check the code for dependency issues, and it's configuration and can be edited in `pyproject.toml`.
105+
[deptry](https://github.com/fpgmaas/deptry) is used to check the code for dependency issues, and its configuration and can be edited in `pyproject.toml`.
90106

91107
```toml
92108
[tool.mypy]

docs/features/makefile.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ available:
77

88
```
99
install Install the poetry environment and install the pre-commit hooks
10-
check Lint and check code by running ruff, mypy and deptry.
10+
check Lint and check code by running ruff, mypy/pyright and deptry.
1111
test Test the code with pytest
1212
build Build wheel file using poetry
1313
clean-build clean build artifacts

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ This is a modern Cookiecutter template that can be used to initiate a Python pro
2020
- [Poetry](https://python-poetry.org/) for dependency management
2121
- CI/CD with [GitHub Actions](https://github.com/features/actions)
2222
- Pre-commit hooks with [pre-commit](https://pre-commit.com/)
23-
- Code quality with [ruff](https://github.com/charliermarsh/ruff), [mypy](https://mypy.readthedocs.io/en/stable/), [deptry](https://github.com/fpgmaas/deptry/) and [prettier](https://prettier.io/)
23+
- Code quality with [ruff](https://github.com/charliermarsh/ruff), [mypy](https://mypy.readthedocs.io/en/stable/) or [pyright](https://github.com/microsoft/pyright), [deptry](https://github.com/fpgmaas/deptry/) and [prettier](https://prettier.io/)
2424
- Publishing to [PyPI](https://pypi.org) or [Artifactory](https://jfrog.com/artifactory) by creating a new release on GitHub
2525
- Testing and coverage with [pytest](https://docs.pytest.org/en/7.1.x/) and [codecov](https://about.codecov.io/)
2626
- Documentation with [MkDocs](https://www.mkdocs.org/)

tests/test_cookiecutter.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ def test_dont_publish(cookies, tmp_path):
7676
assert result.exit_code == 0
7777
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
7878
assert not file_contains_text(
79-
f"{result.project_path}/.github/workflows/on-release-main.yml", "make build-and-publish"
79+
f"{result.project_path}/.github/workflows/on-release-main.yml",
80+
"make build-and-publish",
8081
)
8182

8283

@@ -86,7 +87,10 @@ def test_mkdocs(cookies, tmp_path):
8687
assert result.exit_code == 0
8788
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "main.yml")
8889
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
89-
assert file_contains_text(f"{result.project_path}/.github/workflows/on-release-main.yml", "mkdocs gh-deploy")
90+
assert file_contains_text(
91+
f"{result.project_path}/.github/workflows/on-release-main.yml",
92+
"mkdocs gh-deploy",
93+
)
9094
assert file_contains_text(f"{result.project_path}/Makefile", "docs:")
9195
assert os.path.isdir(f"{result.project_path}/docs")
9296

@@ -98,7 +102,8 @@ def test_not_mkdocs(cookies, tmp_path):
98102
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "main.yml")
99103
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
100104
assert not file_contains_text(
101-
f"{result.project_path}/.github/workflows/on-release-main.yml", "mkdocs gh-deploy"
105+
f"{result.project_path}/.github/workflows/on-release-main.yml",
106+
"mkdocs gh-deploy",
102107
)
103108
assert not file_contains_text(f"{result.project_path}/Makefile", "docs:")
104109
assert not os.path.isdir(f"{result.project_path}/docs")
@@ -153,3 +158,37 @@ def test_remove_release_workflow(cookies, tmp_path):
153158
result = cookies.bake(extra_context={"publish_to": "none", "mkdocs": "n"})
154159
assert result.exit_code == 0
155160
assert not os.path.isfile(f"{result.project_path}/.github/workflows/on-release-main.yml")
161+
162+
163+
def test_pyright(cookies, tmp_path):
164+
with run_within_dir(tmp_path):
165+
result = cookies.bake(extra_context={"typechecking": "pyright"})
166+
assert result.exit_code == 0
167+
# check the toml file
168+
assert file_contains_text(f"{result.project_path}/pyproject.toml", "[tool.pyright]")
169+
assert file_contains_text(f"{result.project_path}/pyproject.toml", "pyright =")
170+
assert not file_contains_text(f"{result.project_path}/pyproject.toml", "[tool.mypy]")
171+
assert not file_contains_text(f"{result.project_path}/pyproject.toml", "mypy =")
172+
# check the make file
173+
assert file_contains_text(f"{result.project_path}/Makefile", "pyright")
174+
assert not file_contains_text(f"{result.project_path}/Makefile", "mypy")
175+
# check the tox file
176+
assert file_contains_text(f"{result.project_path}/tox.ini", "pyright")
177+
assert not file_contains_text(f"{result.project_path}/tox.ini", "mypy")
178+
179+
180+
def test_mypy(cookies, tmp_path):
181+
with run_within_dir(tmp_path):
182+
result = cookies.bake(extra_context={"typechecking": "mypy"})
183+
assert result.exit_code == 0
184+
# check the toml file
185+
assert file_contains_text(f"{result.project_path}/pyproject.toml", "[tool.mypy]")
186+
assert file_contains_text(f"{result.project_path}/pyproject.toml", "mypy =")
187+
assert not file_contains_text(f"{result.project_path}/pyproject.toml", "[tool.pyright]")
188+
assert not file_contains_text(f"{result.project_path}/pyproject.toml", "pyright =")
189+
# check the make file
190+
assert file_contains_text(f"{result.project_path}/Makefile", "mypy")
191+
assert not file_contains_text(f"{result.project_path}/Makefile", "pyright")
192+
# check the tox file
193+
assert file_contains_text(f"{result.project_path}/tox.ini", "mypy")
194+
assert not file_contains_text(f"{result.project_path}/tox.ini", "pyright")

{{cookiecutter.project_name}}/.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
run: poetry run pytest tests --cov --cov-config=pyproject.toml --cov-report=xml
4848

4949
- name: Check typing
50-
run: poetry run mypy
50+
run: poetry run {{ cookiecutter.typechecking }}
5151
{% if cookiecutter.codecov == "y" %}
5252
- name: Upload coverage reports to Codecov with GitHub Action on Python 3.11
5353
uses: codecov/codecov-action@v4

{{cookiecutter.project_name}}/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ check: ## Run code quality tools.
1111
@poetry check --lock
1212
@echo "🚀 Linting code: Running pre-commit"
1313
@poetry run pre-commit run -a
14-
@echo "🚀 Static type checking: Running mypy"
15-
@poetry run mypy
14+
@echo "🚀 Static type checking: Running {{ cookiecutter.typechecking }}"
15+
@poetry run {{ cookiecutter.typechecking }}
1616
{%- if cookiecutter.deptry == 'y' %}
1717
@echo "🚀 Checking for obsolete dependencies: Running deptry"
1818
@poetry run deptry .

{{cookiecutter.project_name}}/pyproject.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ pytest-cov = "^4.0.0"
2121
{% if cookiecutter.deptry == 'y' -%}
2222
deptry = "^0.16.2"
2323
{% endif -%}
24+
{% if cookiecutter.typechecking == 'mypy' -%}
2425
mypy = "^1.5.1"
26+
{% endif -%}
27+
{% if cookiecutter.typechecking == 'pyright' -%}
28+
pyright = "^1.1.382"
29+
{% endif -%}
2530
pre-commit = "^3.4.0"
2631
tox = "^4.11.1"
2732

@@ -36,6 +41,7 @@ mkdocstrings = {extras = ["python"], version = "^0.26.1"}
3641
requires = ["poetry-core>=1.0.0"]
3742
build-backend = "poetry.core.masonry.api"
3843

44+
{% if cookiecutter.typechecking == 'mypy' -%}
3945
[tool.mypy]
4046
files = ["{{cookiecutter.project_slug}}"]
4147
disallow_untyped_defs = "True"
@@ -45,6 +51,15 @@ check_untyped_defs = "True"
4551
warn_return_any = "True"
4652
warn_unused_ignores = "True"
4753
show_error_codes = "True"
54+
{%- endif %}
55+
56+
{% if cookiecutter.typechecking == 'pyright' -%}
57+
[tool.pyright]
58+
include = ["{{cookiecutter.project_slug}}"]
59+
typeCheckingMode = "strict"
60+
venvPath = "."
61+
venv = ".venv"
62+
{%- endif %}
4863

4964
[tool.pytest.ini_options]
5065
testpaths = ["tests"]

{{cookiecutter.project_name}}/tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ allowlist_externals = poetry
1515
commands =
1616
poetry install -v
1717
pytest --doctest-modules tests --cov --cov-config=pyproject.toml --cov-report=xml
18-
mypy
18+
{{cookiecutter.typechecking}}

0 commit comments

Comments
 (0)