singlestoredb 1.16.1__py3-none-any.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.
- singlestoredb/__init__.py +75 -0
- singlestoredb/ai/__init__.py +2 -0
- singlestoredb/ai/chat.py +139 -0
- singlestoredb/ai/embeddings.py +128 -0
- singlestoredb/alchemy/__init__.py +90 -0
- singlestoredb/apps/__init__.py +3 -0
- singlestoredb/apps/_cloud_functions.py +90 -0
- singlestoredb/apps/_config.py +72 -0
- singlestoredb/apps/_connection_info.py +18 -0
- singlestoredb/apps/_dashboards.py +47 -0
- singlestoredb/apps/_process.py +32 -0
- singlestoredb/apps/_python_udfs.py +100 -0
- singlestoredb/apps/_stdout_supress.py +30 -0
- singlestoredb/apps/_uvicorn_util.py +36 -0
- singlestoredb/auth.py +245 -0
- singlestoredb/config.py +484 -0
- singlestoredb/connection.py +1487 -0
- singlestoredb/converters.py +950 -0
- 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/exceptions.py +120 -0
- singlestoredb/functions/__init__.py +16 -0
- singlestoredb/functions/decorator.py +201 -0
- singlestoredb/functions/dtypes.py +1793 -0
- singlestoredb/functions/ext/__init__.py +1 -0
- singlestoredb/functions/ext/arrow.py +375 -0
- singlestoredb/functions/ext/asgi.py +2133 -0
- singlestoredb/functions/ext/json.py +420 -0
- singlestoredb/functions/ext/mmap.py +413 -0
- singlestoredb/functions/ext/rowdat_1.py +724 -0
- singlestoredb/functions/ext/timer.py +89 -0
- singlestoredb/functions/ext/utils.py +218 -0
- singlestoredb/functions/signature.py +1578 -0
- singlestoredb/functions/typing/__init__.py +41 -0
- singlestoredb/functions/typing/numpy.py +20 -0
- singlestoredb/functions/typing/pandas.py +2 -0
- singlestoredb/functions/typing/polars.py +2 -0
- singlestoredb/functions/typing/pyarrow.py +2 -0
- singlestoredb/functions/utils.py +421 -0
- singlestoredb/fusion/__init__.py +11 -0
- singlestoredb/fusion/graphql.py +213 -0
- singlestoredb/fusion/handler.py +916 -0
- singlestoredb/fusion/handlers/__init__.py +0 -0
- singlestoredb/fusion/handlers/export.py +525 -0
- singlestoredb/fusion/handlers/files.py +690 -0
- singlestoredb/fusion/handlers/job.py +660 -0
- singlestoredb/fusion/handlers/models.py +250 -0
- singlestoredb/fusion/handlers/stage.py +502 -0
- singlestoredb/fusion/handlers/utils.py +324 -0
- singlestoredb/fusion/handlers/workspace.py +956 -0
- singlestoredb/fusion/registry.py +249 -0
- singlestoredb/fusion/result.py +399 -0
- singlestoredb/http/__init__.py +27 -0
- singlestoredb/http/connection.py +1267 -0
- singlestoredb/magics/__init__.py +34 -0
- singlestoredb/magics/run_personal.py +137 -0
- singlestoredb/magics/run_shared.py +134 -0
- singlestoredb/management/__init__.py +9 -0
- singlestoredb/management/billing_usage.py +148 -0
- singlestoredb/management/cluster.py +462 -0
- singlestoredb/management/export.py +295 -0
- singlestoredb/management/files.py +1102 -0
- singlestoredb/management/inference_api.py +105 -0
- singlestoredb/management/job.py +887 -0
- singlestoredb/management/manager.py +373 -0
- singlestoredb/management/organization.py +226 -0
- singlestoredb/management/region.py +169 -0
- singlestoredb/management/utils.py +423 -0
- singlestoredb/management/workspace.py +1927 -0
- singlestoredb/mysql/__init__.py +177 -0
- singlestoredb/mysql/_auth.py +298 -0
- singlestoredb/mysql/charset.py +214 -0
- singlestoredb/mysql/connection.py +2032 -0
- singlestoredb/mysql/constants/CLIENT.py +38 -0
- singlestoredb/mysql/constants/COMMAND.py +32 -0
- singlestoredb/mysql/constants/CR.py +78 -0
- singlestoredb/mysql/constants/ER.py +474 -0
- singlestoredb/mysql/constants/EXTENDED_TYPE.py +3 -0
- singlestoredb/mysql/constants/FIELD_TYPE.py +48 -0
- singlestoredb/mysql/constants/FLAG.py +15 -0
- singlestoredb/mysql/constants/SERVER_STATUS.py +10 -0
- singlestoredb/mysql/constants/VECTOR_TYPE.py +6 -0
- singlestoredb/mysql/constants/__init__.py +0 -0
- singlestoredb/mysql/converters.py +271 -0
- singlestoredb/mysql/cursors.py +896 -0
- singlestoredb/mysql/err.py +92 -0
- singlestoredb/mysql/optionfile.py +20 -0
- singlestoredb/mysql/protocol.py +450 -0
- singlestoredb/mysql/tests/__init__.py +19 -0
- singlestoredb/mysql/tests/base.py +126 -0
- singlestoredb/mysql/tests/conftest.py +37 -0
- singlestoredb/mysql/tests/test_DictCursor.py +132 -0
- singlestoredb/mysql/tests/test_SSCursor.py +141 -0
- singlestoredb/mysql/tests/test_basic.py +452 -0
- singlestoredb/mysql/tests/test_connection.py +851 -0
- singlestoredb/mysql/tests/test_converters.py +58 -0
- singlestoredb/mysql/tests/test_cursor.py +141 -0
- singlestoredb/mysql/tests/test_err.py +16 -0
- singlestoredb/mysql/tests/test_issues.py +514 -0
- singlestoredb/mysql/tests/test_load_local.py +75 -0
- singlestoredb/mysql/tests/test_nextset.py +88 -0
- singlestoredb/mysql/tests/test_optionfile.py +27 -0
- singlestoredb/mysql/tests/thirdparty/__init__.py +6 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +9 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +323 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +865 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +110 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +224 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +101 -0
- singlestoredb/mysql/times.py +23 -0
- singlestoredb/notebook/__init__.py +16 -0
- singlestoredb/notebook/_objects.py +213 -0
- singlestoredb/notebook/_portal.py +352 -0
- singlestoredb/py.typed +0 -0
- singlestoredb/pytest.py +352 -0
- singlestoredb/server/__init__.py +0 -0
- singlestoredb/server/docker.py +452 -0
- singlestoredb/server/free_tier.py +267 -0
- singlestoredb/tests/__init__.py +0 -0
- singlestoredb/tests/alltypes.sql +307 -0
- singlestoredb/tests/alltypes_no_nulls.sql +208 -0
- singlestoredb/tests/empty.sql +0 -0
- singlestoredb/tests/ext_funcs/__init__.py +702 -0
- singlestoredb/tests/local_infile.csv +3 -0
- singlestoredb/tests/test.ipynb +18 -0
- singlestoredb/tests/test.sql +680 -0
- singlestoredb/tests/test2.ipynb +18 -0
- singlestoredb/tests/test2.sql +1 -0
- singlestoredb/tests/test_basics.py +1332 -0
- singlestoredb/tests/test_config.py +318 -0
- singlestoredb/tests/test_connection.py +3103 -0
- singlestoredb/tests/test_dbapi.py +27 -0
- singlestoredb/tests/test_exceptions.py +45 -0
- singlestoredb/tests/test_ext_func.py +1472 -0
- singlestoredb/tests/test_ext_func_data.py +1101 -0
- singlestoredb/tests/test_fusion.py +1527 -0
- singlestoredb/tests/test_http.py +288 -0
- singlestoredb/tests/test_management.py +1599 -0
- singlestoredb/tests/test_plugin.py +33 -0
- singlestoredb/tests/test_results.py +171 -0
- singlestoredb/tests/test_types.py +132 -0
- singlestoredb/tests/test_udf.py +737 -0
- singlestoredb/tests/test_udf_returns.py +459 -0
- singlestoredb/tests/test_vectorstore.py +51 -0
- singlestoredb/tests/test_xdict.py +333 -0
- singlestoredb/tests/utils.py +141 -0
- singlestoredb/types.py +373 -0
- singlestoredb/utils/__init__.py +0 -0
- singlestoredb/utils/config.py +950 -0
- singlestoredb/utils/convert_rows.py +69 -0
- singlestoredb/utils/debug.py +13 -0
- singlestoredb/utils/dtypes.py +205 -0
- singlestoredb/utils/events.py +65 -0
- singlestoredb/utils/mogrify.py +151 -0
- singlestoredb/utils/results.py +585 -0
- singlestoredb/utils/xdict.py +425 -0
- singlestoredb/vectorstore.py +192 -0
- singlestoredb/warnings.py +5 -0
- singlestoredb-1.16.1.dist-info/METADATA +165 -0
- singlestoredb-1.16.1.dist-info/RECORD +183 -0
- singlestoredb-1.16.1.dist-info/WHEEL +5 -0
- singlestoredb-1.16.1.dist-info/entry_points.txt +2 -0
- singlestoredb-1.16.1.dist-info/licenses/LICENSE +201 -0
- singlestoredb-1.16.1.dist-info/top_level.txt +3 -0
- sqlx/__init__.py +4 -0
- sqlx/magic.py +113 -0
|
@@ -0,0 +1,1007 @@
|
|
|
1
|
+
"""Tests for Google-style docstring routines."""
|
|
2
|
+
import typing as T
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
import singlestoredb.docstring.google as google
|
|
7
|
+
from singlestoredb.docstring.common import ParseError
|
|
8
|
+
from singlestoredb.docstring.common import RenderingStyle
|
|
9
|
+
from singlestoredb.docstring.google import compose
|
|
10
|
+
from singlestoredb.docstring.google import GoogleParser
|
|
11
|
+
from singlestoredb.docstring.google import parse
|
|
12
|
+
from singlestoredb.docstring.google import Section
|
|
13
|
+
from singlestoredb.docstring.google import SectionType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_google_parser_unknown_section() -> None:
|
|
17
|
+
"""Test parsing an unknown section with default GoogleParser
|
|
18
|
+
configuration.
|
|
19
|
+
"""
|
|
20
|
+
parser = GoogleParser()
|
|
21
|
+
docstring = parser.parse(
|
|
22
|
+
"""
|
|
23
|
+
Unknown:
|
|
24
|
+
spam: a
|
|
25
|
+
""",
|
|
26
|
+
)
|
|
27
|
+
assert docstring.short_description == 'Unknown:'
|
|
28
|
+
assert docstring.long_description == 'spam: a'
|
|
29
|
+
assert len(docstring.meta) == 0
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_google_parser_multi_line_parameter_type() -> None:
|
|
33
|
+
"""Test parsing a multi-line parameter type with default GoogleParser"""
|
|
34
|
+
parser = GoogleParser()
|
|
35
|
+
docstring = parser.parse(
|
|
36
|
+
"""Description of the function.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
output_type (Literal["searchResults", "sourcedAnswer",
|
|
40
|
+
"structured"]): The type of output.
|
|
41
|
+
This can be one of the following:
|
|
42
|
+
- "searchResults": Represents the search results.
|
|
43
|
+
- "sourcedAnswer": Represents a sourced answer.
|
|
44
|
+
- "structured": Represents a structured output format.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
bool: Indicates success or failure.
|
|
48
|
+
|
|
49
|
+
""",
|
|
50
|
+
)
|
|
51
|
+
assert docstring.params[0].arg_name == 'output_type'
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_google_parser_custom_sections() -> None:
|
|
55
|
+
"""Test parsing an unknown section with custom GoogleParser
|
|
56
|
+
configuration.
|
|
57
|
+
"""
|
|
58
|
+
parser = GoogleParser(
|
|
59
|
+
[
|
|
60
|
+
Section('DESCRIPTION', 'desc', SectionType.SINGULAR),
|
|
61
|
+
Section('ARGUMENTS', 'param', SectionType.MULTIPLE),
|
|
62
|
+
Section('ATTRIBUTES', 'attribute', SectionType.MULTIPLE),
|
|
63
|
+
Section('EXAMPLES', 'examples', SectionType.SINGULAR),
|
|
64
|
+
],
|
|
65
|
+
title_colon=False,
|
|
66
|
+
)
|
|
67
|
+
docstring = parser.parse(
|
|
68
|
+
"""
|
|
69
|
+
DESCRIPTION
|
|
70
|
+
This is the description.
|
|
71
|
+
|
|
72
|
+
ARGUMENTS
|
|
73
|
+
arg1: first arg
|
|
74
|
+
arg2: second arg
|
|
75
|
+
|
|
76
|
+
ATTRIBUTES
|
|
77
|
+
attr1: first attribute
|
|
78
|
+
attr2: second attribute
|
|
79
|
+
|
|
80
|
+
EXAMPLES
|
|
81
|
+
Many examples
|
|
82
|
+
More examples
|
|
83
|
+
""",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
assert docstring.short_description is None
|
|
87
|
+
assert docstring.long_description is None
|
|
88
|
+
assert len(docstring.meta) == 6
|
|
89
|
+
assert docstring.meta[0].args == ['desc']
|
|
90
|
+
assert docstring.meta[0].description == 'This is the description.'
|
|
91
|
+
assert docstring.meta[1].args == ['param', 'arg1']
|
|
92
|
+
assert docstring.meta[1].description == 'first arg'
|
|
93
|
+
assert docstring.meta[2].args == ['param', 'arg2']
|
|
94
|
+
assert docstring.meta[2].description == 'second arg'
|
|
95
|
+
assert docstring.meta[3].args == ['attribute', 'attr1']
|
|
96
|
+
assert docstring.meta[3].description == 'first attribute'
|
|
97
|
+
assert docstring.meta[4].args == ['attribute', 'attr2']
|
|
98
|
+
assert docstring.meta[4].description == 'second attribute'
|
|
99
|
+
assert docstring.meta[5].args == ['examples']
|
|
100
|
+
assert docstring.meta[5].description == 'Many examples\nMore examples'
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def test_google_parser_custom_sections_after() -> None:
|
|
104
|
+
"""Test parsing an unknown section with custom GoogleParser configuration
|
|
105
|
+
that was set at a runtime.
|
|
106
|
+
"""
|
|
107
|
+
parser = GoogleParser(title_colon=False)
|
|
108
|
+
parser.add_section(Section('Note', 'note', SectionType.SINGULAR))
|
|
109
|
+
docstring = parser.parse(
|
|
110
|
+
"""
|
|
111
|
+
short description
|
|
112
|
+
|
|
113
|
+
Note:
|
|
114
|
+
a note
|
|
115
|
+
""",
|
|
116
|
+
)
|
|
117
|
+
assert docstring.short_description == 'short description'
|
|
118
|
+
assert docstring.long_description == 'Note:\n a note'
|
|
119
|
+
|
|
120
|
+
docstring = parser.parse(
|
|
121
|
+
"""
|
|
122
|
+
short description
|
|
123
|
+
|
|
124
|
+
Note a note
|
|
125
|
+
""",
|
|
126
|
+
)
|
|
127
|
+
assert docstring.short_description == 'short description'
|
|
128
|
+
assert docstring.long_description == 'Note a note'
|
|
129
|
+
|
|
130
|
+
docstring = parser.parse(
|
|
131
|
+
"""
|
|
132
|
+
short description
|
|
133
|
+
|
|
134
|
+
Note
|
|
135
|
+
a note
|
|
136
|
+
""",
|
|
137
|
+
)
|
|
138
|
+
assert len(docstring.meta) == 1
|
|
139
|
+
assert docstring.meta[0].args == ['note']
|
|
140
|
+
assert docstring.meta[0].description == 'a note'
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@pytest.mark.parametrize(
|
|
144
|
+
'source, expected',
|
|
145
|
+
[
|
|
146
|
+
pytest.param(None, None, id='No __doc__'),
|
|
147
|
+
('', None),
|
|
148
|
+
('\n', None),
|
|
149
|
+
('Short description', 'Short description'),
|
|
150
|
+
('\nShort description\n', 'Short description'),
|
|
151
|
+
('\n Short description\n', 'Short description'),
|
|
152
|
+
],
|
|
153
|
+
)
|
|
154
|
+
def test_short_description(
|
|
155
|
+
source: T.Optional[str], expected: T.Optional[str],
|
|
156
|
+
) -> None:
|
|
157
|
+
"""Test parsing short description."""
|
|
158
|
+
docstring = parse(source)
|
|
159
|
+
assert docstring.short_description == expected
|
|
160
|
+
assert docstring.long_description is None
|
|
161
|
+
assert not docstring.meta
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@pytest.mark.parametrize(
|
|
165
|
+
'source, expected_short_desc, expected_long_desc, expected_blank',
|
|
166
|
+
[
|
|
167
|
+
(
|
|
168
|
+
'Short description\n\nLong description',
|
|
169
|
+
'Short description',
|
|
170
|
+
'Long description',
|
|
171
|
+
True,
|
|
172
|
+
),
|
|
173
|
+
(
|
|
174
|
+
"""
|
|
175
|
+
Short description
|
|
176
|
+
|
|
177
|
+
Long description
|
|
178
|
+
""",
|
|
179
|
+
'Short description',
|
|
180
|
+
'Long description',
|
|
181
|
+
True,
|
|
182
|
+
),
|
|
183
|
+
(
|
|
184
|
+
"""
|
|
185
|
+
Short description
|
|
186
|
+
|
|
187
|
+
Long description
|
|
188
|
+
Second line
|
|
189
|
+
""",
|
|
190
|
+
'Short description',
|
|
191
|
+
'Long description\nSecond line',
|
|
192
|
+
True,
|
|
193
|
+
),
|
|
194
|
+
(
|
|
195
|
+
'Short description\nLong description',
|
|
196
|
+
'Short description',
|
|
197
|
+
'Long description',
|
|
198
|
+
False,
|
|
199
|
+
),
|
|
200
|
+
(
|
|
201
|
+
"""
|
|
202
|
+
Short description
|
|
203
|
+
Long description
|
|
204
|
+
""",
|
|
205
|
+
'Short description',
|
|
206
|
+
'Long description',
|
|
207
|
+
False,
|
|
208
|
+
),
|
|
209
|
+
(
|
|
210
|
+
'\nShort description\nLong description\n',
|
|
211
|
+
'Short description',
|
|
212
|
+
'Long description',
|
|
213
|
+
False,
|
|
214
|
+
),
|
|
215
|
+
(
|
|
216
|
+
"""
|
|
217
|
+
Short description
|
|
218
|
+
Long description
|
|
219
|
+
Second line
|
|
220
|
+
""",
|
|
221
|
+
'Short description',
|
|
222
|
+
'Long description\nSecond line',
|
|
223
|
+
False,
|
|
224
|
+
),
|
|
225
|
+
],
|
|
226
|
+
)
|
|
227
|
+
def test_long_description(
|
|
228
|
+
source: str,
|
|
229
|
+
expected_short_desc: str,
|
|
230
|
+
expected_long_desc: str,
|
|
231
|
+
expected_blank: bool,
|
|
232
|
+
) -> None:
|
|
233
|
+
"""Test parsing long description."""
|
|
234
|
+
docstring = parse(source)
|
|
235
|
+
assert docstring.short_description == expected_short_desc
|
|
236
|
+
assert docstring.long_description == expected_long_desc
|
|
237
|
+
assert docstring.blank_after_short_description == expected_blank
|
|
238
|
+
assert not docstring.meta
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
@pytest.mark.parametrize(
|
|
242
|
+
'source, expected_short_desc, expected_long_desc, '
|
|
243
|
+
'expected_blank_short_desc, expected_blank_long_desc',
|
|
244
|
+
[
|
|
245
|
+
(
|
|
246
|
+
"""
|
|
247
|
+
Short description
|
|
248
|
+
Args:
|
|
249
|
+
asd:
|
|
250
|
+
""",
|
|
251
|
+
'Short description',
|
|
252
|
+
None,
|
|
253
|
+
False,
|
|
254
|
+
False,
|
|
255
|
+
),
|
|
256
|
+
(
|
|
257
|
+
"""
|
|
258
|
+
Short description
|
|
259
|
+
Long description
|
|
260
|
+
Args:
|
|
261
|
+
asd:
|
|
262
|
+
""",
|
|
263
|
+
'Short description',
|
|
264
|
+
'Long description',
|
|
265
|
+
False,
|
|
266
|
+
False,
|
|
267
|
+
),
|
|
268
|
+
(
|
|
269
|
+
"""
|
|
270
|
+
Short description
|
|
271
|
+
First line
|
|
272
|
+
Second line
|
|
273
|
+
Args:
|
|
274
|
+
asd:
|
|
275
|
+
""",
|
|
276
|
+
'Short description',
|
|
277
|
+
'First line\n Second line',
|
|
278
|
+
False,
|
|
279
|
+
False,
|
|
280
|
+
),
|
|
281
|
+
(
|
|
282
|
+
"""
|
|
283
|
+
Short description
|
|
284
|
+
|
|
285
|
+
First line
|
|
286
|
+
Second line
|
|
287
|
+
Args:
|
|
288
|
+
asd:
|
|
289
|
+
""",
|
|
290
|
+
'Short description',
|
|
291
|
+
'First line\n Second line',
|
|
292
|
+
True,
|
|
293
|
+
False,
|
|
294
|
+
),
|
|
295
|
+
(
|
|
296
|
+
"""
|
|
297
|
+
Short description
|
|
298
|
+
|
|
299
|
+
First line
|
|
300
|
+
Second line
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
asd:
|
|
304
|
+
""",
|
|
305
|
+
'Short description',
|
|
306
|
+
'First line\n Second line',
|
|
307
|
+
True,
|
|
308
|
+
True,
|
|
309
|
+
),
|
|
310
|
+
(
|
|
311
|
+
"""
|
|
312
|
+
Args:
|
|
313
|
+
asd:
|
|
314
|
+
""",
|
|
315
|
+
None,
|
|
316
|
+
None,
|
|
317
|
+
False,
|
|
318
|
+
False,
|
|
319
|
+
),
|
|
320
|
+
],
|
|
321
|
+
)
|
|
322
|
+
def test_meta_newlines(
|
|
323
|
+
source: str,
|
|
324
|
+
expected_short_desc: T.Optional[str],
|
|
325
|
+
expected_long_desc: T.Optional[str],
|
|
326
|
+
expected_blank_short_desc: bool,
|
|
327
|
+
expected_blank_long_desc: bool,
|
|
328
|
+
) -> None:
|
|
329
|
+
"""Test parsing newlines around description sections."""
|
|
330
|
+
docstring = parse(source)
|
|
331
|
+
assert docstring.short_description == expected_short_desc
|
|
332
|
+
assert docstring.long_description == expected_long_desc
|
|
333
|
+
assert docstring.blank_after_short_description == expected_blank_short_desc
|
|
334
|
+
assert docstring.blank_after_long_description == expected_blank_long_desc
|
|
335
|
+
assert len(docstring.meta) == 1
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def test_meta_with_multiline_description() -> None:
|
|
339
|
+
"""Test parsing multiline meta documentation."""
|
|
340
|
+
docstring = parse(
|
|
341
|
+
"""
|
|
342
|
+
Short description
|
|
343
|
+
|
|
344
|
+
Args:
|
|
345
|
+
spam: asd
|
|
346
|
+
1
|
|
347
|
+
2
|
|
348
|
+
3
|
|
349
|
+
""",
|
|
350
|
+
)
|
|
351
|
+
assert docstring.short_description == 'Short description'
|
|
352
|
+
assert len(docstring.meta) == 1
|
|
353
|
+
assert docstring.meta[0].args == ['param', 'spam']
|
|
354
|
+
assert isinstance(docstring.meta[0], google.DocstringParam)
|
|
355
|
+
assert docstring.meta[0].arg_name == 'spam'
|
|
356
|
+
assert docstring.meta[0].description == 'asd\n1\n 2\n3'
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def test_default_args() -> None:
|
|
360
|
+
"""Test parsing default arguments."""
|
|
361
|
+
docstring = parse(
|
|
362
|
+
"""A sample function
|
|
363
|
+
|
|
364
|
+
A function the demonstrates docstrings
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
arg1 (int): The firsty arg
|
|
368
|
+
arg2 (str): The second arg
|
|
369
|
+
arg3 (float, optional): The third arg. Defaults to 1.0.
|
|
370
|
+
arg4 (Optional[Dict[str, Any]], optional): The last arg. Defaults to None.
|
|
371
|
+
arg5 (str, optional): The fifth arg. Defaults to DEFAULT_ARG5.
|
|
372
|
+
|
|
373
|
+
Returns:
|
|
374
|
+
Mapping[str, Any]: The args packed in a mapping
|
|
375
|
+
""",
|
|
376
|
+
)
|
|
377
|
+
assert docstring is not None
|
|
378
|
+
assert len(docstring.params) == 5
|
|
379
|
+
|
|
380
|
+
arg4 = docstring.params[3]
|
|
381
|
+
assert arg4.arg_name == 'arg4'
|
|
382
|
+
assert arg4.is_optional
|
|
383
|
+
assert arg4.type_name == 'Optional[Dict[str, Any]]'
|
|
384
|
+
assert arg4.default == 'None'
|
|
385
|
+
assert arg4.description == 'The last arg. Defaults to None.'
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def test_multiple_meta() -> None:
|
|
389
|
+
"""Test parsing multiple meta."""
|
|
390
|
+
docstring = parse(
|
|
391
|
+
"""
|
|
392
|
+
Short description
|
|
393
|
+
|
|
394
|
+
Args:
|
|
395
|
+
spam: asd
|
|
396
|
+
1
|
|
397
|
+
2
|
|
398
|
+
3
|
|
399
|
+
|
|
400
|
+
Raises:
|
|
401
|
+
bla: herp
|
|
402
|
+
yay: derp
|
|
403
|
+
""",
|
|
404
|
+
)
|
|
405
|
+
assert docstring.short_description == 'Short description'
|
|
406
|
+
assert len(docstring.meta) == 3
|
|
407
|
+
assert docstring.meta[0].args == ['param', 'spam']
|
|
408
|
+
assert isinstance(docstring.meta[0], google.DocstringParam)
|
|
409
|
+
assert docstring.meta[0].arg_name == 'spam'
|
|
410
|
+
assert docstring.meta[0].description == 'asd\n1\n 2\n3'
|
|
411
|
+
assert docstring.meta[1].args == ['raises', 'bla']
|
|
412
|
+
assert isinstance(docstring.meta[1], google.DocstringRaises)
|
|
413
|
+
assert docstring.meta[1].type_name == 'bla'
|
|
414
|
+
assert docstring.meta[1].description == 'herp'
|
|
415
|
+
assert isinstance(docstring.meta[2], google.DocstringRaises)
|
|
416
|
+
assert docstring.meta[2].args == ['raises', 'yay']
|
|
417
|
+
assert docstring.meta[2].type_name == 'yay'
|
|
418
|
+
assert docstring.meta[2].description == 'derp'
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def test_params() -> None:
|
|
422
|
+
"""Test parsing params."""
|
|
423
|
+
docstring = parse('Short description')
|
|
424
|
+
assert len(docstring.params) == 0
|
|
425
|
+
|
|
426
|
+
docstring = parse(
|
|
427
|
+
"""
|
|
428
|
+
Short description
|
|
429
|
+
|
|
430
|
+
Args:
|
|
431
|
+
name: description 1
|
|
432
|
+
priority (int): description 2
|
|
433
|
+
sender (str?): description 3
|
|
434
|
+
ratio (Optional[float], optional): description 4
|
|
435
|
+
""",
|
|
436
|
+
)
|
|
437
|
+
assert len(docstring.params) == 4
|
|
438
|
+
assert docstring.params[0].arg_name == 'name'
|
|
439
|
+
assert docstring.params[0].type_name is None
|
|
440
|
+
assert docstring.params[0].description == 'description 1'
|
|
441
|
+
assert not docstring.params[0].is_optional
|
|
442
|
+
assert docstring.params[1].arg_name == 'priority'
|
|
443
|
+
assert docstring.params[1].type_name == 'int'
|
|
444
|
+
assert docstring.params[1].description == 'description 2'
|
|
445
|
+
assert not docstring.params[1].is_optional
|
|
446
|
+
assert docstring.params[2].arg_name == 'sender'
|
|
447
|
+
assert docstring.params[2].type_name == 'str'
|
|
448
|
+
assert docstring.params[2].description == 'description 3'
|
|
449
|
+
assert docstring.params[2].is_optional
|
|
450
|
+
assert docstring.params[3].arg_name == 'ratio'
|
|
451
|
+
assert docstring.params[3].type_name == 'Optional[float]'
|
|
452
|
+
assert docstring.params[3].description == 'description 4'
|
|
453
|
+
assert docstring.params[3].is_optional
|
|
454
|
+
|
|
455
|
+
docstring = parse(
|
|
456
|
+
"""
|
|
457
|
+
Short description
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
name: description 1
|
|
461
|
+
with multi-line text
|
|
462
|
+
priority (int): description 2
|
|
463
|
+
""",
|
|
464
|
+
)
|
|
465
|
+
assert len(docstring.params) == 2
|
|
466
|
+
assert docstring.params[0].arg_name == 'name'
|
|
467
|
+
assert docstring.params[0].type_name is None
|
|
468
|
+
assert docstring.params[0].description == (
|
|
469
|
+
'description 1\nwith multi-line text'
|
|
470
|
+
)
|
|
471
|
+
assert docstring.params[1].arg_name == 'priority'
|
|
472
|
+
assert docstring.params[1].type_name == 'int'
|
|
473
|
+
assert docstring.params[1].description == 'description 2'
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def test_attributes() -> None:
|
|
477
|
+
"""Test parsing attributes."""
|
|
478
|
+
docstring = parse('Short description')
|
|
479
|
+
assert len(docstring.params) == 0
|
|
480
|
+
|
|
481
|
+
docstring = parse(
|
|
482
|
+
"""
|
|
483
|
+
Short description
|
|
484
|
+
|
|
485
|
+
Attributes:
|
|
486
|
+
name: description 1
|
|
487
|
+
priority (int): description 2
|
|
488
|
+
sender (str?): description 3
|
|
489
|
+
ratio (Optional[float], optional): description 4
|
|
490
|
+
""",
|
|
491
|
+
)
|
|
492
|
+
assert len(docstring.params) == 4
|
|
493
|
+
assert docstring.params[0].arg_name == 'name'
|
|
494
|
+
assert docstring.params[0].type_name is None
|
|
495
|
+
assert docstring.params[0].description == 'description 1'
|
|
496
|
+
assert not docstring.params[0].is_optional
|
|
497
|
+
assert docstring.params[1].arg_name == 'priority'
|
|
498
|
+
assert docstring.params[1].type_name == 'int'
|
|
499
|
+
assert docstring.params[1].description == 'description 2'
|
|
500
|
+
assert not docstring.params[1].is_optional
|
|
501
|
+
assert docstring.params[2].arg_name == 'sender'
|
|
502
|
+
assert docstring.params[2].type_name == 'str'
|
|
503
|
+
assert docstring.params[2].description == 'description 3'
|
|
504
|
+
assert docstring.params[2].is_optional
|
|
505
|
+
assert docstring.params[3].arg_name == 'ratio'
|
|
506
|
+
assert docstring.params[3].type_name == 'Optional[float]'
|
|
507
|
+
assert docstring.params[3].description == 'description 4'
|
|
508
|
+
assert docstring.params[3].is_optional
|
|
509
|
+
|
|
510
|
+
docstring = parse(
|
|
511
|
+
"""
|
|
512
|
+
Short description
|
|
513
|
+
|
|
514
|
+
Attributes:
|
|
515
|
+
name: description 1
|
|
516
|
+
with multi-line text
|
|
517
|
+
priority (int): description 2
|
|
518
|
+
""",
|
|
519
|
+
)
|
|
520
|
+
assert len(docstring.params) == 2
|
|
521
|
+
assert docstring.params[0].arg_name == 'name'
|
|
522
|
+
assert docstring.params[0].type_name is None
|
|
523
|
+
assert docstring.params[0].description == (
|
|
524
|
+
'description 1\nwith multi-line text'
|
|
525
|
+
)
|
|
526
|
+
assert docstring.params[1].arg_name == 'priority'
|
|
527
|
+
assert docstring.params[1].type_name == 'int'
|
|
528
|
+
assert docstring.params[1].description == 'description 2'
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
def test_returns() -> None:
|
|
532
|
+
"""Test parsing returns."""
|
|
533
|
+
docstring = parse(
|
|
534
|
+
"""
|
|
535
|
+
Short description
|
|
536
|
+
""",
|
|
537
|
+
)
|
|
538
|
+
assert docstring.returns is None
|
|
539
|
+
assert docstring.many_returns is not None
|
|
540
|
+
assert len(docstring.many_returns) == 0
|
|
541
|
+
|
|
542
|
+
docstring = parse(
|
|
543
|
+
"""
|
|
544
|
+
Short description
|
|
545
|
+
Returns:
|
|
546
|
+
description
|
|
547
|
+
""",
|
|
548
|
+
)
|
|
549
|
+
assert docstring.returns is not None
|
|
550
|
+
assert docstring.returns.type_name is None
|
|
551
|
+
assert docstring.returns.description == 'description'
|
|
552
|
+
assert docstring.many_returns is not None
|
|
553
|
+
assert len(docstring.many_returns) == 1
|
|
554
|
+
assert docstring.many_returns[0] == docstring.returns
|
|
555
|
+
|
|
556
|
+
docstring = parse(
|
|
557
|
+
"""
|
|
558
|
+
Short description
|
|
559
|
+
Returns:
|
|
560
|
+
description with: a colon!
|
|
561
|
+
""",
|
|
562
|
+
)
|
|
563
|
+
assert docstring.returns is not None
|
|
564
|
+
assert docstring.returns.type_name is None
|
|
565
|
+
assert docstring.returns.description == 'description with: a colon!'
|
|
566
|
+
assert docstring.many_returns is not None
|
|
567
|
+
assert len(docstring.many_returns) == 1
|
|
568
|
+
assert docstring.many_returns[0] == docstring.returns
|
|
569
|
+
|
|
570
|
+
docstring = parse(
|
|
571
|
+
"""
|
|
572
|
+
Short description
|
|
573
|
+
Returns:
|
|
574
|
+
int: description
|
|
575
|
+
""",
|
|
576
|
+
)
|
|
577
|
+
assert docstring.returns is not None
|
|
578
|
+
assert docstring.returns.type_name == 'int'
|
|
579
|
+
assert docstring.returns.description == 'description'
|
|
580
|
+
assert docstring.many_returns is not None
|
|
581
|
+
assert len(docstring.many_returns) == 1
|
|
582
|
+
assert docstring.many_returns[0] == docstring.returns
|
|
583
|
+
|
|
584
|
+
docstring = parse(
|
|
585
|
+
"""
|
|
586
|
+
Returns:
|
|
587
|
+
Optional[Mapping[str, List[int]]]: A description: with a colon
|
|
588
|
+
""",
|
|
589
|
+
)
|
|
590
|
+
assert docstring.returns is not None
|
|
591
|
+
assert docstring.returns.type_name == 'Optional[Mapping[str, List[int]]]'
|
|
592
|
+
assert docstring.returns.description == 'A description: with a colon'
|
|
593
|
+
assert docstring.many_returns is not None
|
|
594
|
+
assert len(docstring.many_returns) == 1
|
|
595
|
+
assert docstring.many_returns[0] == docstring.returns
|
|
596
|
+
|
|
597
|
+
docstring = parse(
|
|
598
|
+
"""
|
|
599
|
+
Short description
|
|
600
|
+
Yields:
|
|
601
|
+
int: description
|
|
602
|
+
""",
|
|
603
|
+
)
|
|
604
|
+
assert docstring.returns is not None
|
|
605
|
+
assert docstring.returns.type_name == 'int'
|
|
606
|
+
assert docstring.returns.description == 'description'
|
|
607
|
+
assert docstring.many_returns is not None
|
|
608
|
+
assert len(docstring.many_returns) == 1
|
|
609
|
+
assert docstring.many_returns[0] == docstring.returns
|
|
610
|
+
|
|
611
|
+
docstring = parse(
|
|
612
|
+
"""
|
|
613
|
+
Short description
|
|
614
|
+
Returns:
|
|
615
|
+
int: description
|
|
616
|
+
with much text
|
|
617
|
+
|
|
618
|
+
even some spacing
|
|
619
|
+
""",
|
|
620
|
+
)
|
|
621
|
+
assert docstring.returns is not None
|
|
622
|
+
assert docstring.returns.type_name == 'int'
|
|
623
|
+
assert docstring.returns.description == (
|
|
624
|
+
'description\nwith much text\n\neven some spacing'
|
|
625
|
+
)
|
|
626
|
+
assert docstring.many_returns is not None
|
|
627
|
+
assert len(docstring.many_returns) == 1
|
|
628
|
+
assert docstring.many_returns[0] == docstring.returns
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
def test_raises() -> None:
|
|
632
|
+
"""Test parsing raises."""
|
|
633
|
+
docstring = parse(
|
|
634
|
+
"""
|
|
635
|
+
Short description
|
|
636
|
+
""",
|
|
637
|
+
)
|
|
638
|
+
assert len(docstring.raises) == 0
|
|
639
|
+
|
|
640
|
+
docstring = parse(
|
|
641
|
+
"""
|
|
642
|
+
Short description
|
|
643
|
+
Raises:
|
|
644
|
+
ValueError: description
|
|
645
|
+
""",
|
|
646
|
+
)
|
|
647
|
+
assert len(docstring.raises) == 1
|
|
648
|
+
assert docstring.raises[0].type_name == 'ValueError'
|
|
649
|
+
assert docstring.raises[0].description == 'description'
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
def test_examples() -> None:
|
|
653
|
+
"""Test parsing examples."""
|
|
654
|
+
docstring = parse(
|
|
655
|
+
"""
|
|
656
|
+
Short description
|
|
657
|
+
Example:
|
|
658
|
+
example: 1
|
|
659
|
+
Examples:
|
|
660
|
+
long example
|
|
661
|
+
|
|
662
|
+
more here
|
|
663
|
+
""",
|
|
664
|
+
)
|
|
665
|
+
assert len(docstring.examples) == 2
|
|
666
|
+
assert docstring.examples[0].description == 'example: 1'
|
|
667
|
+
assert docstring.examples[1].description == 'long example\n\nmore here'
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
def test_broken_meta() -> None:
|
|
671
|
+
"""Test parsing broken meta."""
|
|
672
|
+
with pytest.raises(ParseError):
|
|
673
|
+
parse('Args:')
|
|
674
|
+
|
|
675
|
+
with pytest.raises(ParseError):
|
|
676
|
+
parse('Args:\n herp derp')
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
def test_unknown_meta() -> None:
|
|
680
|
+
"""Test parsing unknown meta."""
|
|
681
|
+
docstring = parse(
|
|
682
|
+
"""Short desc
|
|
683
|
+
|
|
684
|
+
Unknown 0:
|
|
685
|
+
title0: content0
|
|
686
|
+
|
|
687
|
+
Args:
|
|
688
|
+
arg0: desc0
|
|
689
|
+
arg1: desc1
|
|
690
|
+
|
|
691
|
+
Unknown1:
|
|
692
|
+
title1: content1
|
|
693
|
+
|
|
694
|
+
Unknown2:
|
|
695
|
+
title2: content2
|
|
696
|
+
""",
|
|
697
|
+
)
|
|
698
|
+
|
|
699
|
+
assert docstring.params[0].arg_name == 'arg0'
|
|
700
|
+
assert docstring.params[0].description == 'desc0'
|
|
701
|
+
assert docstring.params[1].arg_name == 'arg1'
|
|
702
|
+
assert docstring.params[1].description == 'desc1'
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
def test_broken_arguments() -> None:
|
|
706
|
+
"""Test parsing broken arguments."""
|
|
707
|
+
with pytest.raises(ParseError):
|
|
708
|
+
parse(
|
|
709
|
+
"""This is a test
|
|
710
|
+
|
|
711
|
+
Args:
|
|
712
|
+
param - poorly formatted
|
|
713
|
+
""",
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
def test_empty_example() -> None:
|
|
718
|
+
"""Test parsing empty examples section."""
|
|
719
|
+
docstring = parse(
|
|
720
|
+
"""Short description
|
|
721
|
+
|
|
722
|
+
Example:
|
|
723
|
+
|
|
724
|
+
Raises:
|
|
725
|
+
IOError: some error
|
|
726
|
+
""",
|
|
727
|
+
)
|
|
728
|
+
|
|
729
|
+
assert len(docstring.examples) == 1
|
|
730
|
+
assert docstring.examples[0].args == ['examples']
|
|
731
|
+
assert docstring.examples[0].description == ''
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
@pytest.mark.parametrize(
|
|
735
|
+
'source, expected',
|
|
736
|
+
[
|
|
737
|
+
('', ''),
|
|
738
|
+
('\n', ''),
|
|
739
|
+
('Short description', 'Short description'),
|
|
740
|
+
('\nShort description\n', 'Short description'),
|
|
741
|
+
('\n Short description\n', 'Short description'),
|
|
742
|
+
(
|
|
743
|
+
'Short description\n\nLong description',
|
|
744
|
+
'Short description\n\nLong description',
|
|
745
|
+
),
|
|
746
|
+
(
|
|
747
|
+
"""
|
|
748
|
+
Short description
|
|
749
|
+
|
|
750
|
+
Long description
|
|
751
|
+
""",
|
|
752
|
+
'Short description\n\nLong description',
|
|
753
|
+
),
|
|
754
|
+
(
|
|
755
|
+
"""
|
|
756
|
+
Short description
|
|
757
|
+
|
|
758
|
+
Long description
|
|
759
|
+
Second line
|
|
760
|
+
""",
|
|
761
|
+
'Short description\n\nLong description\nSecond line',
|
|
762
|
+
),
|
|
763
|
+
(
|
|
764
|
+
'Short description\nLong description',
|
|
765
|
+
'Short description\nLong description',
|
|
766
|
+
),
|
|
767
|
+
(
|
|
768
|
+
"""
|
|
769
|
+
Short description
|
|
770
|
+
Long description
|
|
771
|
+
""",
|
|
772
|
+
'Short description\nLong description',
|
|
773
|
+
),
|
|
774
|
+
(
|
|
775
|
+
'\nShort description\nLong description\n',
|
|
776
|
+
'Short description\nLong description',
|
|
777
|
+
),
|
|
778
|
+
(
|
|
779
|
+
"""
|
|
780
|
+
Short description
|
|
781
|
+
Long description
|
|
782
|
+
Second line
|
|
783
|
+
""",
|
|
784
|
+
'Short description\nLong description\nSecond line',
|
|
785
|
+
),
|
|
786
|
+
(
|
|
787
|
+
"""
|
|
788
|
+
Short description
|
|
789
|
+
Meta:
|
|
790
|
+
asd
|
|
791
|
+
""",
|
|
792
|
+
'Short description\nMeta:\n asd',
|
|
793
|
+
),
|
|
794
|
+
(
|
|
795
|
+
"""
|
|
796
|
+
Short description
|
|
797
|
+
Long description
|
|
798
|
+
Meta:
|
|
799
|
+
asd
|
|
800
|
+
""",
|
|
801
|
+
'Short description\nLong description\nMeta:\n asd',
|
|
802
|
+
),
|
|
803
|
+
(
|
|
804
|
+
"""
|
|
805
|
+
Short description
|
|
806
|
+
First line
|
|
807
|
+
Second line
|
|
808
|
+
Meta:
|
|
809
|
+
asd
|
|
810
|
+
""",
|
|
811
|
+
'Short description\n'
|
|
812
|
+
'First line\n'
|
|
813
|
+
' Second line\n'
|
|
814
|
+
'Meta:\n'
|
|
815
|
+
' asd',
|
|
816
|
+
),
|
|
817
|
+
(
|
|
818
|
+
"""
|
|
819
|
+
Short description
|
|
820
|
+
|
|
821
|
+
First line
|
|
822
|
+
Second line
|
|
823
|
+
Meta:
|
|
824
|
+
asd
|
|
825
|
+
""",
|
|
826
|
+
'Short description\n'
|
|
827
|
+
'\n'
|
|
828
|
+
'First line\n'
|
|
829
|
+
' Second line\n'
|
|
830
|
+
'Meta:\n'
|
|
831
|
+
' asd',
|
|
832
|
+
),
|
|
833
|
+
(
|
|
834
|
+
"""
|
|
835
|
+
Short description
|
|
836
|
+
|
|
837
|
+
First line
|
|
838
|
+
Second line
|
|
839
|
+
|
|
840
|
+
Meta:
|
|
841
|
+
asd
|
|
842
|
+
""",
|
|
843
|
+
'Short description\n'
|
|
844
|
+
'\n'
|
|
845
|
+
'First line\n'
|
|
846
|
+
' Second line\n'
|
|
847
|
+
'\n'
|
|
848
|
+
'Meta:\n'
|
|
849
|
+
' asd',
|
|
850
|
+
),
|
|
851
|
+
(
|
|
852
|
+
"""
|
|
853
|
+
Short description
|
|
854
|
+
|
|
855
|
+
Meta:
|
|
856
|
+
asd
|
|
857
|
+
1
|
|
858
|
+
2
|
|
859
|
+
3
|
|
860
|
+
""",
|
|
861
|
+
'Short description\n'
|
|
862
|
+
'\n'
|
|
863
|
+
'Meta:\n'
|
|
864
|
+
' asd\n'
|
|
865
|
+
' 1\n'
|
|
866
|
+
' 2\n'
|
|
867
|
+
' 3',
|
|
868
|
+
),
|
|
869
|
+
(
|
|
870
|
+
"""
|
|
871
|
+
Short description
|
|
872
|
+
|
|
873
|
+
Meta1:
|
|
874
|
+
asd
|
|
875
|
+
1
|
|
876
|
+
2
|
|
877
|
+
3
|
|
878
|
+
Meta2:
|
|
879
|
+
herp
|
|
880
|
+
Meta3:
|
|
881
|
+
derp
|
|
882
|
+
""",
|
|
883
|
+
'Short description\n'
|
|
884
|
+
'\n'
|
|
885
|
+
'Meta1:\n'
|
|
886
|
+
' asd\n'
|
|
887
|
+
' 1\n'
|
|
888
|
+
' 2\n'
|
|
889
|
+
' 3\n'
|
|
890
|
+
'Meta2:\n'
|
|
891
|
+
' herp\n'
|
|
892
|
+
'Meta3:\n'
|
|
893
|
+
' derp',
|
|
894
|
+
),
|
|
895
|
+
(
|
|
896
|
+
"""
|
|
897
|
+
Short description
|
|
898
|
+
|
|
899
|
+
Args:
|
|
900
|
+
name: description 1
|
|
901
|
+
priority (int): description 2
|
|
902
|
+
sender (str, optional): description 3
|
|
903
|
+
message (str, optional): description 4, defaults to 'hello'
|
|
904
|
+
multiline (str?):
|
|
905
|
+
long description 5,
|
|
906
|
+
defaults to 'bye'
|
|
907
|
+
""",
|
|
908
|
+
'Short description\n'
|
|
909
|
+
'\n'
|
|
910
|
+
'Args:\n'
|
|
911
|
+
' name: description 1\n'
|
|
912
|
+
' priority (int): description 2\n'
|
|
913
|
+
' sender (str?): description 3\n'
|
|
914
|
+
" message (str?): description 4, defaults to 'hello'\n"
|
|
915
|
+
' multiline (str?): long description 5,\n'
|
|
916
|
+
" defaults to 'bye'",
|
|
917
|
+
),
|
|
918
|
+
(
|
|
919
|
+
"""
|
|
920
|
+
Short description
|
|
921
|
+
Raises:
|
|
922
|
+
ValueError: description
|
|
923
|
+
""",
|
|
924
|
+
'Short description\nRaises:\n ValueError: description',
|
|
925
|
+
),
|
|
926
|
+
],
|
|
927
|
+
)
|
|
928
|
+
def test_compose(source: str, expected: str) -> None:
|
|
929
|
+
"""Test compose in default mode."""
|
|
930
|
+
assert compose(parse(source)) == expected
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
@pytest.mark.parametrize(
|
|
934
|
+
'source, expected',
|
|
935
|
+
[
|
|
936
|
+
(
|
|
937
|
+
"""
|
|
938
|
+
Short description
|
|
939
|
+
|
|
940
|
+
Args:
|
|
941
|
+
name: description 1
|
|
942
|
+
priority (int): description 2
|
|
943
|
+
sender (str, optional): description 3
|
|
944
|
+
message (str, optional): description 4, defaults to 'hello'
|
|
945
|
+
multiline (str?):
|
|
946
|
+
long description 5,
|
|
947
|
+
defaults to 'bye'
|
|
948
|
+
""",
|
|
949
|
+
'Short description\n'
|
|
950
|
+
'\n'
|
|
951
|
+
'Args:\n'
|
|
952
|
+
' name: description 1\n'
|
|
953
|
+
' priority (int): description 2\n'
|
|
954
|
+
' sender (str, optional): description 3\n'
|
|
955
|
+
" message (str, optional): description 4, defaults to 'hello'\n"
|
|
956
|
+
' multiline (str, optional): long description 5,\n'
|
|
957
|
+
" defaults to 'bye'",
|
|
958
|
+
),
|
|
959
|
+
],
|
|
960
|
+
)
|
|
961
|
+
def test_compose_clean(source: str, expected: str) -> None:
|
|
962
|
+
"""Test compose in clean mode."""
|
|
963
|
+
assert (
|
|
964
|
+
compose(parse(source), rendering_style=RenderingStyle.CLEAN)
|
|
965
|
+
== expected
|
|
966
|
+
)
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
@pytest.mark.parametrize(
|
|
970
|
+
'source, expected',
|
|
971
|
+
[
|
|
972
|
+
(
|
|
973
|
+
"""
|
|
974
|
+
Short description
|
|
975
|
+
|
|
976
|
+
Args:
|
|
977
|
+
name: description 1
|
|
978
|
+
priority (int): description 2
|
|
979
|
+
sender (str, optional): description 3
|
|
980
|
+
message (str, optional): description 4, defaults to 'hello'
|
|
981
|
+
multiline (str?):
|
|
982
|
+
long description 5,
|
|
983
|
+
defaults to 'bye'
|
|
984
|
+
""",
|
|
985
|
+
'Short description\n'
|
|
986
|
+
'\n'
|
|
987
|
+
'Args:\n'
|
|
988
|
+
' name:\n'
|
|
989
|
+
' description 1\n'
|
|
990
|
+
' priority (int):\n'
|
|
991
|
+
' description 2\n'
|
|
992
|
+
' sender (str, optional):\n'
|
|
993
|
+
' description 3\n'
|
|
994
|
+
' message (str, optional):\n'
|
|
995
|
+
" description 4, defaults to 'hello'\n"
|
|
996
|
+
' multiline (str, optional):\n'
|
|
997
|
+
' long description 5,\n'
|
|
998
|
+
" defaults to 'bye'",
|
|
999
|
+
),
|
|
1000
|
+
],
|
|
1001
|
+
)
|
|
1002
|
+
def test_compose_expanded(source: str, expected: str) -> None:
|
|
1003
|
+
"""Test compose in expanded mode."""
|
|
1004
|
+
assert (
|
|
1005
|
+
compose(parse(source), rendering_style=RenderingStyle.EXPANDED)
|
|
1006
|
+
== expected
|
|
1007
|
+
)
|