diff -r 7a50d3c0aa61 Lib/collections/__init__.py --- a/Lib/collections/__init__.py Thu Jul 11 13:02:37 2013 +0200 +++ b/Lib/collections/__init__.py Thu Jul 11 17:28:14 2013 +0300 @@ -206,7 +206,12 @@ def copy(self): 'od.copy() -> a shallow copy of od' - return self.__class__(self) + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + copy = self.__class__(self) + copy.__dict__.update(inst_dict) + return copy @classmethod def fromkeys(cls, iterable, value=None): @@ -574,10 +579,12 @@ def copy(self): 'Return a shallow copy.' - return self.__class__(self) + copy = self.__class__(self) + copy.__dict__.update(vars(self)) + return copy def __reduce__(self): - return self.__class__, (dict(self),) + return self.__class__, (dict(self),), vars(self) or None def __delitem__(self, elem): 'Like dict.__delitem__() but does not raise KeyError for missing values.' diff -r 7a50d3c0aa61 Lib/test/test_collections.py --- a/Lib/test/test_collections.py Thu Jul 11 13:02:37 2013 +0200 +++ b/Lib/test/test_collections.py Thu Jul 11 17:28:14 2013 +0300 @@ -916,37 +916,37 @@ # Check that counters are copyable, deepcopyable, picklable, and #have a repr/eval round-trip words = Counter('which witch had which witches wrist watch'.split()) + words.a = 42 + def check1(dup): + self.assertIsNot(dup, words) + self.assertEqual(dup, words) + self.assertEqual(len(dup), len(words)) + self.assertEqual(type(dup), type(words)) + check1(eval(repr(words))) update_test = Counter() update_test.update(words) - for label, dup in [ - ('words.copy()', words.copy()), - ('copy.copy(words)', copy.copy(words)), - ('copy.deepcopy(words)', copy.deepcopy(words)), - ('pickle.loads(pickle.dumps(words, 0))', - pickle.loads(pickle.dumps(words, 0))), - ('pickle.loads(pickle.dumps(words, 1))', - pickle.loads(pickle.dumps(words, 1))), - ('pickle.loads(pickle.dumps(words, 2))', - pickle.loads(pickle.dumps(words, 2))), - ('pickle.loads(pickle.dumps(words, -1))', - pickle.loads(pickle.dumps(words, -1))), - ('eval(repr(words))', eval(repr(words))), - ('update_test', update_test), - ('Counter(words)', Counter(words)), - ]: - with self.subTest(label=label): - msg = "\ncopy: %s\nwords: %s" % (dup, words) - self.assertIsNot(dup, words, msg) - self.assertEqual(dup, words) + check1(update_test) + check1(Counter(words)) + def check2(dup): + check1(dup) + self.assertEqual(dup.a, 42) + check2(words.copy()) + check2(copy.copy(words)) + check2(copy.deepcopy(words)) + for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + check2(pickle.loads(pickle.dumps(words, proto))) def test_copy_subclass(self): class MyCounter(Counter): pass c = MyCounter('slartibartfast') + c.a = 42 d = c.copy() self.assertEqual(d, c) self.assertEqual(len(d), len(c)) self.assertEqual(type(d), type(c)) + self.assertEqual(d.a, 42) def test_conversions(self): # Convert to: set, list, dict @@ -1214,30 +1214,25 @@ # and have a repr/eval round-trip pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] od = OrderedDict(pairs) + od.a = 42 + def check1(dup): + self.assertIsNot(dup, od) + self.assertEqual(dup, od) + self.assertEqual(len(dup), len(od)) + self.assertEqual(type(dup), type(od)) update_test = OrderedDict() update_test.update(od) - for label, dup in [ - ('od.copy()', od.copy()), - ('copy.copy(od)', copy.copy(od)), - ('copy.deepcopy(od)', copy.deepcopy(od)), - ('pickle.loads(pickle.dumps(od, 0))', - pickle.loads(pickle.dumps(od, 0))), - ('pickle.loads(pickle.dumps(od, 1))', - pickle.loads(pickle.dumps(od, 1))), - ('pickle.loads(pickle.dumps(od, 2))', - pickle.loads(pickle.dumps(od, 2))), - ('pickle.loads(pickle.dumps(od, 3))', - pickle.loads(pickle.dumps(od, 3))), - ('pickle.loads(pickle.dumps(od, -1))', - pickle.loads(pickle.dumps(od, -1))), - ('eval(repr(od))', eval(repr(od))), - ('update_test', update_test), - ('OrderedDict(od)', OrderedDict(od)), - ]: - with self.subTest(label=label): - msg = "\ncopy: %s\nod: %s" % (dup, od) - self.assertIsNot(dup, od, msg) - self.assertEqual(dup, od) + check1(update_test) + check1(OrderedDict(od)) + def check2(dup): + check1(dup) + self.assertEqual(dup.a, 42) + check2(od.copy()) + check2(copy.copy(od)) + check2(copy.deepcopy(od)) + for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + check2(pickle.loads(pickle.dumps(od, proto))) def test_yaml_linkage(self): # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.