Title: Implement Axes.format features with individual setters by lukelbd · Pull Request #89 · proplot-dev/proplot · GitHub
Open Graph Title: Implement Axes.format features with individual setters by lukelbd · Pull Request #89 · proplot-dev/proplot
X Title: Implement Axes.format features with individual setters by lukelbd · Pull Request #89 · proplot-dev/proplot
Description: Starting this PR to keep #63 on everyone's radar. Along with #50 and #45 this is one of the major (but mostly internal) changes I am considering for the version 1.0 release. ProPlot adds "batch" setter methods called format to every Axes subclass. The idea is it's quicker to call 1 method with 10 keyword arguments rather than 10 methods on 10 lines. Interestingly, it looks like the Plots.jl julia package follows a similar philosophy (see the "Lorenz attractor" example). However: It seems kind of sloppy / unpythonic to me to have individual settings that can only be modified with a batch setter. It also makes the setter methods really long and difficult to maintain. (no longer valid; see below) I want to encourage batch setting but permit individual one-liner setting if the user so chooses. One of my goals for version 1 is to incorporate ProPlot internals more closely with matplotlib, and matplotlib apparently has its own batch setter, Artist.set. However nobody uses it, probably because (1) it seldom appears in the online examples and (2) the valid arguments are not explicitly documented, which is confusing for new userss. With this PR, I'd like to combine the features of Axes.format with Artist.update and Artist.set by overriding the latter for axes artists. I will deprecate format and break up the format tasks into individual setters, but encourage using the batch setters by using them in all of the examples and documenting the acceptable keyword args. Here is some pseudocode to outline the general idea. # The batch setters @cbook.deprecated("1.0.0", alternative="Axes.set(...)") # use matplotlib's deprecation system? def format(self, **kwargs): _warn_proplot( 'Axes.format() was deprecated in version 1.0.0. Please use `Axes.set()` instead.' ) # or "deprecation" with a simple warning return self.set(*args, **kwargs) def set(self, **kwargs): # Just like Artist.set(), process aliases here, e.g. `xticklabels` for `xformatter` # May just add `_alias_map` and `_prop_order` attributes to Axes! self._alias_map = ... # make sure these hidden props are stable! self._prop_order = ... # then filter out rc props here, and maybe we can have some sort of # rcupdate() method that updates *any* rc property that has changed rcprops, kwargs = _process_kwargs(kwargs) self.applyrc(rcprops) super().set(**kwargs) def update(self, props): # *Superset* of internal matplotlib.artist.Artist.update() # Permit passing *keyword arguments* to each setter # Example: If we get `xlim` and `xlim_kw`, call `Axes.set_xlim(xlim, **xlim_kw)` def _update_property(self, k, v, **kwargs): k = k.lower() if k in {'axes'}: return setattr(self, k, v) else: func = getattr(self, 'set_' + k, None) if not callable(func): raise AttributeError( f'{type(self).__name__!r} object has no property {k!r}.') return func(v) with cbook._setattr_cm(self, eventson=False): ret = [] for key, value in _kwargs_not_ending_in_kw(kwargs).items(): kw = _kwarg_ending_in_kw(key) ret.append(_update_property(self, k, v, **kw)) return ret # Helper method that looks for rc setting names passed # to the bulk setters def applyrc(self, **kwargs): # perform various actions currently spread around Axes.format() with plot.rc.context(**kwargs): # apply "cached" props (i.e. props changed in this block) # plot.rc.fill(props, cached=True) # plot.rc.get(props, cached=True) # etc. pass # The individual setters # These replace features originally coded in Axes.format def set_abcstyle(self, style): if not isinstance(style, str) or (style.count('a') != 1 and style.count('A') != 1): raise ValueError abc = _abc(self.number - 1) if 'A' in style: abc = abc.upper() abc = re.sub('[aA]', abc, abcstyle) self.abc.set_text(abc) def set_xticks(self, locator, **kwargs): locator = axistools.Locator(locator, **kwargs) self.xaxis.set_major_locator(locator) def set_xminorticks(self, locator, **kwargs): locator = axistools.Locator(locator, **kwargs) self.xaxis.set_minor_locator(locator) def set_xticklabels(self, formatter, **kwargs): formatter = axistools.Formatter(formatter, **kwargs) self.xaxis.set_major_formatter(formatter) ... Then to encourage using the batch setters, we can concatenate docstrings from each individual setter: # Documentation builder def _get_setter_docs(self): # Maybe just retrieve first sentence of each docstring, # and look at `Axes._alias_map` for aliases! .... Axes.set.__doc__ = f""" Bulk update the axes. Parameters ----------- {_get_setter_docs(Axes)} """ # Results in the following docstring # (not sure how we can consistently get argument types though) """ Parameters ----------- xlim : (float, float), optional Call `~Axes.set_xlim`. Set the x-axis view limits. ylim : (float, float), optional Call `~Axes.set_ylim`. Set the y-axis view limits. ... etc ... """
Open Graph Description: Starting this PR to keep #63 on everyone's radar. Along with #50 and #45 this is one of the major (but mostly internal) changes I am considering for the version 1.0 release. ProPlot adds "...
X Description: Starting this PR to keep #63 on everyone's radar. Along with #50 and #45 this is one of the major (but mostly internal) changes I am considering for the version 1.0 release. ProPlot adds &a...
Opengraph URL: https://github.com/proplot-dev/proplot/pull/89
X: @github
Domain: patch-diff.githubusercontent.com
| route-pattern | /:user_id/:repository/pull/:id/files(.:format) |
| route-controller | pull_requests |
| route-action | files |
| fetch-nonce | v2:9c5e1c97-1213-70cd-beaa-911e3b4d0979 |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | A45E:39DB0D:A66FB9:E92BD1:697B93E1 |
| html-safe-nonce | 10e8969d472a4251b0cc4db01b6582656b4523c10c0c9c558e55497450df4597 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBNDVFOjM5REIwRDpBNjZGQjk6RTkyQkQxOjY5N0I5M0UxIiwidmlzaXRvcl9pZCI6IjQxMDQ4OTMxOTM2Njc3MTE5NjkiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | f6b12a11918c7adcd8dd5b3f88993bb02a25c8b8b2dfcf7a110caa4b7d257cfd |
| hovercard-subject-tag | pull_request:353384856 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/proplot-dev/proplot/pull/89/files |
| twitter:image | https://avatars.githubusercontent.com/u/19657652?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/19657652?s=400&v=4 |
| og:image:alt | Starting this PR to keep #63 on everyone's radar. Along with #50 and #45 this is one of the major (but mostly internal) changes I am considering for the version 1.0 release. ProPlot adds "... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | 50d60071257d18b32330d912202dc320d501c221ea1591db8fbf19715460d571 |
| turbo-cache-control | no-preview |
| diff-view | unified |
| go-import | github.com/proplot-dev/proplot git https://github.com/proplot-dev/proplot.git |
| octolytics-dimension-user_id | 108025793 |
| octolytics-dimension-user_login | proplot-dev |
| octolytics-dimension-repository_id | 113293661 |
| octolytics-dimension-repository_nwo | proplot-dev/proplot |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 113293661 |
| octolytics-dimension-repository_network_root_nwo | proplot-dev/proplot |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | true |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | dcefb04b18d0f0164691e133411da1c4c92e910c |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width