@@ -52,6 +52,9 @@ def test_sections_without_signature():
5252 nada: SEGFAULT.
5353 rien: SEGFAULT.
5454
55+ Keyword Args:
56+ keywd: SEGFAULT.
57+
5558 Exceptions:
5659 GlobalError: when nothing works as expected.
5760
@@ -60,8 +63,8 @@ def test_sections_without_signature():
6063 """
6164 )
6265
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
6568 for error in errors [:- 1 ]:
6669 assert "param" in error
6770 assert "return" in errors [- 1 ]
@@ -79,43 +82,49 @@ def test_property_docstring():
7982def test_function_without_annotations ():
8083 """Parse a function docstring without signature annotations."""
8184
82- def f (x , y ):
85+ def f (x , y , * , z ):
8386 """
8487 This function has no annotations.
8588
8689 Parameters:
8790 x: X value.
8891 y: Y value.
8992
93+ Keyword Args:
94+ z: Z value.
95+
9096 Returns:
91- Sum X + Y.
97+ Sum X + Y + Z .
9298 """
93- return x + y
99+ return x + y + z
94100
95101 sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
96- assert len (sections ) == 3
102+ assert len (sections ) == 4
97103 assert len (errors ) == 1
98104 assert "No type in return" in errors [0 ]
99105
100106
101107def test_function_with_annotations ():
102108 """Parse a function docstring with signature annotations."""
103109
104- def f (x : int , y : int ) -> int :
110+ def f (x : int , y : int , * , z : int ) -> int :
105111 """
106112 This function has annotations.
107113
108114 Parameters:
109115 x: X value.
110116 y: Y value.
111117
118+ Keyword Arguments:
119+ z: Z value.
120+
112121 Returns:
113122 Sum X + Y.
114123 """
115124 return x + y
116125
117126 sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
118- assert len (sections ) == 3
127+ assert len (sections ) == 4
119128 assert not errors
120129
121130
@@ -188,25 +197,29 @@ def f(x: int, y: int) -> int:
188197def test_types_in_docstring ():
189198 """Parse types in docstring."""
190199
191- def f (x , y ):
200+ def f (x , y , * , z ):
192201 """
193202 The types are written in the docstring.
194203
195204 Parameters:
196205 x (int): X value.
197206 y (int): Y value.
198207
208+ Keyword Args:
209+ z (int): Z value.
210+
199211 Returns:
200- int: Sum X + Y.
212+ int: Sum X + Y + Z .
201213 """
202- return x + y
214+ return x + y + z
203215
204216 sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
205- assert len (sections ) == 3
217+ assert len (sections ) == 4
206218 assert not errors
207219
208220 x , y = sections [1 ].value
209- r = sections [2 ].value
221+ (z ,) = sections [2 ].value
222+ r = sections [3 ].value
210223
211224 assert x .name == "x"
212225 assert x .annotation == "int"
@@ -220,31 +233,41 @@ def f(x, y):
220233 assert y .kind is inspect .Parameter .POSITIONAL_OR_KEYWORD
221234 assert y .default is inspect .Signature .empty
222235
236+ assert z .name == "z"
237+ assert z .annotation == "int"
238+ assert z .description == "Z value."
239+ assert z .kind is inspect .Parameter .KEYWORD_ONLY
240+ assert z .default is inspect .Signature .empty
241+
223242 assert r .annotation == "int"
224- assert r .description == "Sum X + Y."
243+ assert r .description == "Sum X + Y + Z ."
225244
226245
227246def test_types_and_optional_in_docstring ():
228247 """Parse optional types in docstring."""
229248
230- def f (x = 1 , y = None ):
249+ def f (x = 1 , y = None , * , z = None ):
231250 """
232251 The types are written in the docstring.
233252
234253 Parameters:
235254 x (int): X value.
236255 y (int, optional): Y value.
237256
257+ Keyword Args:
258+ z (int, optional): Z value.
259+
238260 Returns:
239- int: Sum X + Y.
261+ int: Sum X + Y + Z .
240262 """
241- return x + (y or 1 )
263+ return x + (y or 1 ) + ( z or 1 )
242264
243265 sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
244- assert len (sections ) == 3
266+ assert len (sections ) == 4
245267 assert not errors
246268
247269 x , y = sections [1 ].value
270+ (z ,) = sections [2 ].value
248271
249272 assert x .name == "x"
250273 assert x .annotation == "int"
@@ -258,25 +281,34 @@ def f(x=1, y=None):
258281 assert y .kind is inspect .Parameter .POSITIONAL_OR_KEYWORD
259282 assert y .default is None
260283
284+ assert z .name == "z"
285+ assert z .annotation == "int"
286+ assert z .description == "Z value."
287+ assert z .kind is inspect .Parameter .KEYWORD_ONLY
288+ assert z .default is None
289+
261290
262291def test_types_in_signature_and_docstring ():
263292 """Parse types in both signature and docstring."""
264293
265- def f (x : int , y : int ) -> int :
294+ def f (x : int , y : int , * , z : int ) -> int :
266295 """
267296 The types are written both in the signature and in the docstring.
268297
269298 Parameters:
270299 x (int): X value.
271300 y (int): Y value.
272301
302+ Keyword Args:
303+ z (int): Z value.
304+
273305 Returns:
274- int: Sum X + Y.
306+ int: Sum X + Y + Z .
275307 """
276- return x + y
308+ return x + y + z
277309
278310 sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
279- assert len (sections ) == 3
311+ assert len (sections ) == 4
280312 assert not errors
281313
282314
@@ -401,6 +433,23 @@ def f(x: int):
401433 assert "Empty" in errors [1 ]
402434
403435
436+ def test_param_line_without_colon_keyword_only ():
437+ """Warn when missing colon."""
438+
439+ def f (* , x : int ):
440+ """
441+ Keyword Args:
442+ x is an integer.
443+ """
444+ return x
445+
446+ sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
447+ assert not sections # getting x fails, so the section is empty and discarded
448+ assert len (errors ) == 2
449+ assert "pair" in errors [0 ]
450+ assert "Empty" in errors [1 ]
451+
452+
404453def test_admonitions ():
405454 """Parse admonitions."""
406455
@@ -493,6 +542,35 @@ def f(a, *args, **kwargs):
493542 assert not errors
494543
495544
545+ def test_parse_args_kwargs_keyword_only ():
546+ """Parse args and kwargs."""
547+
548+ def f (a , * args , ** kwargs ):
549+ """
550+ Arguments:
551+ a: a parameter.
552+ *args: args parameters.
553+
554+ Keyword Args:
555+ **kwargs: kwargs parameters.
556+ """
557+ return 1
558+
559+ sections , errors = parse (inspect .getdoc (f ), inspect .signature (f ))
560+ assert len (sections ) == 2
561+ expected_parameters = {"a" : "a parameter." , "*args" : "args parameters." }
562+ for param in sections [0 ].value :
563+ assert param .name in expected_parameters
564+ assert expected_parameters [param .name ] == param .description
565+
566+ expected_parameters = {"**kwargs" : "kwargs parameters." }
567+ for param in sections [1 ].value :
568+ assert param .name in expected_parameters
569+ assert expected_parameters [param .name ] == param .description
570+
571+ assert not errors
572+
573+
496574def test_different_indentation ():
497575 """Parse different indentations, warn on confusing indentation."""
498576
0 commit comments