Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Mypy for static type checking #2808

Merged
merged 28 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c1bd0be
Add mypy as a dependency
seisman Nov 13, 2023
594e07e
Add a make target for static type check
seisman Nov 13, 2023
16da12b
Run the static type check in the Style Checks workflow
seisman Nov 13, 2023
fec7e8b
Ignore all tests
seisman Nov 13, 2023
ebe7d50
Add pandas-stub
seisman Nov 13, 2023
85e7128
Install more packages
seisman Nov 14, 2023
2310e7e
GMTRemoteDataset's units can be None
seisman Nov 14, 2023
9dc8c98
Remove modules that don't support type hints
seisman Nov 14, 2023
dda26d4
Set ignore_missing_imports to true
seisman Nov 14, 2023
97d3dbc
Ignore the 'Unsupported class scoped import [misc]' error
seisman Nov 15, 2023
8b2a5b9
Add a new workflow for static type checking
seisman Nov 16, 2023
aed77ad
Merge branch 'main' into typehints/mypy
seisman Nov 16, 2023
9fd5a04
Add comments to typecheck workflow
seisman Nov 16, 2023
fa44524
Merge branch 'main' into typehints/mypy
seisman Nov 18, 2023
e62dcb6
Ignore .mypy_cache and run 'make clean' to delete it
seisman Nov 18, 2023
ec25885
Merge branch 'main' into typehints/mypy
seisman Nov 20, 2023
73c9863
Merge branch 'main' into typehints/mypy
seisman Nov 21, 2023
4d31ce3
Merge branch 'main' into typehints/mypy
seisman Nov 25, 2023
a7545ad
Apply suggestions from code review
seisman Nov 27, 2023
49e67d5
Rename typecheck.yml -> type_checks.ym
seisman Nov 27, 2023
253a491
Merge branch 'main' into typehints/mypy
seisman Nov 27, 2023
567bfb8
Fix some typos
seisman Nov 27, 2023
5e401c2
Merge branch 'main' into typehints/mypy
seisman Nov 28, 2023
cd9d3ed
Merge branch 'main' into typehints/mypy
seisman Nov 29, 2023
9bfe49a
Merge branch 'main' into typehints/mypy
seisman Dec 1, 2023
f230b0d
Ignore a specific error code
seisman Dec 1, 2023
0e657bd
Merge branch 'main' into typehints/mypy
seisman Dec 4, 2023
30b45c1
Merge branch 'main' into typehints/mypy
seisman Dec 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/type_checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Static type checks
#
# This workflow runs static type checks using mypy.
#
# It is run on every commit to the main and pull request branches. It is also
# scheduled to run daily on the main branch.
#
name: Static Type Checks

on:
push:
branches: [ main ]
pull_request:
# Schedule daily tests
schedule:
- cron: '0 0 * * *'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

jobs:
static_check:
name: Static Type Check
runs-on: ubuntu-latest

steps:
# Checkout current git repository
- name: Checkout
uses: actions/[email protected]

# Setup Python
- name: Set up Python
uses: actions/[email protected]
with:
python-version: '3.12'

- name: Install packages
run: |
# Need to install four groups of packages:
# 1. required packages
# 2. optional packages
# 3. type checker and stub packages
# 4. other packages that are used somewhere in PyGMT
python -m pip install \
numpy pandas xarray netcdf4 packaging \
contextily geopandas ipython rioxarray \
mypy pandas-stubs \
matplotlib pytest
python -m pip list

- name: Static type check
run: make typecheck
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ MANIFEST
.coverage
coverage.xml
htmlcov/
.mypy_cache/
.pytest_cache/
.ruff_cache/
results/
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ help:
@echo " format run blackdoc, docformatter and ruff to automatically format the code"
@echo " check run code style and quality checks (blackdoc, docformatter, ruff)"
@echo " codespell run codespell to check common misspellings"
@echo " typecheck run mypy for static type check"
@echo " clean clean up build and generated files"
@echo " distclean clean up build and generated files, including project metadata files"
@echo ""
Expand Down Expand Up @@ -73,12 +74,15 @@ check:
codespell:
@codespell

typecheck:
mypy ${PROJECT}

clean:
find . -name "*.pyc" -exec rm -v {} +
find . -name "*~" -exec rm -v {} +
find . -type d -name "__pycache__" -exec rm -rv {} +
rm -rvf build dist .eggs MANIFEST .coverage htmlcov coverage.xml
rm -rvf .cache .pytest_cache .ruff_cache
rm -rvf .cache .mypy_cache .pytest_cache .ruff_cache
rm -rvf $(TESTDIR)
rm -rvf baseline
rm -rvf result_images
Expand Down
3 changes: 3 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ dependencies:
- sphinx-design
- sphinx-gallery
- sphinx_rtd_theme
# Dev dependencies (type hints)
- mypy
- pandas-stubs
Comment on lines +44 to +46
Copy link
Member

Choose a reason for hiding this comment

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

Maybe move this under the # Dev dependencies (style checks) section?

Copy link
Member Author

Choose a reason for hiding this comment

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

I prefer to keep them in a separate section.

4 changes: 2 additions & 2 deletions pygmt/datasets/load_remote_dataset.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Internal function to load GMT remote datasets.
"""
from typing import NamedTuple
from typing import NamedTuple, Union

from pygmt.exceptions import GMTInvalidInput
from pygmt.helpers import kwargs_to_strings
Expand Down Expand Up @@ -58,7 +58,7 @@ class GMTRemoteDataset(NamedTuple):
title: str
name: str
long_name: str
units: str
units: Union[str, None]
Copy link
Member Author

Choose a reason for hiding this comment

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

Fix the following error:

pygmt/datasets/load_remote_dataset.py:150: error: Argument "units" to "GMTRemoteDataset" has incompatible type "None"; expected "str"  [arg-type]

resolutions: dict[str, Resolution]
extra_attributes: dict

Expand Down
2 changes: 1 addition & 1 deletion pygmt/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

_HAS_IPYTHON = True
except ImportError:
_HAS_IPYTHON = False

Check warning on line 14 in pygmt/figure.py

View check run for this annotation

Codecov / codecov/patch

pygmt/figure.py#L14

Added line #L14 was not covered by tests


from pygmt.clib import Session
Expand Down Expand Up @@ -451,7 +451,7 @@
)

if method == "notebook":
if not _HAS_IPYTHON:

Check warning on line 454 in pygmt/figure.py

View check run for this annotation

Codecov / codecov/patch

pygmt/figure.py#L454

Added line #L454 was not covered by tests
raise GMTError(
"Notebook display is selected, but IPython is not available. "
"Make sure you have IPython installed, "
Expand Down Expand Up @@ -517,7 +517,7 @@
html = '<img src="data:image/png;base64,{image}" width="{width}px">'
return html.format(image=base64_png.decode("utf-8"), width=500)

from pygmt.src import (
from pygmt.src import ( # type: ignore [misc]
basemap,
coast,
colorbar,
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ make-summary-multi-line = true
wrap-summaries = 79
wrap-descriptions = 79

[tool.mypy]
exclude = ["pygmt/tests/"]
ignore_missing_imports = true
Copy link
Member Author

Choose a reason for hiding this comment

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

Some packages like geopandas don't provide type hints and mypy reports following errors:

Cannot find implementation or library stub for module named "geopandas"  [import-not-found]

Ignore these errors following https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports.


[tool.ruff]
line-length = 88 # E501 (line-too-long)
show-source = true
Expand Down
Loading