Skip to content

Commit f388e20

Browse files
committed
Actually ensure the attribute access is late...
1 parent 1e2c4d0 commit f388e20

File tree

9 files changed

+41
-31
lines changed

9 files changed

+41
-31
lines changed

src/async_utils/_paramkey.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020

2121
from collections.abc import Hashable
2222

23-
from ._typings import Any, Final, final
23+
from . import _typings as t
2424

2525

26-
@final
26+
@t.final
2727
class _HK:
2828
__slots__ = ("_hashvalue", "_tup")
2929

@@ -40,11 +40,11 @@ def __eq__(self, other: object) -> bool:
4040
return self._tup == other._tup
4141

4242

43-
_marker: Final[tuple[object]] = (object(),)
43+
_marker: t.Final[tuple[object]] = (object(),)
4444

4545

46-
def make_key(args: tuple[Any, ...], kwds: dict[Any, Any]) -> Hashable:
47-
key: tuple[Any, ...] = args
46+
def make_key(args: tuple[t.Any, ...], kwds: dict[t.Any, t.Any]) -> Hashable:
47+
key: tuple[t.Any, ...] = args
4848
if kwds:
4949
key += _marker
5050
for item in kwds.items():

src/async_utils/_typings.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
"""Shim for typing- and annotation-related symbols to avoid runtime dependencies on `typing` or `typing-extensions`.
16+
17+
A warning for annotation-related symbols: Do not directly import them from this module
18+
(e.g. `from ._typing_compat import Any`)! Doing so will trigger the module-level `__getattr__`, causing `typing` to
19+
get imported. Instead, import the module and use symbols via attribute access as needed
20+
(e.g. `from . import _typing_compat [as _t]`). To avoid those symbols being evaluated at runtime, which would also cause
21+
`typing` to get imported, make sure to put `from __future__ import annotations` at the top of the module.
22+
"""
23+
# comment above
24+
# taken verbatim from quote from https://github.com/Sachaa-Thanasius in discord
25+
# cause I forget otherwise too.
1526

1627
from __future__ import annotations
1728

@@ -26,7 +37,6 @@ def final(f): # noqa: ANN001
2637

2738

2839
def __getattr__(name: str):
29-
3040
if name in {"Any", "Final", "Literal", "Self"}:
3141
import typing
3242

src/async_utils/bg_tasks.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
from collections.abc import Coroutine
1919
from contextvars import Context
2020

21-
from ._typings import Any, Self
21+
from . import _typings as t
2222

23-
type _CoroutineLike[T] = Coroutine[Any, Any, T]
23+
type _CoroutineLike[T] = Coroutine[t.Any, t.Any, T]
2424

2525

