Retain dynamic logger caller discovery
Keep the `sys.modules` lookup as the normal fast path, then use `inspect.getmodule()` for unregistered `runpy`, plugin, and `exec()` namespaces. Cover an unregistered module name backed by a real package file and verify implicit logger naming still resolves to that package. Review: PR #478 (goodboy) https://github.com/goodboy/tractor/pull/478#pullrequestreview-4922213201 (this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))wkt/pr478_review
parent
7987f6b8d7
commit
089e158da9
|
|
@ -2,9 +2,11 @@
|
|||
`tractor.log`-wrapping unit tests.
|
||||
|
||||
'''
|
||||
import importlib
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import sys
|
||||
from types import ModuleType
|
||||
|
||||
import pytest
|
||||
|
|
@ -165,6 +167,53 @@ def test_implicit_mod_name_applied_for_child(
|
|||
assert submod.log.logger in sub_logs
|
||||
|
||||
|
||||
def test_implicit_mod_name_from_unregistered_namespace(
|
||||
tmp_path: Path,
|
||||
):
|
||||
'''
|
||||
Preserve implicit logger naming for dynamic module namespaces.
|
||||
|
||||
The fast `sys.modules` caller lookup cannot resolve `runpy`,
|
||||
plugin-loader, or `exec()` namespaces that are not registered.
|
||||
Compile a real package file under an unregistered module name so
|
||||
the rare filename fallback must recover its imported package and
|
||||
retain the same package-level logger name.
|
||||
|
||||
'''
|
||||
pkg_name = 'dynamic_logger_pkg'
|
||||
pkg_dir = tmp_path / pkg_name
|
||||
pkg_dir.mkdir()
|
||||
init_path = pkg_dir / '__init__.py'
|
||||
init_path.write_text('')
|
||||
mod_path = pkg_dir / 'plugin.py'
|
||||
mod_path.write_text('')
|
||||
|
||||
sys.path.insert(0, str(tmp_path))
|
||||
try:
|
||||
importlib.import_module(pkg_name)
|
||||
namespace = {
|
||||
'__name__': f'{pkg_name}.unregistered',
|
||||
'__package__': pkg_name,
|
||||
'tractor': tractor,
|
||||
}
|
||||
exec(
|
||||
compile(
|
||||
'log = tractor.log.get_logger('
|
||||
f'pkg_name={pkg_name!r})',
|
||||
str(mod_path),
|
||||
'exec',
|
||||
),
|
||||
namespace,
|
||||
)
|
||||
dynamic_log = namespace.get('log')
|
||||
finally:
|
||||
sys.path.remove(str(tmp_path))
|
||||
sys.modules.pop(pkg_name, None)
|
||||
|
||||
assert dynamic_log is not None
|
||||
assert dynamic_log.name == pkg_name
|
||||
|
||||
|
||||
def test_io_custom_level_registered():
|
||||
'''
|
||||
The `IO`(21) level (registered via `add_log_level()` at
|
||||
|
|
|
|||
|
|
@ -463,7 +463,14 @@ def get_logger(
|
|||
if mod_name is None:
|
||||
return None
|
||||
|
||||
return sys.modules.get(mod_name)
|
||||
if caller_mod := sys.modules.get(mod_name):
|
||||
return caller_mod
|
||||
|
||||
# Preserve caller discovery for `runpy`, plugin loaders,
|
||||
# and `exec()` namespaces not registered in `sys.modules`.
|
||||
# Import `inspect` only on this rare fallback path.
|
||||
from inspect import getmodule
|
||||
return getmodule(caller_frame)
|
||||
|
||||
# --- Auto--naming-CASE ---
|
||||
# -------------------------
|
||||
|
|
|
|||
Loading…
Reference in New Issue