37
37
)
38
38
from griffe .docstrings .utils import parse_annotation , warning
39
39
from griffe .expressions import ExprName
40
+ from griffe .logger import LogLevel
40
41
41
42
if TYPE_CHECKING :
42
43
from typing import Any , Literal , Pattern
@@ -245,12 +246,7 @@ def _read_parameters_section(
245
246
** options : Any ,
246
247
) -> tuple [DocstringSectionParameters | None , int ]:
247
248
parameters , new_offset = _read_parameters (docstring , offset = offset , ** options )
248
-
249
- if parameters :
250
- return DocstringSectionParameters (parameters ), new_offset
251
-
252
- _warn (docstring , new_offset , f"Empty parameters section at line { offset } " )
253
- return None , new_offset
249
+ return DocstringSectionParameters (parameters ), new_offset
254
250
255
251
256
252
def _read_other_parameters_section (
@@ -261,12 +257,7 @@ def _read_other_parameters_section(
261
257
** options : Any ,
262
258
) -> tuple [DocstringSectionOtherParameters | None , int ]:
263
259
parameters , new_offset = _read_parameters (docstring , offset = offset , warn_unknown_params = False , ** options )
264
-
265
- if parameters :
266
- return DocstringSectionOtherParameters (parameters ), new_offset
267
-
268
- _warn (docstring , new_offset , f"Empty other parameters section at line { offset } " )
269
- return None , new_offset
260
+ return DocstringSectionOtherParameters (parameters ), new_offset
270
261
271
262
272
263
def _read_attributes_section (
@@ -302,11 +293,7 @@ def _read_attributes_section(
302
293
303
294
attributes .append (DocstringAttribute (name = name , annotation = annotation , description = description ))
304
295
305
- if attributes :
306
- return DocstringSectionAttributes (attributes ), new_offset
307
-
308
- _warn (docstring , new_offset , f"Empty attributes section at line { offset } " )
309
- return None , new_offset
296
+ return DocstringSectionAttributes (attributes ), new_offset
310
297
311
298
312
299
def _read_functions_section (
@@ -337,11 +324,7 @@ def _read_functions_section(
337
324
338
325
functions .append (DocstringFunction (name = name , annotation = signature , description = description ))
339
326
340
- if functions :
341
- return DocstringSectionFunctions (functions ), new_offset
342
-
343
- _warn (docstring , new_offset , f"Empty functions/methods section at line { offset } " )
344
- return None , new_offset
327
+ return DocstringSectionFunctions (functions ), new_offset
345
328
346
329
347
330
def _read_classes_section (
@@ -372,11 +355,7 @@ def _read_classes_section(
372
355
373
356
classes .append (DocstringClass (name = name , annotation = signature , description = description ))
374
357
375
- if classes :
376
- return DocstringSectionClasses (classes ), new_offset
377
-
378
- _warn (docstring , new_offset , f"Empty classes section at line { offset } " )
379
- return None , new_offset
358
+ return DocstringSectionClasses (classes ), new_offset
380
359
381
360
382
361
def _read_modules_section (
@@ -397,11 +376,7 @@ def _read_modules_section(
397
376
description = "\n " .join ([description .lstrip (), * module_lines [1 :]]).rstrip ("\n " )
398
377
modules .append (DocstringModule (name = name , description = description ))
399
378
400
- if modules :
401
- return DocstringSectionModules (modules ), new_offset
402
-
403
- _warn (docstring , new_offset , f"Empty modules section at line { offset } " )
404
- return None , new_offset
379
+ return DocstringSectionModules (modules ), new_offset
405
380
406
381
407
382
def _read_raises_section (
@@ -425,11 +400,7 @@ def _read_raises_section(
425
400
annotation = parse_annotation (annotation , docstring )
426
401
exceptions .append (DocstringRaise (annotation = annotation , description = description ))
427
402
428
- if exceptions :
429
- return DocstringSectionRaises (exceptions ), new_offset
430
-
431
- _warn (docstring , new_offset , f"Empty exceptions section at line { offset } " )
432
- return None , new_offset
403
+ return DocstringSectionRaises (exceptions ), new_offset
433
404
434
405
435
406
def _read_warns_section (
@@ -450,11 +421,7 @@ def _read_warns_section(
450
421
description = "\n " .join ([description .lstrip (), * warning_lines [1 :]]).rstrip ("\n " )
451
422
warns .append (DocstringWarn (annotation = annotation , description = description ))
452
423
453
- if warns :
454
- return DocstringSectionWarns (warns ), new_offset
455
-
456
- _warn (docstring , new_offset , f"Empty warns section at line { offset } " )
457
- return None , new_offset
424
+ return DocstringSectionWarns (warns ), new_offset
458
425
459
426
460
427
def _read_returns_section (
@@ -516,11 +483,7 @@ def _read_returns_section(
516
483
517
484
returns .append (DocstringReturn (name = name or "" , annotation = annotation , description = description ))
518
485
519
- if returns :
520
- return DocstringSectionReturns (returns ), new_offset
521
-
522
- _warn (docstring , new_offset , f"Empty returns section at line { offset } " )
523
- return None , new_offset
486
+ return DocstringSectionReturns (returns ), new_offset
524
487
525
488
526
489
def _read_yields_section (
@@ -567,11 +530,7 @@ def _read_yields_section(
567
530
568
531
yields .append (DocstringYield (name = name or "" , annotation = annotation , description = description ))
569
532
570
- if yields :
571
- return DocstringSectionYields (yields ), new_offset
572
-
573
- _warn (docstring , new_offset , f"Empty yields section at line { offset } " )
574
- return None , new_offset
533
+ return DocstringSectionYields (yields ), new_offset
575
534
576
535
577
536
def _read_receives_section (
@@ -614,11 +573,7 @@ def _read_receives_section(
614
573
615
574
receives .append (DocstringReceive (name = name or "" , annotation = annotation , description = description ))
616
575
617
- if receives :
618
- return DocstringSectionReceives (receives ), new_offset
619
-
620
- _warn (docstring , new_offset , f"Empty receives section at line { offset } " )
621
- return None , new_offset
576
+ return DocstringSectionReceives (receives ), new_offset
622
577
623
578
624
579
def _read_examples_section (
@@ -677,11 +632,7 @@ def _read_examples_section(
677
632
elif current_example :
678
633
sub_sections .append ((DocstringSectionKind .examples , "\n " .join (current_example )))
679
634
680
- if sub_sections :
681
- return DocstringSectionExamples (sub_sections ), new_offset
682
-
683
- _warn (docstring , new_offset , f"Empty examples section at line { offset } " )
684
- return None , new_offset
635
+ return DocstringSectionExamples (sub_sections ), new_offset
685
636
686
637
687
638
def _read_deprecated_section (
@@ -692,11 +643,6 @@ def _read_deprecated_section(
692
643
) -> tuple [DocstringSectionDeprecated | None , int ]:
693
644
text , new_offset = _read_block (docstring , offset = offset , ** options )
694
645
695
- # early exit if there is no text in the yield section
696
- if not text :
697
- _warn (docstring , new_offset , f"Empty deprecated section at line { offset } " )
698
- return None , new_offset
699
-
700
646
# check the presence of a name and description, separated by a semi-colon
701
647
try :
702
648
version , text = text .split (":" , 1 )
@@ -733,6 +679,8 @@ def _is_empty_line(line: str) -> bool:
733
679
DocstringSectionKind .deprecated : _read_deprecated_section ,
734
680
}
735
681
682
+ _sentinel = object ()
683
+
736
684
737
685
def parse (
738
686
docstring : Docstring ,
@@ -800,7 +748,41 @@ def parse(
800
748
groups = match .groupdict ()
801
749
title = groups ["title" ]
802
750
admonition_type = groups ["type" ]
803
- if admonition_type .lower () in _section_kind :
751
+ is_section = admonition_type .lower () in _section_kind
752
+
753
+ has_previous_line = offset > 0
754
+ blank_line_above = not has_previous_line or _is_empty_line (lines [offset - 1 ])
755
+ has_next_line = offset < len (lines ) - 1
756
+ has_next_lines = offset < len (lines ) - 2
757
+ blank_line_below = has_next_line and _is_empty_line (lines [offset + 1 ])
758
+ blank_lines_below = has_next_lines and _is_empty_line (lines [offset + 2 ])
759
+ indented_line_below = has_next_line and not blank_line_below and lines [offset + 1 ].startswith (" " )
760
+ indented_lines_below = has_next_lines and not blank_lines_below and lines [offset + 2 ].startswith (" " )
761
+ if not (indented_line_below or indented_lines_below ):
762
+ # Do not warn when there are no contents,
763
+ # this is most probably not a section or admonition.
764
+ current_section .append (lines [offset ])
765
+ offset += 1
766
+ continue
767
+ reasons = []
768
+ kind = "section" if is_section else "admonition"
769
+ if (indented_line_below or indented_lines_below ) and not blank_line_above :
770
+ reasons .append (f"Missing blank line above { kind } " )
771
+ if indented_lines_below and blank_line_below :
772
+ reasons .append (f"Extraneous blank line below { kind } title" )
773
+ if reasons :
774
+ reasons_string = "; " .join (reasons )
775
+ _warn (
776
+ docstring ,
777
+ offset ,
778
+ f"Possible { kind } skipped, reasons: { reasons_string } " ,
779
+ LogLevel .debug ,
780
+ )
781
+ current_section .append (lines [offset ])
782
+ offset += 1
783
+ continue
784
+
785
+ if is_section :
804
786
if current_section :
805
787
if any (current_section ):
806
788
sections .append (DocstringSectionText ("\n " .join (current_section ).rstrip ("\n " )))
0 commit comments