"""Unit tests for the copy module."""
from test
import test_support
class TestCopy(unittest
.TestCase
):
# Attempt full line coverage of copy.py from top to bottom
def test_exceptions(self
):
self
.assert_(copy
.Error
is copy
.error
)
self
.assert_(issubclass(copy
.Error
, Exception))
def test_copy_basic(self
):
def test_copy_copy(self
):
self
.assertEqual(y
.__class
__, x
.__class
__)
self
.assertEqual(y
.foo
, x
.foo
)
def test_copy_registry(self
):
obj
= object.__new
__(cls
)
self
.assertRaises(TypeError, copy
.copy
, x
)
copy_reg
.pickle(C
, pickle_C
, C
)
def test_copy_reduce_ex(self
):
def __reduce_ex__(self
, proto
):
raise test_support
.TestFailed
, "shouldn't call this"
def test_copy_reduce(self
):
def test_copy_cant(self
):
def __getattribute__(self
, name
):
if name
.startswith("__reduce"):
raise AttributeError, name
return object.__getattribute
__(self
, name
)
self
.assertRaises(copy
.Error
, copy
.copy
, x
)
# Type-specific _copy_xxx() methods
def test_copy_atomic(self
):
tests
= [None, 42, 2L**100, 3.14, True, False, 1j
,
"hello", u
"hello\u1234", f
.func_code
,
NewStyle
, xrange(10), Classic
, max]
self
.assert_(copy
.copy(x
) is x
, repr(x
))
def test_copy_list(self
):
self
.assertEqual(copy
.copy(x
), x
)
def test_copy_tuple(self
):
self
.assertEqual(copy
.copy(x
), x
)
def test_copy_dict(self
):
self
.assertEqual(copy
.copy(x
), x
)
def test_copy_inst_vanilla(self
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assertEqual(copy
.copy(x
), x
)
def test_copy_inst_copy(self
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assertEqual(copy
.copy(x
), x
)
def test_copy_inst_getinitargs(self
):
def __getinitargs__(self
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assertEqual(copy
.copy(x
), x
)
def test_copy_inst_getstate(self
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assertEqual(copy
.copy(x
), x
)
def test_copy_inst_setstate(self
):
def __setstate__(self
, state
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assertEqual(copy
.copy(x
), x
)
def test_copy_inst_getstate_setstate(self
):
def __setstate__(self
, state
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assertEqual(copy
.copy(x
), x
)
# tests for copying extension types, iff module trycopy is installed
def test_copy_classictype(self
):
from _testcapi
import make_copyable
self
.assertEqual(x
.tag
, y
.tag
)
self
.assert_(x
.tag
is y
.tag
)
def test_deepcopy_classictype(self
):
from _testcapi
import make_copyable
self
.assertEqual(x
.tag
, y
.tag
)
self
.assert_(x
.tag
is not y
.tag
)
# regression tests for class-vs-instance and metaclass-confusion
def test_copy_classoverinstance(self
):
def __cmp__(self
, other
):
return -cmp(other
, self
.v
)
return self
.__class
__(self
.v
)
self
.assertEqual(copy
.copy(x
), x
)
self
.assertEqual(copy
.copy(x
), x
)
def test_deepcopy_classoverinstance(self
):
def __cmp__(self
, other
):
return -cmp(other
, self
.v
)
def __deepcopy__(self
, memo
):
return self
.__class
__(copy
.deepcopy(self
.v
, memo
))
self
.assertEqual(copy
.deepcopy(x
), x
)
x
.__deepcopy
__ = lambda memo
: 42
self
.assertEqual(copy
.deepcopy(x
), x
)
def test_copy_metaclassconfusion(self
):
class MyOwnError(copy
.Error
):
raise MyOwnError("can't copy classes w/this metaclass")
def __cmp__(self
, other
):
return -cmp(other
, self
.tag
)
# the metaclass can forbid shallow copying of its classes
self
.assertRaises(MyOwnError
, copy
.copy
, C
)
# check that there is no interference with instances
self
.assertEqual(copy
.copy(x
), x
)
def test_deepcopy_metaclassconfusion(self
):
class MyOwnError(copy
.Error
):
def __deepcopy__(cls
, memo
):
raise MyOwnError("can't deepcopy classes w/this metaclass")
def __cmp__(self
, other
):
return -cmp(other
, self
.tag
)
# types are ALWAYS deepcopied atomically, no matter what
self
.assertEqual(copy
.deepcopy(C
), C
)
# check that there is no interference with instances
self
.assertEqual(copy
.deepcopy(x
), x
)
def __getattribute__(self
, attr
):
raise AttributeError, "What, *me*, a __mro__? Nevah!"
return super(C
, self
).__getattribute
__(attr
)
def test_deepcopy_mro(self
):
def test_deepcopy_basic(self
):
def test_deepcopy_memo(self
):
# Tests of reflexive objects are under type-specific sections below.
# This tests only repetitions of objects.
self
.assert_(y
[0] is not x
[0])
self
.assert_(y
[0] is y
[1])
def test_deepcopy_issubclass(self
):
# XXX Note: there's no way to test the TypeError coming out of
# issubclass() -- this can only happen when an extension
# module defines a "type" that doesn't formally inherit from
self
.assertEqual(copy
.deepcopy(C
), C
)
def test_deepcopy_deepcopy(self
):
def __deepcopy__(self
, memo
=None):
self
.assertEqual(y
.__class
__, x
.__class
__)
self
.assertEqual(y
.foo
, x
.foo
)
def test_deepcopy_registry(self
):
obj
= object.__new
__(cls
)
self
.assertRaises(TypeError, copy
.deepcopy
, x
)
copy_reg
.pickle(C
, pickle_C
, C
)
def test_deepcopy_reduce_ex(self
):
def __reduce_ex__(self
, proto
):
raise test_support
.TestFailed
, "shouldn't call this"
def test_deepcopy_reduce(self
):
def test_deepcopy_cant(self
):
def __getattribute__(self
, name
):
if name
.startswith("__reduce"):
raise AttributeError, name
return object.__getattribute
__(self
, name
)
self
.assertRaises(copy
.Error
, copy
.deepcopy
, x
)
# Type-specific _deepcopy_xxx() methods
def test_deepcopy_atomic(self
):
tests
= [None, 42, 2L**100, 3.14, True, False, 1j
,
"hello", u
"hello\u1234", f
.func_code
,
NewStyle
, xrange(10), Classic
, max]
self
.assert_(copy
.deepcopy(x
) is x
, repr(x
))
def test_deepcopy_list(self
):
self
.assert_(x
[0] is not y
[0])
def test_deepcopy_reflexive_list(self
):
self
.assertRaises(RuntimeError, cmp, y
, x
)
self
.assertEqual(len(y
), 1)
def test_deepcopy_tuple(self
):
self
.assert_(x
[0] is not y
[0])
def test_deepcopy_reflexive_tuple(self
):
self
.assertRaises(RuntimeError, cmp, y
, x
)
self
.assert_(y
[0] is not x
[0])
self
.assert_(y
[0][0] is y
)
def test_deepcopy_dict(self
):
x
= {"foo": [1, 2], "bar": 3}
self
.assert_(x
["foo"] is not y
["foo"])
def test_deepcopy_reflexive_dict(self
):
self
.assertRaises(RuntimeError, cmp, y
, x
)
self
.assert_(y
['foo'] is y
)
self
.assertEqual(len(y
), 1)
def test_deepcopy_keepalive(self
):
y
= copy
.deepcopy(x
, memo
)
self
.assert_(memo
[id(x
)] is x
)
def test_deepcopy_inst_vanilla(self
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assert_(y
.foo
is not x
.foo
)
def test_deepcopy_inst_deepcopy(self
):
def __deepcopy__(self
, memo
):
return C(copy
.deepcopy(self
.foo
, memo
))
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assert_(y
.foo
is not x
.foo
)
def test_deepcopy_inst_getinitargs(self
):
def __getinitargs__(self
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assert_(y
.foo
is not x
.foo
)
def test_deepcopy_inst_getstate(self
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assert_(y
.foo
is not x
.foo
)
def test_deepcopy_inst_setstate(self
):
def __setstate__(self
, state
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assert_(y
.foo
is not x
.foo
)
def test_deepcopy_inst_getstate_setstate(self
):
def __setstate__(self
, state
):
def __cmp__(self
, other
):
return cmp(self
.foo
, other
.foo
)
self
.assert_(y
.foo
is not x
.foo
)
def test_deepcopy_reflexive_inst(self
):
def test_reconstruct_string(self
):
def test_reconstruct_nostate(self
):
self
.assert_(y
.__class
__ is x
.__class
__)
self
.assert_(y
.__class
__ is x
.__class
__)
def test_reconstruct_state(self
):
return (C
, (), self
.__dict
__)
def __cmp__(self
, other
):
return cmp(self
.__dict
__, other
.__dict
__)
self
.assert_(y
.foo
is not x
.foo
)
def test_reconstruct_state_setstate(self
):
return (C
, (), self
.__dict
__)
def __setstate__(self
, state
):
self
.__dict
__.update(state
)
def __cmp__(self
, other
):
return cmp(self
.__dict
__, other
.__dict
__)
self
.assert_(y
.foo
is not x
.foo
)
def test_reconstruct_reflexive(self
):
# Additions for Python 2.3 and pickle protocol 2
def test_reduce_4tuple(self
):
return (C
, (), self
.__dict
__, iter(self
))
def __cmp__(self
, other
):
return (cmp(list(self
), list(other
)) or
cmp(self
.__dict
__, other
.__dict
__))
self
.assert_(x
[0] is y
[0])
self
.assert_(x
[0] is not y
[0])
def test_reduce_5tuple(self
):
return (C
, (), self
.__dict
__, None, self
.iteritems())
def __cmp__(self
, other
):
return (cmp(dict(self
), list(dict)) or
cmp(self
.__dict
__, other
.__dict
__))
x
= C([("foo", [1, 2]), ("bar", 3)])
self
.assert_(x
["foo"] is y
["foo"])
self
.assert_(x
["foo"] is not y
["foo"])
def test_copy_slots(self
):
self
.assert_(x
.foo
is y
.foo
)
def test_deepcopy_slots(self
):
self
.assertEqual(x
.foo
, y
.foo
)
self
.assert_(x
.foo
is not y
.foo
)
def test_copy_list_subclass(self
):
self
.assertEqual(list(x
), list(y
))
self
.assertEqual(x
.foo
, y
.foo
)
self
.assert_(x
[0] is y
[0])
self
.assert_(x
.foo
is y
.foo
)
def test_deepcopy_list_subclass(self
):
self
.assertEqual(list(x
), list(y
))
self
.assertEqual(x
.foo
, y
.foo
)
self
.assert_(x
[0] is not y
[0])
self
.assert_(x
.foo
is not y
.foo
)
def test_copy_tuple_subclass(self
):
self
.assertEqual(tuple(x
), (1, 2, 3))
self
.assertEqual(tuple(y
), (1, 2, 3))
def test_deepcopy_tuple_subclass(self
):
self
.assertEqual(tuple(x
), ([1, 2], 3))
self
.assertEqual(tuple(y
), ([1, 2], 3))
self
.assert_(x
[0] is not y
[0])
def test_getstate_exc(self
):
raise ValueError, "ain't got no stickin' state"
self
.assertRaises(ValueError, copy
.copy
, EvilState())
test_support
.run_unittest(TestCopy
)
if __name__
== "__main__":