chore: 添加虚拟环境到仓库
- 添加 backend_service/venv 虚拟环境 - 包含所有Python依赖包 - 注意:虚拟环境约393MB,包含12655个文件
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
"""Attribute docstrings parsing.
|
||||
|
||||
.. seealso:: https://peps.python.org/pep-0257/#what-is-a-docstring
|
||||
"""
|
||||
|
||||
import ast
|
||||
import inspect
|
||||
import textwrap
|
||||
import typing as T
|
||||
from types import ModuleType
|
||||
|
||||
from .common import Docstring, DocstringParam
|
||||
|
||||
|
||||
def ast_get_constant_value(node: ast.AST) -> T.Any:
|
||||
"""Return the constant's value if the given node is a constant."""
|
||||
return getattr(node, "value")
|
||||
|
||||
|
||||
def ast_unparse(node: ast.AST) -> T.Optional[str]:
|
||||
"""Convert the AST node to source code as a string."""
|
||||
if hasattr(ast, "unparse"):
|
||||
return ast.unparse(node)
|
||||
# Support simple cases in Python < 3.9
|
||||
if isinstance(node, ast.Constant):
|
||||
return str(ast_get_constant_value(node))
|
||||
if isinstance(node, ast.Name):
|
||||
return node.id
|
||||
return None
|
||||
|
||||
|
||||
def ast_is_literal_str(node: ast.AST) -> bool:
|
||||
"""Return True if the given node is a literal string."""
|
||||
return (
|
||||
isinstance(node, ast.Expr)
|
||||
and isinstance(node.value, ast.Constant)
|
||||
and isinstance(ast_get_constant_value(node.value), str)
|
||||
)
|
||||
|
||||
|
||||
def ast_get_attribute(
|
||||
node: ast.AST,
|
||||
) -> T.Optional[T.Tuple[str, T.Optional[str], T.Optional[str]]]:
|
||||
"""Return name, type and default if the given node is an attribute."""
|
||||
if isinstance(node, (ast.Assign, ast.AnnAssign)):
|
||||
target = (
|
||||
node.targets[0] if isinstance(node, ast.Assign) else node.target
|
||||
)
|
||||
if isinstance(target, ast.Name):
|
||||
type_str = None
|
||||
if isinstance(node, ast.AnnAssign):
|
||||
type_str = ast_unparse(node.annotation)
|
||||
default = None
|
||||
if node.value:
|
||||
default = ast_unparse(node.value)
|
||||
return target.id, type_str, default
|
||||
return None
|
||||
|
||||
|
||||
class AttributeDocstrings(ast.NodeVisitor):
|
||||
"""An ast.NodeVisitor that collects attribute docstrings."""
|
||||
|
||||
attr_docs = None
|
||||
prev_attr = None
|
||||
|
||||
def visit(self, node):
|
||||
if self.prev_attr and ast_is_literal_str(node):
|
||||
attr_name, attr_type, attr_default = self.prev_attr
|
||||
self.attr_docs[attr_name] = (
|
||||
ast_get_constant_value(node.value),
|
||||
attr_type,
|
||||
attr_default,
|
||||
)
|
||||
self.prev_attr = ast_get_attribute(node)
|
||||
if isinstance(node, (ast.ClassDef, ast.Module)):
|
||||
self.generic_visit(node)
|
||||
|
||||
def get_attr_docs(
|
||||
self, component: T.Any
|
||||
) -> T.Dict[str, T.Tuple[str, T.Optional[str], T.Optional[str]]]:
|
||||
"""Get attribute docstrings from the given component.
|
||||
|
||||
:param component: component to process (class or module)
|
||||
:returns: for each attribute docstring, a tuple with (description,
|
||||
type, default)
|
||||
"""
|
||||
self.attr_docs = {}
|
||||
self.prev_attr = None
|
||||
try:
|
||||
source = textwrap.dedent(inspect.getsource(component))
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
tree = ast.parse(source)
|
||||
if inspect.ismodule(component):
|
||||
self.visit(tree)
|
||||
elif isinstance(tree, ast.Module) and isinstance(
|
||||
tree.body[0], ast.ClassDef
|
||||
):
|
||||
self.visit(tree.body[0])
|
||||
return self.attr_docs
|
||||
|
||||
|
||||
def add_attribute_docstrings(
|
||||
obj: T.Union[type, ModuleType], docstring: Docstring
|
||||
) -> None:
|
||||
"""Add attribute docstrings found in the object's source code.
|
||||
|
||||
:param obj: object from which to parse attribute docstrings
|
||||
:param docstring: Docstring object where found attributes are added
|
||||
:returns: list with names of added attributes
|
||||
"""
|
||||
params = set(p.arg_name for p in docstring.params)
|
||||
for arg_name, (description, type_name, default) in (
|
||||
AttributeDocstrings().get_attr_docs(obj).items()
|
||||
):
|
||||
if arg_name not in params:
|
||||
param = DocstringParam(
|
||||
args=["attribute", arg_name],
|
||||
description=description,
|
||||
arg_name=arg_name,
|
||||
type_name=type_name,
|
||||
is_optional=default is not None,
|
||||
default=default,
|
||||
)
|
||||
docstring.meta.append(param)
|
||||
Reference in New Issue
Block a user