Defer `asyncio` import via PEP-562 `.to_asyncio`
`asyncio` (~5ms) only matters for infected-aio actors yet gets imported by every cold `import tractor` via module-lvl `.to_asyncio` imports in the debug-REPL + spawn-entry mods. Deats, - `devx.debug._trace`/`._tty_lock`: mv `import asyncio` under `TYPE_CHECKING` + fn-local it at the two `asyncio.current_task()` call-sites; fn-local the `run_trio_task_in_future` imports in the infected-aio-only branches. - `spawn._entry`: fn-local `run_as_asyncio_guest` inside the `infect_asyncio=True` branches of `_mp_main()`/ `_trio_main()`. - `tractor/__init__.py`: add a PEP-562 module `__getattr__` lazy-loading `.to_asyncio` on first attr-access so the public `tractor.to_asyncio.<attr>` API (e.g. `LinkedTaskChannel` annots in `test_child_manages_service_nursery.py` + downstream users) keeps working unchanged. Prompt-IO: ai/prompt-io/claude/20260702T155626Z_65bf9df5_prompt_io.md (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-codeboot_latency_470
parent
4f811a87f9
commit
0a97dd4e71
|
|
@ -74,3 +74,26 @@ from .discovery._registry import (
|
||||||
Arbiter as Arbiter,
|
Arbiter as Arbiter,
|
||||||
)
|
)
|
||||||
# from . import hilevel as hilevel
|
# from . import hilevel as hilevel
|
||||||
|
|
||||||
|
|
||||||
|
def __getattr__(name: str):
|
||||||
|
'''
|
||||||
|
PEP 562 lazy sub-module loading, presently only for
|
||||||
|
`.to_asyncio` which (transitively) imports `asyncio`
|
||||||
|
itself: a non-trivial multi-ms chunk of the eager
|
||||||
|
`import tractor` cost (gh #470) unneeded by
|
||||||
|
`trio`-only apps.
|
||||||
|
|
||||||
|
Any `tractor.to_asyncio.<attr>` access (or a
|
||||||
|
`from tractor import to_asyncio`) still works, the
|
||||||
|
sub-mod is simply imported on first-access instead
|
||||||
|
of at pkg-import time.
|
||||||
|
|
||||||
|
'''
|
||||||
|
if name == 'to_asyncio':
|
||||||
|
from importlib import import_module
|
||||||
|
return import_module('.to_asyncio', __name__)
|
||||||
|
|
||||||
|
raise AttributeError(
|
||||||
|
f'module {__name__!r} has no attribute {name!r}'
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ mult-process support within a single actor tree.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import asyncio
|
|
||||||
import bdb
|
import bdb
|
||||||
from contextlib import (
|
from contextlib import (
|
||||||
AbstractContextManager,
|
AbstractContextManager,
|
||||||
|
|
@ -53,7 +52,6 @@ from trio import (
|
||||||
)
|
)
|
||||||
import tractor
|
import tractor
|
||||||
from tractor.log import get_logger
|
from tractor.log import get_logger
|
||||||
from tractor.to_asyncio import run_trio_task_in_future
|
|
||||||
from tractor._context import Context
|
from tractor._context import Context
|
||||||
from tractor.runtime import _state
|
from tractor.runtime import _state
|
||||||
from tractor._exceptions import (
|
from tractor._exceptions import (
|
||||||
|
|
@ -85,6 +83,10 @@ from ..pformat import (
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
# NOTE, `asyncio` (and `.to_asyncio`) are
|
||||||
|
# lazy-imported at their use-sites to keep them off
|
||||||
|
# the eager `import tractor` path (gh #470).
|
||||||
|
import asyncio
|
||||||
from trio.lowlevel import Task
|
from trio.lowlevel import Task
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from tractor.runtime._runtime import (
|
from tractor.runtime._runtime import (
|
||||||
|
|
@ -164,6 +166,7 @@ async def _pause(
|
||||||
'An `asyncio` task should not be calling this!?'
|
'An `asyncio` task should not be calling this!?'
|
||||||
) from rte
|
) from rte
|
||||||
else:
|
else:
|
||||||
|
import asyncio
|
||||||
task = asyncio.current_task()
|
task = asyncio.current_task()
|
||||||
|
|
||||||
if debug_func is not None:
|
if debug_func is not None:
|
||||||
|
|
@ -946,6 +949,7 @@ def pause_from_sync(
|
||||||
|
|
||||||
asyncio_task: asyncio.Task|None = None
|
asyncio_task: asyncio.Task|None = None
|
||||||
if is_infected_aio:
|
if is_infected_aio:
|
||||||
|
import asyncio
|
||||||
asyncio_task = asyncio.current_task()
|
asyncio_task = asyncio.current_task()
|
||||||
|
|
||||||
# TODO: we could also check for a non-`.to_thread` context
|
# TODO: we could also check for a non-`.to_thread` context
|
||||||
|
|
@ -1059,6 +1063,9 @@ def pause_from_sync(
|
||||||
greenback: ModuleType = maybe_import_greenback()
|
greenback: ModuleType = maybe_import_greenback()
|
||||||
|
|
||||||
if greenback.has_portal():
|
if greenback.has_portal():
|
||||||
|
from tractor.to_asyncio import (
|
||||||
|
run_trio_task_in_future,
|
||||||
|
)
|
||||||
DebugStatus.shield_sigint()
|
DebugStatus.shield_sigint()
|
||||||
fute: asyncio.Future = run_trio_task_in_future(
|
fute: asyncio.Future = run_trio_task_in_future(
|
||||||
partial(
|
partial(
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ Root-actor TTY mutex-locking machinery.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import asyncio
|
|
||||||
from contextlib import (
|
from contextlib import (
|
||||||
AbstractContextManager,
|
AbstractContextManager,
|
||||||
asynccontextmanager as acm,
|
asynccontextmanager as acm,
|
||||||
|
|
@ -52,7 +51,6 @@ from trio import (
|
||||||
TaskStatus,
|
TaskStatus,
|
||||||
)
|
)
|
||||||
import tractor
|
import tractor
|
||||||
from tractor.to_asyncio import run_trio_task_in_future
|
|
||||||
from tractor.log import get_logger
|
from tractor.log import get_logger
|
||||||
from tractor._context import Context
|
from tractor._context import Context
|
||||||
from tractor.runtime import _state
|
from tractor.runtime import _state
|
||||||
|
|
@ -66,6 +64,10 @@ from tractor.runtime._state import (
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
# NOTE, `asyncio` (and `.to_asyncio`) are
|
||||||
|
# lazy-imported at their use-sites to keep them off
|
||||||
|
# the eager `import tractor` path (gh #470).
|
||||||
|
import asyncio
|
||||||
from trio.lowlevel import Task
|
from trio.lowlevel import Task
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from tractor.ipc import (
|
from tractor.ipc import (
|
||||||
|
|
@ -910,6 +912,9 @@ class DebugStatus:
|
||||||
async def _set_repl_release():
|
async def _set_repl_release():
|
||||||
repl_release.set()
|
repl_release.set()
|
||||||
|
|
||||||
|
from tractor.to_asyncio import (
|
||||||
|
run_trio_task_in_future,
|
||||||
|
)
|
||||||
fute: asyncio.Future = run_trio_task_in_future(
|
fute: asyncio.Future = run_trio_task_in_future(
|
||||||
_set_repl_release
|
_set_repl_release
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,11 @@ from ..devx import (
|
||||||
pformat,
|
pformat,
|
||||||
)
|
)
|
||||||
# from ..msg import pretty_struct
|
# from ..msg import pretty_struct
|
||||||
from ..to_asyncio import run_as_asyncio_guest
|
#
|
||||||
|
# NOTE, `.to_asyncio` (and thus `asyncio` itself) is
|
||||||
|
# lazy-imported at the `infect_asyncio=True` use-sites
|
||||||
|
# below to keep it off the eager `import tractor` path
|
||||||
|
# (gh #470).
|
||||||
from ..discovery._addr import UnwrappedAddress
|
from ..discovery._addr import UnwrappedAddress
|
||||||
from ..runtime._runtime import (
|
from ..runtime._runtime import (
|
||||||
async_main,
|
async_main,
|
||||||
|
|
@ -96,6 +100,7 @@ def _mp_main(
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
if infect_asyncio:
|
if infect_asyncio:
|
||||||
|
from ..to_asyncio import run_as_asyncio_guest
|
||||||
actor._infected_aio = True
|
actor._infected_aio = True
|
||||||
run_as_asyncio_guest(trio_main)
|
run_as_asyncio_guest(trio_main)
|
||||||
else:
|
else:
|
||||||
|
|
@ -156,6 +161,7 @@ def _trio_main(
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
if infect_asyncio:
|
if infect_asyncio:
|
||||||
|
from ..to_asyncio import run_as_asyncio_guest
|
||||||
actor._infected_aio = True
|
actor._infected_aio = True
|
||||||
run_as_asyncio_guest(trio_main)
|
run_as_asyncio_guest(trio_main)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue