diff --git a/doc/users/next_whats_new/spinesproxyset.rst b/doc/users/next_whats_new/spinesproxyset.rst new file mode 100644 index 000000000000..cfd8d2908ec7 --- /dev/null +++ b/doc/users/next_whats_new/spinesproxyset.rst @@ -0,0 +1,3 @@ +``SpinesProxy`` now supports calling the ``set()`` method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +One can now call e.g. ``ax.spines[:].set(visible=False)``. diff --git a/lib/matplotlib/spines.py b/lib/matplotlib/spines.py index 8560f7b6e4e2..eacb3e7e9d5c 100644 --- a/lib/matplotlib/spines.py +++ b/lib/matplotlib/spines.py @@ -479,7 +479,7 @@ def set_color(self, c): class SpinesProxy: """ - A proxy to broadcast ``set_*`` method calls to all contained `.Spines`. + A proxy to broadcast ``set_*()`` and ``set()`` method calls to contained `.Spines`. The proxy cannot be used for any other operations on its members. @@ -493,7 +493,7 @@ def __init__(self, spine_dict): def __getattr__(self, name): broadcast_targets = [spine for spine in self._spine_dict.values() if hasattr(spine, name)] - if not name.startswith('set_') or not broadcast_targets: + if (name != 'set' and not name.startswith('set_')) or not broadcast_targets: raise AttributeError( f"'SpinesProxy' object has no attribute '{name}'") @@ -531,8 +531,8 @@ class Spines(MutableMapping): spines[:].set_visible(False) - The latter two indexing methods will return a `SpinesProxy` that broadcasts - all ``set_*`` calls to its members, but cannot be used for any other + The latter two indexing methods will return a `SpinesProxy` that broadcasts all + ``set_*()`` and ``set()`` calls to its members, but cannot be used for any other operation. """ def __init__(self, **kwargs): diff --git a/lib/matplotlib/tests/test_spines.py b/lib/matplotlib/tests/test_spines.py index 89bc0c872de5..9ce16fb39227 100644 --- a/lib/matplotlib/tests/test_spines.py +++ b/lib/matplotlib/tests/test_spines.py @@ -12,6 +12,9 @@ class SpineMock: def __init__(self): self.val = None + def set(self, **kwargs): + vars(self).update(kwargs) + def set_val(self, val): self.val = val @@ -35,6 +38,9 @@ def set_val(self, val): spines[:].set_val('y') assert all(spine.val == 'y' for spine in spines.values()) + spines[:].set(foo='bar') + assert all(spine.foo == 'bar' for spine in spines.values()) + with pytest.raises(AttributeError, match='foo'): spines.foo with pytest.raises(KeyError, match='foo'):