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