|
56 | 56 |
|
57 | 57 | PRIVATE_CLASSES = ['NDFrame', 'IndexOpsMixin']
|
58 | 58 | DIRECTIVES = ['versionadded', 'versionchanged', 'deprecated']
|
| 59 | +ALLOWED_SECTIONS = ['Parameters', 'Attributes', 'Methods', 'Returns', 'Yields', |
| 60 | + 'Other Parameters', 'Raises', 'Warns', 'See Also', 'Notes', |
| 61 | + 'References', 'Examples'] |
59 | 62 | ERROR_MSGS = {
|
60 | 63 | 'GL01': 'Docstring text (summary) should start in the line immediately '
|
61 | 64 | 'after the opening quotes (not in the same line, or leaving a '
|
|
69 | 72 | 'mentioned in public docstrings',
|
70 | 73 | 'GL05': 'Tabs found at the start of line "{line_with_tabs}", please use '
|
71 | 74 | 'whitespace only',
|
| 75 | + 'GL06': 'Found unknown section "{section}". Allowed sections are: ' |
| 76 | + '{allowed_sections}', |
| 77 | + 'GL07': 'Wrong order of sections. "{wrong_section}" should be located ' |
| 78 | + 'before "{goes_before}", the right order is: {sorted_sections}', |
72 | 79 | 'SS01': 'No summary found (a short summary in a single line should be '
|
73 | 80 | 'present at the beginning of the docstring)',
|
74 | 81 | 'SS02': 'Summary does not start with a capital letter',
|
@@ -353,6 +360,18 @@ def double_blank_lines(self):
|
353 | 360 | prev = row.strip()
|
354 | 361 | return False
|
355 | 362 |
|
| 363 | + @property |
| 364 | + def section_titles(self): |
| 365 | + sections = [] |
| 366 | + self.doc._doc.reset() |
| 367 | + while not self.doc._doc.eof(): |
| 368 | + content = self.doc._read_to_next_section() |
| 369 | + if (len(content) > 1 |
| 370 | + and len(content[0]) == len(content[1]) |
| 371 | + and set(content[1]) == {'-'}): |
| 372 | + sections.append(content[0]) |
| 373 | + return sections |
| 374 | + |
356 | 375 | @property
|
357 | 376 | def summary(self):
|
358 | 377 | return ' '.join(self.doc['Summary'])
|
@@ -580,6 +599,25 @@ def validate_one(func_name):
|
580 | 599 | if re.match("^ *\t", line):
|
581 | 600 | errs.append(error('GL05', line_with_tabs=line.lstrip()))
|
582 | 601 |
|
| 602 | + unseen_sections = list(ALLOWED_SECTIONS) |
| 603 | + for section in doc.section_titles: |
| 604 | + if section not in ALLOWED_SECTIONS: |
| 605 | + errs.append(error('GL06', |
| 606 | + section=section, |
| 607 | + allowed_sections=', '.join(ALLOWED_SECTIONS))) |
| 608 | + else: |
| 609 | + if section in unseen_sections: |
| 610 | + section_idx = unseen_sections.index(section) |
| 611 | + unseen_sections = unseen_sections[section_idx + 1:] |
| 612 | + else: |
| 613 | + section_idx = ALLOWED_SECTIONS.index(section) |
| 614 | + goes_before = ALLOWED_SECTIONS[section_idx + 1] |
| 615 | + errs.append(error('GL07', |
| 616 | + sorted_sections=' > '.join(ALLOWED_SECTIONS), |
| 617 | + wrong_section=section, |
| 618 | + goes_before=goes_before)) |
| 619 | + break |
| 620 | + |
583 | 621 | if not doc.summary:
|
584 | 622 | errs.append(error('SS01'))
|
585 | 623 | else:
|
|
0 commit comments