import inspect from typing import Any, Optional def get_nested_attr( module: ..., attr_path: str, ) -> Any | None: """Loop through nested attributes.""" x = module for attr in attr_path.split("."): x = getattr(x, attr, None) return x def get_callable_names( prefix: str, module: ..., max_depth: int = 3, depth: int = 0, include: Optional[set[str]] = None, ) -> list[str]: """ Recursively retrieve the names of all callables in a given module. """ callable_names = [] if depth > max_depth: return callable_names for attr in dir(module): if ( attr.startswith("_") or attr in {"model_fields", "model_computed_fields"} or include and attr not in include ): continue try: value = getattr(module, attr) except Exception: continue full_name = f"{prefix}.{attr}" if callable(value): callable_names.append(full_name) elif hasattr(value, "__dict__") or hasattr(value, "__module__"): callable_names.extend( get_callable_names( full_name, value, max_depth, depth + 1 ) # Recurse ) return callable_names def get_callable_params( prefix: str, module: ..., callable_name: str ) -> list[dict[str, str]]: """ Get parameter names and default values for a given callable. """ callable = get_nested_attr( module, callable_name.replace(f"{prefix}.", "", 1) ) if not callable: return [] try: sig = inspect.signature(callable) params = [] for name, param in sig.parameters.items(): if name == "self": continue default = ( param.default if param.default is not inspect.Parameter.empty else "" ) kind = param.kind params.append({ "name": name, "default": default, "kind": kind }) return params except Exception: return [] def test_callable( prefix: str, module: ..., callable_name: str, *args, **kwargs ) -> str: """Test a given callable and return the output.""" callable = get_nested_attr( module, callable_name.replace("_", ".").replace(f"{prefix}.", "", 1) ) if not callable: return f"Callable '{callable_name}' not found." try: result = callable(*args, **kwargs) return result except TypeError as e: return f"Callable '{callable_name}' requires arguments: {e}" except Exception as e: return f"Error running '{callable_name}': {e}" def generate_callable_guides(prefix: str, module: ..., callable_names: list[str]) -> list[str]: """ Generate callable reference guides from docstrings, parameters, and parameter/return types. """ guide = [] for callable in callable_names: callable = get_nested_attr(module, callable.replace(f"{prefix}.", "", 1)) doc = callable.__doc__ if callable and hasattr(callable, "__doc__") else "No docstring available." guide.append(f"{doc}") return guide