Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4adf436

Browse files
authored
Merge pull request #13744 from timhoffm/restructure-boilerplate
Restructure boilerplate.py
2 parents cce3ef4 + 235cd4d commit 4adf436

File tree

1 file changed

+115
-90
lines changed

1 file changed

+115
-90
lines changed

tools/boilerplate.py

Lines changed: 115 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,17 @@
3535
# Autogenerated by boilerplate.py. Do not edit as changes will be lost."""
3636

3737
CMAPPABLE_TEMPLATE = AUTOGEN_MSG + """
38-
@docstring.copy(Axes.%(real_name)s)
39-
def %(func)s%(sig)s:
40-
__ret = gca().%(real_name)s%(call)s
41-
%(mappable)s
38+
@docstring.copy(Axes.{called_name})
39+
def {name}{signature}:
40+
__ret = gca().{called_name}{call}
41+
{sci_command}
4242
return __ret
4343
"""
4444

4545
NON_CMAPPABLE_TEMPLATE = AUTOGEN_MSG + """
46-
@docstring.copy(Axes.%(real_name)s)
47-
def %(func)s%(sig)s:
48-
return gca().%(real_name)s%(call)s
46+
@docstring.copy(Axes.{called_name})
47+
def {name}{signature}:
48+
return gca().{called_name}{call}
4949
"""
5050

