singlestoredb 1.15.0__cp38-abi3-win_amd64.whl → 1.15.2__cp38-abi3-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of singlestoredb might be problematic. Click here for more details.
- _singlestoredb_accel.pyd +0 -0
- singlestoredb/__init__.py +1 -1
- singlestoredb/ai/chat.py +14 -0
- singlestoredb/apps/_python_udfs.py +18 -3
- singlestoredb/apps/_stdout_supress.py +1 -1
- singlestoredb/apps/_uvicorn_util.py +4 -0
- singlestoredb/config.py +24 -0
- singlestoredb/converters.py +1 -1
- singlestoredb/docstring/__init__.py +33 -0
- singlestoredb/docstring/attrdoc.py +126 -0
- singlestoredb/docstring/common.py +230 -0
- singlestoredb/docstring/epydoc.py +267 -0
- singlestoredb/docstring/google.py +412 -0
- singlestoredb/docstring/numpydoc.py +562 -0
- singlestoredb/docstring/parser.py +100 -0
- singlestoredb/docstring/py.typed +1 -0
- singlestoredb/docstring/rest.py +256 -0
- singlestoredb/docstring/tests/__init__.py +1 -0
- singlestoredb/docstring/tests/_pydoctor.py +21 -0
- singlestoredb/docstring/tests/test_epydoc.py +729 -0
- singlestoredb/docstring/tests/test_google.py +1007 -0
- singlestoredb/docstring/tests/test_numpydoc.py +1100 -0
- singlestoredb/docstring/tests/test_parse_from_object.py +109 -0
- singlestoredb/docstring/tests/test_parser.py +248 -0
- singlestoredb/docstring/tests/test_rest.py +547 -0
- singlestoredb/docstring/tests/test_util.py +70 -0
- singlestoredb/docstring/util.py +141 -0
- singlestoredb/functions/decorator.py +19 -18
- singlestoredb/functions/ext/asgi.py +304 -32
- singlestoredb/functions/ext/timer.py +2 -11
- singlestoredb/functions/ext/utils.py +55 -6
- singlestoredb/functions/signature.py +374 -241
- singlestoredb/fusion/handlers/files.py +4 -4
- singlestoredb/fusion/handlers/models.py +1 -1
- singlestoredb/fusion/handlers/stage.py +4 -4
- singlestoredb/management/cluster.py +1 -1
- singlestoredb/management/manager.py +15 -5
- singlestoredb/management/region.py +12 -2
- singlestoredb/management/workspace.py +17 -25
- singlestoredb/tests/ext_funcs/__init__.py +39 -0
- singlestoredb/tests/test_connection.py +18 -8
- singlestoredb/tests/test_management.py +24 -57
- singlestoredb/tests/test_udf.py +43 -15
- {singlestoredb-1.15.0.dist-info → singlestoredb-1.15.2.dist-info}/METADATA +1 -1
- {singlestoredb-1.15.0.dist-info → singlestoredb-1.15.2.dist-info}/RECORD +49 -30
- {singlestoredb-1.15.0.dist-info → singlestoredb-1.15.2.dist-info}/LICENSE +0 -0
- {singlestoredb-1.15.0.dist-info → singlestoredb-1.15.2.dist-info}/WHEEL +0 -0
- {singlestoredb-1.15.0.dist-info → singlestoredb-1.15.2.dist-info}/entry_points.txt +0 -0
- {singlestoredb-1.15.0.dist-info → singlestoredb-1.15.2.dist-info}/top_level.txt +0 -0
_singlestoredb_accel.pyd
CHANGED
|
Binary file
|
singlestoredb/__init__.py
CHANGED
singlestoredb/ai/chat.py
CHANGED
|
@@ -24,3 +24,17 @@ class SingleStoreChatOpenAI(ChatOpenAI):
|
|
|
24
24
|
model=model_name,
|
|
25
25
|
**kwargs,
|
|
26
26
|
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SingleStoreChat(ChatOpenAI):
|
|
30
|
+
def __init__(self, model_name: str, **kwargs: Any):
|
|
31
|
+
inference_api_manger = (
|
|
32
|
+
get_workspace_manager().organizations.current.inference_apis
|
|
33
|
+
)
|
|
34
|
+
info = inference_api_manger.get(model_name=model_name)
|
|
35
|
+
super().__init__(
|
|
36
|
+
base_url=info.connection_url,
|
|
37
|
+
api_key=os.environ.get('SINGLESTOREDB_USER_TOKEN'),
|
|
38
|
+
model=model_name,
|
|
39
|
+
**kwargs,
|
|
40
|
+
)
|
|
@@ -13,6 +13,9 @@ if typing.TYPE_CHECKING:
|
|
|
13
13
|
# Keep track of currently running server
|
|
14
14
|
_running_server: 'typing.Optional[AwaitableUvicornServer]' = None
|
|
15
15
|
|
|
16
|
+
# Maximum number of UDFs allowed
|
|
17
|
+
MAX_UDFS_LIMIT = 10
|
|
18
|
+
|
|
16
19
|
|
|
17
20
|
async def run_udf_app(
|
|
18
21
|
log_level: str = 'error',
|
|
@@ -44,20 +47,32 @@ async def run_udf_app(
|
|
|
44
47
|
udf_suffix = ''
|
|
45
48
|
if app_config.running_interactively:
|
|
46
49
|
udf_suffix = '_test'
|
|
47
|
-
app = Application(
|
|
50
|
+
app = Application(
|
|
51
|
+
url=base_url,
|
|
52
|
+
app_mode='managed',
|
|
53
|
+
name_suffix=udf_suffix,
|
|
54
|
+
log_level=log_level,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
if not app.endpoints:
|
|
58
|
+
raise ValueError('You must define at least one function.')
|
|
59
|
+
if len(app.endpoints) > MAX_UDFS_LIMIT:
|
|
60
|
+
raise ValueError(
|
|
61
|
+
f'You can only define a maximum of {MAX_UDFS_LIMIT} functions.',
|
|
62
|
+
)
|
|
48
63
|
|
|
49
64
|
config = uvicorn.Config(
|
|
50
65
|
app,
|
|
51
66
|
host='0.0.0.0',
|
|
52
67
|
port=app_config.listen_port,
|
|
53
|
-
|
|
68
|
+
log_config=app.get_uvicorn_log_config(),
|
|
54
69
|
)
|
|
55
|
-
_running_server = AwaitableUvicornServer(config)
|
|
56
70
|
|
|
57
71
|
# Register the functions only if the app is running interactively.
|
|
58
72
|
if app_config.running_interactively:
|
|
59
73
|
app.register_functions(replace=True)
|
|
60
74
|
|
|
75
|
+
_running_server = AwaitableUvicornServer(config)
|
|
61
76
|
asyncio.create_task(_running_server.serve())
|
|
62
77
|
await _running_server.wait_for_startup()
|
|
63
78
|
|
|
@@ -30,3 +30,7 @@ class AwaitableUvicornServer(uvicorn.Server):
|
|
|
30
30
|
|
|
31
31
|
async def wait_for_startup(self) -> None:
|
|
32
32
|
await self._startup_future
|
|
33
|
+
|
|
34
|
+
async def shutdown(self, sockets: Optional[list[socket.socket]] = None) -> None:
|
|
35
|
+
if self.started:
|
|
36
|
+
await super().shutdown(sockets)
|
singlestoredb/config.py
CHANGED
|
@@ -407,6 +407,12 @@ register_option(
|
|
|
407
407
|
environ=['SINGLESTOREDB_EXT_FUNC_LOG_LEVEL'],
|
|
408
408
|
)
|
|
409
409
|
|
|
410
|
+
register_option(
|
|
411
|
+
'external_function.log_file', 'string', check_str, None,
|
|
412
|
+
'File path to write logs to instead of console.',
|
|
413
|
+
environ=['SINGLESTOREDB_EXT_FUNC_LOG_FILE'],
|
|
414
|
+
)
|
|
415
|
+
|
|
410
416
|
register_option(
|
|
411
417
|
'external_function.name_prefix', 'string', check_str, '',
|
|
412
418
|
'Prefix to add to external function names.',
|
|
@@ -419,6 +425,12 @@ register_option(
|
|
|
419
425
|
environ=['SINGLESTOREDB_EXT_FUNC_NAME_SUFFIX'],
|
|
420
426
|
)
|
|
421
427
|
|
|
428
|
+
register_option(
|
|
429
|
+
'external_function.function_database', 'string', check_str, '',
|
|
430
|
+
'Database to use for the function definitions.',
|
|
431
|
+
environ=['SINGLESTOREDB_EXT_FUNC_FUNCTION_DATABASE'],
|
|
432
|
+
)
|
|
433
|
+
|
|
422
434
|
register_option(
|
|
423
435
|
'external_function.connection', 'string', check_str,
|
|
424
436
|
os.environ.get('SINGLESTOREDB_URL') or None,
|
|
@@ -444,6 +456,18 @@ register_option(
|
|
|
444
456
|
environ=['SINGLESTOREDB_EXT_FUNC_TIMEOUT'],
|
|
445
457
|
)
|
|
446
458
|
|
|
459
|
+
register_option(
|
|
460
|
+
'external_function.disable_metrics', 'bool', check_bool, False,
|
|
461
|
+
'Disable logging of function call metrics.',
|
|
462
|
+
environ=['SINGLESTOREDB_EXT_FUNC_DISABLE_METRICS'],
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
register_option(
|
|
466
|
+
'external_function.app_name', 'string', check_str, None,
|
|
467
|
+
'Name for the external function application instance.',
|
|
468
|
+
environ=['SINGLESTOREDB_EXT_FUNC_APP_NAME'],
|
|
469
|
+
)
|
|
470
|
+
|
|
447
471
|
#
|
|
448
472
|
# Debugging options
|
|
449
473
|
#
|
singlestoredb/converters.py
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Parse docstrings as per Sphinx notation."""
|
|
2
|
+
from .common import Docstring
|
|
3
|
+
from .common import DocstringDeprecated
|
|
4
|
+
from .common import DocstringMeta
|
|
5
|
+
from .common import DocstringParam
|
|
6
|
+
from .common import DocstringRaises
|
|
7
|
+
from .common import DocstringReturns
|
|
8
|
+
from .common import DocstringStyle
|
|
9
|
+
from .common import ParseError
|
|
10
|
+
from .common import RenderingStyle
|
|
11
|
+
from .parser import compose
|
|
12
|
+
from .parser import parse
|
|
13
|
+
from .parser import parse_from_object
|
|
14
|
+
from .util import combine_docstrings
|
|
15
|
+
|
|
16
|
+
Style = DocstringStyle # backwards compatibility
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
'parse',
|
|
20
|
+
'parse_from_object',
|
|
21
|
+
'combine_docstrings',
|
|
22
|
+
'compose',
|
|
23
|
+
'ParseError',
|
|
24
|
+
'Docstring',
|
|
25
|
+
'DocstringMeta',
|
|
26
|
+
'DocstringParam',
|
|
27
|
+
'DocstringRaises',
|
|
28
|
+
'DocstringReturns',
|
|
29
|
+
'DocstringDeprecated',
|
|
30
|
+
'DocstringStyle',
|
|
31
|
+
'RenderingStyle',
|
|
32
|
+
'Style',
|
|
33
|
+
]
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Attribute docstrings parsing.
|
|
2
|
+
|
|
3
|
+
.. seealso:: https://peps.python.org/pep-0257/#what-is-a-docstring
|
|
4
|
+
"""
|
|
5
|
+
import ast
|
|
6
|
+
import inspect
|
|
7
|
+
import textwrap
|
|
8
|
+
import typing as T
|
|
9
|
+
from types import ModuleType
|
|
10
|
+
|
|
11
|
+
from .common import Docstring
|
|
12
|
+
from .common import DocstringParam
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def ast_get_constant_value(node: ast.AST) -> T.Any:
|
|
16
|
+
"""Return the constant's value if the given node is a constant."""
|
|
17
|
+
return getattr(node, 'value')
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def ast_unparse(node: ast.AST) -> T.Optional[str]:
|
|
21
|
+
"""Convert the AST node to source code as a string."""
|
|
22
|
+
if hasattr(ast, 'unparse'):
|
|
23
|
+
return ast.unparse(node)
|
|
24
|
+
# Support simple cases in Python < 3.9
|
|
25
|
+
if isinstance(node, ast.Constant):
|
|
26
|
+
return str(ast_get_constant_value(node))
|
|
27
|
+
if isinstance(node, ast.Name):
|
|
28
|
+
return node.id
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def ast_is_literal_str(node: ast.AST) -> bool:
|
|
33
|
+
"""Return True if the given node is a literal string."""
|
|
34
|
+
return (
|
|
35
|
+
isinstance(node, ast.Expr)
|
|
36
|
+
and isinstance(node.value, ast.Constant)
|
|
37
|
+
and isinstance(ast_get_constant_value(node.value), str)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def ast_get_attribute(
|
|
42
|
+
node: ast.AST,
|
|
43
|
+
) -> T.Optional[T.Tuple[str, T.Optional[str], T.Optional[str]]]:
|
|
44
|
+
"""Return name, type and default if the given node is an attribute."""
|
|
45
|
+
if isinstance(node, (ast.Assign, ast.AnnAssign)):
|
|
46
|
+
target = (
|
|
47
|
+
node.targets[0] if isinstance(node, ast.Assign) else node.target
|
|
48
|
+
)
|
|
49
|
+
if isinstance(target, ast.Name):
|
|
50
|
+
type_str = None
|
|
51
|
+
if isinstance(node, ast.AnnAssign):
|
|
52
|
+
type_str = ast_unparse(node.annotation)
|
|
53
|
+
default = None
|
|
54
|
+
if node.value:
|
|
55
|
+
default = ast_unparse(node.value)
|
|
56
|
+
return target.id, type_str, default
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class AttributeDocstrings(ast.NodeVisitor):
|
|
61
|
+
"""An ast.NodeVisitor that collects attribute docstrings."""
|
|
62
|
+
|
|
63
|
+
attr_docs: T.Dict[str, T.Tuple[str, T.Optional[str], T.Optional[str]]] = {}
|
|
64
|
+
prev_attr = None
|
|
65
|
+
|
|
66
|
+
def visit(self, node: T.Any) -> None:
|
|
67
|
+
if self.prev_attr and ast_is_literal_str(node):
|
|
68
|
+
attr_name, attr_type, attr_default = self.prev_attr
|
|
69
|
+
self.attr_docs[attr_name] = (
|
|
70
|
+
ast_get_constant_value(node.value),
|
|
71
|
+
attr_type,
|
|
72
|
+
attr_default,
|
|
73
|
+
)
|
|
74
|
+
self.prev_attr = ast_get_attribute(node)
|
|
75
|
+
if isinstance(node, (ast.ClassDef, ast.Module)):
|
|
76
|
+
self.generic_visit(node)
|
|
77
|
+
|
|
78
|
+
def get_attr_docs(
|
|
79
|
+
self, component: T.Any,
|
|
80
|
+
) -> T.Dict[str, T.Tuple[str, T.Optional[str], T.Optional[str]]]:
|
|
81
|
+
"""Get attribute docstrings from the given component.
|
|
82
|
+
|
|
83
|
+
:param component: component to process (class or module)
|
|
84
|
+
:returns: for each attribute docstring, a tuple with (description,
|
|
85
|
+
type, default)
|
|
86
|
+
"""
|
|
87
|
+
self.attr_docs = {}
|
|
88
|
+
self.prev_attr = None
|
|
89
|
+
try:
|
|
90
|
+
source = textwrap.dedent(inspect.getsource(component))
|
|
91
|
+
except OSError:
|
|
92
|
+
pass
|
|
93
|
+
else:
|
|
94
|
+
tree = ast.parse(source)
|
|
95
|
+
if inspect.ismodule(component):
|
|
96
|
+
self.visit(tree)
|
|
97
|
+
elif isinstance(tree, ast.Module) and isinstance(
|
|
98
|
+
tree.body[0], ast.ClassDef,
|
|
99
|
+
):
|
|
100
|
+
self.visit(tree.body[0])
|
|
101
|
+
return self.attr_docs
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def add_attribute_docstrings(
|
|
105
|
+
obj: T.Union[type, ModuleType], docstring: Docstring,
|
|
106
|
+
) -> None:
|
|
107
|
+
"""Add attribute docstrings found in the object's source code.
|
|
108
|
+
|
|
109
|
+
:param obj: object from which to parse attribute docstrings
|
|
110
|
+
:param docstring: Docstring object where found attributes are added
|
|
111
|
+
:returns: list with names of added attributes
|
|
112
|
+
"""
|
|
113
|
+
params = set(p.arg_name for p in docstring.params)
|
|
114
|
+
for arg_name, (description, type_name, default) in (
|
|
115
|
+
AttributeDocstrings().get_attr_docs(obj).items()
|
|
116
|
+
):
|
|
117
|
+
if arg_name not in params:
|
|
118
|
+
param = DocstringParam(
|
|
119
|
+
args=['attribute', arg_name],
|
|
120
|
+
description=description,
|
|
121
|
+
arg_name=arg_name,
|
|
122
|
+
type_name=type_name,
|
|
123
|
+
is_optional=default is not None,
|
|
124
|
+
default=default,
|
|
125
|
+
)
|
|
126
|
+
docstring.meta.append(param)
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"""Common methods for parsing."""
|
|
2
|
+
import enum
|
|
3
|
+
import typing as T
|
|
4
|
+
|
|
5
|
+
PARAM_KEYWORDS = {
|
|
6
|
+
'param',
|
|
7
|
+
'parameter',
|
|
8
|
+
'arg',
|
|
9
|
+
'argument',
|
|
10
|
+
'attribute',
|
|
11
|
+
'key',
|
|
12
|
+
'keyword',
|
|
13
|
+
}
|
|
14
|
+
RAISES_KEYWORDS = {'raises', 'raise', 'except', 'exception'}
|
|
15
|
+
DEPRECATION_KEYWORDS = {'deprecation', 'deprecated'}
|
|
16
|
+
RETURNS_KEYWORDS = {'return', 'returns'}
|
|
17
|
+
YIELDS_KEYWORDS = {'yield', 'yields'}
|
|
18
|
+
EXAMPLES_KEYWORDS = {'example', 'examples'}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ParseError(RuntimeError):
|
|
22
|
+
"""Base class for all parsing related errors."""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DocstringStyle(enum.Enum):
|
|
26
|
+
"""Docstring style."""
|
|
27
|
+
|
|
28
|
+
REST = 1
|
|
29
|
+
GOOGLE = 2
|
|
30
|
+
NUMPYDOC = 3
|
|
31
|
+
EPYDOC = 4
|
|
32
|
+
AUTO = 255
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class RenderingStyle(enum.Enum):
|
|
36
|
+
"""Rendering style when unparsing parsed docstrings."""
|
|
37
|
+
|
|
38
|
+
COMPACT = 1
|
|
39
|
+
CLEAN = 2
|
|
40
|
+
EXPANDED = 3
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class DocstringMeta:
|
|
44
|
+
"""Docstring meta information.
|
|
45
|
+
|
|
46
|
+
Symbolizes lines in form of
|
|
47
|
+
|
|
48
|
+
:param arg: description
|
|
49
|
+
:raises ValueError: if something happens
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(
|
|
53
|
+
self, args: T.List[str], description: T.Optional[str],
|
|
54
|
+
) -> None:
|
|
55
|
+
"""Initialize self.
|
|
56
|
+
|
|
57
|
+
:param args: list of arguments. The exact content of this variable is
|
|
58
|
+
dependent on the kind of docstring; it's used to distinguish
|
|
59
|
+
between custom docstring meta information items.
|
|
60
|
+
:param description: associated docstring description.
|
|
61
|
+
"""
|
|
62
|
+
self.args = args
|
|
63
|
+
self.description = description
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class DocstringParam(DocstringMeta):
|
|
67
|
+
"""DocstringMeta symbolizing :param metadata."""
|
|
68
|
+
|
|
69
|
+
def __init__(
|
|
70
|
+
self,
|
|
71
|
+
args: T.List[str],
|
|
72
|
+
description: T.Optional[str],
|
|
73
|
+
arg_name: str,
|
|
74
|
+
type_name: T.Optional[str],
|
|
75
|
+
is_optional: T.Optional[bool],
|
|
76
|
+
default: T.Optional[str],
|
|
77
|
+
) -> None:
|
|
78
|
+
"""Initialize self."""
|
|
79
|
+
super().__init__(args, description)
|
|
80
|
+
self.arg_name = arg_name
|
|
81
|
+
self.type_name = type_name
|
|
82
|
+
self.is_optional = is_optional
|
|
83
|
+
self.default = default
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class DocstringReturns(DocstringMeta):
|
|
87
|
+
"""DocstringMeta symbolizing :returns or :yields metadata."""
|
|
88
|
+
|
|
89
|
+
def __init__(
|
|
90
|
+
self,
|
|
91
|
+
args: T.List[str],
|
|
92
|
+
description: T.Optional[str],
|
|
93
|
+
type_name: T.Optional[str],
|
|
94
|
+
is_generator: bool,
|
|
95
|
+
return_name: T.Optional[str] = None,
|
|
96
|
+
) -> None:
|
|
97
|
+
"""Initialize self."""
|
|
98
|
+
super().__init__(args, description)
|
|
99
|
+
self.type_name = type_name
|
|
100
|
+
self.is_generator = is_generator
|
|
101
|
+
self.return_name = return_name
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class DocstringRaises(DocstringMeta):
|
|
105
|
+
"""DocstringMeta symbolizing :raises metadata."""
|
|
106
|
+
|
|
107
|
+
def __init__(
|
|
108
|
+
self,
|
|
109
|
+
args: T.List[str],
|
|
110
|
+
description: T.Optional[str],
|
|
111
|
+
type_name: T.Optional[str],
|
|
112
|
+
) -> None:
|
|
113
|
+
"""Initialize self."""
|
|
114
|
+
super().__init__(args, description)
|
|
115
|
+
self.type_name = type_name
|
|
116
|
+
self.description = description
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class DocstringDeprecated(DocstringMeta):
|
|
120
|
+
"""DocstringMeta symbolizing deprecation metadata."""
|
|
121
|
+
|
|
122
|
+
def __init__(
|
|
123
|
+
self,
|
|
124
|
+
args: T.List[str],
|
|
125
|
+
description: T.Optional[str],
|
|
126
|
+
version: T.Optional[str],
|
|
127
|
+
) -> None:
|
|
128
|
+
"""Initialize self."""
|
|
129
|
+
super().__init__(args, description)
|
|
130
|
+
self.version = version
|
|
131
|
+
self.description = description
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class DocstringExample(DocstringMeta):
|
|
135
|
+
"""DocstringMeta symbolizing example metadata."""
|
|
136
|
+
|
|
137
|
+
def __init__(
|
|
138
|
+
self,
|
|
139
|
+
args: T.List[str],
|
|
140
|
+
snippet: T.Optional[str],
|
|
141
|
+
description: T.Optional[str],
|
|
142
|
+
post_snippet: T.Optional[str] = None,
|
|
143
|
+
) -> None:
|
|
144
|
+
"""Initialize self."""
|
|
145
|
+
super().__init__(args, description)
|
|
146
|
+
self.snippet = snippet
|
|
147
|
+
self.description = description
|
|
148
|
+
self.post_snippet = post_snippet
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class Docstring:
|
|
152
|
+
"""Docstring object representation."""
|
|
153
|
+
|
|
154
|
+
def __init__(
|
|
155
|
+
self,
|
|
156
|
+
style=None, # type: T.Optional[DocstringStyle]
|
|
157
|
+
) -> None:
|
|
158
|
+
"""Initialize self."""
|
|
159
|
+
self.short_description = None # type: T.Optional[str]
|
|
160
|
+
self.long_description = None # type: T.Optional[str]
|
|
161
|
+
self.blank_after_short_description = False
|
|
162
|
+
self.blank_after_long_description = False
|
|
163
|
+
self.meta = [] # type: T.List[DocstringMeta]
|
|
164
|
+
self.style = style # type: T.Optional[DocstringStyle]
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def description(self) -> T.Optional[str]:
|
|
168
|
+
"""Return the full description of the function
|
|
169
|
+
|
|
170
|
+
Returns None if the docstring did not include any description
|
|
171
|
+
"""
|
|
172
|
+
ret = []
|
|
173
|
+
if self.short_description:
|
|
174
|
+
ret.append(self.short_description)
|
|
175
|
+
if self.blank_after_short_description:
|
|
176
|
+
ret.append('')
|
|
177
|
+
if self.long_description:
|
|
178
|
+
ret.append(self.long_description)
|
|
179
|
+
|
|
180
|
+
if not ret:
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
return '\n'.join(ret)
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def params(self) -> T.List[DocstringParam]:
|
|
187
|
+
"""Return a list of information on function params."""
|
|
188
|
+
return [item for item in self.meta if isinstance(item, DocstringParam)]
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def raises(self) -> T.List[DocstringRaises]:
|
|
192
|
+
"""Return a list of information on the exceptions that the function
|
|
193
|
+
may raise.
|
|
194
|
+
"""
|
|
195
|
+
return [
|
|
196
|
+
item for item in self.meta if isinstance(item, DocstringRaises)
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def returns(self) -> T.Optional[DocstringReturns]:
|
|
201
|
+
"""Return a single information on function return.
|
|
202
|
+
|
|
203
|
+
Takes the first return information.
|
|
204
|
+
"""
|
|
205
|
+
for item in self.meta:
|
|
206
|
+
if isinstance(item, DocstringReturns):
|
|
207
|
+
return item
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def many_returns(self) -> T.List[DocstringReturns]:
|
|
212
|
+
"""Return a list of information on function return."""
|
|
213
|
+
return [
|
|
214
|
+
item for item in self.meta if isinstance(item, DocstringReturns)
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def deprecation(self) -> T.Optional[DocstringDeprecated]:
|
|
219
|
+
"""Return a single information on function deprecation notes."""
|
|
220
|
+
for item in self.meta:
|
|
221
|
+
if isinstance(item, DocstringDeprecated):
|
|
222
|
+
return item
|
|
223
|
+
return None
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def examples(self) -> T.List[DocstringExample]:
|
|
227
|
+
"""Return a list of information on function examples."""
|
|
228
|
+
return [
|
|
229
|
+
item for item in self.meta if isinstance(item, DocstringExample)
|
|
230
|
+
]
|