Skip to content

Commit

Permalink
Add pyright support (#125)
Browse files Browse the repository at this point in the history
* attempt setting up pyright

* fix cookiecutter

* add tests for typechecking config

* add some comments

* fix formatting
  • Loading branch information
szvsw authored Oct 2, 2024
1 parent 5354d43 commit 4355a33
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This is a modern Cookiecutter template that can be used to initiate a Python pro
- [Poetry](https://python-poetry.org/) for dependency management
- CI/CD with [GitHub Actions](https://github.com/features/actions)
- Pre-commit hooks with [pre-commit](https://pre-commit.com/)
- 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/)
- 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/)
- Publishing to [PyPI](https://pypi.org) or [Artifactory](https://jfrog.com/artifactory) by creating a new release on GitHub
- Testing and coverage with [pytest](https://docs.pytest.org/en/7.1.x/) and [codecov](https://about.codecov.io/)
- Documentation with [MkDocs](https://www.mkdocs.org/)
Expand Down
1 change: 1 addition & 0 deletions cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"project_description": "This is a template repository for Python projects that use Poetry for their dependency management.",
"include_github_actions": ["y", "n"],
"publish_to": ["pypi", "artifactory", "none"],
"typechecking": ["mypy", "pyright"],
"deptry": ["y", "n"],
"mkdocs": ["y", "n"],
"codecov": ["y", "n"],
Expand Down
22 changes: 19 additions & 3 deletions docs/features/linting.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,13 @@ ignore = [
"tests/*" = ["S101"]
```

# mypy
# Typechecking

[mypy](https://mypy.readthedocs.io/en/stable/) is used for static type checking, and it's configuration and can be edited in `pyproject.toml`.
Two typechecking options are available, `mypy` or `pyright`.

## mypy

[mypy](https://mypy.readthedocs.io/en/stable/) can be used for static type checking, and its configuration and can be edited in `pyproject.toml`.

```toml
[tool.mypy]
Expand All @@ -84,9 +88,21 @@ exclude = [
]
```

## pyright

[pyright](https://github.com/microsoft/pyright) can be used for static type checking, and its configuration and can be edited in `pyproject.toml`:

```toml
[tool.pyright]
include = ['{{cookiecutter.project_slug}}']
typeCheckingMode = "strict"
venvPath = "."
venv = ".venv"
```

# deptry

[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`.
[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`.

```toml
[tool.mypy]
Expand Down
2 changes: 1 addition & 1 deletion docs/features/makefile.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ available:

```
install Install the poetry environment and install the pre-commit hooks
check Lint and check code by running ruff, mypy and deptry.
check Lint and check code by running ruff, mypy/pyright and deptry.
test Test the code with pytest
build Build wheel file using poetry
clean-build clean build artifacts
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ This is a modern Cookiecutter template that can be used to initiate a Python pro
- [Poetry](https://python-poetry.org/) for dependency management
- CI/CD with [GitHub Actions](https://github.com/features/actions)
- Pre-commit hooks with [pre-commit](https://pre-commit.com/)
- 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/)
- 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/)
- Publishing to [PyPI](https://pypi.org) or [Artifactory](https://jfrog.com/artifactory) by creating a new release on GitHub
- Testing and coverage with [pytest](https://docs.pytest.org/en/7.1.x/) and [codecov](https://about.codecov.io/)
- Documentation with [MkDocs](https://www.mkdocs.org/)
Expand Down
45 changes: 42 additions & 3 deletions tests/test_cookiecutter.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ def test_dont_publish(cookies, tmp_path):
assert result.exit_code == 0
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
assert not file_contains_text(
f"{result.project_path}/.github/workflows/on-release-main.yml", "make build-and-publish"
f"{result.project_path}/.github/workflows/on-release-main.yml",
"make build-and-publish",
)


Expand All @@ -86,7 +87,10 @@ def test_mkdocs(cookies, tmp_path):
assert result.exit_code == 0
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "main.yml")
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
assert file_contains_text(f"{result.project_path}/.github/workflows/on-release-main.yml", "mkdocs gh-deploy")
assert file_contains_text(
f"{result.project_path}/.github/workflows/on-release-main.yml",
"mkdocs gh-deploy",
)
assert file_contains_text(f"{result.project_path}/Makefile", "docs:")
assert os.path.isdir(f"{result.project_path}/docs")

Expand All @@ -98,7 +102,8 @@ def test_not_mkdocs(cookies, tmp_path):
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "main.yml")
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
assert not file_contains_text(
f"{result.project_path}/.github/workflows/on-release-main.yml", "mkdocs gh-deploy"
f"{result.project_path}/.github/workflows/on-release-main.yml",
"mkdocs gh-deploy",
)
assert not file_contains_text(f"{result.project_path}/Makefile", "docs:")
assert not os.path.isdir(f"{result.project_path}/docs")
Expand Down Expand Up @@ -153,3 +158,37 @@ def test_remove_release_workflow(cookies, tmp_path):
result = cookies.bake(extra_context={"publish_to": "none", "mkdocs": "n"})
assert result.exit_code == 0
assert not os.path.isfile(f"{result.project_path}/.github/workflows/on-release-main.yml")


def test_pyright(cookies, tmp_path):
with run_within_dir(tmp_path):
result = cookies.bake(extra_context={"typechecking": "pyright"})
assert result.exit_code == 0
# check the toml file
assert file_contains_text(f"{result.project_path}/pyproject.toml", "[tool.pyright]")
assert file_contains_text(f"{result.project_path}/pyproject.toml", "pyright =")
assert not file_contains_text(f"{result.project_path}/pyproject.toml", "[tool.mypy]")
assert not file_contains_text(f"{result.project_path}/pyproject.toml", "mypy =")
# check the make file
assert file_contains_text(f"{result.project_path}/Makefile", "pyright")
assert not file_contains_text(f"{result.project_path}/Makefile", "mypy")
# check the tox file
assert file_contains_text(f"{result.project_path}/tox.ini", "pyright")
assert not file_contains_text(f"{result.project_path}/tox.ini", "mypy")


def test_mypy(cookies, tmp_path):
with run_within_dir(tmp_path):
result = cookies.bake(extra_context={"typechecking": "mypy"})
assert result.exit_code == 0
# check the toml file
assert file_contains_text(f"{result.project_path}/pyproject.toml", "[tool.mypy]")
assert file_contains_text(f"{result.project_path}/pyproject.toml", "mypy =")
assert not file_contains_text(f"{result.project_path}/pyproject.toml", "[tool.pyright]")
assert not file_contains_text(f"{result.project_path}/pyproject.toml", "pyright =")
# check the make file
assert file_contains_text(f"{result.project_path}/Makefile", "mypy")
assert not file_contains_text(f"{result.project_path}/Makefile", "pyright")
# check the tox file
assert file_contains_text(f"{result.project_path}/tox.ini", "mypy")
assert not file_contains_text(f"{result.project_path}/tox.ini", "pyright")
2 changes: 1 addition & 1 deletion {{cookiecutter.project_name}}/.github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
run: poetry run pytest tests --cov --cov-config=pyproject.toml --cov-report=xml

- name: Check typing
run: poetry run mypy
run: poetry run {{ cookiecutter.typechecking }}
{% if cookiecutter.codecov == "y" %}
- name: Upload coverage reports to Codecov with GitHub Action on Python 3.11
uses: codecov/codecov-action@v4
Expand Down
4 changes: 2 additions & 2 deletions {{cookiecutter.project_name}}/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ check: ## Run code quality tools.
@poetry check --lock
@echo "🚀 Linting code: Running pre-commit"
@poetry run pre-commit run -a
@echo "🚀 Static type checking: Running mypy"
@poetry run mypy
@echo "🚀 Static type checking: Running {{ cookiecutter.typechecking }}"
@poetry run {{ cookiecutter.typechecking }}
{%- if cookiecutter.deptry == 'y' %}
@echo "🚀 Checking for obsolete dependencies: Running deptry"
@poetry run deptry .
Expand Down
15 changes: 15 additions & 0 deletions {{cookiecutter.project_name}}/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ pytest-cov = "^4.0.0"
{% if cookiecutter.deptry == 'y' -%}
deptry = "^0.16.2"
{% endif -%}
{% if cookiecutter.typechecking == 'mypy' -%}
mypy = "^1.5.1"
{% endif -%}
{% if cookiecutter.typechecking == 'pyright' -%}
pyright = "^1.1.382"
{% endif -%}
pre-commit = "^3.4.0"
tox = "^4.11.1"

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

{% if cookiecutter.typechecking == 'mypy' -%}
[tool.mypy]
files = ["{{cookiecutter.project_slug}}"]
disallow_untyped_defs = "True"
Expand All @@ -45,6 +51,15 @@ check_untyped_defs = "True"
warn_return_any = "True"
warn_unused_ignores = "True"
show_error_codes = "True"
{%- endif %}

{% if cookiecutter.typechecking == 'pyright' -%}
[tool.pyright]
include = ["{{cookiecutter.project_slug}}"]
typeCheckingMode = "strict"
venvPath = "."
venv = ".venv"
{%- endif %}

[tool.pytest.ini_options]
testpaths = ["tests"]
Expand Down
2 changes: 1 addition & 1 deletion {{cookiecutter.project_name}}/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ allowlist_externals = poetry
commands =
poetry install -v
pytest --doctest-modules tests --cov --cov-config=pyproject.toml --cov-report=xml
mypy
{{cookiecutter.typechecking}}

1 comment on commit 4355a33

@major
Copy link

@major major commented on 4355a33 Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! 👏

Please sign in to comment.