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

Skip to content

Commit 996b647

Browse files
committed
Implement Path.__deepcopy__ avoiding infinite recursion
Give it a metaclass that lets us remove the __deepcopy__ method from sight when executing that method. Closes #29157 without relying on private CPython methods. Does not fix the other issue with TransformNode.__copy__.
1 parent bebb263 commit 996b647

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

lib/matplotlib/path.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,38 @@
1616
import numpy as np
1717

1818
import matplotlib as mpl
19+
1920
from . import _api, _path
2021
from .cbook import _to_unmasked_float_array, simple_linear_interpolation
2122
from .bezier import BezierSegment
2223

2324

24-
class Path:
25+
class _HideDeepcopyMeta(type):
26+
"""Metaclass that allows conditionally hiding the __deepcopy__ method.
27+
28+
Set __hide_deepcopy__ to True to hide the __deepcopy__ method,
29+
which will then be looked up in the usual method resolution order.
30+
"""
31+
32+
def __new__(cls, name, bases, namespace):
33+
orig_ga = namespace.get("__getattribute__") or object.__getattribute__
34+
35+
def __getattribute__(self, attr_name):
36+
if attr_name == "__deepcopy__" and orig_ga(self, "__hide_deepcopy__"):
37+
for base in type(self).__mro__[1:]:
38+
if attr_name in base.__dict__:
39+
method = base.__dict__[attr_name]
40+
return method.__get__(self, type(self))
41+
raise AttributeError(
42+
f"'{type(self).__name__}' object has no attribute '{attr_name}'"
43+
)
44+
return orig_ga(self, attr_name)
45+
46+
namespace["__getattribute__"] = __getattribute__
47+
return super().__new__(cls, name, bases, namespace)
48+
49+
50+
class Path(metaclass=_HideDeepcopyMeta):
2551
"""
2652
A series of possibly disconnected, possibly closed, line and curve
2753
segments.
@@ -281,9 +307,13 @@ def __deepcopy__(self, memo=None):
281307
readonly, even if the source `Path` is.
282308
"""
283309
# Deepcopying arrays (vertices, codes) strips the writeable=False flag.
284-
p = copy.deepcopy(super(), memo)
285-
p._readonly = False
286-
return p
310+
self.__hide_deepcopy__ = True
311+
try:
312+
p = copy.deepcopy(self, memo)
313+
p._readonly = False
314+
return p
315+
finally:
316+
self.__hide_deepcopy__ = False
287317

288318
deepcopy = __deepcopy__
289319

0 commit comments

Comments
 (0)