/Lib/test/test_copy.py

http://unladen-swallow.googlecode.com/ · Python · 594 lines · 511 code · 69 blank · 14 comment · 5 complexity · 50ba370a42297ff3dba9b00f2b0b3f76 MD5 · raw file

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