diff --git a/docs/api.rst b/docs/api.rst index 866051d69..dab35c2f4 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -4,14 +4,23 @@ API reference ============= -The comprehensive API reference. All of the below objects are imported -into the top-level namespace. Use ``help(pplt.object)`` to read -the docs during a python session. +Comprehensive documentation of ProPlot functions and classes. All of these +objects are imported into the top-level namespace, so you can read the +documentation within python sessions using ``help(pplt.function_or_class)``. +Please note that the "wrapper" function documentation from proplot < 0.8 +is now located on the individual plotting commands under +`proplot.axes.PlotAxes`. When calling ``help(axes.command)`` on +plotting commands during a python session, both the ProPlot +documentation and the original matplotlib documentation are shown. + +Top-level functions +=================== + +.. automodule:: proplot.ui + +.. automodsumm:: proplot.ui + :toctree: api -Please note that the documentation for "wrapper" functions from -proplot < 0.8 is now found under the individual `~proplot.axes.PlotAxes` -plotting commands. Using ``help(ax.command)`` during a python session shows both -the proplot documentation and the original matplotlib documentation. Figure class ============ @@ -20,16 +29,16 @@ Figure class .. automodsumm:: proplot.figure :toctree: api + :skip: SubplotsContainer -Grid classes -============ +Gridspec class +============== .. automodule:: proplot.gridspec .. automodsumm:: proplot.gridspec :toctree: api - :skip: SubplotsContainer Axes classes @@ -41,15 +50,6 @@ Axes classes :toctree: api -Top-level functions -=================== - -.. automodule:: proplot.ui - -.. automodsumm:: proplot.ui - :toctree: api - - Configuration tools =================== @@ -107,20 +107,29 @@ Projection classes :toctree: api -Demo functions -============== +Artist subclass +=============== -.. automodule:: proplot.demos +.. automodule:: proplot.artist -.. automodsumm:: proplot.demos +.. automodsumm:: proplot.artist :toctree: api -Miscellaneous functions -======================= +Miscellaneous tools +=================== .. automodule:: proplot.utils .. automodsumm:: proplot.utils :toctree: api :skip: shade, saturate + + +Demo functions +============== + +.. automodule:: proplot.demos + +.. automodsumm:: proplot.demos + :toctree: api diff --git a/proplot/__init__.py b/proplot/__init__.py index 17c150d14..b94da2354 100644 --- a/proplot/__init__.py +++ b/proplot/__init__.py @@ -50,6 +50,7 @@ from .ui import * # noqa: F401 F403 with _benchmark('demos'): from .demos import * # noqa: F401 F403 + from .artist import * # noqa: F401 F403 # Dynamically add registered classes to top-level namespace from .constructor import NORMS, LOCATORS, FORMATTERS, SCALES, PROJS diff --git a/proplot/artist.py b/proplot/artist.py new file mode 100644 index 000000000..86a39e680 --- /dev/null +++ b/proplot/artist.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +""" +Add dot-notation properties for matplotlib setter and getter functions. +""" +import warnings + +import matplotlib.artist as martist +from matplotlib import MatplotlibDeprecationWarning + +__all__ = [] + + +PROPS_IGNORE = ( + # Axes props + 'axes', + 'figure', + 'xaxis', # axes prop + 'yaxis', # axes prop + 'zaxis', # axes prop + 'units', # axis prop + 'gridlines', + # Method conflicts + 'legend', + 'tight_layout', + # Class-level conflicts + 'contains', + 'zorder', + 'pickradius', # line property related to 'contains' + # Instance-level artist conflicts + 'label', + 'label_position', + # Instance-level axes conflicts + 'cmap', + 'norm', + 'lines', + 'images', + 'title', # TODO: use internal title handling +) + + +def _iter_subclasses(cls): + """ + Iterate through all subclasses. + """ + yield cls + try: + for subclass in cls.__subclasses__(): + yield from _iter_subclasses(subclass) + except TypeError: + pass + + +def _add_properties(cls): + """ + Generate property definitions for every artist getter. + """ + for attr in dir(cls): + try: + getter = getattr(cls, attr) + except MatplotlibDeprecationWarning: + continue + if not callable(getter) or attr[:4] != 'get_': + continue + prop = attr[4:] + if prop in PROPS_IGNORE: + continue + if hasattr(cls, prop): + value = getattr(cls, prop) + if not isinstance(value, property): # i.e. this is not child of a class + warnings._warn_proplot(f'Skipping property {prop!r}. Already exists as attribute.') # noqa: E501 + continue + args = [getter] # property() function args + setter = getattr(cls, 'set_' + prop, None) + if callable(setter): + args.append(setter) + obj = property(*args, doc=getter.__doc__) + setattr(cls, prop, obj) + + +# Apply properties +# NOTE: While we can guard against class-level attribute conflicts we *cannot* guard +# against instance-level attribute conflicts. Therefore this may never work. +for cls in _iter_subclasses(martist.Artist): + with warnings.catch_warnings(): + warnings.simplefilter('error', MatplotlibDeprecationWarning) + _add_properties(cls)