fix(loaders): render clean signatures, drop unresolvable aliases from models
- Stringify Object.signature() instead of str()-ing the bound method, which produced "<bound method Class.signature of ...>" reprs - Skip alias members that cannot resolve (stdlib/third-party imports) while preserving resolvable package re-exports; return None for empty signatures (classes without __init__ args) - Add MCP renderer regression tests for signature cleanliness, alias filtering, and package re-export preservation
This commit is contained in:
@@ -12,6 +12,8 @@ into doc-forge documentation models.
|
||||
Notes:
|
||||
- All analysis is static; analyzed modules are never executed.
|
||||
- Private members (names starting with `_`) are skipped during conversion.
|
||||
- Imported aliases that cannot be resolved (stdlib/third-party names) are
|
||||
skipped; aliases that resolve within the documented project are kept.
|
||||
|
||||
---
|
||||
"""
|
||||
@@ -232,6 +234,8 @@ class GriffeLoader:
|
||||
for name, member in obj.members.items():
|
||||
if name.startswith("_"):
|
||||
continue
|
||||
if not self._is_resolvable_alias(member):
|
||||
continue
|
||||
|
||||
module.add_object(self._convert_object(member))
|
||||
|
||||
@@ -268,6 +272,8 @@ class GriffeLoader:
|
||||
for name, member in obj.members.items():
|
||||
if name.startswith("_"):
|
||||
continue
|
||||
if not self._is_resolvable_alias(member):
|
||||
continue
|
||||
doc_obj.add_member(self._convert_object(member))
|
||||
except AliasResolutionError:
|
||||
pass
|
||||
@@ -299,17 +305,53 @@ class GriffeLoader:
|
||||
"""
|
||||
Safely extract the signature of a Griffe object.
|
||||
|
||||
Griffe exposes signatures as callables (``Object.signature``); the
|
||||
method is invoked and stringified to produce a clean, stable signature.
|
||||
Aliases that point outside the loaded project fail resolution and are
|
||||
reported as `None`.
|
||||
|
||||
Args:
|
||||
obj (Object):
|
||||
Griffe object to inspect.
|
||||
|
||||
Returns:
|
||||
str | None:
|
||||
String representation of the object's signature if available, otherwise `None`.
|
||||
Clean string representation of the object's signature if
|
||||
available, otherwise `None`.
|
||||
"""
|
||||
try:
|
||||
if hasattr(obj, "signature") and obj.signature:
|
||||
return str(obj.signature)
|
||||
except AliasResolutionError:
|
||||
signature = getattr(obj, "signature", None)
|
||||
if signature is None:
|
||||
return None
|
||||
if callable(signature):
|
||||
signature = signature()
|
||||
if not signature:
|
||||
return None
|
||||
return str(signature).strip() or None
|
||||
except Exception:
|
||||
return None
|
||||
return None
|
||||
|
||||
def _is_resolvable_alias(self, obj: Object) -> bool:
|
||||
"""
|
||||
Report whether an object is a resolvable part of the documented API.
|
||||
|
||||
Aliases that cannot be resolved (stdlib or third-party imports) are
|
||||
treated as noise and excluded from the model. Non-alias objects are
|
||||
always resolvable.
|
||||
|
||||
Args:
|
||||
obj (Object):
|
||||
Griffe object to test.
|
||||
|
||||
Returns:
|
||||
bool:
|
||||
True if the object should be kept, False if it is an
|
||||
unresolvable alias.
|
||||
"""
|
||||
if obj.kind.value != "alias":
|
||||
return True
|
||||
try:
|
||||
_ = obj.canonical_path
|
||||
except AliasResolutionError:
|
||||
return False
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user