Skip to content

Commit e6db01f

Browse files
committed
ENH: restore class level attributes by un-shadowing in _setattr_cm
1 parent 066e6ef commit e6db01f

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

lib/matplotlib/cbook/__init__.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2039,8 +2039,19 @@ def _setattr_cm(obj, **kwargs):
20392039
# of MethodType every time so replace them with sentinel
20402040
#
20412041
# https://docs.python.org/3/howto/descriptor.html#functions-and-methods
2042-
origs = [(attr, _ if not inspect.ismethod(_) else sentinel)
2043-
for attr, _ in origs]
2042+
def filter_restores(obj, attr, val):
2043+
if inspect.ismethod(val):
2044+
return False
2045+
2046+
if attr in obj.__dict__:
2047+
return True
2048+
2049+
if isinstance(getattr(type(obj), attr), property):
2050+
return True
2051+
return False
2052+
2053+
origs = [(attr, val if filter_restores(obj, attr, val) else sentinel)
2054+
for attr, val in origs]
20442055
try:
20452056
for attr, val in kwargs.items():
20462057
setattr(obj, attr, val)

lib/matplotlib/tests/test_cbook.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,12 @@ def test_check_shape(target, test_shape):
655655

656656
def test_setattr_cm():
657657
class A:
658+
659+
cls_level = object()
660+
override = object()
658661
def __init__(self):
659662
self.aardvark = 'aardvark'
663+
self.override = 'override'
660664
self._p = 'p'
661665

662666
def meth(self):
@@ -670,7 +674,10 @@ def prop(self):
670674
def prop(self, val):
671675
self._p = val
672676

673-
a = A()
677+
class B(A):
678+
...
679+
680+
a = B()
674681
# When you access a Python method the function is bound
675682
# to the object at access time so you get a new instance
676683
# of MethodType every time.
@@ -683,19 +690,28 @@ def prop(self, val):
683690
# and our property happens to give the same instance every time
684691
assert a.prop is a.prop
685692

693+
assert a.cls_level is A.cls_level
694+
695+
assert a.override == 'override'
696+
686697
with cbook._setattr_cm(
687698
a,
688-
aardvark='moose', meth=lambda: None, prop='b'
699+
aardvark='moose', meth=lambda: None, prop='b', cls_level='bob',
700+
override='boo'
689701
):
690702
# because we have set a lambda, it is normal attribute access
691703
# and the same every time
692704
assert a.meth is a.meth
693705
assert a.aardvark is a.aardvark
694706
assert a.aardvark == 'moose'
695707
assert a.prop == 'b'
708+
assert a.cls_level == 'bob'
709+
assert a.override == 'boo'
696710

697711
# check that we get different MethodType instances each time
698712
assert a.meth is not a.meth
699713
assert a.aardvark is a.aardvark
700714
assert a.aardvark == 'aardvark'
701715
assert a.prop is a.prop
716+
assert a.cls_level is A.cls_level
717+
assert a.override == 'override'

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy