Skip to content

Commit f0a92d6

Browse files
committed
Implement geo plotting overrides with metaclasses
1 parent 4945474 commit f0a92d6

File tree

2 files changed

+104
-215
lines changed

2 files changed

+104
-215
lines changed

proplot/axes/base.py

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
The base axes class used for all ProPlot figures.
44
"""
55
import copy
6+
import functools
67
import re
8+
import types
79
from numbers import Integral, Number
810

911
import matplotlib.axes as maxes
@@ -57,7 +59,7 @@
5759
}
5860

5961

60-
docstring.snippets['axes.other'] = """
62+
_format_other_docstring = """
6163
rc_kw : dict, optional
6264
Dictionary containing `~proplot.config.rc` settings applied to
6365
this axes using `~proplot.config.RcConfigurator.context`.
@@ -66,24 +68,16 @@
6668
and used to update axes `~proplot.config.rc` settings. For example,
6769
``abcstyle='A.'`` modifies the :rcraw:`abc.style` setting.
6870
"""
71+
docstring.snippets['axes.format_other'] = _format_other_docstring
6972

70-
docstring.snippets['axes.patch_kw'] = """
73+
_patch_kw_docstring = """
7174
patch_kw : dict-like, optional
7275
Keyword arguments used to update the background patch. This can
7376
be used e.g. to apply background hatching with ``patch_kw={'hatch': 'xxx'}``.
7477
"""
78+
docstring.snippets['axes.patch_kw'] = _patch_kw_docstring
7579

76-
docstring.snippets['axes.proj'] = """
77-
The map projection specification(s). If ``'cartesian'`` (the default), a
78-
`~proplot.axes.CartesianAxes` is created. If ``'polar'``, a
79-
`~proplot.axes.PolarAxes` is created. Otherwise, the argument is
80-
interpreted by `~proplot.constructor.Proj`, and the result is used
81-
to make a `~proplot.axes.GeoAxes` (in this case the argument can be
82-
a `cartopy.crs.Projection` instance, a `~mpl_toolkits.basemap.Basemap`
83-
instance, or a projection name listed in :ref:`this table <proj_table>`).
84-
"""
85-
86-
docstring.snippets['axes.inset'] = """
80+
_inset_docstring = """
8781
Return an inset `CartesianAxes`. This is similar to the builtin
8882
`~matplotlib.axes.Axes.inset_axes` but includes some extra options.
8983
@@ -129,9 +123,10 @@
129123
----------------
130124
**kwargs
131125
Passed to `CartesianAxes`.
132-
""" % docstring.snippets
126+
"""
127+
docstring.snippets['axes.inset'] = _inset_docstring
133128

134-
docstring.snippets['axes.panel'] = """
129+
_panel_docstring = """
135130
Return a panel drawn along the edge of this axes.
136131
137132
Parameters
@@ -166,9 +161,34 @@
166161
`~proplot.axes.CartesianAxes`
167162
The panel axes.
168163
"""
164+
docstring.snippets['axes.panel'] = _panel_docstring
165+
166+
167+
class _MetaAxes(type):
168+
"""
169+
Redirect internal plotting calls to native matplotlib methods.
170+
"""
171+
# NOTE: This obviates the need for basemap-specific redirection to mpl.axes.Axes.
172+
def __new__(cls, name, bases, dct_orig):
173+
dct = dct_orig.copy()
174+
for attr, func_proplot in tuple(dct_orig.items()):
175+
if attr[:1] == '_':
176+
continue
177+
func_matplotlib = getattr(maxes.Axes, attr, None)
178+
if not isinstance(func_proplot, types.FunctionType):
179+
continue
180+
if not isinstance(func_matplotlib, types.FunctionType):
181+
continue
182+
dct[attr] = functools.wraps(func_proplot)(
183+
lambda self, *args, _func_proplot=func_proplot, _func_matplotlib=func_matplotlib, **kwargs: # noqa: E501
184+
_func_matplotlib(self, *args, **kwargs)
185+
if getattr(self, '_internal_call', None) else
186+
_func_proplot(self, *args, **kwargs)
187+
)
188+
return super().__new__(cls, name, bases, dct)
169189

170190

171-
class Axes(maxes.Axes):
191+
class Axes(maxes.Axes, metaclass=_MetaAxes):
172192
"""
173193
Lowest-level axes subclass. Handles titles and axis
174194
sharing. Adds several new methods and overrides existing ones.

0 commit comments

Comments
 (0)