Compare commits
4 Commits
b461b94f05
...
7f602db50d
| Author | SHA1 | Date |
|---|---|---|
|
|
7f602db50d | |
|
|
c79a4a0bf6 | |
|
|
84af2b8535 | |
|
|
5850844297 |
|
|
@ -4,6 +4,7 @@
|
||||||
'''
|
'''
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import shutil
|
import shutil
|
||||||
|
from types import ModuleType
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import tractor
|
import tractor
|
||||||
|
|
@ -57,28 +58,32 @@ def test_implicit_mod_name_applied_for_child(
|
||||||
mod_code: str = (
|
mod_code: str = (
|
||||||
f'import tractor\n'
|
f'import tractor\n'
|
||||||
f'\n'
|
f'\n'
|
||||||
# f'breakpoint()\n' # if you want to trace it all
|
# if you need to trace `testdir` stuff @ import-time..
|
||||||
|
# f'breakpoint()\n'
|
||||||
f'log = tractor.log.get_logger(pkg_name="{proj_name}")\n'
|
f'log = tractor.log.get_logger(pkg_name="{proj_name}")\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
# create a sub-module for each pkg layer
|
# create a sub-module for each pkg layer
|
||||||
_lib = testdir.mkpydir(proj_name)
|
_lib = testdir.mkpydir(proj_name)
|
||||||
pkg: Path = Path(_lib)
|
pkg: Path = Path(_lib)
|
||||||
|
pkg_init_mod: Path = pkg / "__init__.py"
|
||||||
|
pkg_init_mod.write_text(mod_code)
|
||||||
|
|
||||||
subpkg: Path = pkg / 'subpkg'
|
subpkg: Path = pkg / 'subpkg'
|
||||||
subpkg.mkdir()
|
subpkg.mkdir()
|
||||||
|
subpkgmod: Path = subpkg / "__init__.py"
|
||||||
pkgmod: Path = subpkg / "__init__.py"
|
subpkgmod.touch()
|
||||||
pkgmod.touch()
|
subpkgmod.write_text(mod_code)
|
||||||
|
|
||||||
_submod: Path = testdir.makepyfile(
|
_submod: Path = testdir.makepyfile(
|
||||||
_mod=mod_code,
|
_mod=mod_code,
|
||||||
)
|
)
|
||||||
|
|
||||||
pkg_mod = pkg / 'mod.py'
|
pkg_submod = pkg / 'mod.py'
|
||||||
pkg_subpkg_submod = subpkg / 'submod.py'
|
pkg_subpkg_submod = subpkg / 'submod.py'
|
||||||
shutil.copyfile(
|
shutil.copyfile(
|
||||||
_submod,
|
_submod,
|
||||||
pkg_mod,
|
pkg_submod,
|
||||||
)
|
)
|
||||||
shutil.copyfile(
|
shutil.copyfile(
|
||||||
_submod,
|
_submod,
|
||||||
|
|
@ -91,10 +96,11 @@ def test_implicit_mod_name_applied_for_child(
|
||||||
# XXX NOTE, once the "top level" pkg mod has been
|
# XXX NOTE, once the "top level" pkg mod has been
|
||||||
# imported, we can then use `import` syntax to
|
# imported, we can then use `import` syntax to
|
||||||
# import it's sub-pkgs and modules.
|
# import it's sub-pkgs and modules.
|
||||||
pkgmod = _code_load.load_module_from_path(
|
subpkgmod: ModuleType = _code_load.load_module_from_path(
|
||||||
Path(pkg / '__init__.py'),
|
Path(pkg / '__init__.py'),
|
||||||
module_name=proj_name,
|
module_name=proj_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
pkg_root_log = log.get_logger(
|
pkg_root_log = log.get_logger(
|
||||||
pkg_name=proj_name,
|
pkg_name=proj_name,
|
||||||
mk_sublog=False,
|
mk_sublog=False,
|
||||||
|
|
@ -107,16 +113,31 @@ def test_implicit_mod_name_applied_for_child(
|
||||||
# ^TODO! test this same output but created via a `get_logger()`
|
# ^TODO! test this same output but created via a `get_logger()`
|
||||||
# call in the `snakelib.__init__py`!!
|
# call in the `snakelib.__init__py`!!
|
||||||
|
|
||||||
# a first-pkg-level module should only
|
# NOTE, the pkg-level "init mod" should of course
|
||||||
# use
|
# have the same name as the package ns-path.
|
||||||
|
import snakelib as init_mod
|
||||||
|
assert init_mod.log.name == proj_name
|
||||||
|
|
||||||
|
# NOTE, a first-pkg-level sub-module should only
|
||||||
|
# use the package-name since the leaf-node-module
|
||||||
|
# will be included in log headers by default.
|
||||||
from snakelib import mod
|
from snakelib import mod
|
||||||
assert mod.log.name == proj_name
|
assert mod.log.name == proj_name
|
||||||
|
|
||||||
|
from snakelib import subpkg
|
||||||
|
assert (
|
||||||
|
subpkg.log.name
|
||||||
|
==
|
||||||
|
subpkg.__package__
|
||||||
|
==
|
||||||
|
f'{proj_name}.subpkg'
|
||||||
|
)
|
||||||
|
|
||||||
from snakelib.subpkg import submod
|
from snakelib.subpkg import submod
|
||||||
assert (
|
assert (
|
||||||
submod.log.name
|
submod.log.name
|
||||||
==
|
==
|
||||||
submod.__package__ # ?TODO, use this in `.get_logger()` instead?
|
submod.__package__
|
||||||
==
|
==
|
||||||
f'{proj_name}.subpkg'
|
f'{proj_name}.subpkg'
|
||||||
)
|
)
|
||||||
|
|
@ -125,8 +146,6 @@ def test_implicit_mod_name_applied_for_child(
|
||||||
assert len(sub_logs) == 1 # only one nested sub-pkg module
|
assert len(sub_logs) == 1 # only one nested sub-pkg module
|
||||||
assert submod.log.logger in sub_logs
|
assert submod.log.logger in sub_logs
|
||||||
|
|
||||||
# breakpoint()
|
|
||||||
|
|
||||||
|
|
||||||
# TODO, moar tests against existing feats:
|
# TODO, moar tests against existing feats:
|
||||||
# ------ - ------
|
# ------ - ------
|
||||||
|
|
|
||||||
|
|
@ -284,6 +284,10 @@ async def _errors_relayed_via_ipc(
|
||||||
try:
|
try:
|
||||||
yield # run RPC invoke body
|
yield # run RPC invoke body
|
||||||
|
|
||||||
|
except TransportClosed:
|
||||||
|
log.exception('Tpt disconnect during remote-exc relay?')
|
||||||
|
raise
|
||||||
|
|
||||||
# box and ship RPC errors for wire-transit via
|
# box and ship RPC errors for wire-transit via
|
||||||
# the task's requesting parent IPC-channel.
|
# the task's requesting parent IPC-channel.
|
||||||
except (
|
except (
|
||||||
|
|
@ -319,6 +323,9 @@ async def _errors_relayed_via_ipc(
|
||||||
and debug_kbis
|
and debug_kbis
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
# TODO? better then `debug_filter` below?
|
||||||
|
and
|
||||||
|
not isinstance(err, TransportClosed)
|
||||||
):
|
):
|
||||||
# XXX QUESTION XXX: is there any case where we'll
|
# XXX QUESTION XXX: is there any case where we'll
|
||||||
# want to debug IPC disconnects as a default?
|
# want to debug IPC disconnects as a default?
|
||||||
|
|
@ -327,13 +334,25 @@ async def _errors_relayed_via_ipc(
|
||||||
# recovery logic - the only case is some kind of
|
# recovery logic - the only case is some kind of
|
||||||
# strange bug in our transport layer itself? Going
|
# strange bug in our transport layer itself? Going
|
||||||
# to keep this open ended for now.
|
# to keep this open ended for now.
|
||||||
log.debug(
|
|
||||||
'RPC task crashed, attempting to enter debugger\n'
|
if _state.debug_mode():
|
||||||
f'|_{ctx}'
|
log.exception(
|
||||||
)
|
f'RPC task crashed!\n'
|
||||||
|
f'Attempting to enter debugger\n'
|
||||||
|
f'\n'
|
||||||
|
f'{ctx}'
|
||||||
|
)
|
||||||
|
|
||||||
entered_debug = await debug._maybe_enter_pm(
|
entered_debug = await debug._maybe_enter_pm(
|
||||||
err,
|
err,
|
||||||
api_frame=inspect.currentframe(),
|
api_frame=inspect.currentframe(),
|
||||||
|
|
||||||
|
# don't REPL any psuedo-expected tpt-disconnect
|
||||||
|
# debug_filter=lambda exc: (
|
||||||
|
# type (exc) not in {
|
||||||
|
# TransportClosed,
|
||||||
|
# }
|
||||||
|
# ),
|
||||||
)
|
)
|
||||||
if not entered_debug:
|
if not entered_debug:
|
||||||
# if we prolly should have entered the REPL but
|
# if we prolly should have entered the REPL but
|
||||||
|
|
@ -450,7 +469,7 @@ async def _invoke(
|
||||||
kwargs: dict[str, Any],
|
kwargs: dict[str, Any],
|
||||||
|
|
||||||
is_rpc: bool = True,
|
is_rpc: bool = True,
|
||||||
hide_tb: bool = True,
|
hide_tb: bool = False,
|
||||||
return_msg_type: Return|CancelAck = Return,
|
return_msg_type: Return|CancelAck = Return,
|
||||||
|
|
||||||
task_status: TaskStatus[
|
task_status: TaskStatus[
|
||||||
|
|
@ -675,6 +694,22 @@ async def _invoke(
|
||||||
f'{pretty_struct.pformat(return_msg)}\n'
|
f'{pretty_struct.pformat(return_msg)}\n'
|
||||||
)
|
)
|
||||||
await chan.send(return_msg)
|
await chan.send(return_msg)
|
||||||
|
# ?TODO, remove the below since .send() already
|
||||||
|
# doesn't raise on tpt-closed?
|
||||||
|
# try:
|
||||||
|
# await chan.send(return_msg)
|
||||||
|
# except TransportClosed:
|
||||||
|
# log.exception(
|
||||||
|
# f"Failed send final result to 'parent'-side of IPC-ctx!\n"
|
||||||
|
# f'\n'
|
||||||
|
# f'{chan}\n'
|
||||||
|
# f'Channel already disconnected ??\n'
|
||||||
|
# f'\n'
|
||||||
|
# f'{pretty_struct.pformat(return_msg)}'
|
||||||
|
# )
|
||||||
|
# # ?TODO? will this ever be true though?
|
||||||
|
# if chan.connected():
|
||||||
|
# raise
|
||||||
|
|
||||||
# NOTE: this happens IFF `ctx._scope.cancel()` is
|
# NOTE: this happens IFF `ctx._scope.cancel()` is
|
||||||
# called by any of,
|
# called by any of,
|
||||||
|
|
|
||||||
|
|
@ -459,21 +459,23 @@ class MsgpackTransport(MsgTransport):
|
||||||
)
|
)
|
||||||
raise tpt_closed from trans_err
|
raise tpt_closed from trans_err
|
||||||
|
|
||||||
# case trio.ClosedResourceError() if (
|
# ??TODO??, what case in piker does this and HOW
|
||||||
# 'this socket was already closed'
|
# CAN WE RE-PRODUCE IT?!?!?
|
||||||
# in
|
case trio.ClosedResourceError() if (
|
||||||
# trans_err.args[0]
|
'this socket was already closed'
|
||||||
# ):
|
in
|
||||||
# tpt_closed = TransportClosed.from_src_exc(
|
trans_err.args[0]
|
||||||
# message=(
|
):
|
||||||
# f'{tpt_name} already closed by peer\n'
|
tpt_closed = TransportClosed.from_src_exc(
|
||||||
# ),
|
message=(
|
||||||
# body=f'{self}\n',
|
f'{tpt_name} already closed by peer\n'
|
||||||
# src_exc=trans_err,
|
),
|
||||||
# raise_on_report=True,
|
body=f'{self}\n',
|
||||||
# loglevel='transport',
|
src_exc=trans_err,
|
||||||
# )
|
raise_on_report=True,
|
||||||
# raise tpt_closed from trans_err
|
loglevel='transport',
|
||||||
|
)
|
||||||
|
raise tpt_closed from trans_err
|
||||||
|
|
||||||
# unless the disconnect condition falls under "a
|
# unless the disconnect condition falls under "a
|
||||||
# normal operation breakage" we usualy console warn
|
# normal operation breakage" we usualy console warn
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue