Skip to content

Commit 55964ad

Browse files
committed
Get rid of a bunch more Anys and resolve mypy issues
1 parent 521c1b7 commit 55964ad

16 files changed

+172
-89
lines changed

src/trio/_core/_concat_tb.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from types import TracebackType
4-
from typing import ClassVar, cast
4+
from typing import TYPE_CHECKING, ClassVar, cast
55

66
################################################################
77
# concat_tb
@@ -88,7 +88,7 @@ def copy_tb(base_tb: TracebackType, tb_next: TracebackType | None) -> TracebackT
8888
# cpython/pypy in current type checkers.
8989
def controller( # type: ignore[no-any-unimported]
9090
operation: tputil.ProxyOperation,
91-
) -> object | None:
91+
) -> TracebackType | None:
9292
# Rationale for pragma: I looked fairly carefully and tried a few
9393
# things, and AFAICT it's not actually possible to get any
9494
# 'opname' that isn't __getattr__ or __getattribute__. So there's
@@ -101,8 +101,10 @@ def controller( # type: ignore[no-any-unimported]
101101
"__getattr__",
102102
}
103103
and operation.args[0] == "tb_next"
104-
): # pragma: no cover
104+
) or TYPE_CHECKING: # pragma: no cover
105105
return tb_next
106+
if TYPE_CHECKING:
107+
raise RuntimeError("Should not be possible")
106108
return operation.delegate() # Delegate is reverting to original behaviour
107109

