2026-08-21 05:11:25 +00:00
|
|
|
'''
|
|
|
|
|
Package logger namespace regression tests.
|
|
|
|
|
|
|
|
|
|
'''
|
2026-10-28 17:13:26 +00:00
|
|
|
import logging
|
|
|
|
|
from types import SimpleNamespace
|
|
|
|
|
|
2026-08-21 05:11:25 +00:00
|
|
|
import pytest
|
2026-10-28 17:13:26 +00:00
|
|
|
import trio
|
2026-08-21 05:11:25 +00:00
|
|
|
|
|
|
|
|
from piker.log import (
|
|
|
|
|
get_console_log,
|
|
|
|
|
get_logger,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
'factory',
|
|
|
|
|
[
|
|
|
|
|
get_logger,
|
|
|
|
|
get_console_log,
|
|
|
|
|
],
|
|
|
|
|
)
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
'name',
|
|
|
|
|
[
|
|
|
|
|
'piker.service._daemon',
|
|
|
|
|
'piker.paper',
|
|
|
|
|
],
|
|
|
|
|
)
|
|
|
|
|
def test_package_logger_name(
|
|
|
|
|
factory,
|
|
|
|
|
name: str,
|
|
|
|
|
):
|
|
|
|
|
'''
|
|
|
|
|
`str.lstrip('piker.')` treated the package prefix as a set of
|
|
|
|
|
removable characters. A submodule beginning with any of those
|
|
|
|
|
characters, such as `piker.paper`, was silently renamed to
|
|
|
|
|
`piker.aper`, while service code asserted a stale parent name.
|
|
|
|
|
|
|
|
|
|
Exercise both logger factories with service and prefix-sensitive
|
|
|
|
|
submodule names, proving they retain the exact requested package
|
|
|
|
|
namespace.
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
log = factory(name=name)
|
|
|
|
|
|
|
|
|
|
assert log.name == name
|
2026-10-28 17:13:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_feed_startup_configures_transport_logger(
|
|
|
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
|
|
|
capsys: pytest.CaptureFixture,
|
|
|
|
|
) -> None:
|
|
|
|
|
'''
|
|
|
|
|
Daemon INFO did not enable websocket reconnection diagnostics.
|
|
|
|
|
|
|
|
|
|
Feed startup configured piker.data.feed, but ._util.log and
|
|
|
|
|
._web_bs.log emit on piker.data. Errors fell back to bare stderr
|
|
|
|
|
while connection-success INFO stayed hidden. Client verbosity
|
|
|
|
|
must also not demote that shared actor-wide transport logger.
|
|
|
|
|
|
|
|
|
|
Run production feed startup and logger configuration with an INFO
|
|
|
|
|
actor and ERROR client. Stop at feed-bus lookup before touching
|
|
|
|
|
any provider. Use real logging/console emission, not mocked logger
|
|
|
|
|
methods, to prove INFO from the websocket emitter is visible.
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
from piker.data import feed, _web_bs
|
|
|
|
|
|
|
|
|
|
saved = {}
|
|
|
|
|
for name in ('piker.data', 'piker.data.feed', 'tractor'):
|
|
|
|
|
logger = logging.getLogger(name)
|
|
|
|
|
saved[logger] = (logger.level, list(logger.handlers))
|
|
|
|
|
|
|
|
|
|
boundary = RuntimeError('stop before provider lookup')
|
|
|
|
|
|
|
|
|
|
def stop_at_bus(brokername: str):
|
|
|
|
|
raise boundary
|
|
|
|
|
|
|
|
|
|
monkeypatch.setattr(
|
|
|
|
|
feed.tractor,
|
|
|
|
|
'current_actor',
|
|
|
|
|
lambda **kwargs: SimpleNamespace(
|
|
|
|
|
name='brokerd.binance', loglevel='info',
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
monkeypatch.setattr(feed, 'get_feed_bus', stop_at_bus)
|
|
|
|
|
|
|
|
|
|
async def main() -> None:
|
|
|
|
|
with pytest.raises(RuntimeError) as caught:
|
|
|
|
|
await feed.open_feed_bus(
|
|
|
|
|
ctx=None, brokername='binance', symbols=[],
|
|
|
|
|
loglevel='error',
|
|
|
|
|
)
|
|
|
|
|
assert caught.value is boundary
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
logging.getLogger('piker.data').setLevel(logging.WARNING)
|
|
|
|
|
trio.run(main)
|
|
|
|
|
assert _web_bs.log.isEnabledFor(logging.INFO)
|
|
|
|
|
_web_bs.log.info('websocket INFO visibility probe')
|
|
|
|
|
assert 'websocket INFO visibility probe' in (
|
|
|
|
|
capsys.readouterr().err
|
|
|
|
|
)
|
|
|
|
|
finally:
|
|
|
|
|
for logger, (level, handlers) in saved.items():
|
|
|
|
|
for handler in list(logger.handlers):
|
|
|
|
|
if handler not in handlers:
|
|
|
|
|
logger.removeHandler(handler)
|
|
|
|
|
handler.close()
|
|
|
|
|
logger.setLevel(level)
|