PageRenderTime 50ms CodeModel.GetById 14ms app.highlight 31ms RepoModel.GetById 2ms app.codeStats 0ms

/Lib/test/test_copy.py

http://unladen-swallow.googlecode.com/
Python | 594 lines | 575 code | 13 blank | 6 comment | 0 complexity | 50ba370a42297ff3dba9b00f2b0b3f76 MD5 | raw file
  1"""Unit tests for the copy module."""
  2
  3import copy
  4import copy_reg
  5
  6import unittest
  7from test import test_support
  8
  9class TestCopy(unittest.TestCase):
 10
 11    # Attempt full line coverage of copy.py from top to bottom
 12
 13    def test_exceptions(self):
 14        self.assert_(copy.Error is copy.error)
 15        self.assert_(issubclass(copy.Error, Exception))
 16
 17    # The copy() method
 18
 19    def test_copy_basic(self):
 20        x = 42
 21        y = copy.copy(x)
 22        self.assertEqual(x, y)
 23
 24    def test_copy_copy(self):
 25        class C(object):
 26            def __init__(self, foo):
 27                self.foo = foo
 28            def __copy__(self):
 29                return C(self.foo)
 30        x = C(42)
 31        y = copy.copy(x)
 32        self.assertEqual(y.__class__, x.__class__)
 33        self.assertEqual(y.foo, x.foo)
 34
 35    def test_copy_registry(self):
 36        class C(object):
 37            def __new__(cls, foo):
 38                obj = object.__new__(cls)
 39                obj.foo = foo
 40                return obj
 41        def pickle_C(obj):
 42            return (C, (obj.foo,))
 43        x = C(42)
 44        self.assertRaises(TypeError, copy.copy, x)
 45        copy_reg.pickle(C, pickle_C, C)
 46        y = copy.copy(x)
 47
 48    def test_copy_reduce_ex(self):
 49        class C(object):
 50            def __reduce_ex__(self, proto):
 51                return ""
 52            def __reduce__(self):
 53                raise test_support.TestFailed, "shouldn't call this"
 54        x = C()
 55        y = copy.copy(x)
 56        self.assert_(y is x)
 57
 58    def test_copy_reduce(self):
 59        class C(object):
 60            def __reduce__(self):
 61                return ""
 62        x = C()
 63        y = copy.copy(x)
 64        self.assert_(y is x)
 65
 66    def test_copy_cant(self):
 67        class C(object):
 68            def __getattribute__(self, name):
 69                if name.startswith("__reduce"):
 70                    raise AttributeError, name
 71                return object.__getattribute__(self, name)
 72        x = C()
 73        self.assertRaises(copy.Error, copy.copy, x)
 74
 75    # Type-specific _copy_xxx() methods
 76
 77    def test_copy_atomic(self):
 78        class Classic:
 79            pass
 80        class NewStyle(object):
 81            pass
 82        def f():
 83            pass
 84        tests = [None, 42, 2L**100, 3.14, True, False, 1j,
 85                 "hello", u"hello\u1234", f.func_code,
 86                 NewStyle, xrange(10), Classic, max]
 87        for x in tests:
 88            self.assert_(copy.copy(x) is x, repr(x))
 89
 90    def test_copy_list(self):
 91        x = [1, 2, 3]
 92        self.assertEqual(copy.copy(x), x)
 93
 94    def test_copy_tuple(self):
 95        x = (1, 2, 3)
 96        self.assertEqual(copy.copy(x), x)
 97
 98    def test_copy_dict(self):
 99        x = {"foo": 1, "bar": 2}
