Skip to content

Commit 7b755f7

Browse files
Add mypy, ruff, and refurb. (#16)
Co-authored-by: Tobias Raabe <[email protected]>
1 parent b8129b8 commit 7b755f7

20 files changed

+183
-102
lines changed

.pre-commit-config.yaml

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.3.0
3+
rev: v4.4.0
44
hooks:
55
- id: check-added-large-files
66
args: ['--maxkb=100']
@@ -24,50 +24,33 @@ repos:
2424
- id: python-no-log-warn
2525
- id: python-use-type-annotations
2626
- id: text-unicode-replacement-char
27-
- repo: https://github.com/asottile/pyupgrade
28-
rev: v3.1.0
29-
hooks:
30-
- id: pyupgrade
31-
args: [--py37-plus]
3227
- repo: https://github.com/asottile/reorder_python_imports
33-
rev: v3.8.5
28+
rev: v3.9.0
3429
hooks:
3530
- id: reorder-python-imports
3631
args: [--py37-plus, --add-import, 'from __future__ import annotations']
3732
- repo: https://github.com/asottile/setup-cfg-fmt
38-
rev: v2.1.0
33+
rev: v2.2.0
3934
hooks:
4035
- id: setup-cfg-fmt
4136
- repo: https://github.com/PyCQA/docformatter
42-
rev: v1.5.0
37+
rev: v1.5.1
4338
hooks:
4439
- id: docformatter
4540
args: [--in-place, --wrap-summaries, "88", --wrap-descriptions, "88", --blank]
4641
- repo: https://github.com/psf/black
47-
rev: 22.10.0
42+
rev: 22.12.0
4843
hooks:
4944
- id: black
50-
- repo: https://github.com/PyCQA/flake8
51-
rev: 5.0.4
45+
- repo: https://github.com/charliermarsh/ruff-pre-commit
46+
rev: v0.0.215
5247
hooks:
53-
- id: flake8
54-
types: [python]
55-
additional_dependencies: [
56-
flake8-alfred,
57-
flake8-bugbear,
58-
flake8-builtins,
59-
flake8-comprehensions,
60-
flake8-docstrings,
61-
flake8-eradicate,
62-
flake8-print,
63-
flake8-pytest-style,
64-
flake8-todo,
65-
flake8-typing-imports,
66-
flake8-unused-arguments,
67-
pep8-naming,
68-
pydocstyle,
69-
Pygments,
70-
]
48+
- id: ruff
49+
- repo: https://github.com/dosisod/refurb
50+
rev: v1.9.1
51+
hooks:
52+
- id: refurb
53+
args: [--ignore, FURB126]
7154
- repo: https://github.com/executablebooks/mdformat
7255
rev: 0.7.16
7356
hooks:
@@ -82,12 +65,27 @@ repos:
8265
hooks:
8366
- id: interrogate
8467
args: [-v, --fail-under=40, src]
68+
- repo: https://github.com/pre-commit/mirrors-mypy
69+
rev: 'v0.991'
70+
hooks:
71+
- id: mypy
72+
args: [
73+
--no-strict-optional,
74+
--ignore-missing-imports,
75+
]
76+
additional_dependencies: [
77+
attrs>=21.3.0,
78+
click,
79+
types-PyYAML,
80+
types-setuptools
81+
]
82+
pass_filenames: false
8583
- repo: https://github.com/codespell-project/codespell
8684
rev: v2.2.2
8785
hooks:
8886
- id: codespell
8987
- repo: https://github.com/mgedmin/check-manifest
90-
rev: "0.48"
88+
rev: "0.49"
9189
hooks:
9290
- id: check-manifest
9391
args: [--no-build-isolation]

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ releases are available on [PyPI](https://pypi.org/project/pytask-julia) and
77

88
## 0.3.0 - 2023-xx-xx
99

10+
- {pull}`16` adds mypy, refurb, and ruff.
1011
- {pull}`18` deprecates INI configurations and aligns the package with pytask v0.3.
1112

1213
## 0.2.1 - 2022-04-16

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ exclude *.yml
1010
include README.md
1111
include LICENSE
1212
include pyproject.toml
13+
14+
recursive-include src py.typed

pyproject.toml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,58 @@ build-backend = "setuptools.build_meta"
55

66
[tool.setuptools_scm]
77
write_to = "src/pytask_julia/_version.py"
8+
9+
10+
[tool.mypy]
11+
files = ["src", "tests"]
12+
check_untyped_defs = true
13+
disallow_any_generics = true
14+
disallow_incomplete_defs = true
15+
disallow_untyped_defs = true
16+
no_implicit_optional = true
17+
warn_redundant_casts = true
18+
warn_unused_ignores = true
19+
20+
21+
[[tool.mypy.overrides]]
22+
module = "tests.*"
23+
disallow_untyped_defs = false
24+
ignore_errors = true
25+
26+
27+
[tool.ruff]
28+
target-version = "py37"
29+
select = ["ALL"]
30+
fix = true
31+
extend-ignore = [
32+
# Numpy docstyle
33+
"D107",
34+
"D203",
35+
"D212",
36+
"D213",
37+
"D402",
38+
"D413",
39+
"D415",
40+
"D416",
41+
"D417",
42+
# Others.
43+
"D404", # Do not start module docstring with "This".
44+
"RET504", # unnecessary variable assignment before return.
45+
"S101", # raise errors for asserts.
46+
"B905", # strict parameter for zip that was implemented in py310.
47+
"I", # ignore isort
48+
"ANN101", # type annotating self
49+
"ANN102", # type annotating cls
50+
"FBT", # flake8-boolean-trap
51+
"EM", # flake8-errmsg
52+
"ANN401", # flake8-annotate typing.Any
53+
"PD", # pandas-vet
54+
]
55+
56+
57+
[tool.ruff.per-file-ignores]
58+
"tests/*" = ["D", "ANN"]
59+
60+
61+
[tool.ruff.pydocstyle]
62+
convention = "numpy"

src/pytask_julia/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
"""This module contains the main namespace."""
12
from __future__ import annotations
23

34
try:

src/pytask_julia/collect.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import subprocess
66
import types
77
from pathlib import Path
8+
from typing import Any
9+
from typing import Callable
810

911
from pytask import depends_on
1012
from pytask import has_mark
@@ -13,6 +15,7 @@
1315
from pytask import parse_nodes
1416
from pytask import produces
1517
from pytask import remove_marks
18+
from pytask import Session
1619
from pytask import Task
1720
from pytask_julia.serialization import SERIALIZERS
1821
from pytask_julia.shared import julia
@@ -33,12 +36,15 @@ def run_jl_script(
3336

3437

3538
@hookimpl
36-
def pytask_collect_task(session, path, name, obj):
39+
def pytask_collect_task(
40+
session: Session, path: Path, name: str, obj: Any
41+
) -> Task | None:
3742
"""Collect a task which is a function.
3843
3944
There is some discussion on how to detect functions in this `thread
40-
<https://stackoverflow.com/q/624926/7523785>`_. :class:`types.FunctionType` does not
41-
detect built-ins which is not possible anyway.
45+
46+
<https://stackoverflow.com/q/624926/7523785>`_. :class:`types.FunctionType`
47+
does notdetect built-ins which is not possible anyway.
4248
4349
"""
4450
__tracebackhide__ = True
@@ -76,7 +82,7 @@ def pytask_collect_task(session, path, name, obj):
7682
task = Task(
7783
base_name=name,
7884
path=path,
79-
function=_copy_func(run_jl_script),
85+
function=_copy_func(run_jl_script), # type: ignore[arg-type]
8086
depends_on=dependencies,
8187
produces=products,
8288
markers=markers,
@@ -104,30 +110,34 @@ def pytask_collect_task(session, path, name, obj):
104110
)
105111

106112
return task
113+
return None
107114

108115

109116
def _parse_julia_mark(
110-
mark, default_options, default_serializer, default_suffix, default_project
111-
):
117+
mark: Mark,
118+
default_options: list[str] | None,
119+
default_serializer: Callable[..., str] | str | None,
120+
default_suffix: str | None,
121+
default_project: str | None,
122+
) -> Mark:
112123
"""Parse a Julia mark."""
113124
script, options, serializer, suffix, project = julia(**mark.kwargs)
114125

115126
parsed_kwargs = {}
116-
for arg_name, value, default in [
127+
for arg_name, value, default in (
117128
("script", script, None),
118129
("options", options, default_options),
119130
("serializer", serializer, default_serializer),
120-
]:
121-
parsed_kwargs[arg_name] = value if value else default
131+
):
132+
parsed_kwargs[arg_name] = value or default
122133

123-
if (
124-
isinstance(parsed_kwargs["serializer"], str)
134+
proposed_suffix = (
135+
SERIALIZERS[parsed_kwargs["serializer"]]["suffix"]
136+
if isinstance(parsed_kwargs["serializer"], str)
125137
and parsed_kwargs["serializer"] in SERIALIZERS
126-
):
127-
proposed_suffix = SERIALIZERS[parsed_kwargs["serializer"]]["suffix"]
128-
else:
129-
proposed_suffix = default_suffix
130-
parsed_kwargs["suffix"] = suffix if suffix else proposed_suffix
138+
else default_suffix
139+
)
140+
parsed_kwargs["suffix"] = suffix or proposed_suffix # type: ignore[assignment]
131141

132142
if isinstance(project, (str, Path)):
133143
parsed_kwargs["project"] = project

src/pytask_julia/config.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
@hookimpl
12-
def pytask_parse_config(config):
12+
def pytask_parse_config(config: dict[str, Any]) -> None:
1313
"""Register the julia marker."""
1414
config["markers"]["julia"] = "Tasks which are executed with Julia."
1515
config["julia_serializer"] = config.get("julia_serializer", "json")
@@ -35,5 +35,4 @@ def _parse_value_or_whitespace_option(value: Any) -> None | list[str]:
3535
return None
3636
if isinstance(value, list):
3737
return list(map(str, value))
38-
else:
39-
raise ValueError(f"'julia_options' is {value} and not a list.")
38+
raise ValueError(f"'julia_options' is {value} and not a list.")

src/pytask_julia/execute.py

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

1616

1717
@hookimpl
18-
def pytask_execute_task_setup(task):
18+
def pytask_execute_task_setup(task: Task) -> None:
1919
"""Check whether environment allows executing Julia files."""
2020
marks = get_marks(task, "julia")
2121
if marks:

src/pytask_julia/parametrize.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
"""Parametrize tasks."""
22
from __future__ import annotations
33

4+
from typing import Any
5+
46
import pytask
57
from pytask import hookimpl
68

79

810
@hookimpl
9-
def pytask_parametrize_kwarg_to_marker(obj, kwargs):
11+
def pytask_parametrize_kwarg_to_marker(obj: Any, kwargs: dict[str, Any]) -> None:
1012
"""Attach parametrized Julia arguments to the function with a marker."""
11-
if callable(obj):
12-
if "julia" in kwargs:
13-
pytask.mark.julia(**kwargs.pop("julia"))(obj)
13+
if callable(obj) and "julia" in kwargs:
14+
pytask.mark.julia(**kwargs.pop("julia"))(obj)

src/pytask_julia/plugin.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Register hook specifications and implementations."""
22
from __future__ import annotations
33

4+
from pluggy import PluginManager
45
from pytask import hookimpl
56
from pytask_julia import collect
67
from pytask_julia import config
@@ -9,7 +10,7 @@
910

1011

1112
@hookimpl
12-
def pytask_add_hooks(pm):
13+
def pytask_add_hooks(pm: PluginManager) -> None:
1314
"""Register hook implementations."""
1415
pm.register(collect)
1516
pm.register(config)

src/pytask_julia/py.typed

Whitespace-only changes.

src/pytask_julia/serialization.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,17 @@ def create_file_name(task: Task, suffix: str) -> str:
5151

5252

5353
def serialize_keyword_arguments(
54-
serializer: str | Callable[dict[str, Any], str],
54+
serializer: str | Callable[..., str],
5555
path_to_serialized: Path,
5656
kwargs: dict[str, Any],
5757
) -> None:
58+
"""Serialize keyword arguments."""
5859
if callable(serializer):
5960
serializer_func = serializer
6061
elif isinstance(serializer, str) and serializer in SERIALIZERS:
61-
serializer_func = SERIALIZERS[serializer]["serializer"]
62+
serializer_func = SERIALIZERS[serializer][
63+
"serializer"
64+
] # type: ignore[assignment]
6265
else: # pragma: no cover
6366
raise ValueError(f"Serializer {serializer!r} is not known.")
6467

src/pytask_julia/shared.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
"""This module contains shared functions."""
12
from __future__ import annotations
23

34
from pathlib import Path
5+
from typing import Any
46
from typing import Callable
57
from typing import Iterable
68
from typing import Sequence
@@ -9,7 +11,7 @@
911
def julia(
1012
script: str | Path,
1113
options: str | Iterable[str] | None = None,
12-
serializer: str | Callable[..., str] | str | None = None,
14+
serializer: Callable[..., str] | str | None = None,
1315
suffix: str | None = None,
1416
project: str | Path = None,
1517
) -> tuple[
@@ -43,7 +45,7 @@ def julia(
4345
return script, options, serializer, suffix, project
4446

4547

46-
def _to_list(scalar_or_iter):
48+
def _to_list(scalar_or_iter: Any) -> list[Any]:
4749
"""Convert scalars and iterables to list.
4850
4951
Parameters

0 commit comments

Comments
 (0)