Be explicit with `SpawnSpec` processing in subs
As per the outstanding TODO just above the redic `setattr()` loop in `Actor._from_parent()`!! Instead of all that risk-ay monkeying, add detailed comment-sections around each explicit assignment of each `SpawnSpec` field, including those that were already being explicitly set. Those and other deats, - ONLY enable the `.devx.debug._tty_lock` module from `Actor.__init__()` in the root actor. - add a new `get_mod_nsps2fps()` to replace the loop in init and assign the initial `.enable_modules: dict[str, str]` from it. - do `self.enable_modules.update(spawnspec.enable_modules)` instead of an overwrite and assert the table is by default empty in all subs.repl_fixture
parent
1012581a0b
commit
006ee0752c
|
@ -115,6 +115,20 @@ def _get_mod_abspath(module):
|
||||||
return os.path.abspath(module.__file__)
|
return os.path.abspath(module.__file__)
|
||||||
|
|
||||||
|
|
||||||
|
def get_mod_nsps2fps(mod_ns_paths: list[str]) -> dict[str, str]:
|
||||||
|
'''
|
||||||
|
Deliver a table of py module namespace-path-`str`s mapped to
|
||||||
|
their "physical" `.py` file paths in the file-sys.
|
||||||
|
|
||||||
|
'''
|
||||||
|
nsp2fp: dict[str, str] = {}
|
||||||
|
for nsp in mod_ns_paths:
|
||||||
|
mod: ModuleType = importlib.import_module(nsp)
|
||||||
|
nsp2fp[nsp] = _get_mod_abspath(mod)
|
||||||
|
|
||||||
|
return nsp2fp
|
||||||
|
|
||||||
|
|
||||||
class Actor:
|
class Actor:
|
||||||
'''
|
'''
|
||||||
The fundamental "runtime" concurrency primitive.
|
The fundamental "runtime" concurrency primitive.
|
||||||
|
@ -219,13 +233,14 @@ class Actor:
|
||||||
# will be passed to children
|
# will be passed to children
|
||||||
self._parent_main_data = _mp_fixup_main._mp_figure_out_main()
|
self._parent_main_data = _mp_fixup_main._mp_figure_out_main()
|
||||||
|
|
||||||
|
# TODO? only add this when `is_debug_mode() == True` no?
|
||||||
# always include debugging tools module
|
# always include debugging tools module
|
||||||
enable_modules.append('tractor.devx.debug')
|
if _state.is_root_process():
|
||||||
|
enable_modules.append('tractor.devx.debug._tty_lock')
|
||||||
|
|
||||||
self.enable_modules: dict[str, str] = {}
|
self.enable_modules: dict[str, str] = get_mod_nsps2fps(
|
||||||
for name in enable_modules:
|
mod_ns_paths=enable_modules,
|
||||||
mod: ModuleType = importlib.import_module(name)
|
)
|
||||||
self.enable_modules[name] = _get_mod_abspath(mod)
|
|
||||||
|
|
||||||
self._mods: dict[str, ModuleType] = {}
|
self._mods: dict[str, ModuleType] = {}
|
||||||
self.loglevel: str = loglevel
|
self.loglevel: str = loglevel
|
||||||
|
@ -729,25 +744,33 @@ class Actor:
|
||||||
f'Received invalid non-`SpawnSpec` payload !?\n'
|
f'Received invalid non-`SpawnSpec` payload !?\n'
|
||||||
f'{spawnspec}\n'
|
f'{spawnspec}\n'
|
||||||
)
|
)
|
||||||
|
# ^^XXX TODO XXX^^^
|
||||||
# ^^TODO XXX!! when the `SpawnSpec` fails to decode
|
# when the `SpawnSpec` fails to decode the above will
|
||||||
# the above will raise a `MsgTypeError` which if we
|
# raise a `MsgTypeError` which if we do NOT ALSO
|
||||||
# do NOT ALSO RAISE it will tried to be pprinted in
|
# RAISE it will tried to be pprinted in the
|
||||||
# the log.runtime() below..
|
# log.runtime() below..
|
||||||
#
|
#
|
||||||
# SO we gotta look at how other `chan.recv()` calls
|
# SO we gotta look at how other `chan.recv()` calls
|
||||||
# are wrapped and do the same for this spec receive!
|
# are wrapped and do the same for this spec receive!
|
||||||
# -[ ] see `._rpc` likely has the answer?
|
# -[ ] see `._rpc` likely has the answer?
|
||||||
|
|
||||||
|
# ^^^XXX NOTE XXX^^^, can't be called here!
|
||||||
#
|
#
|
||||||
# XXX NOTE, can't be called here in subactor
|
|
||||||
# bc we haven't yet received the
|
|
||||||
# `SpawnSpec._runtime_vars: dict` which would
|
|
||||||
# declare whether `debug_mode` is set!
|
|
||||||
# breakpoint()
|
# breakpoint()
|
||||||
# import pdbp; pdbp.set_trace()
|
# import pdbp; pdbp.set_trace()
|
||||||
|
#
|
||||||
|
# => bc we haven't yet received the
|
||||||
|
# `spawnspec._runtime_vars` which contains
|
||||||
|
# `debug_mode: bool`..
|
||||||
|
|
||||||
|
# `SpawnSpec.bind_addrs`
|
||||||
|
# ---------------------
|
||||||
accept_addrs: list[UnwrappedAddress] = spawnspec.bind_addrs
|
accept_addrs: list[UnwrappedAddress] = spawnspec.bind_addrs
|
||||||
|
|
||||||
# TODO: another `Struct` for rtvs..
|
# `SpawnSpec._runtime_vars`
|
||||||
|
# -------------------------
|
||||||
|
# => update process-wide globals
|
||||||
|
# TODO! -[ ] another `Struct` for rtvs..
|
||||||
rvs: dict[str, Any] = spawnspec._runtime_vars
|
rvs: dict[str, Any] = spawnspec._runtime_vars
|
||||||
if rvs['_debug_mode']:
|
if rvs['_debug_mode']:
|
||||||
from .devx import (
|
from .devx import (
|
||||||
|
@ -805,18 +828,20 @@ class Actor:
|
||||||
f'self._infected_aio = {aio_attr}\n'
|
f'self._infected_aio = {aio_attr}\n'
|
||||||
)
|
)
|
||||||
if aio_rtv:
|
if aio_rtv:
|
||||||
assert trio_runtime.GLOBAL_RUN_CONTEXT.runner.is_guest
|
assert (
|
||||||
# ^TODO^ possibly add a `sniffio` or
|
trio_runtime.GLOBAL_RUN_CONTEXT.runner.is_guest
|
||||||
# `trio` pub-API for `is_guest_mode()`?
|
# and
|
||||||
|
# ^TODO^ possibly add a `sniffio` or
|
||||||
|
# `trio` pub-API for `is_guest_mode()`?
|
||||||
|
)
|
||||||
|
|
||||||
rvs['_is_root'] = False # obvi XD
|
rvs['_is_root'] = False # obvi XD
|
||||||
|
|
||||||
# update process-wide globals
|
|
||||||
_state._runtime_vars.update(rvs)
|
_state._runtime_vars.update(rvs)
|
||||||
|
|
||||||
# XXX: ``msgspec`` doesn't support serializing tuples
|
# `SpawnSpec.reg_addrs`
|
||||||
# so just cash manually here since it's what our
|
# ---------------------
|
||||||
# internals expect.
|
# => update parent provided registrar contact info
|
||||||
#
|
#
|
||||||
self.reg_addrs = [
|
self.reg_addrs = [
|
||||||
# TODO: we don't really NEED these as tuples?
|
# TODO: we don't really NEED these as tuples?
|
||||||
|
@ -827,12 +852,24 @@ class Actor:
|
||||||
for val in spawnspec.reg_addrs
|
for val in spawnspec.reg_addrs
|
||||||
]
|
]
|
||||||
|
|
||||||
# TODO: better then monkey patching..
|
# `SpawnSpec.enable_modules`
|
||||||
# -[ ] maybe read the actual f#$-in `._spawn_spec` XD
|
# ---------------------
|
||||||
for _, attr, value in pretty_struct.iter_fields(
|
# => extend RPC-python-module (capabilities) with
|
||||||
spawnspec,
|
# those permitted by parent.
|
||||||
):
|
#
|
||||||
setattr(self, attr, value)
|
# NOTE, only the root actor should have
|
||||||
|
# a pre-permitted entry for `.devx.debug._tty_lock`.
|
||||||
|
assert not self.enable_modules
|
||||||
|
self.enable_modules.update(
|
||||||
|
spawnspec.enable_modules
|
||||||
|
)
|
||||||
|
|
||||||
|
self._parent_main_data = spawnspec._parent_main_data
|
||||||
|
# XXX QUESTION(s)^^^
|
||||||
|
# -[ ] already set in `.__init__()` right, but how is
|
||||||
|
# it diff from this blatant parent copy?
|
||||||
|
# -[ ] do we need/want the .__init__() value in
|
||||||
|
# just the root case orr?
|
||||||
|
|
||||||
return (
|
return (
|
||||||
chan,
|
chan,
|
||||||
|
|
Loading…
Reference in New Issue