5151
# Used for colormap functions
@@ -61,11 +61,111 @@ def {name}():
6161
'''
6262

6363

64+
class value_formatter:
65+
"""
66+
Format function default values as needed for inspect.formatargspec.
67+
The interesting part is a hard-coded list of functions used
68+
as defaults in pyplot methods.
69+
"""
70+
71+
def __init__(self, value):
72+
if value is mlab.detrend_none:
73+
self._repr = "mlab.detrend_none"
74+
elif value is mlab.window_hanning:
75+
self._repr = "mlab.window_hanning"
76+
elif value is np.mean:
77+
self._repr = "np.mean"
78+
elif value is cbook.deprecation._deprecated_parameter:
79+
self._repr = "cbook.deprecation._deprecated_parameter"
80+
else:
81+
self._repr = repr(value)
82+
83+
def __repr__(self):
84+
return self._repr
85+
86+
87+
def generate_function(name, called_name, template, **kwargs):
88+
"""
89+
Create a wrapper function *pyplot_name* calling *call_name*.
90+
91+
Parameters
92+
----------
93+
name : str
94+
The function to be created.
95+
called_name : str
96+
The function to be wrapped.
97+
template : str
98+
The template to be used. The template must contain {}-style format
99+
placeholders. The following placeholders are filled in:
100+
101+
- name: The function name.
102+
- signature: The function signature (including parentheses).
103+
- called_name: The name of the called function.
104+
- call: Parameters passed to *called_name* (including parentheses).
105+
106+
**kwargs
107+
Additional parameters are passed to ``template.format()``.
108+
"""
109+
text_wrapper = textwrap.TextWrapper(
110+
break_long_words=False, width=70,
111+
initial_indent=' ' * 8, subsequent_indent=' ' * 8)
112+
113+
# Get signature of wrapped function.
114+
signature = inspect.signature(getattr(Axes, called_name))
115+
# Replace self argument.
116+
params = list(signature.parameters.values())[1:]
117+
signature = str(signature.replace(parameters=[
118+
param.replace(default=value_formatter(param.default))
119+
if param.default is not param.empty else param
120+
for param in params]))
121+
if len('def ' + name + signature) >= 80:
122+
# Move opening parenthesis before newline.
123+
signature = '(\n' + text_wrapper.fill(signature).replace('(', '', 1)
124+
# How to call the wrapped function.
125+
call = '(' + ', '.join((
126+
# Pass "intended-as-positional" parameters positionally to avoid
127+
# forcing third-party subclasses to reproduce the parameter names.
128+
'{0}'
129+
if param.kind in [
130+
Parameter.POSITIONAL_OR_KEYWORD]
131+
and param.default is Parameter.empty else
132+
# Only pass the data kwarg if it is actually set, to avoid forcing
133+
# third-party subclasses to support it.
134+
'**({{"data": data}} if data is not None else {{}})'
135+
if param.name == "data" else
136+
'{0}={0}'
137+
if param.kind in [
138+
Parameter.POSITIONAL_OR_KEYWORD,
139+
Parameter.KEYWORD_ONLY] else
140+
'*{0}'
141+
if param.kind is Parameter.VAR_POSITIONAL else
142+
'**{0}'
143+
if param.kind is Parameter.VAR_KEYWORD else
144+
# Intentionally crash for Parameter.POSITIONAL_ONLY.
145+
None).format(param.name)
146+
for param in params) + ')'
147+
MAX_CALL_PREFIX = 18 # len(' __ret = gca().')
148+
if MAX_CALL_PREFIX + max(len(name), len(called_name)) + len(call) >= 80:
149+
call = '(\n' + text_wrapper.fill(call[1:])
150+
# Bail out in case of name collision.
151+
for reserved in ('gca', 'gci', '__ret'):
152+
if reserved in params:
153+
raise ValueError(
154+
f'Axes method {called_name} has kwarg named {reserved}')
155+
156+
return template.format(
157+
name=name,
158+
called_name=called_name,
159+
signature=signature,
160+
call=call,
161+
**kwargs)
162+
163+
64164
def boilerplate_gen():
65165
"""Generator of lines for the automated part of pyplot."""
66166

67167
# These methods are all simple wrappers of Axes methods by the same name.
68-
_commands = (
168+
_axes_commands = (
69169
'acorr',
70170
'angle_spectrum',
71171
'annotate',
@@ -161,91 +261,16 @@ def boilerplate_gen():
161261
'tripcolor': 'sci(__ret)',
162262
}
163263

164-
class value_formatter:
165-
"""
166-
Format function default values as needed for inspect.formatargspec.
167-
The interesting part is a hard-coded list of functions used
168-
as defaults in pyplot methods.
169-
"""
170-
171-
def __init__(self, value):
172-
if value is mlab.detrend_none:
173-
self._repr = "mlab.detrend_none"
174-
elif value is mlab.window_hanning:
175-
self._repr = "mlab.window_hanning"
176-
elif value is np.mean:
177-
self._repr = "np.mean"
178-
elif value is cbook.deprecation._deprecated_parameter:
179-
self._repr = "cbook.deprecation._deprecated_parameter"
180-
else:
181-
self._repr = repr(value)
182-
183-
def __repr__(self):
184-
return self._repr
185-
186-
text_wrapper = textwrap.TextWrapper(
187-
break_long_words=False, width=70,
188-
initial_indent=' ' * 8, subsequent_indent=' ' * 8)
189-
190-
for spec in _commands:
264+
for spec in _axes_commands:
191265
if ':' in spec:
192-
func, real_name = spec.split(':')
266+
name, called_name = spec.split(':')
193267
else:
194-
func = real_name = spec
268+
name = called_name = spec
195269

196-
# For some commands, an additional line is needed to set the color map.
197-
if func in cmappable:
198-
fmt = CMAPPABLE_TEMPLATE
199-
mappable = ' ' + cmappable[func]
200-
else:
201-
fmt = NON_CMAPPABLE_TEMPLATE
202-
203-
# Get signature of wrapped function.
204-
sig = inspect.signature(getattr(Axes, real_name))
205-
206-
# Replace self argument.
207-
params = list(sig.parameters.values())[1:]
208-
209-
sig = str(sig.replace(parameters=[
210-
param.replace(default=value_formatter(param.default))
211-
if param.default is not param.empty else param
212-
for param in params]))
213-
if len('def ' + func + sig) >= 80:
214-
# Move opening parenthesis before newline.
215-
sig = '(\n' + text_wrapper.fill(sig).replace('(', '', 1)
216-
217-
# How to call the wrapped function.
218-
call = '(' + ', '.join((
219-
# Pass "intended-as-positional" parameters positionally to avoid
220-
# forcing third-party subclasses to reproduce the parameter names.
221-
'{0}'
222-
if param.kind in [Parameter.POSITIONAL_OR_KEYWORD]
223-
and param.default is Parameter.empty else
224-
# Only pass the data kwarg if it is actually set, to avoid forcing
225-
# third-party subclasses to support it.
226-
'**({{"data": data}} if data is not None else {{}})'
227-
if param.name == "data" else
228-
'{0}={0}'
229-
if param.kind in [Parameter.POSITIONAL_OR_KEYWORD,
230-
Parameter.KEYWORD_ONLY] else
231-
'*{0}'
232-
if param.kind is Parameter.VAR_POSITIONAL else
233-
'**{0}'
234-
if param.kind is Parameter.VAR_KEYWORD else
235-
# Intentionally crash for Parameter.POSITIONAL_ONLY.
236-
None).format(param.name)
237-
for param in params) + ')'
238-
MAX_CALL_PREFIX = 18 # len(' __ret = gca().')
239-
if MAX_CALL_PREFIX + max(len(func), len(real_name)) + len(call) >= 80:
240-
call = '(\n' + text_wrapper.fill(call[1:])
241-
242-
# Bail out in case of name collision.
243-
for reserved in ('gca', 'gci', '__ret'):
244-
if reserved in params:
245-
raise ValueError(
246-
'Axes method {} has kwarg named {}'.format(func, reserved))
247-
248-
yield fmt % locals()
270+
template = (CMAPPABLE_TEMPLATE if name in cmappable else
271+
NON_CMAPPABLE_TEMPLATE)
272+
yield generate_function(name, called_name, template,
273+
sci_command=cmappable.get(name))
249274

250275
cmaps = (
251276
'autumn',

0 commit comments

Comments
 (0)