|
1 |
| -# wrap the plot commands defined in axes. The code generated by this |
| 1 | +# Wrap the plot commands defined in axes. The code generated by this |
2 | 2 | # file is pasted into pylab.py. We did try to do this the smart way,
|
3 | 3 | # with callable functions and new.function, but could never get the
|
4 | 4 | # docstrings right for python2.2. See
|
5 | 5 | # http://groups.google.com/group/comp.lang.python/browse_frm/thread/dcd63ec13096a0f6/1b14640f3a4ad3dc?#1b14640f3a4ad3dc
|
| 6 | +# For some later history, see |
| 7 | +# http://thread.gmane.org/gmane.comp.python.matplotlib.devel/7068 |
6 | 8 |
|
| 9 | +import inspect |
| 10 | +import random |
| 11 | +import re |
| 12 | +import sys |
| 13 | +import types |
7 | 14 |
|
8 |
| -# note we check for __doc__ is not None since py2exe optimize removes |
9 |
| -# the docstrings |
| 15 | +# import the local copy of matplotlib, not the installed one |
| 16 | +sys.path.insert(0, './lib') |
| 17 | +from matplotlib.axes import Axes |
| 18 | +from matplotlib.cbook import dedent |
10 | 19 |
|
11 | 20 | _fmtplot = """\
|
12 | 21 | # This function was autogenerated by boilerplate.py. Do not edit as
|
13 | 22 | # changes will be lost
|
14 |
| -def %(func)s(*args, **kwargs): |
| 23 | +def %(func)s(%(argspec)s): |
| 24 | + %(docstring)s |
| 25 | + %(ax)s = gca() |
15 | 26 | # allow callers to override the hold state by passing hold=True|False
|
16 |
| - b = ishold() |
17 |
| - h = kwargs.pop('hold', None) |
18 |
| - if h is not None: |
19 |
| - hold(h) |
| 27 | + %(washold)s = %(ax)s.ishold() |
| 28 | + %(sethold)s |
| 29 | + if hold is not None: |
| 30 | + %(ax)s.hold(hold) |
20 | 31 | try:
|
21 |
| - ret = gca().%(func)s(*args, **kwargs) |
| 32 | + %(ret)s = %(ax)s.%(func)s(%(call)s) |
22 | 33 | draw_if_interactive()
|
23 |
| - except: |
24 |
| - hold(b) |
25 |
| - raise |
| 34 | + finally: |
| 35 | + %(ax)s.hold(%(washold)s) |
26 | 36 | %(mappable)s
|
27 |
| - hold(b) |
28 |
| - return ret |
29 |
| -if Axes.%(func)s.__doc__ is not None: |
30 |
| - %(func)s.__doc__ = dedent(Axes.%(func)s.__doc__) + \"\"\" |
31 |
| -
|
32 |
| -Additional kwargs: hold = [True|False] overrides default hold state\"\"\" |
| 37 | + return %(ret)s |
33 | 38 | """
|
34 | 39 |
|
35 | 40 | _fmtmisc = """\
|
36 | 41 | # This function was autogenerated by boilerplate.py. Do not edit as
|
37 | 42 | # changes will be lost
|
38 |
| -def %(func)s(*args, **kwargs): |
39 |
| -
|
40 |
| - ret = gca().%(func)s(*args, **kwargs) |
| 43 | +def %(func)s(%(argspec)s): |
| 44 | + %(docstring)s |
| 45 | + %(ret)s = gca().%(func)s(%(call)s) |
41 | 46 | draw_if_interactive()
|
42 |
| - return ret |
43 |
| -if Axes.%(func)s.__doc__ is not None: |
44 |
| - %(func)s.__doc__ = dedent(Axes.%(func)s.__doc__) |
| 47 | + return %(ret)s |
45 | 48 | """
|
46 | 49 |
|
47 | 50 | # these methods are all simple wrappers of Axes methods by the same
|
@@ -101,32 +104,112 @@ def %(func)s(*args, **kwargs):
|
101 | 104 | )
|
102 | 105 |
|
103 | 106 | cmappable = {
|
104 |
| - 'contour' : 'if ret._A is not None: gci._current = ret', |
105 |
| - 'contourf': 'if ret._A is not None: gci._current = ret', |
106 |
| - 'hexbin' : 'gci._current = ret[0]', |
107 |
| - 'scatter' : 'gci._current = ret', |
108 |
| - 'pcolor' : 'gci._current = ret', |
109 |
| - 'pcolormesh' : 'gci._current = ret', |
110 |
| - 'imshow' : 'gci._current = ret', |
111 |
| - 'spy' : 'gci._current = ret', |
112 |
| - 'quiver' : 'gci._current = ret', |
113 |
| - 'specgram' : 'gci._current = ret[-1]', |
| 107 | + 'contour' : 'if %(ret)s._A is not None: gci._current = %(ret)s', |
| 108 | + 'contourf': 'if %(ret)s._A is not None: gci._current = %(ret)s', |
| 109 | + 'hexbin' : 'gci._current = %(ret)s', |
| 110 | + 'scatter' : 'gci._current = %(ret)s', |
| 111 | + 'pcolor' : 'gci._current = %(ret)s', |
| 112 | + 'pcolormesh' : 'gci._current = %(ret)s', |
| 113 | + 'imshow' : 'gci._current = %(ret)s', |
| 114 | + 'spy' : 'gci._current = %(ret)s', |
| 115 | + 'quiver' : 'gci._current = %(ret)s', |
| 116 | + 'specgram' : 'gci._current = %(ret)s[-1]', |
114 | 117 |
|
115 | 118 | }
|
116 | 119 |
|
117 |
| - |
118 |
| -for func in _plotcommands: |
119 |
| - if func in cmappable: |
120 |
| - mappable = cmappable[func] |
121 |
| - else: |
122 |
| - mappable = '' |
123 |
| - print _fmtplot%locals() |
124 |
| - |
125 |
| - |
126 |
| -for func in _misccommands: |
127 |
| - print _fmtmisc%locals() |
128 |
| - |
129 |
| - |
| 120 | +def format_value(value): |
| 121 | + """ |
| 122 | + Format function default values as needed for inspect.formatargspec. |
| 123 | + The interesting part is a hard-coded list of functions used |
| 124 | + as defaults in pyplot methods. |
| 125 | + """ |
| 126 | + if isinstance(value, types.FunctionType): |
| 127 | + if value.func_name in ('detrend_none', 'window_hanning'): |
| 128 | + return '=mlab.' + value.func_name |
| 129 | + if value.func_name == 'mean': |
| 130 | + return '=np.' + value.func_name |
| 131 | + raise ValueError, ('default value %s unknown to boilerplate.formatvalue' |
| 132 | + % value) |
| 133 | + return '='+repr(value) |
| 134 | + |
| 135 | +def remove_final_whitespace(string): |
| 136 | + """ |
| 137 | + Return a copy of *string* with final whitespace removed from each line. |
| 138 | + """ |
| 139 | + return '\n'.join(x.rstrip() for x in string.split('\n')) |
| 140 | + |
| 141 | +def make_docstring(cmd, mention_hold): |
| 142 | + func = getattr(Axes, cmd) |
| 143 | + docstring = inspect.getdoc(func) |
| 144 | + if docstring is None: |
| 145 | + return "" |
| 146 | + escaped = re.sub(r'\\', r'\\\\', docstring) |
| 147 | + if mention_hold: |
| 148 | + escaped += ''' |
| 149 | +
|
| 150 | +Additional kwargs: hold = [True|False] overrides default hold state |
| 151 | +''' |
| 152 | + return '"""'+escaped+'"""' |
| 153 | + |
| 154 | +for fmt,cmdlist in (_fmtplot,_plotcommands),(_fmtmisc,_misccommands): |
| 155 | + for func in cmdlist: |
| 156 | + # For some commands, an additional line is needed to set the |
| 157 | + # color map |
| 158 | + if func in cmappable: |
| 159 | + mappable = cmappable[func] % locals() |
| 160 | + else: |
| 161 | + mappable = '' |
| 162 | + |
| 163 | + # Format docstring |
| 164 | + docstring = make_docstring(func, fmt is _fmtplot) |
| 165 | + |
| 166 | + # Get argspec of wrapped function |
| 167 | + args, varargs, varkw, defaults = inspect.getargspec(getattr(Axes, func)) |
| 168 | + args.pop(0) # remove 'self' argument |
| 169 | + if defaults is None: |
| 170 | + defaults = () |
| 171 | + |
| 172 | + # How to call the wrapped function |
| 173 | + call = map(str, args) |
| 174 | + if varargs is not None: |
| 175 | + call.append('*'+varargs) |
| 176 | + if varkw is not None: |
| 177 | + call.append('**'+varkw) |
| 178 | + call = ', '.join(call) |
| 179 | + |
| 180 | + # Add a hold keyword argument if needed (fmt is _fmtplot) and |
| 181 | + # possible (if *args is used, we can't just add a hold |
| 182 | + # argument in front of it since it would gobble one of the |
| 183 | + # arguments the user means to pass via *args) |
| 184 | + if varargs: |
| 185 | + sethold = "hold = %(varkw)s.pop('hold', None)" % locals() |
| 186 | + elif fmt is _fmtplot: |
| 187 | + args.append('hold') |
| 188 | + defaults = defaults + (None,) |
| 189 | + sethold = '' |
| 190 | + |
| 191 | + # Now we can build the argspec for defining the wrapper |
| 192 | + argspec = inspect.formatargspec(args, varargs, varkw, defaults, |
| 193 | + formatvalue=format_value) |
| 194 | + argspec = argspec[1:-1] # remove parens |
| 195 | + |
| 196 | + # A gensym-like facility in case some function takes an |
| 197 | + # argument named washold, ax, or ret |
| 198 | + washold,ret,ax = 'washold', 'ret', 'ax' |
| 199 | + bad = set(args) | set((varargs, varkw)) |
| 200 | + while washold in bad or ret in bad or ax in bad: |
| 201 | + washold = 'washold' + str(random.randrange(10**12)) |
| 202 | + ret = 'ret' + str(random.randrange(10**12)) |
| 203 | + ax = 'ax' + str(random.randrange(10**12)) |
| 204 | + |
| 205 | + # Since we can't avoid using some function names, |
| 206 | + # bail out if they are used as argument names |
| 207 | + for reserved in ('gca', 'gci', 'draw_if_interactive'): |
| 208 | + if reserved in bad: |
| 209 | + raise ValueError, \ |
| 210 | + 'Axes method %s has kwarg named %s' % (func, reserved) |
| 211 | + |
| 212 | + print remove_final_whitespace(fmt%locals()) |
130 | 213 |
|
131 | 214 | # define the colormap functions
|
132 | 215 | _fmtcmap = """\
|
|
0 commit comments