From ef942b93d1e9bfc28bf607dfaf501cc7d9685e7b Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Thu, 24 Sep 2026 17:42:10 +0200 Subject: test(node): read the daemon's source wherever it is split Tests that read daemon.py now take their text from node_source (daemon.py, NodeDaemon's bases, the cli package once it exists). The CLI tests that sliced main() run the CLI instead. Co-Authored-By: Claude Opus 5.5 --- packages/meshbay-node/tests/node_source.py | 59 ++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'packages/meshbay-node/tests/node_source.py') diff --git a/packages/meshbay-node/tests/node_source.py b/packages/meshbay-node/tests/node_source.py index df63773..918cf05 100644 --- a/packages/meshbay-node/tests/node_source.py +++ b/packages/meshbay-node/tests/node_source.py @@ -9,6 +9,7 @@ file sets below are derived from the tree rather than listed, so that a module added later is read without anybody having to remember it. """ +import ast import inspect import textwrap from pathlib import Path @@ -50,3 +51,61 @@ def session_method(name: str) -> str: from meshbay_node.transport.webrtc_server import WebRTCPeerSession return textwrap.dedent(inspect.getsource(getattr(WebRTCPeerSession, name))) + + +# The daemon is `daemon.py`, every class NodeDaemon is built from, and the CLI +# once `main()` is split out into a package of its own. +CLI_PACKAGE = SRC / "cli" + + +def daemon_files() -> list[Path]: + """Every module of the daemon and its CLI, however they are split up.""" + from meshbay_node.daemon import NodeDaemon + + files = [SRC / "daemon.py"] + for klass in NodeDaemon.__mro__: + if klass.__module__.startswith("meshbay_node."): + where = Path(inspect.getsourcefile(klass)).resolve() + if where not in files: + files.append(where) + if CLI_PACKAGE.is_dir(): + files += sorted(p for p in CLI_PACKAGE.rglob("*.py") + if "__pycache__" not in p.parts) + return files + + +def daemon_source() -> str: + return "\n".join(p.read_text(encoding="utf-8") for p in daemon_files()) + + +def daemon_class_source() -> str: + """The body of NodeDaemon, including every class it is built from.""" + from meshbay_node.daemon import NodeDaemon + + return "\n".join(inspect.getsource(k) for k in NodeDaemon.__mro__ + if k.__module__.startswith("meshbay_node.")) + + +def cli_source() -> str: + """`meshbay-node`'s entry point and whatever it hands the work to.""" + from meshbay_node import daemon + + files = [] + if CLI_PACKAGE.is_dir(): + files = sorted(p for p in CLI_PACKAGE.rglob("*.py") + if "__pycache__" not in p.parts) + return "\n".join([inspect.getsource(daemon.main)] + + [p.read_text(encoding="utf-8") for p in files]) + + +def daemon_call(name: str) -> str: + """The one call to `name(...)` in the daemon, found by name, not position.""" + found = [] + for path in daemon_files(): + text = path.read_text(encoding="utf-8") + for node in ast.walk(ast.parse(text)): + if (isinstance(node, ast.Call) + and getattr(node.func, "id", getattr(node.func, "attr", None)) == name): + found.append(ast.get_source_segment(text, node)) + assert len(found) == 1, f"{len(found)} calls to {name} in the daemon — re-read this test" + return found[0] -- cgit v1.2.3