2626
__all__ = ["BGTasks"]
@@ -61,7 +61,7 @@ def create_task[T](
6161
t.add_done_callback(self._tasks.discard)
6262
return t
6363

64-
async def __aenter__(self: Self) -> Self:
64+
async def __aenter__(self: t.Self) -> t.Self:
6565
return self
6666

6767
async def __aexit__(self, *_dont_care: object) -> None:

src/async_utils/corofunc_cache.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
from collections.abc import Awaitable, Callable, Coroutine, Hashable
1919
from functools import partial, wraps
2020

21+
from . import _typings as t
2122
from ._paramkey import make_key
22-
from ._typings import Any
2323
from .lru import LRU
2424

2525
__all__ = ("corocache", "lrucorocache")
2626

2727

28-
type CoroFunc[**P, R] = Callable[P, Coroutine[Any, Any, R]]
28+
type CoroFunc[**P, R] = Callable[P, Coroutine[t.Any, t.Any, R]]
2929
type CoroLike[**P, R] = Callable[P, Awaitable[R]]
3030

3131
type Deco[**P, R] = Callable[[CoroLike[P, R]], CoroFunc[P, R]]

src/async_utils/priority_sem.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from collections.abc import Callable, Generator
2323
from contextlib import contextmanager
2424

25-
from ._typings import Any, Self
25+
from . import _typings as t
2626

2727
__all__ = ["PrioritySemaphore", "priority_context"]
2828

@@ -34,7 +34,7 @@
3434
class PriorityWaiter(tuple[int, float, asyncio.Future[None]]):
3535
__slots__ = ()
3636

37-
def __new__(cls, priority: int, ts: float, future: asyncio.Future[None]) -> Self:
37+
def __new__(cls, priority: int, ts: float, future: asyncio.Future[None]) -> t.Self:
3838
return super().__new__(cls, (priority, ts, future))
3939

4040
@property
@@ -57,10 +57,10 @@ def cancelled(self) -> Callable[[], bool]:
5757
def done(self) -> Callable[[], bool]:
5858
return self.future.done
5959

60-
def __await__(self) -> Generator[Any, Any, None]:
60+
def __await__(self) -> Generator[t.Any, t.Any, None]:
6161
return self.future.__await__()
6262

63-
def __lt__(self, other: Any) -> bool:
63+
def __lt__(self, other: t.Any) -> bool:
6464
if not isinstance(other, PriorityWaiter):
6565
return NotImplemented
6666
return self[:2] < other[:2]
@@ -82,7 +82,7 @@ def priority_context(priority: int, /) -> Generator[None, None, None]:
8282
_priority.reset(token)
8383

8484

85-
_default: Any = object()
85+
_default: t.Any = object()
8686

8787

8888
class PrioritySemaphore:

src/async_utils/scheduler.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
from functools import total_ordering
1919
from time import time
2020

21-
from ._typings import Any, Self
21+
from . import _typings as t
2222

2323
__all__ = ("Scheduler",)
2424

25-
MISSING: Any = object()
25+
MISSING: t.Any = object()
2626

2727

2828
class CancellationToken:
@@ -76,7 +76,7 @@ def __init__(self, granularity: float, /) -> None:
7676
self.__tqueue = MISSING
7777
self.__l = MISSING
7878

79-
async def __aenter__(self) -> Self:
79+
async def __aenter__(self) -> t.Self:
8080
self.__closed = False
8181
asyncio.get_running_loop()
8282

@@ -94,7 +94,7 @@ async def __aenter__(self) -> Self:
9494
async def __aexit__(self, *_dont_care: object) -> None:
9595
self.__closed = True
9696

97-
def __aiter__(self) -> Self:
97+
def __aiter__(self) -> t.Self:
9898
return self
9999

100100
async def __anext__(self) -> T:

src/async_utils/sig_service.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@
2222
from collections.abc import Callable
2323
from types import FrameType
2424

25-
from ._typings import Any, Final, Literal
25+
from . import _typings as t
2626

2727
__all__ = ["SignalService", "SpecialExit"]
2828

29-
type SignalCallback = Callable[[signal.Signals | SpecialExit], Any]
30-
type StartStopCall = Callable[[], Any]
31-
type _HTC = Callable[[int, FrameType | None], Any]
29+
type SignalCallback = Callable[[signal.Signals | SpecialExit], t.Any]
30+
type StartStopCall = Callable[[], t.Any]
31+
type _HTC = Callable[[int, FrameType | None], t.Any]
3232
type _HANDLER = _HTC | int | signal.Handlers | None
3333

34-
type HandleableSignals = Literal["SIGINT", "SIGTERM", "SIGBREAK", "SIGHUP"]
34+
type HandleableSignals = t.Literal["SIGINT", "SIGTERM", "SIGBREAK", "SIGHUP"]
3535
type SignalTuple = tuple[HandleableSignals, ...]
3636

37-
default_handled: Final = "SIGINT", "SIGTERM", "SIGBREAK"
37+
default_handled: t.Final = "SIGINT", "SIGTERM", "SIGBREAK"
3838

3939

4040
class SpecialExit(enum.IntEnum):

src/async_utils/task_cache.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
from collections.abc import Callable, Coroutine, Hashable
2020
from functools import partial, wraps
2121

22+
from . import _typings as t
2223
from ._paramkey import make_key
23-
from ._typings import Any
2424
from .lru import LRU
2525

2626
__all__ = ("lrutaskcache", "taskcache")
2727

2828

2929
# Use below doesn't accept non-task Futures, so can't accept general awaitables
30-
type CoroFunc[**P, R] = Callable[P, Coroutine[Any, Any, R]]
30+
type CoroFunc[**P, R] = Callable[P, Coroutine[t.Any, t.Any, R]]
3131
type TaskFunc[**P, R] = CoroFunc[P, R] | Callable[P, asyncio.Task[R]]
3232
type TaskCoroFunc[**P, R] = CoroFunc[P, R] | TaskFunc[P, R]
3333

src/async_utils/waterfall.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
import time
2020
from collections.abc import Callable, Coroutine, Sequence
2121

22-
from ._typings import Any
22+
from . import _typings as t
2323

2424
__all__ = ("Waterfall",)
2525

26-
type CBT[T] = Callable[[Sequence[T]], Coroutine[Any, Any, Any]]
27-
type NC = Coroutine[Any, Any, None]
26+
type CBT[T] = Callable[[Sequence[T]], Coroutine[t.Any, t.Any, t.Any]]
27+
type NC = Coroutine[t.Any, t.Any, None]
2828

2929

3030
class Waterfall[T]:

0 commit comments

Comments
 (0)