Skip to content

Commit 6f92606

Browse files
authored
Typing Utilities (#265)
* remove ignores * no drmaa stubs * fix typing * lint * Update CHANGELOG.rst
1 parent 930ac2e commit 6f92606

File tree

4 files changed

+33
-19
lines changed

4 files changed

+33
-19
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
**2.1.13 - 06/11/25**
2+
3+
- Type-hinting: Fix mypy errors in utilities.py
4+
15
**2.1.12 - 06/11/25**
26

37
- Move deprecated rtd for redis

pyproject.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ exclude = [
4747
"src/vivarium_cluster_tools/psimulate/runner.py",
4848
"src/vivarium_cluster_tools/vipin/cli.py",
4949
"src/vivarium_cluster_tools/vipin/perf_counters.py",
50-
"src/vivarium_cluster_tools/utilities.py",
5150
"tests/psimulate/cluster/test_interface.py",
5251
"tests/psimulate/redis_dbs/test_registry.py",
5352
"tests/psimulate/results/test_processing.py",
@@ -56,12 +55,11 @@ exclude = [
5655
"tests/psimulate/test_appending_perf_logs.py",
5756
"tests/psimulate/test_branches.py",
5857
"tests/psimulate/test_runner.py",
59-
"tests/psimulate/test_utilities.py",
6058
]
6159

6260
disable_error_code = []
6361

6462
# handle mypy errors when 3rd party packages are not typed.
6563
[[tool.mypy.overrides]]
66-
module = []
64+
module = ["drmaa"]
6765
ignore_missing_imports = true

src/vivarium_cluster_tools/utilities.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# mypy: ignore-errors
21
"""
32
================================
43
vivarium_cluster_tools Utilities
@@ -15,12 +14,15 @@
1514
import warnings
1615
from collections.abc import Callable
1716
from pathlib import Path
18-
from typing import Any
17+
from typing import Any, ParamSpec, TypeVar
1918

2019
from vivarium_cluster_tools.psimulate.environment import ENV_VARIABLES
2120

2221
NUM_ROWS_PER_CENTRAL_LOG_FILE = 100_000
2322

23+
P = ParamSpec("P")
24+
T = TypeVar("T")
25+
2426

2527
def get_cluster_name() -> str:
2628
"""Returns the hostname"""
@@ -67,7 +69,7 @@ def backoff_and_retry(
6769
backoff_seconds: int | float = 30,
6870
num_retries: int = 3,
6971
log_function: Callable[[str], None] = warnings.warn,
70-
) -> Callable:
72+
) -> Callable[[Callable[P, T]], Callable[P, T]]:
7173
"""Adds a retry handler to the decorated function.
7274
7375
Parameters
@@ -85,9 +87,9 @@ def backoff_and_retry(
8587
A function that retries the decorated function a specified number of times.
8688
"""
8789

88-
def _wrap(func):
90+
def _wrap(func: Callable[P, T]) -> Callable[P, T]:
8991
@functools.wraps(func)
90-
def _wrapped(*args, **kwargs):
92+
def _wrapped(*args: P.args, **kwargs: P.kwargs) -> T:
9193
retries = num_retries
9294
while retries:
9395
try:

tests/psimulate/test_utilities.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,22 @@
33
import time
44
from pathlib import Path
55
from subprocess import PIPE, Popen
6+
from typing import Any, TypedDict
67

78
import pytest
9+
from pytest import FixtureRequest
810

911
from vivarium_cluster_tools.utilities import backoff_and_retry, mkdir
1012

1113

14+
class MkdirParams(TypedDict, total=False):
15+
"""Parameters for the mkdir function."""
16+
17+
parents: bool
18+
exists_ok: bool
19+
umask: int
20+
21+
1222
@pytest.fixture(
1323
params=[
1424
({}, None),
@@ -20,11 +30,11 @@
2030
({"exists_ok": True, "parents": True}, None),
2131
]
2232
)
23-
def permissions_params(request):
24-
return request.param
33+
def permissions_params(request: FixtureRequest) -> tuple[MkdirParams, str | None]:
34+
return request.param # type: ignore[no-any-return]
2535

2636

27-
def test_mkdir_set_permissions(permissions_params: list) -> None:
37+
def test_mkdir_set_permissions(permissions_params: tuple[MkdirParams, str | None]) -> None:
2838
# Get prior umask value
2939
prior_umask = os.umask(0)
3040
os.umask(prior_umask)
@@ -36,10 +46,10 @@ def test_mkdir_set_permissions(permissions_params: list) -> None:
3646
parent_path = cwd / parent_dir_name
3747
path = parent_path / child_dir_name
3848

39-
mkdir_params: dict = permissions_params[0]
49+
mkdir_params: MkdirParams = permissions_params[0]
4050
permissions: str | None = permissions_params[1] if permissions_params[1] else "drwxrwxr-x"
4151

42-
def test_mkdir_permissions():
52+
def test_mkdir_permissions() -> None:
4353
mkdir(path, **mkdir_params)
4454
proc = Popen(
4555
f"ls -l | grep '{parent_dir_name}' | grep '{permissions}'",
@@ -76,18 +86,18 @@ def test_mkdir_permissions():
7686
assert prior_umask == os.umask(prior_umask), "umask was changed and not reset"
7787

7888

79-
def test_backoff_and_retry():
89+
def test_backoff_and_retry() -> None:
8090
class WarningCatcher:
81-
def __init__(self):
82-
self.caught_warnings = []
91+
def __init__(self) -> None:
92+
self.caught_warnings: list[str] = []
8393

84-
def warn(self, message, *args, **kwargs):
94+
def warn(self, message: str, *args: Any, **kwargs: Any) -> None:
8595
self.caught_warnings.append(message)
8696

8797
wc = WarningCatcher()
8898

8999
@backoff_and_retry(log_function=wc.warn)
90-
def successful_function():
100+
def successful_function() -> bool:
91101
return True
92102

93103
assert successful_function()
@@ -96,7 +106,7 @@ def successful_function():
96106
wc = WarningCatcher()
97107

98108
@backoff_and_retry(backoff_seconds=0.1, num_retries=5, log_function=wc.warn)
99-
def failing_function():
109+
def failing_function() -> None:
100110
raise ValueError
101111

102112
start = time.time()

0 commit comments

Comments
 (0)