Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
f797268
Change first argument to add_axes from list to tuple
oscargus Aug 29, 2024
db4e67c
Change first argument to set_[xyz]lim to two arguments
oscargus Aug 29, 2024
edc8b20
Ensure tuples are passed to Axes.set([xyz]lim=...)
QuLogic Apr 16, 2025
31d92dc
Prepare to turn matplotlib.style into a plain module.
anntzer Jun 11, 2025
f5851da
Simplify RendererAgg::draw_markers buffers
QuLogic Jun 20, 2025
b154237
Clean up image files that may be symbolic links to files
ayshih Jun 19, 2025
8c75238
Clean up GIF image files from passing tests
ayshih Jun 19, 2025
5539d12
Merge pull request #30188 from ayshih/image_cleanup
scottshambaugh Jun 20, 2025
bebb263
Merge pull request #30191 from QuLogic/simplify-marker
scottshambaugh Jun 20, 2025
fc99473
DOC: Remove last userdemo example
QuLogic Jun 21, 2025
5a10e4d
Merge pull request #30197 from QuLogic/no-userdemo
timhoffm Jun 21, 2025
bbff84c
Replace facepair_t with std::optional
QuLogic Jun 20, 2025
e77c17f
Use collections.deque to store animation cache data.
anntzer Jun 22, 2025
9340190
Merge pull request #28764 from oscargus/exampletesttyping
QuLogic Jun 23, 2025
6e51bec
Support individual styling of major and minor grid through rcParams (…
konmenel Jun 24, 2025
0dcd06f
Merge pull request #30206 from anntzer/ad
jkseppan Jun 24, 2025
68c67c9
Merge pull request #30163 from anntzer/ms
jkseppan Jun 24, 2025
e3c7a64
Simplify dviFontInfo layout in backend pdf.
anntzer May 19, 2025
fed8c20
Merge pull request #30082 from anntzer/simple-dvifontinfo
QuLogic Jun 25, 2025
c7edce3
Implement Path.__deepcopy__ avoiding infinite recursion
jkseppan Jun 21, 2025
b20cf20
Compare arrays with assert_array_equal
jkseppan Jun 24, 2025
5c7c915
Fix TransformNode.__copy__
jkseppan Jun 21, 2025
4ab1ab5
Update deprecations.rst
ztw33 Jun 25, 2025
dd03655
Update removals.rst
ztw33 Jun 25, 2025
58b6a06
Merge pull request #30212 from ztw33/main
timhoffm Jun 25, 2025
3ea5b63
Fix label_outer in the presence of colorbars.
anntzer May 23, 2025
d05b43d
Merge pull request #30198 from jkseppan/path-deepcopy-via-metaclass
tacaswell Jun 26, 2025
257430e
ci: Enable wheel builds on Python 3.14
QuLogic Jun 20, 2025
b06d1f4
Clean up Qt socket notifier to avoid spurious interrupt handler calls
chrisjbillington Jun 26, 2025
c78c2f4
Refactoring: Removing axis parameter from scales (#29988)
vagnermcj Jun 27, 2025
ac863bc
BUG: Include python-including headers first
DWesl Jun 27, 2025
4b03f0c
Add explicit overloads for pyplot.{show,subplot} (#30202)
ZPyrolink Jun 27, 2025
e36bffb
Add explicit getter / setter overloads for pyplot.{xlim,ylim} (#30199)
ZPyrolink Jun 27, 2025
75c9b0a
Merge pull request #30220 from DWesl/python-h-first
timhoffm Jun 28, 2025
0b2fa3f
BUG: fix future incompatibility with Pillow 13
neutrinoceros Jun 28, 2025
7edd74a
Abstract base class for Normalize (#30178)
trygvrad Jun 28, 2025
99480b9
Fix polar inner patch boundary and spine location for log scale
rcomer Jun 28, 2025
f47f9a2
Fix polar inner patch boundary and spine location for log scale (#30223)
timhoffm Jun 30, 2025
d797ee5
Merge pull request #30098 from anntzer/locb
timhoffm Jun 30, 2025
6ede069
fixup
neutrinoceros Jun 30, 2025
9c184c1
Merge pull request #30221 from neutrinoceros/bug/pillow13-compat
timhoffm Jun 30, 2025
0e430b9
Add explicit signatures for pyplot.{polar,savefig,set_loglevel} (#30200)
ZPyrolink Jun 30, 2025
4c06e71
Bump github/codeql-action from 3.29.0 to 3.29.2 in the actions group
dependabot[bot] Jun 30, 2025
c805967
Merge pull request #30195 from QuLogic/py314
ianthomas23 Jul 1, 2025
413ea8f
Merge pull request #30209 from chrisjbillington/qt-interrupt-cleanup
anntzer Jul 1, 2025
b523581
Copy-edit the docstring of AuxTransformBox.
anntzer Jul 1, 2025
f6ae9e7
Merge pull request #30196 from QuLogic/optional-face
anntzer Jul 1, 2025
1295158
Add explicit `**options: Any` for `add_subplot` method to remove "par…
gameroman Jul 1, 2025
384fb6e
Merge pull request #30236 from anntzer/atb
timhoffm Jul 1, 2025
c8361f0
DOC: Recommend to use bare Figure instances for saving to file
timhoffm Jul 2, 2025
d1673ec
Merge pull request #30232 from matplotlib/dependabot/github_actions/a…
jkseppan Jul 2, 2025
919c7b9
adjust logic to allow inherritance
cvanelteren Jul 2, 2025
77f868c
chore: remove redundant words in comment
ianlv Jul 2, 2025
72aa3f7
Merge pull request #30246 from ianlv/main
timhoffm Jul 2, 2025
e22a6e8
Merge pull request #30245 from cvanelteren/allow-inherritance-rc
jklymak Jul 2, 2025
40516e8
Merge pull request #30244 from timhoffm/doc-save-image
jklymak Jul 2, 2025
70d5ad4
Fix FancyArrow rendering for zero-length arrows (#30243)
nrnavaneet Jul 3, 2025
a87684f
Upgrade to Visual Studio 2022 in appveyor.yml
jkseppan Jul 1, 2025
2899656
Merge pull request #30239 from jkseppan/vcvars
QuLogic Jul 3, 2025
d231a25
Don't expose private styles in style.available
QuLogic Jul 1, 2025
73d0317
Merge pull request #30237 from GameRoMan/patch-1
jkseppan Jul 4, 2025
6a01311
Time out in _get_executable_info
jkseppan Jul 3, 2025
ede1ebb
Merge pull request #30256 from jkseppan/timeout-get-executable-info
anntzer Jul 4, 2025
bf96be4
Fix linting in test notebooks
QuLogic Jul 4, 2025
ca3d239
Clean up unused ruff config
QuLogic Jul 4, 2025
18f93ee
Clean up mypy settings
QuLogic Jul 4, 2025
f4398bf
Clean up some simple linting exceptions
QuLogic Jul 4, 2025
7572823
Check that stem input is 1D
QuLogic Jul 1, 2025
e78735b
Tweak docstrings of get_window_extent/get_tightbbox.
anntzer Jul 4, 2025
cfc366b
Merge pull request #30262 from anntzer/gwegtb
timhoffm Jul 5, 2025
faa3670
Merge pull request #30258 from QuLogic/ruff-update
timhoffm Jul 5, 2025
9c3f73b
DOC: fix artist see also sections
rcomer Jul 5, 2025
90db4c1
Merge pull request #30266 from rcomer/artist-seealso
jklymak Jul 6, 2025
947590d
Merge pull request #30233 from QuLogic/stem-1d
dstansby Jul 6, 2025
db6cf15
Fix figure legend when drawing stackplots
dstansby Jun 18, 2025
b370e30
Add smoke test
dstansby Jul 6, 2025
99b4ee3
Merge pull request #30186 from dstansby/fig-legend-error
timhoffm Jul 7, 2025
b6777b1
Merge pull request #30235 from QuLogic/private-style
timhoffm Jul 7, 2025
f31ba35
Use old stride_windows implementation on 32-bit builds
QuLogic Aug 22, 2022
4c345b4
Merge pull request #29115 from QuLogic/old-strides
QuLogic Jul 7, 2025
a7fd524
Merge branch 'main' into text-overhaul
QuLogic Jul 7, 2025
389373e
ci: Preload existing test images from text-overhaul-figures branch
QuLogic Jun 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Implement Path.__deepcopy__ avoiding infinite recursion
To deep copy an object without calling deepcopy on the object itself,
create a new object of the correct class and iterate calling deepcopy on
its __dict__.

Closes #29157 without relying on private CPython methods.
Does not fix the other issue with TransformNode.__copy__.

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
  • Loading branch information
jkseppan and serhiy-storchaka committed Jun 25, 2025
commit c7edce3820d918474fadb42e55818d1c40be1979
26 changes: 23 additions & 3 deletions lib/matplotlib/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,17 +275,37 @@ def copy(self):
"""
return copy.copy(self)

def __deepcopy__(self, memo=None):
def __deepcopy__(self, memo):
"""
Return a deepcopy of the `Path`. The `Path` will not be
readonly, even if the source `Path` is.
"""
# Deepcopying arrays (vertices, codes) strips the writeable=False flag.
p = copy.deepcopy(super(), memo)
cls = type(self)
memo[id(self)] = p = cls.__new__(cls)

for k, v in self.__dict__.items():
setattr(p, k, copy.deepcopy(v, memo))

p._readonly = False
return p

deepcopy = __deepcopy__
def deepcopy(self, memo=None):
"""
Return a deep copy of the `Path`. The `Path` will not be readonly,
even if the source `Path` is.

Parameters
----------
memo : dict, optional
A dictionary to use for memoizing, passed to `copy.deepcopy`.

Returns
-------
Path
A deep copy of the `Path`, but not readonly.
"""
return copy.deepcopy(self, memo)

@classmethod
def make_compound_path_from_polys(cls, XY):
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/path.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ class Path:
@property
def readonly(self) -> bool: ...
def copy(self) -> Path: ...
def __deepcopy__(self, memo: dict[int, Any] | None = ...) -> Path: ...
deepcopy = __deepcopy__
def __deepcopy__(self, memo: dict[int, Any]) -> Path: ...
def deepcopy(self, memo: dict[int, Any] | None = None) -> Path: ...

@classmethod
def make_compound_path_from_polys(cls, XY: ArrayLike) -> Path: ...
Expand Down
38 changes: 36 additions & 2 deletions lib/matplotlib/tests/test_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,15 +355,49 @@ def test_path_deepcopy():
# Should not raise any error
verts = [[0, 0], [1, 1]]
codes = [Path.MOVETO, Path.LINETO]
path1 = Path(verts)
path2 = Path(verts, codes)
path1 = Path(verts, readonly=True)
path2 = Path(verts, codes, readonly=True)
path1_copy = path1.deepcopy()
path2_copy = path2.deepcopy()
assert path1 is not path1_copy
assert path1.vertices is not path1_copy.vertices
assert np.all(path1.vertices == path1_copy.vertices)
assert path1.readonly
assert not path1_copy.readonly
assert path2 is not path2_copy
assert path2.vertices is not path2_copy.vertices
assert np.all(path2.vertices == path2_copy.vertices)
assert path2.codes is not path2_copy.codes
assert all(path2.codes == path2_copy.codes)
assert path2.readonly
assert not path2_copy.readonly


def test_path_deepcopy_cycle():
class PathWithCycle(Path):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.x = self

p = PathWithCycle([[0, 0], [1, 1]], readonly=True)
p_copy = p.deepcopy()
assert p_copy is not p
assert p.readonly
assert not p_copy.readonly
assert p_copy.x is p_copy

class PathWithCycle2(Path):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.x = [self] * 2

p2 = PathWithCycle2([[0, 0], [1, 1]], readonly=True)
p2_copy = p2.deepcopy()
assert p2_copy is not p2
assert p2.readonly
assert not p2_copy.readonly
assert p2_copy.x[0] is p2_copy
assert p2_copy.x[1] is p2_copy


def test_path_shallowcopy():
Expand Down