108110
return cast(

src/trio/_core/_ki.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,13 @@ class _IdRef(weakref.ref[_T]):
8585
__slots__ = ("_hash",)
8686
_hash: int
8787

88-
def __new__(cls, ob: _T, callback: Callable[[Self], Any] | None = None, /) -> Self:
88+
# Explicit "Any" is not allowed
89+
def __new__( # type: ignore[misc]
90+
cls,
91+
ob: _T,
92+
callback: Callable[[Self], Any] | None = None,
93+
/,
94+
) -> Self:
8995
self: Self = weakref.ref.__new__(cls, ob, callback)
9096
self._hash = object.__hash__(ob)
9197
return self

src/trio/_core/_run.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,16 @@
7171
# for some strange reason Sphinx works with outcome.Outcome, but not Outcome, in
7272
# start_guest_run. Same with types.FrameType in iter_await_frames
7373
import outcome
74-
from typing_extensions import ParamSpec, Self, TypeVar, TypeVarTuple, Unpack
74+
from typing_extensions import Self, TypeVar, TypeVarTuple, Unpack
7575

7676
PosArgT = TypeVarTuple("PosArgT")
7777
StatusT = TypeVar("StatusT", default=None)
7878
StatusT_contra = TypeVar("StatusT_contra", contravariant=True, default=None)
79-
PS = ParamSpec("PS")
8079
else:
8180
from typing import TypeVar
8281

8382
StatusT = TypeVar("StatusT")
8483
StatusT_contra = TypeVar("StatusT_contra", contravariant=True)
85-
PS = TypeVar("PS")
8684

8785
RetT = TypeVar("RetT")
8886

@@ -103,7 +101,7 @@ class _NoStatus(metaclass=NoPublicConstructor):
103101

104102
# Decorator to mark methods public. This does nothing by itself, but
105103
# trio/_tools/gen_exports.py looks for it.
106-
def _public(fn: Callable[PS, RetT]) -> Callable[PS, RetT]:
104+
def _public(fn: RetT) -> RetT:
107105
return fn
108106

109107

src/trio/_core/_tests/test_guest_mode.py

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@
1111
import time
1212
import traceback
1313
import warnings
14-
from collections.abc import AsyncGenerator, Awaitable, Callable
14+
from collections.abc import AsyncGenerator, Awaitable, Callable, Sequence
1515
from functools import partial
1616
from math import inf
1717
from typing import (
1818
TYPE_CHECKING,
19-
Any,
2019
NoReturn,
2120
TypeVar,
2221
)
@@ -26,7 +25,7 @@
2625

2726
import trio
2827
import trio.testing
29-
from trio.abc import Instrument
28+
from trio.abc import Clock, Instrument
3029

3130
from ..._util import signal_raise
3231
from .tutil import gc_collect_harder, restore_unraisablehook
@@ -37,7 +36,7 @@
3736
from trio._channel import MemorySendChannel
3837

3938
T = TypeVar("T")
40-
InHost: TypeAlias = Callable[[object], None]
39+
InHost: TypeAlias = Callable[[Callable[[], object]], None]
4140

4241

4342
# The simplest possible "host" loop.
@@ -46,12 +45,15 @@
4645
# our main
4746
# - final result is returned
4847
# - any unhandled exceptions cause an immediate crash
49-
# Explicit "Any" is not allowed
50-
def trivial_guest_run( # type: ignore[misc]
51-
trio_fn: Callable[..., Awaitable[T]],
48+
def trivial_guest_run(
49+
trio_fn: Callable[[InHost], Awaitable[T]],
5250
*,
5351
in_host_after_start: Callable[[], None] | None = None,
54-
**start_guest_run_kwargs: Any,
52+
host_uses_signal_set_wakeup_fd: bool = False,
53+
clock: Clock | None = None,
54+
instruments: Sequence[Instrument] = (),
55+
restrict_keyboard_interrupt_to_checkpoints: bool = False,
56+
strict_exception_groups: bool = True,
5557
) -> T:
5658
todo: queue.Queue[tuple[str, Outcome[T] | Callable[[], object]]] = queue.Queue()
5759

@@ -87,7 +89,11 @@ def done_callback(outcome: Outcome[T]) -> None:
8789
run_sync_soon_threadsafe=run_sync_soon_threadsafe,
8890
run_sync_soon_not_threadsafe=run_sync_soon_not_threadsafe,
8991
done_callback=done_callback,
90-
**start_guest_run_kwargs,
92+
host_uses_signal_set_wakeup_fd=host_uses_signal_set_wakeup_fd,
93+
clock=clock,
94+
instruments=instruments,
95+
restrict_keyboard_interrupt_to_checkpoints=restrict_keyboard_interrupt_to_checkpoints,
96+
strict_exception_groups=strict_exception_groups,
9197
)
9298
if in_host_after_start is not None:
9399
in_host_after_start()
@@ -171,10 +177,16 @@ async def early_task() -> None:
171177
assert res == "ok"
172178
assert set(record) == {"system task ran", "main task ran", "run_sync_soon cb ran"}
173179

174-
class BadClock:
180+
class BadClock(Clock):
175181
def start_clock(self) -> NoReturn:
176182
raise ValueError("whoops")
177183

184+
def current_time(self) -> float:
185+
raise NotImplementedError()
186+
187+
def deadline_to_sleep_time(self, deadline: float) -> float:
188+
raise NotImplementedError()
189+
178190
def after_start_never_runs() -> None: # pragma: no cover
179191
pytest.fail("shouldn't get here")
180192

@@ -431,12 +443,16 @@ async def abandoned_main(in_host: InHost) -> None:
431443
trio.current_time()
432444

433445

434-
# Explicit "Any" is not allowed
435-
def aiotrio_run( # type: ignore[misc]
436-
trio_fn: Callable[..., Awaitable[T]],
446+
def aiotrio_run(
447+
trio_fn: Callable[[], Awaitable[T]],
437448
*,
438449
pass_not_threadsafe: bool = True,
439-
**start_guest_run_kwargs: Any,
450+
run_sync_soon_not_threadsafe: InHost | None = None,
451+
host_uses_signal_set_wakeup_fd: bool = False,
452+
clock: Clock | None = None,
453+
instruments: Sequence[Instrument] = (),
454+
restrict_keyboard_interrupt_to_checkpoints: bool = False,
455+
strict_exception_groups: bool = True,
440456
) -> T:
441457
loop = asyncio.new_event_loop()
442458

@@ -448,13 +464,18 @@ def trio_done_callback(main_outcome: Outcome[object]) -> None:
448464
trio_done_fut.set_result(main_outcome)
449465

450466
if pass_not_threadsafe:
451-
start_guest_run_kwargs["run_sync_soon_not_threadsafe"] = loop.call_soon
467+
run_sync_soon_not_threadsafe = loop.call_soon
452468

453469
trio.lowlevel.start_guest_run(
454470
trio_fn,
455471
run_sync_soon_threadsafe=loop.call_soon_threadsafe,
456472
done_callback=trio_done_callback,
457-
**start_guest_run_kwargs,
473+
run_sync_soon_not_threadsafe=run_sync_soon_not_threadsafe,
474+
host_uses_signal_set_wakeup_fd=host_uses_signal_set_wakeup_fd,
475+
clock=clock,
476+
instruments=instruments,
477+
restrict_keyboard_interrupt_to_checkpoints=restrict_keyboard_interrupt_to_checkpoints,
478+
strict_exception_groups=strict_exception_groups,
458479
)
459480

460481
return (await trio_done_fut).unwrap() # type: ignore[no-any-return]
@@ -557,12 +578,14 @@ async def crash_in_worker_thread_io(in_host: InHost) -> None:
557578
t = threading.current_thread()
558579
old_get_events = trio._core._run.TheIOManager.get_events
559580

560-
# Explicit "Any" is not allowed
561-
def bad_get_events(*args: Any) -> object: # type: ignore[misc]
581+
def bad_get_events(
582+
self: trio._core._run.TheIOManager,
583+
timeout: float,
584+
) -> trio._core._run.EventResult:
562585
if threading.current_thread() is not t:
563586
raise ValueError("oh no!")
564587
else:
565-
return old_get_events(*args)
588+
return old_get_events(self, timeout)
566589

567590
m.setattr("trio._core._run.TheIOManager.get_events", bad_get_events)
568591

src/trio/_core/_tests/test_ki.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,10 @@ async def _consume_async_generator(agen: AsyncGenerator[None, None]) -> None:
678678
await agen.aclose()
679679

680680

681-
def _consume_function_for_coverage(fn: Callable[..., object]) -> None:
681+
# Explicit "Any" is not allowed
682+
def _consume_function_for_coverage( # type: ignore[misc]
683+
fn: Callable[..., object],
684+
) -> None:
682685
result = fn()
683686
if inspect.isasyncgen(result):
684687
result = _consume_async_generator(result)

src/trio/_core/_tests/test_parking_lot.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,9 +304,10 @@ async def test_parking_lot_breaker_registration() -> None:
304304

305305
# registering a task as breaker on an already broken lot is fine
306306
lot.break_lot()
307-
child_task = None
307+
child_task: _core.Task | None = None
308308
async with trio.open_nursery() as nursery:
309309
child_task = await nursery.start(dummy_task)
310+
assert isinstance(child_task, _core.Task)
310311
add_parking_lot_breaker(child_task, lot)
311312
nursery.cancel_scope.cancel()
312313
assert lot.broken_by == [task, child_task]
@@ -339,6 +340,9 @@ async def test_parking_lot_multiple_breakers_exit() -> None:
339340
child_task1 = await nursery.start(dummy_task)
340341
child_task2 = await nursery.start(dummy_task)
341342
child_task3 = await nursery.start(dummy_task)
343+
assert isinstance(child_task1, _core.Task)
344+
assert isinstance(child_task2, _core.Task)
345+
assert isinstance(child_task3, _core.Task)
342346
add_parking_lot_breaker(child_task1, lot)
343347
add_parking_lot_breaker(child_task2, lot)
344348
add_parking_lot_breaker(child_task3, lot)
@@ -350,9 +354,11 @@ async def test_parking_lot_multiple_breakers_exit() -> None:
350354

351355
async def test_parking_lot_breaker_register_exited_task() -> None:
352356
lot = ParkingLot()
353-
child_task = None
357+
child_task: _core.Task | None = None
354358
async with trio.open_nursery() as nursery:
355-
child_task = await nursery.start(dummy_task)
359+
value = await nursery.start(dummy_task)
360+
assert isinstance(value, _core.Task)
361+
child_task = value
356362
nursery.cancel_scope.cancel()
357363
# trying to register an exited task as lot breaker errors
358364
with pytest.raises(

src/trio/_core/_tests/test_run.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,9 @@ async def task3(task_status: _core.TaskStatus[_core.CancelScope]) -> None:
823823
await sleep_forever()
824824

825825
async with _core.open_nursery() as nursery:
826-
scope: _core.CancelScope = await nursery.start(task3)
826+
value = await nursery.start(task3)
827+
assert isinstance(value, _core.CancelScope)
828+
scope: _core.CancelScope = value
827829
with pytest.raises(RuntimeError, match="from unrelated"):
828830
scope.__exit__(None, None, None)
829831
scope.cancel()
@@ -1963,15 +1965,19 @@ async def sleeping_children(
19631965

19641966
# Cancelling the setup_nursery just *before* calling started()
19651967
async with _core.open_nursery() as nursery:
1966-
target_nursery: _core.Nursery = await nursery.start(setup_nursery)
1968+
value = await nursery.start(setup_nursery)
1969+
assert isinstance(value, _core.Nursery)
1970+
target_nursery: _core.Nursery = value
19671971
await target_nursery.start(
19681972
sleeping_children,
19691973
target_nursery.cancel_scope.cancel,
19701974
)
19711975

19721976
# Cancelling the setup_nursery just *after* calling started()
19731977
async with _core.open_nursery() as nursery:
1974-
target_nursery = await nursery.start(setup_nursery)
1978+
value = await nursery.start(setup_nursery)
1979+
assert isinstance(value, _core.Nursery)
1980+
target_nursery = value
19751981
await target_nursery.start(sleeping_children, lambda: None)
19761982
target_nursery.cancel_scope.cancel()
19771983

src/trio/_core/_thread_cache.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
from functools import partial
88
from itertools import count
99
from threading import Lock, Thread
10-
from typing import Any, Callable, Generic, TypeVar
10+
from typing import TYPE_CHECKING, Any, Generic, TypeVar
1111

1212
import outcome
1313

14+
if TYPE_CHECKING:
15+
from collections.abc import Callable
16+
1417
RetT = TypeVar("RetT")
1518

1619

@@ -126,6 +129,8 @@ def darwin_namefunc(
126129

127130

128131
class WorkerThread(Generic[RetT]):
132+
__slots__ = ("_default_name", "_job", "_thread", "_thread_cache", "_worker_lock")
133+
129134
def __init__(self, thread_cache: ThreadCache) -> None:
130135
self._job: (
131136
tuple[
@@ -207,8 +212,10 @@ def _work(self) -> None:
207212

208213

209214
class ThreadCache:
215+
__slots__ = ("_idle_workers",)
216+
210217
def __init__(self) -> None:
211-
# Explicit "Any" is not allowed
218+
# Explicit "Any" not allowed
212219
self._idle_workers: dict[WorkerThread[Any], None] = {} # type: ignore[misc]
213220

214221
def start_thread_soon(

0 commit comments

Comments
 (0)