Skip to content

Commit 1d5b3ef

Browse files
authored
Update mypy. (#708)
1 parent 44846cf commit 1d5b3ef

File tree

12 files changed

+44
-24
lines changed

12 files changed

+44
-24
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ releases are available on [PyPI](https://pypi.org/project/pytask) and
1111
- {pull}`704` adds the `--explain` flag to show why tasks would be executed. Closes {issue}`466`.
1212
- {pull}`706` disables syntax highlighting for platform version information in session header.
1313
- {pull}`707` drops support for Python 3.9 as it has reached end of life.
14+
- {pull}`708` updates mypy and fixes type issues.
1415

1516
## 0.5.5 - 2025-07-25
1617

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ test = [
7676
"coiled>=1.42.0",
7777
"cloudpickle>=3.0.0",
7878
]
79-
typing = ["mypy>=1.9.0,<1.11", "nbqa>=1.8.5"]
79+
typing = ["mypy>=1.11.0", "nbqa>=1.8.5"]
8080

8181
[project.urls]
8282
Changelog = "https://pytask-dev.readthedocs.io/en/stable/changes.html"

src/_pytask/capture.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
from typing import Generic
4040
from typing import NamedTuple
4141
from typing import TextIO
42+
from typing import cast
4243
from typing import final
4344

4445
import click
@@ -125,8 +126,10 @@ def name(self) -> str:
125126

126127
@property
127128
def mode(self) -> str:
128-
# TextIOWrapper doesn't expose a mode, but at least some of our tests check it.
129-
return self.buffer.mode.replace("b", "")
129+
# TextIOWrapper doesn't expose a mode, but at least some of our
130+
# tests check it.
131+
assert hasattr(self.buffer, "mode")
132+
return cast("str", self.buffer.mode.replace("b", ""))
130133

131134

132135
class CaptureIO(io.TextIOWrapper):
@@ -153,6 +156,7 @@ class DontReadFromInput(TextIO):
153156

154157
@property
155158
def encoding(self) -> str:
159+
assert sys.__stdin__ is not None
156160
return sys.__stdin__.encoding
157161

158162
def read(self, size: int = -1) -> str: # noqa: ARG002
@@ -539,7 +543,7 @@ def snap(self) -> bytes:
539543
res = self.tmpfile.buffer.read()
540544
self.tmpfile.seek(0)
541545
self.tmpfile.truncate()
542-
return res
546+
return res # type: ignore[return-value]
543547

544548
def writeorg(self, data: bytes) -> None:
545549
"""Write to original file descriptor."""

src/_pytask/collect_command.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,15 @@ def _find_common_ancestor_of_all_nodes(
124124
for task in tasks:
125125
all_paths.append(task.path)
126126
if show_nodes:
127-
all_paths.extend(
128-
x.path for x in tree_leaves(task.depends_on) if isinstance(x, PPathNode)
127+
all_paths.extend( # type: ignore[var-annotated]
128+
x.path
129+
for x in tree_leaves(task.depends_on) # type: ignore[arg-type]
130+
if isinstance(x, PPathNode)
129131
)
130-
all_paths.extend(
131-
x.path for x in tree_leaves(task.produces) if isinstance(x, PPathNode)
132+
all_paths.extend( # type: ignore[var-annotated]
133+
x.path
134+
for x in tree_leaves(task.produces) # type: ignore[arg-type]
135+
if isinstance(x, PPathNode)
132136
)
133137

134138
return find_common_ancestor(*all_paths, *paths)
@@ -196,7 +200,7 @@ def _print_collected_tasks(
196200
)
197201

198202
if show_nodes:
199-
deps = list(tree_leaves(task.depends_on))
203+
deps: list[Any] = list(tree_leaves(task.depends_on)) # type: ignore[arg-type]
200204
for node in sorted(
201205
deps,
202206
key=(
@@ -208,7 +212,7 @@ def _print_collected_tasks(
208212
text = format_node_name(node, (common_ancestor,))
209213
task_branch.add(Text.assemble(FILE_ICON, "<Dependency ", text, ">"))
210214

211-
products = list(tree_leaves(task.produces))
215+
products: list[Any] = list(tree_leaves(task.produces)) # type: ignore[arg-type]
212216
for node in sorted(
213217
products,
214218
key=lambda x: x.path.as_posix()

src/_pytask/dag.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ def _add_product(
8888
for task in tasks:
8989
dag.add_node(task.signature, task=task)
9090

91-
tree_map(lambda x: _add_dependency(dag, task, x), task.depends_on)
92-
tree_map(lambda x: _add_product(dag, task, x), task.produces)
91+
tree_map(lambda x: _add_dependency(dag, task, x), task.depends_on) # type: ignore[arg-type]
92+
tree_map(lambda x: _add_product(dag, task, x), task.produces) # type: ignore[arg-type]
9393

9494
# If a node is a PythonNode wrapped in another PythonNode, it is a product from
9595
# another task that is a dependency in the current task. Thus, draw an edge
@@ -98,7 +98,7 @@ def _add_product(
9898
lambda x: dag.add_edge(x.value.signature, x.signature)
9999
if isinstance(x, PythonNode) and isinstance(x.value, PythonNode)
100100
else None,
101-
task.depends_on,
101+
task.depends_on, # type: ignore[arg-type]
102102
)
103103
return dag
104104

src/_pytask/dag_command.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def _shorten_node_labels(dag: nx.DiGraph, paths: list[Path]) -> nx.DiGraph:
215215
"""Shorten the node labels in the graph for a better experience."""
216216
node_names = dag.nodes
217217
short_names = reduce_names_of_multiple_nodes(node_names, dag, paths)
218-
short_names = [i.plain if isinstance(i, Text) else i for i in short_names] # type: ignore[attr-defined]
218+
short_names = [i.plain if isinstance(i, Text) else i for i in short_names]
219219
old_to_new = dict(zip(node_names, short_names, strict=False))
220220
return nx.relabel_nodes(dag, old_to_new)
221221

src/_pytask/debugging.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
import click
1313

14+
from _pytask.capture import CaptureManager
1415
from _pytask.console import console
16+
from _pytask.live import LiveManager
1517
from _pytask.node_protocols import PTask
1618
from _pytask.outcomes import Exit
1719
from _pytask.pluginmanager import hookimpl
@@ -24,8 +26,6 @@
2426

2527
from pluggy import PluginManager
2628

27-
from _pytask.capture import CaptureManager
28-
from _pytask.live import LiveManager
2929
from _pytask.session import Session
3030

3131

@@ -289,6 +289,7 @@ def _init_pdb(
289289
if header is not None:
290290
console.rule(header, characters=">", style="default")
291291
else:
292+
assert isinstance(capman, CaptureManager)
292293
capturing = cls._is_capturing(capman)
293294
if capturing:
294295
console.rule(
@@ -299,6 +300,8 @@ def _init_pdb(
299300
else:
300301
console.rule(f"PDB {method}", characters=">", style="default")
301302

303+
assert isinstance(capman, CaptureManager)
304+
assert isinstance(live_manager, LiveManager)
302305
return cls._import_pdb_cls(capman, live_manager)(**kwargs)
303306

304307
@classmethod
@@ -392,7 +395,7 @@ def wrap_function_for_tracing(session: Session, task: PTask) -> None:
392395
# 3.7.4) runcall's first param is `func`, which means we'd get an exception if one
393396
# of the kwargs to task_function was called `func`.
394397
@functools.wraps(task_function)
395-
def wrapper(*args: Any, **kwargs: Any) -> None:
398+
def wrapper(*args: Any, **kwargs: Any) -> Any:
396399
capman = session.config["pm"].get_plugin("capturemanager")
397400
live_manager = session.config["pm"].get_plugin("live_manager")
398401

src/_pytask/execute.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,11 @@ def pytask_execute_task_teardown(session: Session, task: PTask) -> None:
301301
return
302302

303303
collect_provisional_products(session, task)
304-
missing_nodes = [node for node in tree_leaves(task.produces) if not node.state()]
304+
missing_nodes: list[Any] = [ # type: ignore[var-annotated]
305+
node
306+
for node in tree_leaves(task.produces) # type: ignore[arg-type]
307+
if not node.state()
308+
]
305309
if missing_nodes:
306310
paths = session.config["paths"]
307311
files = [format_node_name(i, paths).plain for i in missing_nodes]

src/_pytask/git.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ def is_git_installed() -> bool:
1616
def cmd_output(*cmd: str, **kwargs: Any) -> tuple[int, str, str]:
1717
"""Execute a command and capture the output."""
1818
r = subprocess.run(cmd, capture_output=True, check=False, **kwargs)
19-
stdout = r.stdout.decode() if r.stdout is not None else None
20-
stderr = r.stderr.decode() if r.stderr is not None else None
19+
stdout = r.stdout.decode() if r.stdout is not None else ""
20+
stderr = r.stderr.decode() if r.stderr is not None else ""
21+
assert isinstance(stdout, str)
22+
assert isinstance(stderr, str)
2123
return r.returncode, stdout, stderr
2224

2325

src/_pytask/provisional.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ def pytask_execute_task_setup(session: Session, task: PTask) -> None:
4040
4141
"""
4242
task.depends_on = tree_map_with_path( # type: ignore[assignment]
43-
lambda p, x: collect_provisional_nodes(session, task, x, p), task.depends_on
43+
lambda p, x: collect_provisional_nodes(session, task, x, p),
44+
task.depends_on, # type: ignore[arg-type]
4445
)
4546
if task.signature in TASKS_WITH_PROVISIONAL_NODES:
4647
recreate_dag(session, task)

0 commit comments

Comments
 (0)