test_classdef.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #!/usr/bin/env python
  2. #
  3. # Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
  4. # Copyright (c) 2008-2016 California Institute of Technology.
  5. # Copyright (c) 2016-2022 The Uncertainty Quantification Foundation.
  6. # License: 3-clause BSD. The full license text is available at:
  7. # - https://github.com/uqfoundation/dill/blob/master/LICENSE
  8. import dill
  9. import sys
  10. dill.settings['recurse'] = True
  11. # test classdefs
  12. class _class:
  13. def _method(self):
  14. pass
  15. def ok(self):
  16. return True
  17. class _class2:
  18. def __call__(self):
  19. pass
  20. def ok(self):
  21. return True
  22. class _newclass(object):
  23. def _method(self):
  24. pass
  25. def ok(self):
  26. return True
  27. class _newclass2(object):
  28. def __call__(self):
  29. pass
  30. def ok(self):
  31. return True
  32. class _meta(type):
  33. pass
  34. def __call__(self):
  35. pass
  36. def ok(self):
  37. return True
  38. _mclass = _meta("_mclass", (object,), {"__call__": __call__, "ok": ok})
  39. del __call__
  40. del ok
  41. o = _class()
  42. oc = _class2()
  43. n = _newclass()
  44. nc = _newclass2()
  45. m = _mclass()
  46. # test pickles for class instances
  47. def test_class_instances():
  48. assert dill.pickles(o)
  49. assert dill.pickles(oc)
  50. assert dill.pickles(n)
  51. assert dill.pickles(nc)
  52. assert dill.pickles(m)
  53. def test_class_objects():
  54. clslist = [_class,_class2,_newclass,_newclass2,_mclass]
  55. objlist = [o,oc,n,nc,m]
  56. _clslist = [dill.dumps(obj) for obj in clslist]
  57. _objlist = [dill.dumps(obj) for obj in objlist]
  58. for obj in clslist:
  59. globals().pop(obj.__name__)
  60. del clslist
  61. for obj in ['o','oc','n','nc']:
  62. globals().pop(obj)
  63. del objlist
  64. del obj
  65. for obj,cls in zip(_objlist,_clslist):
  66. _cls = dill.loads(cls)
  67. _obj = dill.loads(obj)
  68. assert _obj.ok()
  69. assert _cls.ok(_cls())
  70. if _cls.__name__ == "_mclass":
  71. assert type(_cls).__name__ == "_meta"
  72. # test NoneType
  73. def test_specialtypes():
  74. assert dill.pickles(type(None))
  75. assert dill.pickles(type(NotImplemented))
  76. assert dill.pickles(type(Ellipsis))
  77. from collections import namedtuple
  78. Z = namedtuple("Z", ['a','b'])
  79. Zi = Z(0,1)
  80. X = namedtuple("Y", ['a','b'])
  81. X.__name__ = "X"
  82. X.__qualname__ = "X" #XXX: name must 'match' or fails to pickle
  83. Xi = X(0,1)
  84. Bad = namedtuple("FakeName", ['a','b'])
  85. Badi = Bad(0,1)
  86. # test namedtuple
  87. def test_namedtuple():
  88. assert Z is dill.loads(dill.dumps(Z))
  89. assert Zi == dill.loads(dill.dumps(Zi))
  90. assert X is dill.loads(dill.dumps(X))
  91. assert Xi == dill.loads(dill.dumps(Xi))
  92. assert Bad is not dill.loads(dill.dumps(Bad))
  93. assert Bad._fields == dill.loads(dill.dumps(Bad))._fields
  94. assert tuple(Badi) == tuple(dill.loads(dill.dumps(Badi)))
  95. class A:
  96. class B(namedtuple("B", ["one", "two"])):
  97. '''docstring'''
  98. B.__module__ = 'testing'
  99. a = A()
  100. assert dill.copy(a)
  101. assert dill.copy(A.B).__name__ == 'B'
  102. assert dill.copy(A.B).__qualname__.endswith('.<locals>.A.B')
  103. assert dill.copy(A.B).__doc__ == 'docstring'
  104. assert dill.copy(A.B).__module__ == 'testing'
  105. def test_dtype():
  106. try:
  107. import numpy as np
  108. dti = np.dtype('int')
  109. assert np.dtype == dill.copy(np.dtype)
  110. assert dti == dill.copy(dti)
  111. except ImportError: pass
  112. def test_array_nested():
  113. try:
  114. import numpy as np
  115. x = np.array([1])
  116. y = (x,)
  117. assert y == dill.copy(y)
  118. except ImportError: pass
  119. def test_array_subclass():
  120. try:
  121. import numpy as np
  122. class TestArray(np.ndarray):
  123. def __new__(cls, input_array, color):
  124. obj = np.asarray(input_array).view(cls)
  125. obj.color = color
  126. return obj
  127. def __array_finalize__(self, obj):
  128. if obj is None:
  129. return
  130. if isinstance(obj, type(self)):
  131. self.color = obj.color
  132. def __getnewargs__(self):
  133. return np.asarray(self), self.color
  134. a1 = TestArray(np.zeros(100), color='green')
  135. if not dill._dill.IS_PYPY:
  136. assert dill.pickles(a1)
  137. assert a1.__dict__ == dill.copy(a1).__dict__
  138. a2 = a1[0:9]
  139. if not dill._dill.IS_PYPY:
  140. assert dill.pickles(a2)
  141. assert a2.__dict__ == dill.copy(a2).__dict__
  142. class TestArray2(np.ndarray):
  143. color = 'blue'
  144. a3 = TestArray2([1,2,3,4,5])
  145. a3.color = 'green'
  146. if not dill._dill.IS_PYPY:
  147. assert dill.pickles(a3)
  148. assert a3.__dict__ == dill.copy(a3).__dict__
  149. except ImportError: pass
  150. def test_method_decorator():
  151. class A(object):
  152. @classmethod
  153. def test(cls):
  154. pass
  155. a = A()
  156. res = dill.dumps(a)
  157. new_obj = dill.loads(res)
  158. new_obj.__class__.test()
  159. # test slots
  160. class Y(object):
  161. __slots__ = ('y', '__weakref__')
  162. def __init__(self, y):
  163. self.y = y
  164. value = 123
  165. y = Y(value)
  166. def test_slots():
  167. assert dill.pickles(Y)
  168. assert dill.pickles(y)
  169. assert dill.pickles(Y.y)
  170. assert dill.copy(y).y == value
  171. def test_attr():
  172. import attr
  173. @attr.s
  174. class A:
  175. a = attr.ib()
  176. v = A(1)
  177. assert dill.copy(v) == v
  178. def test_metaclass():
  179. class metaclass_with_new(type):
  180. def __new__(mcls, name, bases, ns, **kwds):
  181. cls = super().__new__(mcls, name, bases, ns, **kwds)
  182. assert mcls is not None
  183. assert cls.method(mcls)
  184. return cls
  185. def method(cls, mcls):
  186. return isinstance(cls, mcls)
  187. l = locals()
  188. exec("""class subclass_with_new(metaclass=metaclass_with_new):
  189. def __new__(cls):
  190. self = super().__new__(cls)
  191. return self""", None, l)
  192. subclass_with_new = l['subclass_with_new']
  193. assert dill.copy(subclass_with_new())
  194. if __name__ == '__main__':
  195. test_class_instances()
  196. test_class_objects()
  197. test_specialtypes()
  198. test_namedtuple()
  199. test_dtype()
  200. test_array_nested()
  201. test_array_subclass()
  202. test_method_decorator()
  203. test_slots()
  204. test_metaclass()