Files
codex-bot a64378956a
Some checks failed
Pre-commit / run (ubuntu-latest) (push) Has been cancelled
Deploy Sphinx documentation to Pages / build_en (ubuntu-latest, 3.10) (push) Has been cancelled
Deploy Sphinx documentation to Pages / build_zh (ubuntu-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.12) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.12) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.12) (push) Has been cancelled
chore: initialize sandbox and overwrite remote content
2026-03-02 22:32:27 +08:00

307 lines
9.7 KiB
Python

# -*- coding: utf-8 -*-
# pylint: skip-file
"""Get the signatures of functions and classes in the agentscope library."""
from typing import Literal, Callable
import agentscope
import inspect
from pydantic import BaseModel
def get_class_signature(cls: type) -> str:
"""Get the signature of a class.
Args:
cls (`type`):
A class object.
Returns:
str: The signature of the class.
"""
# Obtain class name and docstring
class_name = cls.__name__
class_docstring = cls.__doc__ or ""
# Construct the class string
class_str = f"class {class_name}:\n"
if class_docstring:
class_str += f' """{class_docstring}"""\n'
# Obtain the module of the class
methods = []
for name, method in inspect.getmembers(cls, predicate=inspect.isfunction):
# Skip methods that are not part of the class
if method.__qualname__.split(".")[0] != class_name:
continue
if name.startswith("_") and name not in ["__init__", "__call__"]:
continue
# Obtain the method's signature
sig = inspect.signature(method)
# Construct the method string
method_str = f" def {name}{sig}:\n"
# Add the method's docstring if it exists
method_docstring = method.__doc__ or ""
if method_docstring:
method_str += f' """{method_docstring}"""\n'
methods.append(method_str)
class_str += "\n".join(methods)
return class_str
def get_function_signature(func: Callable) -> str:
"""Get the signature of a function."""
sig = inspect.signature(func)
method_str = f"def {func.__name__}{sig}:\n"
method_docstring = func.__doc__ or ""
if method_docstring:
method_str += f' """{method_docstring}"""\n'
return method_str
class FuncOrCls(BaseModel):
"""The class records the module, signature, docstring, reference, and
type"""
module: str
"""The module of the function or class."""
signature: str
"""The signature of the function or class."""
docstring: str
"""The docstring of the function or class."""
reference: str
"""The reference to the source code of the function or class"""
type: Literal["function", "class"]
"""The type of the function or class, either 'function' or 'class'."""
def __init__(
self,
module: str,
signature: str,
docstring: str,
reference: str,
# pylint: disable=redefined-builtin
type: Literal["function", "class"],
) -> None:
"""Initialize the FuncOrCls instance."""
super().__init__(
module=module,
signature=signature.strip(),
docstring=docstring.strip(),
reference=reference,
type=type,
)
def _truncate_docstring(docstring: str, max_length: int = 200) -> str:
"""Truncate the docstring to a maximum length.
Args:
docstring (`str`):
The docstring to truncate.
max_length (`int`, *optional*, defaults to 200):
The maximum length of the docstring.
Returns:
`str`:
The truncated docstring.
"""
if len(docstring) > max_length:
return docstring[:max_length] + "..."
return docstring
def get_agentscope_module_signatures() -> list[FuncOrCls]:
"""Get the signatures of functions and classes in the agentscope library.
Returns:
`list[FuncOrCls]`:
A list of FuncOrCls instances representing the functions and
classes in the agentscope library.
"""
signatures = []
for module in agentscope.__all__:
as_module = getattr(agentscope, module)
path_module = ".".join(["agentscope", module])
# Functions
if inspect.isfunction(as_module):
file = inspect.getfile(as_module)
source_lines, start_line = inspect.getsourcelines(as_module)
signatures.append(
FuncOrCls(
module=path_module,
signature=get_function_signature(as_module),
docstring=_truncate_docstring(as_module.__doc__ or ""),
reference=f"{file}: {start_line}-"
f"{start_line + len(source_lines)}",
type="function",
),
)
else:
if not hasattr(as_module, "__all__"):
continue
# Modules with __all__ attribute
for name in as_module.__all__:
func_or_cls = getattr(as_module, name)
path_func_or_cls = ".".join([path_module, name])
if inspect.isclass(func_or_cls):
file = inspect.getfile(func_or_cls)
source_lines, start_line = inspect.getsourcelines(
func_or_cls,
)
signatures.append(
FuncOrCls(
module=path_func_or_cls,
signature=get_class_signature(func_or_cls),
docstring=_truncate_docstring(
func_or_cls.__doc__ or "",
),
reference=(
f"{file}: {start_line}-"
f"{start_line + len(source_lines)}"
),
type="class",
),
)
elif inspect.isfunction(func_or_cls):
file = inspect.getfile(func_or_cls)
source_lines, start_line = inspect.getsourcelines(
func_or_cls,
)
signatures.append(
FuncOrCls(
module=path_func_or_cls,
signature=get_function_signature(func_or_cls),
docstring=_truncate_docstring(
func_or_cls.__doc__ or "",
),
reference=(
f"{file}: {start_line}-"
f"{start_line + len(source_lines)}"
),
type="function",
),
)
return signatures
def view_agentscope_library(
module: str,
) -> str:
"""View AgentScope's Python library by given a module name
(e.g. agentscope), and return the module's submodules, classes, and
functions. Given a class name, return the class's documentation, methods,
and their signatures. Given a function name, return the function's
documentation and signature. If you don't have any information about
AgentScope library, try to use "agentscope" to view the available top
modules.
Note this function only provide the module's brief information.
For more information, you should view the source code.
Args:
module (`str`):
The module name to view, which should be a module path separated
by dots (e.g. "agentscope.models"). It can refer to a module,
a class, or a function.
"""
if not module.startswith("agentscope"):
return (
f"Module '{module}' is invalid. The input module should be "
f"'agentscope' or submodule of 'agentscope.xxx.xxx' "
f"(separated by dots)."
)
agentscope_top_modules = {}
for as_module in agentscope.__all__:
if as_module in ["__version__", "logger"]:
continue
agentscope_top_modules[as_module] = getattr(
agentscope,
as_module,
).__doc__
# top modules
if module == "agentscope":
top_modules_description = (
[
"The top-level modules in AgentScope library:",
]
+ [
f"- agentscope.{k}: {v}"
for k, v in agentscope_top_modules.items()
]
+ [
"You can further view the classes/function within above "
"modules by calling this function with the above module name.",
]
)
return "\n".join(top_modules_description)
# class, functions
modules = get_agentscope_module_signatures()
for as_module in modules:
if as_module.module == module:
return f"""- The signature of '{module}':
```python
{as_module.signature}
```
- Source code reference: {as_module.reference}"""
# two-level modules
collected_modules = []
for as_module in modules:
if as_module.module.startswith(module):
collected_modules.append(as_module)
if len(collected_modules) > 0:
collected_modules_content = (
[
f"The classes/functions and their truncated docstring in "
f"'{module}' module:",
]
+ [f"- {_.module}: {repr(_.docstring)}" for _ in collected_modules]
+ [
"The docstring is truncated for limited context. For detailed "
"signature and methods, call this function with the above "
"module name",
]
)
return "\n".join(collected_modules_content)
return (
f"Module '{module}' not found. Use 'agentscope' to view the "
f"top-level modules to ensure the given module is valid."
)
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"--module",
type=str,
default="agentscope",
help="The module name to view, e.g. 'agentscope'",
)
args = parser.parse_args()
res = view_agentscope_library(module=args.module)
print(res)