Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f4e1bab

Browse filesBrowse files
bharelserhiy-storchaka
authored andcommitted
bpo-27141: Fix collections.UserList and UserDict shallow copy. (GH-4094)
1 parent c661b30 commit f4e1bab
Copy full SHA for f4e1bab

File tree

Expand file treeCollapse file tree

3 files changed

+41
-0
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+41
-0
lines changed

‎Lib/collections/__init__.py

Copy file name to clipboardExpand all lines: Lib/collections/__init__.py
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,13 @@ def __contains__(self, key):
10381038

10391039
# Now, add the methods in dicts but not in MutableMapping
10401040
def __repr__(self): return repr(self.data)
1041+
def __copy__(self):
1042+
inst = self.__class__.__new__(self.__class__)
1043+
inst.__dict__.update(self.__dict__)
1044+
# Create a copy and avoid triggering descriptors
1045+
inst.__dict__["data"] = self.__dict__["data"].copy()
1046+
return inst
1047+
10411048
def copy(self):
10421049
if self.__class__ is UserDict:
10431050
return UserDict(self.data.copy())
@@ -1050,6 +1057,7 @@ def copy(self):
10501057
self.data = data
10511058
c.update(self)
10521059
return c
1060+
10531061
@classmethod
10541062
def fromkeys(cls, iterable, value=None):
10551063
d = cls()
@@ -1118,6 +1126,12 @@ def __mul__(self, n):
11181126
def __imul__(self, n):
11191127
self.data *= n
11201128
return self
1129+
def __copy__(self):
1130+
inst = self.__class__.__new__(self.__class__)
1131+
inst.__dict__.update(self.__dict__)
1132+
# Create a copy and avoid triggering descriptors
1133+
inst.__dict__["data"] = self.__dict__["data"][:]
1134+
return inst
11211135
def append(self, item): self.data.append(item)
11221136
def insert(self, i, item): self.data.insert(i, item)
11231137
def pop(self, i=-1): return self.data.pop(i)

‎Lib/test/test_collections.py

Copy file name to clipboardExpand all lines: Lib/test/test_collections.py
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@ def _superset_test(self, a, b):
3737
b=b.__name__,
3838
),
3939
)
40+
41+
def _copy_test(self, obj):
42+
# Test internal copy
43+
obj_copy = obj.copy()
44+
self.assertIsNot(obj.data, obj_copy.data)
45+
self.assertEqual(obj.data, obj_copy.data)
46+
47+
# Test copy.copy
48+
obj.test = [1234] # Make sure instance vars are also copied.
49+
obj_copy = copy.copy(obj)
50+
self.assertIsNot(obj.data, obj_copy.data)
51+
self.assertEqual(obj.data, obj_copy.data)
52+
self.assertIs(obj.test, obj_copy.test)
53+
4054
def test_str_protocol(self):
4155
self._superset_test(UserString, str)
4256

@@ -46,6 +60,16 @@ def test_list_protocol(self):
4660
def test_dict_protocol(self):
4761
self._superset_test(UserDict, dict)
4862

63+
def test_list_copy(self):
64+
obj = UserList()
65+
obj.append(123)
66+
self._copy_test(obj)
67+
68+
def test_dict_copy(self):
69+
obj = UserDict()
70+
obj[123] = "abc"
71+
self._copy_test(obj)
72+
4973

5074
################################################################################
5175
### ChainMap (helper class for configparser and the string module)
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added a ``__copy__()`` to ``collections.UserList`` and
2+
``collections.UserDict`` in order to correctly implement shallow copying of
3+
the objects. Patch by Bar Harel.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.