""" The node's source text, for the tests that have to read it. A test that reads source to prove something is *absent* โ€” no bare `ensure_future`, no exception text sent to a peer, no GEK unwrapped over MNP โ€” goes on passing when the code it guards moves to another file: it simply stops looking at that code. So every such test takes its text from here, and the 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 SRC = Path(__file__).resolve().parents[1] / "src" / "meshbay_node" TRANSPORT = SRC / "transport" # The WebRTC transport is `webrtc_server.py` and whatever has been split out of # it into `transport/webrtc/`. The other modules beside them are not part of it # and are not held to its rules by these tests: QUIC is a transport of its own # and not at parity (docs/MESHBAY_DESIGN.md ยง15.3), and `wire.py`, `tls_cert.py` # and the ICE helpers serve both or neither. WEBRTC_PACKAGE = TRANSPORT / "webrtc" def webrtc_files() -> list[Path]: """Every module of the WebRTC transport, however it is split up.""" files = [TRANSPORT / "webrtc_server.py"] if WEBRTC_PACKAGE.is_dir(): files += sorted(p for p in WEBRTC_PACKAGE.rglob("*.py") if "__pycache__" not in p.parts) return files def webrtc_source() -> str: return "\n".join(p.read_text(encoding="utf-8") for p in webrtc_files()) def session_source() -> str: """The body of WebRTCPeerSession, including every class it is built from.""" from meshbay_node.transport.webrtc_server import WebRTCPeerSession return "\n".join(inspect.getsource(k) for k in WebRTCPeerSession.__mro__ if k.__module__.startswith("meshbay_node.")) def session_method(name: str) -> str: """One method of WebRTCPeerSession, wherever it is defined.""" 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] # `ops.py`, or the package it becomes: every file of it either way. OPS_PACKAGE = SRC / "ops" def ops_files() -> list[Path]: """Every module of the operations layer, however it is split up.""" files = [SRC / "ops.py"] if (SRC / "ops.py").exists() else [] if OPS_PACKAGE.is_dir(): files += sorted(p for p in OPS_PACKAGE.rglob("*.py") if "__pycache__" not in p.parts) return files def ops_source() -> str: return "\n".join(p.read_text(encoding="utf-8") for p in ops_files())