__ __ __ __ _____ _ _ _____ _ _ _ | \/ | \ \ / / | __ \ (_) | | / ____| | | | | | \ / |_ __\ V / | |__) | __ ___ ____ _| |_ ___ | (___ | |__ ___| | | | |\/| | '__|> < | ___/ '__| \ \ / / _` | __/ _ \ \___ \| '_ \ / _ \ | | | | | | |_ / . \ | | | | | |\ V / (_| | || __/ ____) | | | | __/ | | |_| |_|_(_)_/ \_\ |_| |_| |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1 if you need WebShell for Seo everyday contact me on Telegram Telegram Address : @jackleetFor_More_Tools:
"""Utilities related to attribute docstring extraction."""
from __future__ import annotations
import ast
import inspect
import textwrap
from typing import Any
class DocstringVisitor(ast.NodeVisitor):
def __init__(self) -> None:
super().__init__()
self.target: str | None = None
self.attrs: dict[str, str] = {}
self.previous_node_type: type[ast.AST] | None = None
def visit(self, node: ast.AST) -> Any:
node_result = super().visit(node)
self.previous_node_type = type(node)
return node_result
def visit_AnnAssign(self, node: ast.AnnAssign) -> Any:
if isinstance(node.target, ast.Name):
self.target = node.target.id
def visit_Expr(self, node: ast.Expr) -> Any:
if (
isinstance(node.value, ast.Constant)
and isinstance(node.value.value, str)
and self.previous_node_type is ast.AnnAssign
):
docstring = inspect.cleandoc(node.value.value)
if self.target:
self.attrs[self.target] = docstring
self.target = None
def _dedent_source_lines(source: list[str]) -> str:
# Required for nested class definitions, e.g. in a function block
dedent_source = textwrap.dedent(''.join(source))
if dedent_source.startswith((' ', '\t')):
# We are in the case where there's a dedented (usually multiline) string
# at a lower indentation level than the class itself. We wrap our class
# in a function as a workaround.
dedent_source = f'def dedent_workaround():\n{dedent_source}'
return dedent_source
def _extract_source_from_frame(cls: type[Any]) -> list[str] | None:
frame = inspect.currentframe()
while frame:
if inspect.getmodule(frame) is inspect.getmodule(cls):
lnum = frame.f_lineno
try:
lines, _ = inspect.findsource(frame)
except OSError:
# Source can't be retrieved (maybe because running in an interactive terminal),
# we don't want to error here.
pass
else:
block_lines = inspect.getblock(lines[lnum - 1 :])
dedent_source = _dedent_source_lines(block_lines)
try:
block_tree = ast.parse(dedent_source)
except SyntaxError:
pass
else:
stmt = block_tree.body[0]
if isinstance(stmt, ast.FunctionDef) and stmt.name == 'dedent_workaround':
# `_dedent_source_lines` wrapped the class around the workaround function
stmt = stmt.body[0]
if isinstance(stmt, ast.ClassDef) and stmt.name == cls.__name__:
return block_lines
frame = frame.f_back
def extract_docstrings_from_cls(cls: type[Any], use_inspect: bool = False) -> dict[str, str]:
"""Map model attributes and their corresponding docstring.
Args:
cls: The class of the Pydantic model to inspect.
use_inspect: Whether to skip usage of frames to find the object and use
the `inspect` module instead.
Returns:
A mapping containing attribute names and their corresponding docstring.
"""
if use_inspect:
# Might not work as expected if two classes have the same name in the same source file.
try:
source, _ = inspect.getsourcelines(cls)
except OSError:
return {}
else:
source = _extract_source_from_frame(cls)
if not source:
return {}
dedent_source = _dedent_source_lines(source)
visitor = DocstringVisitor()
visitor.visit(ast.parse(dedent_source))
return visitor.attrs
| Name | Type | Size | Permission | Actions |
|---|---|---|---|---|
| __pycache__ | Folder | 0755 |
|
|
| __init__.py | File | 0 B | 0644 |
|
| _config.py | File | 12.31 KB | 0644 |
|
| _core_metadata.py | File | 3.44 KB | 0644 |
|
| _core_utils.py | File | 23.7 KB | 0644 |
|
| _dataclasses.py | File | 8.53 KB | 0644 |
|
| _decorators.py | File | 31.21 KB | 0644 |
|
| _decorators_v1.py | File | 6.06 KB | 0644 |
|
| _discriminated_union.py | File | 25.82 KB | 0644 |
|
| _docs_extraction.py | File | 3.7 KB | 0644 |
|
| _fields.py | File | 14.58 KB | 0644 |
|
| _forward_ref.py | File | 611 B | 0644 |
|
| _generate_schema.py | File | 102.91 KB | 0644 |
|
| _generics.py | File | 21.69 KB | 0644 |
|
| _git.py | File | 784 B | 0644 |
|
| _internal_dataclass.py | File | 144 B | 0644 |
|
| _known_annotated_metadata.py | File | 13.86 KB | 0644 |
|
| _mock_val_ser.py | File | 7.14 KB | 0644 |
|
| _model_construction.py | File | 30.63 KB | 0644 |
|
| _repr.py | File | 4.46 KB | 0644 |
|
| _schema_generation_shared.py | File | 4.74 KB | 0644 |
|
| _signature.py | File | 6.15 KB | 0644 |
|
| _std_types_schema.py | File | 28.2 KB | 0644 |
|
| _typing_extra.py | File | 18.97 KB | 0644 |
|
| _utils.py | File | 12.36 KB | 0644 |
|
| _validate_call.py | File | 3.7 KB | 0644 |
|
| _validators.py | File | 10.86 KB | 0644 |
|