@@ -52,6 +52,9 @@ def test_sections_without_signature():
52
52
nada: SEGFAULT.
53
53
rien: SEGFAULT.
54
54
55
+ Keyword Args:
56
+ keywd: SEGFAULT.
57
+
55
58
Exceptions:
56
59
GlobalError: when nothing works as expected.
57
60
@@ -60,8 +63,8 @@ def test_sections_without_signature():
60
63
"""
61
64
)
62
65
63
- assert len (sections ) == 4
64
- assert len (errors ) == 5 # missing annotations for params and return
66
+ assert len (sections ) == 5
67
+ assert len (errors ) == 6 # missing annotations for params and return
65
68
for error in errors [:- 1 ]:
66
69
assert "param" in error
67
70
assert "return" in errors [- 1 ]
@@ -79,43 +82,49 @@ def test_property_docstring():
79
82
def test_function_without_annotations ():
80
83
"""Parse a function docstring without signature annotations."""
81
84
82
- def f (x , y ):
85
+ def f (x , y , * , z ):
83
86
"""
84
87
This function has no annotations.
85
88
86
89
Parameters:
87
90
x: X value.
88
91
y: Y value.
89
92
93
+ Keyword Args:
94
+ z: Z value.
95
+
90
96
Returns:
91
- Sum X + Y.
97
+ Sum X + Y + Z .
92
98
"""
93
- return x + y
99
+ return x + y + z
94
100
95
101
sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
96
- assert len (sections ) == 3
102
+ assert len (sections ) == 4
97
103
assert len (errors ) == 1
98
104
assert "No type in return" in errors [0 ]
99
105
100
106
101
107
def test_function_with_annotations ():
102
108
"""Parse a function docstring with signature annotations."""
103
109
104
- def f (x : int , y : int ) -> int :
110
+ def f (x : int , y : int , * , z : int ) -> int :
105
111
"""
106
112
This function has annotations.
107
113
108
114
Parameters:
109
115
x: X value.
110
116
y: Y value.
111
117
118
+ Keyword Arguments:
119
+ z: Z value.
120
+
112
121
Returns:
113
122
Sum X + Y.
114
123
"""
115
124
return x + y
116
125
117
126
sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
118
- assert len (sections ) == 3
127
+ assert len (sections ) == 4
119
128
assert not errors
120
129
121
130
@@ -188,25 +197,34 @@ def f(x: int, y: int) -> int:
188
197
def test_types_in_docstring ():
189
198
"""Parse types in docstring."""
190
199
191
- def f (x , y ):
200
+ def f (x , y , * , z ):
192
201
"""
193
202
The types are written in the docstring.
194
203
195
204
Parameters:
196
205
x (int): X value.
197
206
y (int): Y value.
198
207
208
+ Keyword Args:
209
+ z (int): Z value.
210
+
199
211
Returns:
200
- int: Sum X + Y.
212
+ int: Sum X + Y + Z .
201
213
"""
202
- return x + y
214
+ return x + y + z
203
215
204
216
sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
205
- assert len (sections ) == 3
217
+ assert len (sections ) == 4
206
218
assert not errors
207
219
220
+ assert sections [0 ].type == Section .Type .MARKDOWN
221
+ assert sections [1 ].type == Section .Type .PARAMETERS
222
+ assert sections [2 ].type == Section .Type .KEYWORD_ARGS
223
+ assert sections [3 ].type == Section .Type .RETURN
224
+
208
225
x , y = sections [1 ].value
209
- r = sections [2 ].value
226
+ (z ,) = sections [2 ].value
227
+ r = sections [3 ].value
210
228
211
229
assert x .name == "x"
212
230
assert x .annotation == "int"
@@ -220,31 +238,45 @@ def f(x, y):
220
238
assert y .kind is inspect .Parameter .POSITIONAL_OR_KEYWORD
221
239
assert y .default is inspect .Signature .empty
222
240
241
+ assert z .name == "z"
242
+ assert z .annotation == "int"
243
+ assert z .description == "Z value."
244
+ assert z .kind is inspect .Parameter .KEYWORD_ONLY
245
+ assert z .default is inspect .Signature .empty
246
+
223
247
assert r .annotation == "int"
224
- assert r .description == "Sum X + Y."
248
+ assert r .description == "Sum X + Y + Z ."
225
249
226
250
227
251
def test_types_and_optional_in_docstring ():
228
252
"""Parse optional types in docstring."""
229
253
230
- def f (x = 1 , y = None ):
254
+ def f (x = 1 , y = None , * , z = None ):
231
255
"""
232
256
The types are written in the docstring.
233
257
234
258
Parameters:
235
259
x (int): X value.
236
260
y (int, optional): Y value.
237
261
262
+ Keyword Args:
263
+ z (int, optional): Z value.
264
+
238
265
Returns:
239
- int: Sum X + Y.
266
+ int: Sum X + Y + Z .
240
267
"""
241
- return x + (y or 1 )
268
+ return x + (y or 1 ) + ( z or 1 )
242
269
243
270
sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
244
- assert len (sections ) == 3
271
+ assert len (sections ) == 4
245
272
assert not errors
246
273
274
+ assert sections [0 ].type == Section .Type .MARKDOWN
275
+ assert sections [1 ].type == Section .Type .PARAMETERS
276
+ assert sections [2 ].type == Section .Type .KEYWORD_ARGS
277
+
247
278
x , y = sections [1 ].value
279
+ (z ,) = sections [2 ].value
248
280
249
281
assert x .name == "x"
250
282
assert x .annotation == "int"
@@ -258,25 +290,34 @@ def f(x=1, y=None):
258
290
assert y .kind is inspect .Parameter .POSITIONAL_OR_KEYWORD
259
291
assert y .default is None
260
292
293
+ assert z .name == "z"
294
+ assert z .annotation == "int"
295
+ assert z .description == "Z value."
296
+ assert z .kind is inspect .Parameter .KEYWORD_ONLY
297
+ assert z .default is None
298
+
261
299
262
300
def test_types_in_signature_and_docstring ():
263
301
"""Parse types in both signature and docstring."""
264
302
265
- def f (x : int , y : int ) -> int :
303
+ def f (x : int , y : int , * , z : int ) -> int :
266
304
"""
267
305
The types are written both in the signature and in the docstring.
268
306
269
307
Parameters:
270
308
x (int): X value.
271
309
y (int): Y value.
272
310
311
+ Keyword Args:
312
+ z (int): Z value.
313
+
273
314
Returns:
274
- int: Sum X + Y.
315
+ int: Sum X + Y + Z .
275
316
"""
276
- return x + y
317
+ return x + y + z
277
318
278
319
sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
279
- assert len (sections ) == 3
320
+ assert len (sections ) == 4
280
321
assert not errors
281
322
282
323
@@ -401,6 +442,23 @@ def f(x: int):
401
442
assert "Empty" in errors [1 ]
402
443
403
444
445
+ def test_param_line_without_colon_keyword_only ():
446
+ """Warn when missing colon."""
447
+
448
+ def f (* , x : int ):
449
+ """
450
+ Keyword Args:
451
+ x is an integer.
452
+ """
453
+ return x
454
+
455
+ sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
456
+ assert not sections # getting x fails, so the section is empty and discarded
457
+ assert len (errors ) == 2
458
+ assert "pair" in errors [0 ]
459
+ assert "Empty" in errors [1 ]
460
+
461
+
404
462
def test_admonitions ():
405
463
"""Parse admonitions."""
406
464
@@ -493,6 +551,35 @@ def f(a, *args, **kwargs):
493
551
assert not errors
494
552
495
553
554
+ def test_parse_args_kwargs_keyword_only ():
555
+ """Parse args and kwargs."""
556
+
557
+ def f (a , * args , ** kwargs ):
558
+ """
559
+ Arguments:
560
+ a: a parameter.
561
+ *args: args parameters.
562
+
563
+ Keyword Args:
564
+ **kwargs: kwargs parameters.
565
+ """
566
+ return 1
567
+
568
+ sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
569
+ assert len (sections ) == 2
570
+ expected_parameters = {"a" : "a parameter." , "*args" : "args parameters." }
571
+ for param in sections [0 ].value :
572
+ assert param .name in expected_parameters
573
+ assert expected_parameters [param .name ] == param .description
574
+
575
+ expected_parameters = {"**kwargs" : "kwargs parameters." }
576
+ for param in sections [1 ].value :
577
+ assert param .name in expected_parameters
578
+ assert expected_parameters [param .name ] == param .description
579
+
580
+ assert not errors
581
+
582
+
496
583
def test_different_indentation ():
497
584
"""Parse different indentations, warn on confusing indentation."""
498
585
0 commit comments