Skip to content

Commit 072d240

Browse files
authored
Merge pull request #41 from rsokl/fix-merging-with-inherit
Fix merging with inherit
2 parents 8894116 + 5532e77 commit 072d240

File tree

8 files changed

+250
-75
lines changed

8 files changed

+250
-75
lines changed

README.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -170,26 +170,25 @@ Utilize a built-in style by specifying any of the following names (as a string),
170170
from the parent and child are merged gracefully with nice formatting. The child's docstring sections take precedence
171171
in the case of overlap.
172172

173-
- `"numpy_with_merge"`: Behaves identically to the "numpy" style, but also merges sections that overlap,
174-
instead of only keeping the child's section. All sections are concerned except sections "Short Summary",
175-
"Extended Summary", "Deprecation Warning" and "Examples" for which the "numpy" style behaviour applies.
173+
- `"numpy_with_merge"`: Behaves identically to the "numpy" style, but also merges - with de-duplication - sections that overlap,
174+
instead of only keeping the child's section. The sections that are merged are "Attributes", "Parameters",
175+
"Methods", "Other Parameters", and "Keyword Arguments".
176176

177177
- `"google"`: Google-styled docstrings from the parent and child are merged gracefully
178178
with nice formatting. The child's docstring sections take precedence in the case of overlap.
179179
This adheres to the [napoleon specification for the Google style](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html#example-google-style-python-docstrings).
180180

181-
- `"google_with_merge"`: Behaves identically to the "google" style, but also merges sections that overlap,
182-
instead of only keeping the child's section. All sections are concerned except sections "Short Summary",
183-
"Example" and "Examples" (or coresponding aliases) for which the 'google' style applies.
181+
- `"google_with_merge"`: Behaves identically to the "google" style, but also merges - with de-duplication - sections that overlap,
182+
instead of only keeping the child's section. The sections that are merged are "Attributes", "Parameters",
183+
"Methods", "Other Parameters", and "Keyword Arguments" (or their [aliases](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/index.html#docstring-sections)).
184184

185185
- `"numpy_napoleon"`: NumPy-styled docstrings from the parent and child are merged gracefully
186186
with nice formatting. The child's docstring sections take precedence in the case of overlap.
187187
This adheres to the [napoleon specification for the NumPy style](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html#example-numpy).
188188

189-
- `"numpy_napoleon_with_merge"`: Behaves identically to the 'numpy_napoleon' style, but also merges sections
190-
that overlap, instead of only keeping the child's section. All sections are concerned except sections
191-
"Short Summary", "Example" and "Examples" (or coresponding aliases) for which the 'numpy_napoleon' style
192-
behaviour applies.
189+
- `"numpy_napoleon_with_merge"`: Behaves identically to the 'numpy_napoleon' style, but also merges - with de-duplication - sections
190+
that overlap, instead of only keeping the child's section. The sections that are merged are "Attributes", "Parameters",
191+
"Methods", "Other Parameters", and "Keyword Arguments" (or their [aliases](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/index.html#docstring-sections)).
193192

194193
- `"reST"`: reST-styled docstrings from the parent and child are merged gracefully
195194
with nice formatting. Docstring sections are specified by
@@ -198,7 +197,7 @@ Utilize a built-in style by specifying any of the following names (as a string),
198197

199198
For the `numpy`, `numpy_with_merge`, `numpy_napoleon`, `numpy_napoleon_with_merge`, `google` and `google_with_merge` styles, if the parent's docstring contains a "Raises" section and the child's docstring implements a "Returns" or a "Yields" section instead, then the "Raises" section is not included in the resulting docstring. This is to accomodate for the relatively common use case in which an abstract method/property raises `NotImplementedError`. Child classes that implement this method/property clearly will not raise this. Of course, any "Raises" section that is explicitly included in the child's docstring will appear in the resulting docstring.
200199

201-
Detailed documentation and example cases for the default styles can be found [here](https://github.com/meowklaski/custom_inherit/blob/master/custom_inherit/_style_store.py)
200+
Detailed documentation and example cases for the default styles can be found [here](https://github.com/rsokl/custom_inherit/blob/master/src/custom_inherit/_style_store.py)
202201

203202
## Making New Inheritance Styles
204203
Implementing your inheritance style is simple.

src/custom_inherit/_doc_parse_tools/napoleon_parse_tools.py

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@
77

88
__all__ = ["merge_google_napoleon_docs", "merge_numpy_napoleon_docs"]
99

10+
ALIASES = {
11+
"Args": "Parameters",
12+
"Arguments": "Parameters",
13+
"Keyword Args": "Keyword Arguments",
14+
"Return": "Returns",
15+
"Warnings": "Warning",
16+
"Yield": "Yields",
17+
"Note": "Notes",
18+
"Example": "Examples",
19+
}
20+
1021

1122
def parse_napoleon_doc(doc, style):
1223
""" Extract the text from the various sections of a numpy-formatted docstring.
@@ -29,30 +40,20 @@ def parse_napoleon_doc(doc, style):
2940
"Attributes",
3041
"Methods",
3142
"Warning",
32-
"Note",
3343
"Parameters",
3444
"Other Parameters",
3545
"Keyword Arguments",
3646
"Returns",
3747
"Yields",
3848
"Raises",
49+
"Notes",
3950
"Warns",
4051
"See Also",
4152
"References",
4253
"Todo",
43-
"Example",
4454
"Examples",
4555
]
4656

47-
aliases = {
48-
"Args": "Parameters",
49-
"Arguments": "Parameters",
50-
"Keyword Args": "Keyword Arguments",
51-
"Return": "Returns",
52-
"Warnings": "Warning",
53-
"Yield": "Yields",
54-
}
55-
5657
doc_sections = OrderedDict([(key, None) for key in napoleon_sections])
5758

5859
section_items.set_defaults(doc_sections)
@@ -75,8 +76,8 @@ def parse_napoleon_doc(doc, style):
7576
if style == "numpy"
7677
else (line[:-1] if line.endswith(":") else line)
7778
)
78-
if header and (header in doc_sections or header in aliases):
79-
doc_sections[aliases.get(key, key)] = (
79+
if header and (header in doc_sections or header in ALIASES):
80+
doc_sections[ALIASES.get(key, key)] = (
8081
"\n".join(body).rstrip() if body else None
8182
)
8283
body = []
@@ -86,7 +87,7 @@ def parse_napoleon_doc(doc, style):
8687
else:
8788
body.append(line)
8889
except StopIteration:
89-
doc_sections[aliases.get(key, key)] = "\n".join(body)
90+
doc_sections[ALIASES.get(key, key)] = "\n".join(body)
9091
break
9192

9293
section_items.parse(doc_sections)
@@ -110,12 +111,6 @@ def merge_section(key, prnt_sec, child_sec, style, merge_within_sections=False):
110111
Optional[str]
111112
The output docstring section."""
112113

113-
napoleon_sections_that_cant_merge = [
114-
"Short Summary",
115-
"Example",
116-
"Examples",
117-
]
118-
119114
if not prnt_sec and not child_sec:
120115
return None
121116

@@ -131,14 +126,6 @@ def merge_section(key, prnt_sec, child_sec, style, merge_within_sections=False):
131126

132127
if key in section_items.SECTION_NAMES:
133128
body = section_items.merge(prnt_sec, child_sec, merge_within_sections, style)
134-
135-
elif merge_within_sections and key not in napoleon_sections_that_cant_merge:
136-
if child_sec is None:
137-
body = prnt_sec
138-
elif prnt_sec is None:
139-
body = child_sec
140-
else:
141-
body = '\n'.join((prnt_sec, child_sec))
142129
else:
143130
body = prnt_sec if child_sec is None else child_sec
144131

src/custom_inherit/_doc_parse_tools/numpy_parse_tools.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,6 @@ def merge_section(key, prnt_sec, child_sec, merge_within_sections=False):
8484
Optional[str]
8585
The output docstring section."""
8686

87-
doc_sections_that_cant_merge = [
88-
"Short Summary",
89-
"Deprecation Warning",
90-
"Extended Summary",
91-
"Examples"
92-
]
93-
9487
if not prnt_sec and not child_sec:
9588
return None
9689

@@ -101,14 +94,6 @@ def merge_section(key, prnt_sec, child_sec, merge_within_sections=False):
10194

10295
if key in section_items.SECTION_NAMES:
10396
body = section_items.merge(prnt_sec, child_sec, merge_within_sections, "numpy")
104-
105-
elif merge_within_sections and key not in doc_sections_that_cant_merge:
106-
if child_sec is None:
107-
body = prnt_sec
108-
elif prnt_sec is None:
109-
body = child_sec
110-
else:
111-
body = '\n'.join((prnt_sec, child_sec))
11297
else:
11398
body = prnt_sec if child_sec is None else child_sec
11499

src/custom_inherit/_doc_parse_tools/section_items.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,26 @@
99
except ImportError:
1010
# for Python < 3.3
1111
def indent(text, padding):
12-
return ''.join(padding+line for line in text.splitlines(True))
12+
return "".join(padding + line for line in text.splitlines(True))
1313

1414

15-
_RE_PATTERN_ITEMS = re.compile(
16-
r"(\**\w+)(.*?)(?:$|(?=\n\**\w+))", flags=re.DOTALL
17-
)
15+
_RE_PATTERN_ITEMS = re.compile(r"(\**\w+)(.*?)(?:$|(?=\n\**\w+))", flags=re.DOTALL)
1816

1917
_STYLE_TO_PADDING = {
2018
"numpy": "",
2119
"google": " " * 4,
2220
}
2321

24-
SECTION_NAMES = ("Attributes", "Parameters")
22+
SECTION_NAMES = {
23+
"Attributes",
24+
"Parameters",
25+
"Methods",
26+
"Other Parameters",
27+
"Args",
28+
"Arguments",
29+
"Keyword Args",
30+
"Keyword Arguments",
31+
}
2532

2633

2734
def _render(body, style):
@@ -66,7 +73,9 @@ def parse(doc_sections):
6673
for section_name in SECTION_NAMES:
6774
section_content = doc_sections[section_name]
6875
if section_content:
69-
doc_sections[section_name] = OrderedDict(_RE_PATTERN_ITEMS.findall(inspect.cleandoc(section_content)))
76+
doc_sections[section_name] = OrderedDict(
77+
_RE_PATTERN_ITEMS.findall(inspect.cleandoc(section_content))
78+
)
7079

7180

7281
def merge(prnt_sec, child_sec, merge_within_sections, style):

src/custom_inherit/_metaclass_base.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616

1717
class DocInheritorBase(type):
18-
""" A metaclass that merges the respective docstrings of a parent class and of its child, along with their
18+
"""A metaclass that merges the respective docstrings of a parent class and of its child, along with their
1919
properties, methods (including classmethod, staticmethod, decorated methods).
2020
2121
This merge-style must be implemented via the static methods `class_doc_inherit`
@@ -45,9 +45,10 @@ def __new__(mcs, class_name, class_bases, class_dict):
4545
(FunctionType, MethodType, classmethod, staticmethod, property),
4646
)
4747
if (
48-
(attr.startswith("__") and attr.endswith("__") and not mcs.include_special_methods) or
49-
not is_doc_type
50-
):
48+
attr.startswith("__")
49+
and attr.endswith("__")
50+
and not mcs.include_special_methods
51+
) or not is_doc_type:
5152
continue
5253

5354
is_static_or_class = isinstance(attribute, (staticmethod, classmethod))
@@ -90,7 +91,7 @@ def __new__(mcs, class_name, class_bases, class_dict):
9091

9192
@staticmethod
9293
def class_doc_inherit(prnt_cls_doc, child_doc):
93-
""" Merge the docstrings of a parent class and its child.
94+
"""Merge the docstrings of a parent class and its child.
9495
9596
Parameters
9697
----------
@@ -104,7 +105,7 @@ def class_doc_inherit(prnt_cls_doc, child_doc):
104105

105106
@staticmethod
106107
def attr_doc_inherit(prnt_attr_doc, child_doc):
107-
""" Merge the docstrings of method or property from parent class and the corresponding
108+
"""Merge the docstrings of method or property from parent class and the corresponding
108109
attribute of its child.
109110
110111
Parameters

src/custom_inherit/_style_store.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -444,9 +444,9 @@ def numpy_with_merge(prnt_doc, child_doc):
444444
Parameters
445445
----------
446446
x: int
447-
description of x
447+
parent's description of x
448448
y: Union[None, int]
449-
description of y
449+
parent's description of y
450450
451451
Raises
452452
------
@@ -463,8 +463,10 @@ def numpy_with_merge(prnt_doc, child_doc):
463463
464464
Parameters
465465
----------
466+
y: int
467+
childs's description of y
466468
z: Union[None, int]
467-
description of z
469+
child's description of z
468470
469471
Returns
470472
-------
@@ -486,11 +488,11 @@ def numpy_with_merge(prnt_doc, child_doc):
486488
Parameters
487489
----------
488490
x: int
489-
description of x
490-
y: Union[None, int]
491-
description of y
491+
parent's description of x
492+
y: int
493+
childs's description of y
492494
z: Union[None, int]
493-
description of z
495+
child's description of z
494496
495497
Returns
496498
-------

tests/default_styles_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ def child():
434434
"multi-line\n\nMethods:\n parent methods\n\nWarning:\n warnings\n\nParameters:\n "
435435
"parent's Parameters\n alias for Parameters - child's section\n\nOther Parameters:\n "
436436
"other\n\nKeyword Arguments:\n parent's section\n alias for Keyword Arguments - child's section"
437-
"\n\nReturns:\n return\n\nYields:\n alias of Yields - parent's\n yield\n\nRaises:\n "
437+
"\n\nReturns:\n return\n\nYields:\n yield\n\nRaises:\n "
438438
"raise\n\nNotes:\n note\n\nWarns:\n warns\n\nSee Also:\n see\n\nReferences:\n "
439439
"ref\n\nTodo:\n todo\n\nExamples:\n child's example"
440440
)
@@ -629,7 +629,7 @@ def child():
629629
"\nParameters\n----------\nparent's Parameters\nalias for Parameters - child's section\n"
630630
"\nOther Parameters\n----------------\nother\n\nKeyword Arguments\n-----------------\n"
631631
"parent's section\nalias for Keyword Arguments - child's section\n\nReturns\n-------\n"
632-
"return\n\nYields\n------\nalias of Yields - parent's\nyield\n\nRaises\n------\nraise\n"
632+
"return\n\nYields\n------\nyield\n\nRaises\n------\nraise\n"
633633
"\nNotes\n-----\nnote\n\nWarns\n-----\nwarns\n\nSee Also\n--------\nsee\n\nReferences\n"
634634
"----------\nref\n\nTodo\n----\ntodo\n\nExamples\n--------\nchild's example"
635635
)

0 commit comments

Comments
 (0)