diff --git a/changelog/991.bugfix.rst b/changelog/991.bugfix.rst new file mode 100644 index 000000000..3e21631ef --- /dev/null +++ b/changelog/991.bugfix.rst @@ -0,0 +1 @@ +Fixed a memory leak when deep-copying an ``NDCube`` object or its coordinates by properly implementing ``__deepcopy__`` for ``ExtraCoords`` and ``GlobalCoords``. diff --git a/ndcube/extra_coords/extra_coords.py b/ndcube/extra_coords/extra_coords.py index bcbf6724d..c78dd448c 100644 --- a/ndcube/extra_coords/extra_coords.py +++ b/ndcube/extra_coords/extra_coords.py @@ -1,4 +1,5 @@ import abc +import copy from collections.abc import Iterable from functools import partial, reduce from numbers import Integral @@ -155,6 +156,18 @@ def __init__(self, ndcube=None): # We need a reference to the parent NDCube self._ndcube = ndcube + def __deepcopy__(self, memo): + + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + for k, v in self.__dict__.items(): + if k == '_ndcube': + setattr(result, k, None) + else: + setattr(result, k, copy.deepcopy(v, memo)) + return result + @classmethod def from_lookup_tables(cls, names, pixel_dimensions, lookup_tables, physical_types=None): """ diff --git a/ndcube/global_coords.py b/ndcube/global_coords.py index 3514a1799..bd564eb31 100644 --- a/ndcube/global_coords.py +++ b/ndcube/global_coords.py @@ -88,6 +88,18 @@ def __init__(self, ndcube=None): self._ndcube = ndcube self._internal_coords = OrderedDict() + def __deepcopy__(self, memo): + + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + for k, v in self.__dict__.items(): + if k == '_ndcube': + setattr(result, k, None) + else: + setattr(result, k, copy.deepcopy(v, memo)) + return result + @staticmethod def _convert_dropped_to_internal(dropped_dimensions): """