Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/scipy/_lib/doccer.py : 79%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1''' Utilities to allow inserting docstring fragments for common
2parameters into function and method docstrings'''
4import sys
6__all__ = ['docformat', 'inherit_docstring_from', 'indentcount_lines',
7 'filldoc', 'unindent_dict', 'unindent_string', 'doc_replace']
10def docformat(docstring, docdict=None):
11 ''' Fill a function docstring from variables in dictionary
13 Adapt the indent of the inserted docs
15 Parameters
16 ----------
17 docstring : string
18 docstring from function, possibly with dict formatting strings
19 docdict : dict, optional
20 dictionary with keys that match the dict formatting strings
21 and values that are docstring fragments to be inserted. The
22 indentation of the inserted docstrings is set to match the
23 minimum indentation of the ``docstring`` by adding this
24 indentation to all lines of the inserted string, except the
25 first.
27 Returns
28 -------
29 outstring : string
30 string with requested ``docdict`` strings inserted
32 Examples
33 --------
34 >>> docformat(' Test string with %(value)s', {'value':'inserted value'})
35 ' Test string with inserted value'
36 >>> docstring = 'First line\\n Second line\\n %(value)s'
37 >>> inserted_string = "indented\\nstring"
38 >>> docdict = {'value': inserted_string}
39 >>> docformat(docstring, docdict)
40 'First line\\n Second line\\n indented\\n string'
41 '''
42 if not docstring:
43 return docstring
44 if docdict is None:
45 docdict = {}
46 if not docdict:
47 return docstring
48 lines = docstring.expandtabs().splitlines()
49 # Find the minimum indent of the main docstring, after first line
50 if len(lines) < 2:
51 icount = 0
52 else:
53 icount = indentcount_lines(lines[1:])
54 indent = ' ' * icount
55 # Insert this indent to dictionary docstrings
56 indented = {}
57 for name, dstr in docdict.items():
58 lines = dstr.expandtabs().splitlines()
59 try:
60 newlines = [lines[0]]
61 for line in lines[1:]:
62 newlines.append(indent+line)
63 indented[name] = '\n'.join(newlines)
64 except IndexError:
65 indented[name] = dstr
66 return docstring % indented
69def inherit_docstring_from(cls):
70 """
71 This decorator modifies the decorated function's docstring by
72 replacing occurrences of '%(super)s' with the docstring of the
73 method of the same name from the class `cls`.
75 If the decorated method has no docstring, it is simply given the
76 docstring of `cls`s method.
78 Parameters
79 ----------
80 cls : Python class or instance
81 A class with a method with the same name as the decorated method.
82 The docstring of the method in this class replaces '%(super)s' in the
83 docstring of the decorated method.
85 Returns
86 -------
87 f : function
88 The decorator function that modifies the __doc__ attribute
89 of its argument.
91 Examples
92 --------
93 In the following, the docstring for Bar.func created using the
94 docstring of `Foo.func`.
96 >>> class Foo(object):
97 ... def func(self):
98 ... '''Do something useful.'''
99 ... return
100 ...
101 >>> class Bar(Foo):
102 ... @inherit_docstring_from(Foo)
103 ... def func(self):
104 ... '''%(super)s
105 ... Do it fast.
106 ... '''
107 ... return
108 ...
109 >>> b = Bar()
110 >>> b.func.__doc__
111 'Do something useful.\n Do it fast.\n '
113 """
114 def _doc(func):
115 cls_docstring = getattr(cls, func.__name__).__doc__
116 func_docstring = func.__doc__
117 if func_docstring is None:
118 func.__doc__ = cls_docstring
119 else:
120 new_docstring = func_docstring % dict(super=cls_docstring)
121 func.__doc__ = new_docstring
122 return func
123 return _doc
126def extend_notes_in_docstring(cls, notes):
127 """
128 This decorator replaces the decorated function's docstring
129 with the docstring from corresponding method in `cls`.
130 It extends the 'Notes' section of that docstring to include
131 the given `notes`.
132 """
133 def _doc(func):
134 cls_docstring = getattr(cls, func.__name__).__doc__
135 # If python is called with -OO option,
136 # there is no docstring
137 if cls_docstring is None:
138 return func
139 end_of_notes = cls_docstring.find(' References\n')
140 if end_of_notes == -1:
141 end_of_notes = cls_docstring.find(' Examples\n')
142 if end_of_notes == -1:
143 end_of_notes = len(cls_docstring)
144 func.__doc__ = (cls_docstring[:end_of_notes] + notes +
145 cls_docstring[end_of_notes:])
146 return func
147 return _doc
150def replace_notes_in_docstring(cls, notes):
151 """
152 This decorator replaces the decorated function's docstring
153 with the docstring from corresponding method in `cls`.
154 It replaces the 'Notes' section of that docstring with
155 the given `notes`.
156 """
157 def _doc(func):
158 cls_docstring = getattr(cls, func.__name__).__doc__
159 notes_header = ' Notes\n -----\n'
160 # If python is called with -OO option,
161 # there is no docstring
162 if cls_docstring is None:
163 return func
164 start_of_notes = cls_docstring.find(notes_header)
165 end_of_notes = cls_docstring.find(' References\n')
166 if end_of_notes == -1:
167 end_of_notes = cls_docstring.find(' Examples\n')
168 if end_of_notes == -1:
169 end_of_notes = len(cls_docstring)
170 func.__doc__ = (cls_docstring[:start_of_notes + len(notes_header)] +
171 notes +
172 cls_docstring[end_of_notes:])
173 return func
174 return _doc
177def indentcount_lines(lines):
178 ''' Minimum indent for all lines in line list
180 >>> lines = [' one', ' two', ' three']
181 >>> indentcount_lines(lines)
182 1
183 >>> lines = []
184 >>> indentcount_lines(lines)
185 0
186 >>> lines = [' one']
187 >>> indentcount_lines(lines)
188 1
189 >>> indentcount_lines([' '])
190 0
191 '''
192 indentno = sys.maxsize
193 for line in lines:
194 stripped = line.lstrip()
195 if stripped:
196 indentno = min(indentno, len(line) - len(stripped))
197 if indentno == sys.maxsize:
198 return 0
199 return indentno
202def filldoc(docdict, unindent_params=True):
203 ''' Return docstring decorator using docdict variable dictionary
205 Parameters
206 ----------
207 docdict : dictionary
208 dictionary containing name, docstring fragment pairs
209 unindent_params : {False, True}, boolean, optional
210 If True, strip common indentation from all parameters in
211 docdict
213 Returns
214 -------
215 decfunc : function
216 decorator that applies dictionary to input function docstring
218 '''
219 if unindent_params:
220 docdict = unindent_dict(docdict)
222 def decorate(f):
223 f.__doc__ = docformat(f.__doc__, docdict)
224 return f
225 return decorate
228def unindent_dict(docdict):
229 ''' Unindent all strings in a docdict '''
230 can_dict = {}
231 for name, dstr in docdict.items():
232 can_dict[name] = unindent_string(dstr)
233 return can_dict
236def unindent_string(docstring):
237 ''' Set docstring to minimum indent for all lines, including first
239 >>> unindent_string(' two')
240 'two'
241 >>> unindent_string(' two\\n three')
242 'two\\n three'
243 '''
244 lines = docstring.expandtabs().splitlines()
245 icount = indentcount_lines(lines)
246 if icount == 0:
247 return docstring
248 return '\n'.join([line[icount:] for line in lines])
251def doc_replace(obj, oldval, newval):
252 """Decorator to take the docstring from obj, with oldval replaced by newval
254 Equivalent to ``func.__doc__ = obj.__doc__.replace(oldval, newval)``
256 Parameters
257 ----------
258 obj: object
259 The object to take the docstring from.
260 oldval: string
261 The string to replace from the original docstring.
262 newval: string
263 The string to replace ``oldval`` with.
264 """
265 # __doc__ may be None for optimized Python (-OO)
266 doc = (obj.__doc__ or '').replace(oldval, newval)
268 def inner(func):
269 func.__doc__ = doc
270 return func
272 return inner