Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions Lib/collections/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,13 @@ def __contains__(self, key):

# Now, add the methods in dicts but not in MutableMapping
def __repr__(self): return repr(self.data)
def __copy__(self):
inst = self.__class__.__new__(self.__class__)
inst.__dict__.update(self.__dict__)
# Create a copy and avoid triggering descriptors
inst.__dict__["data"] = self.__dict__["data"].copy()
return inst

def copy(self):
if self.__class__ is UserDict:
return UserDict(self.data.copy())
Expand All @@ -1050,6 +1057,7 @@ def copy(self):
self.data = data
c.update(self)
return c

@classmethod
def fromkeys(cls, iterable, value=None):
d = cls()
Expand Down Expand Up @@ -1118,6 +1126,12 @@ def __mul__(self, n):
def __imul__(self, n):
self.data *= n
return self
def __copy__(self):
inst = self.__class__.__new__(self.__class__)
inst.__dict__.update(self.__dict__)
# Create a copy and avoid triggering descriptors
inst.__dict__["data"] = self.__dict__["data"][:]
return inst
def append(self, item): self.data.append(item)
def insert(self, i, item): self.data.insert(i, item)
def pop(self, i=-1): return self.data.pop(i)
Expand Down
24 changes: 24 additions & 0 deletions Lib/test/test_collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ def _superset_test(self, a, b):
b=b.__name__,
),
)

def _copy_test(self, obj):
# Test internal copy
obj_copy = obj.copy()
self.assertIsNot(obj.data, obj_copy.data)
self.assertEqual(obj.data, obj_copy.data)

# Test copy.copy
obj.test = [1234] # Make sure instance vars are also copied.
obj_copy = copy.copy(obj)
self.assertIsNot(obj.data, obj_copy.data)
self.assertEqual(obj.data, obj_copy.data)
self.assertIs(obj.test, obj_copy.test)

def test_str_protocol(self):
self._superset_test(UserString, str)

Expand All @@ -46,6 +60,16 @@ def test_list_protocol(self):
def test_dict_protocol(self):
self._superset_test(UserDict, dict)

def test_list_copy(self):
obj = UserList()
obj.append(123)
self._copy_test(obj)

def test_dict_copy(self):
obj = UserDict()
obj[123] = "abc"
self._copy_test(obj)


################################################################################
### ChainMap (helper class for configparser and the string module)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added a ``__copy__()`` to ``collections.UserList`` and
``collections.UserDict`` in order to correctly implement shallow copying of
the objects. Patch by Bar Harel.