Skip to content

Commit 37909b0

Browse files
committed
Ensure typing module is only imported if annotations are introspected
1 parent d1295f5 commit 37909b0

File tree

11 files changed

+93
-35
lines changed

11 files changed

+93
-35
lines changed

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ select = [
3636
"TRY", "UP", "YTT"
3737
]
3838

39+
typing-modules = ["async_utils._typings"]
40+
3941
ignore = [
4042
"ANN202", # implied return fine sometimes
4143
"ANN401", # Any is the correct type in some cases

src/async_utils/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
__author__ = "Michael Hall"
1010
__license__ = "Apache-2.0"
1111
__copyright__ = "Copyright 2020-Present Michael Hall"
12-
__version__ = "2024.12.27"
12+
__version__ = "2025.01.06"
1313

1414
import os
1515
import sys

src/async_utils/_paramkey.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
1+
# Copyright 2020-present Michael Hall
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
115
# This used to include CPython code, some minor performance losses have been
216
# taken to not tightly include upstream code
317

418

519
from __future__ import annotations
620

721
from collections.abc import Hashable
8-
from typing import Any, Final, final
22+
23+
from ._typings import Any, Final, final
924

1025

1126
@final

src/async_utils/_typings.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2020-present Michael Hall
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
from __future__ import annotations
17+
18+
TYPE_CHECKING = False
19+
20+
if TYPE_CHECKING:
21+
from typing import Any, Final, Literal, Self, final
22+
else:
23+
24+
def final(f): # noqa: ANN001
25+
return f
26+
27+
28+
def __getattr__(name: str):
29+
if name == "final": # this one actually executes at runtime
30+
return final
31+
32+
if name in {"Any", "Final", "Literal", "Self"}:
33+
import typing
34+
35+
return getattr(typing, name)
36+
37+
msg = f"module {__name__!r} has no attribute {name!r}"
38+
raise AttributeError(msg)
39+
40+
41+
__all__ = ["Any", "Final", "Literal", "Self", "final"]

src/async_utils/bg_tasks.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
import asyncio
1818
from collections.abc import Coroutine
1919
from contextvars import Context
20-
from typing import Any, Self
20+
21+
from ._typings import Any, Self
2122

2223
type _CoroutineLike[T] = Coroutine[Any, Any, T]
2324

src/async_utils/corofunc_cache.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
import asyncio
1818
from collections.abc import Awaitable, Callable, Coroutine, Hashable
1919
from functools import partial, wraps
20-
from typing import Any
2120

2221
from ._paramkey import make_key
22+
from ._typings import Any
2323
from .lru import LRU
2424

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

src/async_utils/priority_sem.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
import threading
2222
from collections.abc import Callable, Generator
2323
from contextlib import contextmanager
24-
from typing import Any, NamedTuple
24+
25+
from ._typings import Any, Self
2526

2627
__all__ = ["PrioritySemaphore", "priority_context"]
2728

@@ -30,10 +31,23 @@
3031
_priority: contextvars.ContextVar[int] = contextvars.ContextVar("_priority", default=0)
3132

3233

33-
class PriorityWaiter(NamedTuple):
34-
priority: int
35-
ts: float
36-
future: asyncio.Future[None]
34+
class PriorityWaiter(tuple[int, float, asyncio.Future[None]]):
35+
__slots__ = ()
36+
37+
def __new__(cls, priority: int, ts: float, future: asyncio.Future[None]) -> Self:
38+
return super().__new__(cls, (priority, ts, future))
39+
40+
@property
41+
def priority(self) -> int:
42+
return self[0]
43+
44+
@property
45+
def ts(self) -> float:
46+
return self[1]
47+
48+
@property
49+
def future(self) -> asyncio.Future[None]:
50+
return self[2]
3751

3852
@property
3953
def cancelled(self) -> Callable[[], bool]:
@@ -49,7 +63,7 @@ def __await__(self) -> Generator[Any, Any, None]:
4963
def __lt__(self, other: Any) -> bool:
5064
if not isinstance(other, PriorityWaiter):
5165
return NotImplemented
52-
return (self.priority, self.ts) < (other.priority, other.ts)
66+
return self[:2] < other[:2]
5367

5468

5569
@contextmanager

src/async_utils/scheduler.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
import asyncio
1818
from functools import total_ordering
1919
from time import time
20-
from typing import Any, Self
20+
21+
from ._typings import Any, Self
2122

2223
__all__ = ("Scheduler",)
2324

src/async_utils/sig_service.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
import sys
2222
from collections.abc import Callable
2323
from types import FrameType
24-
from typing import Any, Final, Literal
24+
25+
from ._typings import Any, Final, Literal
2526

2627
__all__ = ["SignalService", "SpecialExit"]
2728

src/async_utils/task_cache.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
import inspect
1919
from collections.abc import Callable, Coroutine, Hashable
2020
from functools import partial, wraps
21-
from typing import Any
2221

2322
from ._paramkey import make_key
23+
from ._typings import Any
2424
from .lru import LRU
2525

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

0 commit comments

Comments
 (0)