Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c38c405

Browse files
committed
MNT: Use WeakKeyDictionary and WeakSet in Grouper
Rather than handling the weakrefs ourselves, just use the builtin WeakKeyDictionary instead. This will automatically remove dead references meaning we can remove the clean() method.
1 parent 3742e7e commit c38c405

File tree

5 files changed

+23
-35
lines changed

5 files changed

+23
-35
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``Grouper.clean()``
2+
~~~~~~~~~~~~~~~~~~~
3+
4+
with no replacement. The Grouper class now cleans itself up automatically.

lib/matplotlib/axes/_base.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,8 +1363,6 @@ def __clear(self):
13631363
self.xaxis.set_clip_path(self.patch)
13641364
self.yaxis.set_clip_path(self.patch)
13651365

1366-
self._shared_axes["x"].clean()
1367-
self._shared_axes["y"].clean()
13681366
if self._sharex is not None:
13691367
self.xaxis.set_visible(xaxis_visible)
13701368
self.patch.set_visible(patch_visible)

lib/matplotlib/cbook.py

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -786,78 +786,68 @@ class Grouper:
786786
"""
787787

788788
def __init__(self, init=()):
789-
self._mapping = {weakref.ref(x): [weakref.ref(x)] for x in init}
789+
self._mapping = weakref.WeakKeyDictionary(
790+
{x: weakref.WeakSet([x]) for x in init})
790791

791792
def __getstate__(self):
792793
return {
793794
**vars(self),
794795
# Convert weak refs to strong ones.
795-
"_mapping": {k(): [v() for v in vs] for k, vs in self._mapping.items()},
796+
"_mapping": {k: set(v) for k, v in self._mapping.items()},
796797
}
797798

798799
def __setstate__(self, state):
799800
vars(self).update(state)
800801
# Convert strong refs to weak ones.
801-
self._mapping = {weakref.ref(k): [*map(weakref.ref, vs)]
802-
for k, vs in self._mapping.items()}
802+
self._mapping = weakref.WeakKeyDictionary(
803+
{k: weakref.WeakSet(v) for k, v in self._mapping.items()})
803804

804805
def __contains__(self, item):
805-
return weakref.ref(item) in self._mapping
806+
return item in self._mapping
806807

808+
@_api.deprecated("3.8", alternative="none, you no longer need to clean a Grouper")
807809
def clean(self):
808810
"""Clean dead weak references from the dictionary."""
809-
mapping = self._mapping
810-
to_drop = [key for key in mapping if key() is None]
811-
for key in to_drop:
812-
val = mapping.pop(key)
813-
val.remove(key)
814811

815812
def join(self, a, *args):
816813
"""
817814
Join given arguments into the same set. Accepts one or more arguments.
818815
"""
819816
mapping = self._mapping
820-
set_a = mapping.setdefault(weakref.ref(a), [weakref.ref(a)])
817+
set_a = mapping.setdefault(a, weakref.WeakSet([a]))
821818

822819
for arg in args:
823-
set_b = mapping.get(weakref.ref(arg), [weakref.ref(arg)])
820+
set_b = mapping.get(arg, weakref.WeakSet([arg]))
824821
if set_b is not set_a:
825822
if len(set_b) > len(set_a):
826823
set_a, set_b = set_b, set_a
827-
set_a.extend(set_b)
824+
set_a.update(set_b)
828825
for elem in set_b:
829826
mapping[elem] = set_a
830827

831-
self.clean()
832-
833828
def joined(self, a, b):
834829
"""Return whether *a* and *b* are members of the same set."""
835-
self.clean()
836-
return (self._mapping.get(weakref.ref(a), object())
837-
is self._mapping.get(weakref.ref(b)))
830+
return (self._mapping.get(a, object()) is self._mapping.get(b))
838831

839832
def remove(self, a):
840-
self.clean()
841-
set_a = self._mapping.pop(weakref.ref(a), None)
833+
set_a = self._mapping.pop(a, None)
842834
if set_a:
843-
set_a.remove(weakref.ref(a))
835+
set_a.remove(a)
844836

845837
def __iter__(self):
846838
"""
847839
Iterate over each of the disjoint sets as a list.
848840
849841
The iterator is invalid if interleaved with calls to join().
850842
"""
851-
self.clean()
852843
unique_groups = {id(group): group for group in self._mapping.values()}
853844
for group in unique_groups.values():
854-
yield [x() for x in group]
845+
yield [x for x in group]
855846

856847
def get_siblings(self, a):
857848
"""Return all of the items joined with *a*, including itself."""
858-
self.clean()
859-
siblings = self._mapping.get(weakref.ref(a), [weakref.ref(a)])
860-
return [x() for x in siblings]
849+
siblings = self._mapping.get(a, [a])
850+
return [x for x in siblings]
861851

862852

863853
class GrouperView:

lib/matplotlib/tests/test_cbook.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import itertools
22
import pickle
33

4-
from weakref import ref
54
from unittest.mock import patch, Mock
65

76
from datetime import datetime, date, timedelta
@@ -590,11 +589,11 @@ class Dummy:
590589
mapping = g._mapping
591590

592591
for o in objs:
593-
assert ref(o) in mapping
592+
assert o in mapping
594593

595-
base_set = mapping[ref(objs[0])]
594+
base_set = mapping[objs[0]]
596595
for o in objs[1:]:
597-
assert mapping[ref(o)] is base_set
596+
assert mapping[o] is base_set
598597

599598

600599
def test_flatiter():

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,6 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True,
640640
_tight = self._tight = bool(tight)
641641

642642
if scalex and self.get_autoscalex_on():
643-
self._shared_axes["x"].clean()
644643
x0, x1 = self.xy_dataLim.intervalx
645644
xlocator = self.xaxis.get_major_locator()
646645
x0, x1 = xlocator.nonsingular(x0, x1)
@@ -653,7 +652,6 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True,
653652
self.set_xbound(x0, x1)
654653

655654
if scaley and self.get_autoscaley_on():
656-
self._shared_axes["y"].clean()
657655
y0, y1 = self.xy_dataLim.intervaly
658656
ylocator = self.yaxis.get_major_locator()
659657
y0, y1 = ylocator.nonsingular(y0, y1)
@@ -666,7 +664,6 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True,
666664
self.set_ybound(y0, y1)
667665

668666
if scalez and self.get_autoscalez_on():
669-
self._shared_axes["z"].clean()
670667
z0, z1 = self.zz_dataLim.intervalx
671668
zlocator = self.zaxis.get_major_locator()
672669
z0, z1 = zlocator.nonsingular(z0, z1)

0 commit comments

Comments
 (0)