diff --git a/cldk/analysis/python/backend.py b/cldk/analysis/python/backend.py index c0c64ad..8911e5e 100644 --- a/cldk/analysis/python/backend.py +++ b/cldk/analysis/python/backend.py @@ -156,7 +156,8 @@ def get_callables_overview(self) -> List[PyCallableOverview]: @abstractmethod def get_method_bodies(self, signatures: List[str]) -> Dict[str, str]: """Source bodies for the given callable signatures, keyed by signature. Signatures with no - matching callable are omitted.""" + matching callable are omitted, as are callables whose ``code`` is ``None`` (e.g. synthesized + callables the analyzer emits with no source text) — every returned value is a real ``str``.""" @abstractmethod def get_decorated_callables(self, markers: List[str]) -> List[PyCallableOverview]: diff --git a/cldk/analysis/python/codeanalyzer/codeanalyzer.py b/cldk/analysis/python/codeanalyzer/codeanalyzer.py index 8ddaced..fead2f5 100644 --- a/cldk/analysis/python/codeanalyzer/codeanalyzer.py +++ b/cldk/analysis/python/codeanalyzer/codeanalyzer.py @@ -583,9 +583,10 @@ def get_callables_overview(self) -> List[PyCallableOverview]: return [_overview(c, class_sig, kind) for c, class_sig, kind in self._iter_callables()] def get_method_bodies(self, signatures: List[str]) -> Dict[str, str]: - """Return ``{signature: code}`` for the requested signatures that exist.""" + """Return ``{signature: code}`` for the requested signatures that exist and have a body + (omits callables whose ``code`` is ``None``).""" wanted = set(signatures) - return {c.signature: c.code for c, _, _ in self._iter_callables() if c.signature in wanted} + return {c.signature: c.code for c, _, _ in self._iter_callables() if c.signature in wanted and c.code is not None} def get_decorated_callables(self, markers: List[str]) -> List[PyCallableOverview]: """Return overviews of callables decorated with any of ``markers``.""" diff --git a/cldk/analysis/python/neo4j/neo4j_backend.py b/cldk/analysis/python/neo4j/neo4j_backend.py index e01e817..455ba36 100644 --- a/cldk/analysis/python/neo4j/neo4j_backend.py +++ b/cldk/analysis/python/neo4j/neo4j_backend.py @@ -498,12 +498,12 @@ def get_callables_overview(self) -> List[PyCallableOverview]: def get_method_bodies(self, signatures: List[str]) -> Dict[str, str]: rows = self._run( - "MATCH (c:PyCallable) WHERE c._module IN $mods AND c.signature IN $sigs " + "MATCH (c:PyCallable) WHERE c._module IN $mods AND c.signature IN $sigs AND c.code IS NOT NULL " "RETURN c.signature AS signature, c.code AS code", mods=self._modules, sigs=list(signatures), ) - return {r["signature"]: r.get("code") for r in rows} + return {r["signature"]: r["code"] for r in rows} def get_decorated_callables(self, markers: List[str]) -> List[PyCallableOverview]: rows = self._run( diff --git a/cldk/analysis/python/python_analysis.py b/cldk/analysis/python/python_analysis.py index 3262309..233ad2a 100644 --- a/cldk/analysis/python/python_analysis.py +++ b/cldk/analysis/python/python_analysis.py @@ -552,7 +552,8 @@ def get_method_bodies(self, signatures: List[str]) -> Dict[str, str]: Returns: A dict mapping each signature to its source body. Signatures with no matching callable - are omitted. + are omitted, as are callables whose ``code`` is ``None`` — every returned value is a + real ``str``. """ return self.backend.get_method_bodies(signatures)