100        self.assertEqual(copy.copy(x), x)
101
102    def test_copy_inst_vanilla(self):
103        class C:
104            def __init__(self, foo):
105                self.foo = foo
106            def __cmp__(self, other):
107                return cmp(self.foo, other.foo)
108        x = C(42)
109        self.assertEqual(copy.copy(x), x)
110
111    def test_copy_inst_copy(self):
112        class C:
113            def __init__(self, foo):
114                self.foo = foo
115            def __copy__(self):
116                return C(self.foo)
117            def __cmp__(self, other):
118                return cmp(self.foo, other.foo)
119        x = C(42)
120        self.assertEqual(copy.copy(x), x)
121
122    def test_copy_inst_getinitargs(self):
123        class C:
124            def __init__(self, foo):
125                self.foo = foo
126            def __getinitargs__(self):
127                return (self.foo,)
128            def __cmp__(self, other):
129                return cmp(self.foo, other.foo)
130        x = C(42)
131        self.assertEqual(copy.copy(x), x)
132
133    def test_copy_inst_getstate(self):
134        class C:
135            def __init__(self, foo):
136                self.foo = foo
137            def __getstate__(self):
138                return {"foo": self.foo}
139            def __cmp__(self, other):
140                return cmp(self.foo, other.foo)
141        x = C(42)
142        self.assertEqual(copy.copy(x), x)
143
144    def test_copy_inst_setstate(self):
145        class C:
146            def __init__(self, foo):
147                self.foo = foo
148            def __setstate__(self, state):
149                self.foo = state["foo"]
150            def __cmp__(self, other):
151                return cmp(self.foo, other.foo)
152        x = C(42)
153        self.assertEqual(copy.copy(x), x)
154
155    def test_copy_inst_getstate_setstate(self):
156        class C:
157            def __init__(self, foo):
158                self.foo = foo
159            def __getstate__(self):
160                return self.foo
161            def __setstate__(self, state):
162                self.foo = state
163            def __cmp__(self, other):
164                return cmp(self.foo, other.foo)
165        x = C(42)
166        self.assertEqual(copy.copy(x), x)
167
168    # The deepcopy() method
169
170    def test_deepcopy_basic(self):
171        x = 42
172        y = copy.deepcopy(x)
173        self.assertEqual(y, x)
174
175    def test_deepcopy_memo(self):
176        # Tests of reflexive objects are under type-specific sections below.
177        # This tests only repetitions of objects.
178        x = []
179        x = [x, x]
180        y = copy.deepcopy(x)
181        self.assertEqual(y, x)
182        self.assert_(y is not x)
183        self.assert_(y[0] is not x[0])
184        self.assert_(y[0] is y[1])
185
186    def test_deepcopy_issubclass(self):
187        # XXX Note: there's no way to test the TypeError coming out of
188        # issubclass() -- this can only happen when an extension
189        # module defines a "type" that doesn't formally inherit from
190        # type.
191        class Meta(type):
192            pass
193        class C:
194            __metaclass__ = Meta
195        self.assertEqual(copy.deepcopy(C), C)
196
197    def test_deepcopy_deepcopy(self):
198        class C(object):
199            def __init__(self, foo):
200                self.foo = foo
201            def __deepcopy__(self, memo=None):
202                return C(self.foo)
203        x = C(42)
204        y = copy.deepcopy(x)
205        self.assertEqual(y.__class__, x.__class__)
206        self.assertEqual(y.foo, x.foo)
207
208    def test_deepcopy_registry(self):
209        class C(object):
210            def __new__(cls, foo):
211                obj = object.__new__(cls)
212                obj.foo = foo
213                return obj
214        def pickle_C(obj):
215            return (C, (obj.foo,))
216        x = C(42)
217        self.assertRaises(TypeError, copy.deepcopy, x)
218        copy_reg.pickle(C, pickle_C, C)
219        y = copy.deepcopy(x)
220
221    def test_deepcopy_reduce_ex(self):
222        class C(object):
223            def __reduce_ex__(self, proto):
224                return ""
225            def __reduce__(self):
226                raise test_support.TestFailed, "shouldn't call this"
227        x = C()
228        y = copy.deepcopy(x)
229        self.assert_(y is x)
230
231    def test_deepcopy_reduce(self):
232        class C(object):
233            def __reduce__(self):
234                return ""
235        x = C()
236        y = copy.deepcopy(x)
237        self.assert_(y is x)
238
239    def test_deepcopy_cant(self):
240        class C(object):
241            def __getattribute__(self, name):
242                if name.startswith("__reduce"):
243                    raise AttributeError, name
244                return object.__getattribute__(self, name)
245        x = C()
246        self.assertRaises(copy.Error, copy.deepcopy, x)
247
248    # Type-specific _deepcopy_xxx() methods
249
250    def test_deepcopy_atomic(self):
251        class Classic:
252            pass
253        class NewStyle(object):
254            pass
255        def f():
256            pass
257        tests = [None, 42, 2L**100, 3.14, True, False, 1j,
258                 "hello", u"hello\u1234", f.func_code,
259                 NewStyle, xrange(10), Classic, max]
260        for x in tests:
261            self.assert_(copy.deepcopy(x) is x, repr(x))
262
263    def test_deepcopy_list(self):
264        x = [[1, 2], 3]
265        y = copy.deepcopy(x)
266        self.assertEqual(y, x)
267        self.assert_(x is not y)
268        self.assert_(x[0] is not y[0])
269
270    def test_deepcopy_reflexive_list(self):
271        x = []
272        x.append(x)
273        y = copy.deepcopy(x)
274        self.assertRaises(RuntimeError, cmp, y, x)
275        self.assert_(y is not x)
276        self.assert_(y[0] is y)
277        self.assertEqual(len(y), 1)
278
279    def test_deepcopy_tuple(self):
280        x = ([1, 2], 3)
281        y = copy.deepcopy(x)
282        self.assertEqual(y, x)
283        self.assert_(x is not y)
284        self.assert_(x[0] is not y[0])
285
286    def test_deepcopy_reflexive_tuple(self):
287        x = ([],)
288        x[0].append(x)
289        y = copy.deepcopy(x)
290        self.assertRaises(RuntimeError, cmp, y, x)
291        self.assert_(y is not x)
292        self.assert_(y[0] is not x[0])
293        self.assert_(y[0][0] is y)
294
295    def test_deepcopy_dict(self):
296        x = {"foo": [1, 2], "bar": 3}
297        y = copy.deepcopy(x)
298        self.assertEqual(y, x)
299        self.assert_(x is not y)
300        self.assert_(x["foo"] is not y["foo"])
301
302    def test_deepcopy_reflexive_dict(self):
303        x = {}
304        x['foo'] = x
305        y = copy.deepcopy(x)
306        self.assertRaises(RuntimeError, cmp, y, x)
307        self.assert_(y is not x)
308        self.assert_(y['foo'] is y)
309        self.assertEqual(len(y), 1)
310
311    def test_deepcopy_keepalive(self):
312        memo = {}
313        x = 42
314        y = copy.deepcopy(x, memo)
315        self.assert_(memo[id(x)] is x)
316
317    def test_deepcopy_inst_vanilla(self):
318        class C:
319            def __init__(self, foo):
320                self.foo = foo
321            def __cmp__(self, other):
322                return cmp(self.foo, other.foo)
323        x = C([42])
324        y = copy.deepcopy(x)
325        self.assertEqual(y, x)
326        self.assert_(y.foo is not x.foo)
327
328    def test_deepcopy_inst_deepcopy(self):
329        class C:
330            def __init__(self, foo):
331                self.foo = foo
332            def __deepcopy__(self, memo):
333                return C(copy.deepcopy(self.foo, memo))
334            def __cmp__(self, other):
335                return cmp(self.foo, other.foo)
336        x = C([42])
337        y = copy.deepcopy(x)
338        self.assertEqual(y, x)
339        self.assert_(y is not x)
340        self.assert_(y.foo is not x.foo)
341
342    def test_deepcopy_inst_getinitargs(self):
343        class C:
344            def __init__(self, foo):
345                self.foo = foo
346            def __getinitargs__(self):
347                return (self.foo,)
348            def __cmp__(self, other):
349                return cmp(self.foo, other.foo)
350        x = C([42])
351        y = copy.deepcopy(x)
352        self.assertEqual(y, x)
353        self.assert_(y is not x)
354        self.assert_(y.foo is not x.foo)
355
356    def test_deepcopy_inst_getstate(self):
357        class C:
358            def __init__(self, foo):
359                self.foo = foo
360            def __getstate__(self):
361                return {"foo": self.foo}
362            def __cmp__(self, other):
363                return cmp(self.foo, other.foo)
364        x = C([42])
365        y = copy.deepcopy(x)
366        self.assertEqual(y, x)
367        self.assert_(y is not x)
368        self.assert_(y.foo is not x.foo)
369
370    def test_deepcopy_inst_setstate(self):
371        class C:
372            def __init__(self, foo):
373                self.foo = foo
374            def __setstate__(self, state):
375                self.foo = state["foo"]
376            def __cmp__(self, other):
377                return cmp(self.foo, other.foo)
378        x = C([42])
379        y = copy.deepcopy(x)
380        self.assertEqual(y, x)
381        self.assert_(y is not x)
382        self.assert_(y.foo is not x.foo)
383
384    def test_deepcopy_inst_getstate_setstate(self):
385        class C:
386            def __init__(self, foo):
387                self.foo = foo
388            def __getstate__(self):
389                return self.foo
390            def __setstate__(self, state):
391                self.foo = state
392            def __cmp__(self, other):
393                return cmp(self.foo, other.foo)
394        x = C([42])
395        y = copy.deepcopy(x)
396        self.assertEqual(y, x)
397        self.assert_(y is not x)
398        self.assert_(y.foo is not x.foo)
399
400    def test_deepcopy_reflexive_inst(self):
401        class C:
402            pass
403        x = C()
404        x.foo = x
405        y = copy.deepcopy(x)
406        self.assert_(y is not x)
407        self.assert_(y.foo is y)
408
409    # _reconstruct()
410
411    def test_reconstruct_string(self):
412        class C(object):
413            def __reduce__(self):
414                return ""
415        x = C()
416        y = copy.copy(x)
417        self.assert_(y is x)
418        y = copy.deepcopy(x)
419        self.assert_(y is x)
420
421    def test_reconstruct_nostate(self):
422        class C(object):
423            def __reduce__(self):
424                return (C, ())
425        x = C()
426        x.foo = 42
427        y = copy.copy(x)
428        self.assert_(y.__class__ is x.__class__)
429        y = copy.deepcopy(x)
430        self.assert_(y.__class__ is x.__class__)
431
432    def test_reconstruct_state(self):
433        class C(object):
434            def __reduce__(self):
435                return (C, (), self.__dict__)
436            def __cmp__(self, other):
437                return cmp(self.__dict__, other.__dict__)
438            __hash__ = None # Silence Py3k warning
439        x = C()
440        x.foo = [42]
441        y = copy.copy(x)
442        self.assertEqual(y, x)
443        y = copy.deepcopy(x)
444        self.assertEqual(y, x)
445        self.assert_(y.foo is not x.foo)
446
447    def test_reconstruct_state_setstate(self):
448        class C(object):
449            def __reduce__(self):
450                return (C, (), self.__dict__)
451            def __setstate__(self, state):
452                self.__dict__.update(state)
453            def __cmp__(self, other):
454                return cmp(self.__dict__, other.__dict__)
455            __hash__ = None # Silence Py3k warning
456        x = C()
457        x.foo = [42]
458        y = copy.copy(x)
459        self.assertEqual(y, x)
460        y = copy.deepcopy(x)
461        self.assertEqual(y, x)
462        self.assert_(y.foo is not x.foo)
463
464    def test_reconstruct_reflexive(self):
465        class C(object):
466            pass
467        x = C()
468        x.foo = x
469        y = copy.deepcopy(x)
470        self.assert_(y is not x)
471        self.assert_(y.foo is y)
472
473    # Additions for Python 2.3 and pickle protocol 2
474
475    def test_reduce_4tuple(self):
476        class C(list):
477            def __reduce__(self):
478                return (C, (), self.__dict__, iter(self))
479            def __cmp__(self, other):
480                return (cmp(list(self), list(other)) or
481                        cmp(self.__dict__, other.__dict__))
482            __hash__ = None # Silence Py3k warning
483        x = C([[1, 2], 3])
484        y = copy.copy(x)
485        self.assertEqual(x, y)
486        self.assert_(x is not y)
487        self.assert_(x[0] is y[0])
488        y = copy.deepcopy(x)
489        self.assertEqual(x, y)
490        self.assert_(x is not y)
491        self.assert_(x[0] is not y[0])
492
493    def test_reduce_5tuple(self):
494        class C(dict):
495            def __reduce__(self):
496                return (C, (), self.__dict__, None, self.iteritems())
497            def __cmp__(self, other):
498                return (cmp(dict(self), list(dict)) or
499                        cmp(self.__dict__, other.__dict__))
500            __hash__ = None # Silence Py3k warning
501        x = C([("foo", [1, 2]), ("bar", 3)])
502        y = copy.copy(x)
503        self.assertEqual(x, y)
504        self.assert_(x is not y)
505        self.assert_(x["foo"] is y["foo"])
506        y = copy.deepcopy(x)
507        self.assertEqual(x, y)
508        self.assert_(x is not y)
509        self.assert_(x["foo"] is not y["foo"])
510
511    def test_copy_slots(self):
512        class C(object):
513            __slots__ = ["foo"]
514        x = C()
515        x.foo = [42]
516        y = copy.copy(x)
517        self.assert_(x.foo is y.foo)
518
519    def test_deepcopy_slots(self):
520        class C(object):
521            __slots__ = ["foo"]
522        x = C()
523        x.foo = [42]
524        y = copy.deepcopy(x)
525        self.assertEqual(x.foo, y.foo)
526        self.assert_(x.foo is not y.foo)
527
528    def test_copy_list_subclass(self):
529        class C(list):
530            pass
531        x = C([[1, 2], 3])
532        x.foo = [4, 5]
533        y = copy.copy(x)
534        self.assertEqual(list(x), list(y))
535        self.assertEqual(x.foo, y.foo)
536        self.assert_(x[0] is y[0])
537        self.assert_(x.foo is y.foo)
538
539    def test_deepcopy_list_subclass(self):
540        class C(list):
541            pass
542        x = C([[1, 2], 3])
543        x.foo = [4, 5]
544        y = copy.deepcopy(x)
545        self.assertEqual(list(x), list(y))
546        self.assertEqual(x.foo, y.foo)
547        self.assert_(x[0] is not y[0])
548        self.assert_(x.foo is not y.foo)
549
550    def test_copy_tuple_subclass(self):
551        class C(tuple):
552            pass
553        x = C([1, 2, 3])
554        self.assertEqual(tuple(x), (1, 2, 3))
555        y = copy.copy(x)
556        self.assertEqual(tuple(y), (1, 2, 3))
557
558    def test_deepcopy_tuple_subclass(self):
559        class C(tuple):
560            pass
561        x = C([[1, 2], 3])
562        self.assertEqual(tuple(x), ([1, 2], 3))
563        y = copy.deepcopy(x)
564        self.assertEqual(tuple(y), ([1, 2], 3))
565        self.assert_(x is not y)
566        self.assert_(x[0] is not y[0])
567
568    def test_getstate_exc(self):
569        class EvilState(object):
570            def __getstate__(self):
571                raise ValueError, "ain't got no stickin' state"
572        self.assertRaises(ValueError, copy.copy, EvilState())
573
574    def test_copy_function(self):
575        self.assertEqual(copy.copy(global_foo), global_foo)
576        def foo(x, y): return x+y
577        self.assertEqual(copy.copy(foo), foo)
578        bar = lambda: None
579        self.assertEqual(copy.copy(bar), bar)
580
581    def test_deepcopy_function(self):
582        self.assertEqual(copy.deepcopy(global_foo), global_foo)
583        def foo(x, y): return x+y
584        self.assertEqual(copy.deepcopy(foo), foo)
585        bar = lambda: None
586        self.assertEqual(copy.deepcopy(bar), bar)
587
588def global_foo(x, y): return x+y
589
590def test_main():
591    test_support.run_unittest(TestCopy)
592
593if __name__ == "__main__":
594    test_main()