From 29f1c873086abfc1d6906cd8a2d9107fe54df81f Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 30 Mar 2019 22:38:48 +0100 Subject: [PATCH] Generate Figure method wrappers via boilerplate.py --- lib/matplotlib/pyplot.py | 67 +++++++++++++++++++++++++--------------- tools/boilerplate.py | 48 +++++++++++++++++++++------- 2 files changed, 79 insertions(+), 36 deletions(-) diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 84cf4fc723cd..b79c0f7b2439 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -700,34 +700,9 @@ def savefig(*args, **kwargs): return res -@docstring.copy(Figure.ginput) -def ginput(*args, **kwargs): - return gcf().ginput(*args, **kwargs) - - -@docstring.copy(Figure.waitforbuttonpress) -def waitforbuttonpress(*args, **kwargs): - return gcf().waitforbuttonpress(*args, **kwargs) - - ## Putting things in figures ## -@docstring.copy(Figure.text) -def figtext(x, y, s, *args, **kwargs): - return gcf().text(x, y, s, *args, **kwargs) - - -@docstring.copy(Figure.suptitle) -def suptitle(t, **kwargs): - return gcf().suptitle(t, **kwargs) - - -@docstring.copy(Figure.figimage) -def figimage(*args, **kwargs): - return gcf().figimage(*args, **kwargs) - - def figlegend(*args, **kwargs): return gcf().legend(*args, **kwargs) if Figure.legend.__doc__: @@ -2327,6 +2302,48 @@ def getname_val(identifier): ################# REMAINING CONTENT GENERATED BY boilerplate.py ############## +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@docstring.copy(Figure.figimage) +def figimage( + X, xo=0, yo=0, alpha=None, norm=None, cmap=None, vmin=None, + vmax=None, origin=None, resize=False, **kwargs): + return gcf().figimage( + X, xo=xo, yo=yo, alpha=alpha, norm=norm, cmap=cmap, vmin=vmin, + vmax=vmax, origin=origin, resize=resize, **kwargs) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@docstring.copy(Figure.text) +def figtext( + x, y, s, fontdict=None, + withdash=cbook.deprecation._deprecated_parameter, **kwargs): + return gcf().text( + x, y, s, fontdict=fontdict, withdash=withdash, **kwargs) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@docstring.copy(Figure.ginput) +def ginput( + n=1, timeout=30, show_clicks=True, mouse_add=1, mouse_pop=3, + mouse_stop=2): + return gcf().ginput( + n=n, timeout=timeout, show_clicks=show_clicks, + mouse_add=mouse_add, mouse_pop=mouse_pop, + mouse_stop=mouse_stop) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@docstring.copy(Figure.suptitle) +def suptitle(t, **kwargs): + return gcf().suptitle(t, **kwargs) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@docstring.copy(Figure.waitforbuttonpress) +def waitforbuttonpress(timeout=-1): + return gcf().waitforbuttonpress(timeout=timeout) + + # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @docstring.copy(Axes.acorr) def acorr(x, *, data=None, **kwargs): diff --git a/tools/boilerplate.py b/tools/boilerplate.py index 3cc470fba803..caec5247410e 100644 --- a/tools/boilerplate.py +++ b/tools/boilerplate.py @@ -22,6 +22,7 @@ import numpy as np from matplotlib import cbook, mlab from matplotlib.axes import Axes +from matplotlib.figure import Figure # This is the magic line that must exist in pyplot, after which the boilerplate @@ -34,7 +35,7 @@ # Autogenerated by boilerplate.py. Do not edit as changes will be lost.""" -CMAPPABLE_TEMPLATE = AUTOGEN_MSG + """ +AXES_CMAPPABLE_METHOD_TEMPLATE = AUTOGEN_MSG + """ @docstring.copy(Axes.{called_name}) def {name}{signature}: __ret = gca().{called_name}{call} @@ -42,12 +43,18 @@ def {name}{signature}: return __ret """ -NON_CMAPPABLE_TEMPLATE = AUTOGEN_MSG + """ +AXES_METHOD_TEMPLATE = AUTOGEN_MSG + """ @docstring.copy(Axes.{called_name}) def {name}{signature}: return gca().{called_name}{call} """ +FIGURE_METHOD_TEMPLATE = AUTOGEN_MSG + """ +@docstring.copy(Figure.{called_name}) +def {name}{signature}: + return gcf().{called_name}{call} +""" + # Used for colormap functions CMAP_TEMPLATE = AUTOGEN_MSG + ''' def {name}(): @@ -84,7 +91,7 @@ def __repr__(self): return self._repr -def generate_function(name, called_name, template, **kwargs): +def generate_function(name, called_fullname, template, **kwargs): """ Create a wrapper function *pyplot_name* calling *call_name*. @@ -92,8 +99,8 @@ def generate_function(name, called_name, template, **kwargs): ---------- name : str The function to be created. - called_name : str - The function to be wrapped. + called_fullname : str + The method to be wrapped in the format ``"Class.method"``. template : str The template to be used. The template must contain {}-style format placeholders. The following placeholders are filled in: @@ -111,7 +118,10 @@ def generate_function(name, called_name, template, **kwargs): initial_indent=' ' * 8, subsequent_indent=' ' * 8) # Get signature of wrapped function. - signature = inspect.signature(getattr(Axes, called_name)) + class_name, called_name = called_fullname.split('.') + class_ = {'Axes': Axes, 'Figure': Figure}[class_name] + + signature = inspect.signature(getattr(class_, called_name)) # Replace self argument. params = list(signature.parameters.values())[1:] signature = str(signature.replace(parameters=[ @@ -148,10 +158,10 @@ def generate_function(name, called_name, template, **kwargs): if MAX_CALL_PREFIX + max(len(name), len(called_name)) + len(call) >= 80: call = '(\n' + text_wrapper.fill(call[1:]) # Bail out in case of name collision. - for reserved in ('gca', 'gci', '__ret'): + for reserved in ('gca', 'gci', 'gcf', '__ret'): if reserved in params: raise ValueError( - f'Axes method {called_name} has kwarg named {reserved}') + f'Method {called_fullname} has kwarg named {reserved}') return template.format( name=name, @@ -164,6 +174,14 @@ def generate_function(name, called_name, template, **kwargs): def boilerplate_gen(): """Generator of lines for the automated part of pyplot.""" + _figure_commands = ( + 'figimage', + 'figtext:text', + 'ginput', + 'suptitle', + 'waitforbuttonpress', + ) + # These methods are all simple wrappers of Axes methods by the same name. _axes_commands = ( 'acorr', @@ -261,15 +279,23 @@ def boilerplate_gen(): 'tripcolor': 'sci(__ret)', } + for spec in _figure_commands: + if ':' in spec: + name, called_name = spec.split(':') + else: + name = called_name = spec + yield generate_function(name, f'Figure.{called_name}', + FIGURE_METHOD_TEMPLATE) + for spec in _axes_commands: if ':' in spec: name, called_name = spec.split(':') else: name = called_name = spec - template = (CMAPPABLE_TEMPLATE if name in cmappable else - NON_CMAPPABLE_TEMPLATE) - yield generate_function(name, called_name, template, + template = (AXES_CMAPPABLE_METHOD_TEMPLATE if name in cmappable else + AXES_METHOD_TEMPLATE) + yield generate_function(name, f'Axes.{called_name}', template, sci_command=cmappable.get(name)) cmaps = (