test_abc.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #!/usr/bin/env python
  2. """
  3. test dill's ability to pickle abstract base class objects
  4. """
  5. import dill
  6. import abc
  7. from abc import ABC
  8. import warnings
  9. from types import FunctionType
  10. dill.settings['recurse'] = True
  11. class OneTwoThree(ABC):
  12. @abc.abstractmethod
  13. def foo(self):
  14. """A method"""
  15. pass
  16. @property
  17. @abc.abstractmethod
  18. def bar(self):
  19. """Property getter"""
  20. pass
  21. @bar.setter
  22. @abc.abstractmethod
  23. def bar(self, value):
  24. """Property setter"""
  25. pass
  26. @classmethod
  27. @abc.abstractmethod
  28. def cfoo(cls):
  29. """Class method"""
  30. pass
  31. @staticmethod
  32. @abc.abstractmethod
  33. def sfoo():
  34. """Static method"""
  35. pass
  36. class EasyAsAbc(OneTwoThree):
  37. def __init__(self):
  38. self._bar = None
  39. def foo(self):
  40. return "Instance Method FOO"
  41. @property
  42. def bar(self):
  43. return self._bar
  44. @bar.setter
  45. def bar(self, value):
  46. self._bar = value
  47. @classmethod
  48. def cfoo(cls):
  49. return "Class Method CFOO"
  50. @staticmethod
  51. def sfoo():
  52. return "Static Method SFOO"
  53. def test_abc_non_local():
  54. assert dill.copy(OneTwoThree) is not OneTwoThree
  55. assert dill.copy(EasyAsAbc) is not EasyAsAbc
  56. with warnings.catch_warnings():
  57. warnings.simplefilter("ignore", dill.PicklingWarning)
  58. assert dill.copy(OneTwoThree, byref=True) is OneTwoThree
  59. assert dill.copy(EasyAsAbc, byref=True) is EasyAsAbc
  60. instance = EasyAsAbc()
  61. # Set a property that StockPickle can't preserve
  62. instance.bar = lambda x: x**2
  63. depickled = dill.copy(instance)
  64. assert type(depickled) is not type(instance)
  65. assert type(depickled.bar) is FunctionType
  66. assert depickled.bar(3) == 9
  67. assert depickled.sfoo() == "Static Method SFOO"
  68. assert depickled.cfoo() == "Class Method CFOO"
  69. assert depickled.foo() == "Instance Method FOO"
  70. def test_abc_local():
  71. """
  72. Test using locally scoped ABC class
  73. """
  74. class LocalABC(ABC):
  75. @abc.abstractmethod
  76. def foo(self):
  77. pass
  78. def baz(self):
  79. return repr(self)
  80. labc = dill.copy(LocalABC)
  81. assert labc is not LocalABC
  82. assert type(labc) is type(LocalABC)
  83. # TODO should work like it does for non local classes
  84. # <class '__main__.LocalABC'>
  85. # <class '__main__.test_abc_local.<locals>.LocalABC'>
  86. class Real(labc):
  87. def foo(self):
  88. return "True!"
  89. def baz(self):
  90. return "My " + super(Real, self).baz()
  91. real = Real()
  92. assert real.foo() == "True!"
  93. try:
  94. labc()
  95. except TypeError as e:
  96. # Expected error
  97. pass
  98. else:
  99. print('Failed to raise type error')
  100. assert False
  101. labc2, pik = dill.copy((labc, Real()))
  102. assert 'Real' == type(pik).__name__
  103. assert '.Real' in type(pik).__qualname__
  104. assert type(pik) is not Real
  105. assert labc2 is not LocalABC
  106. assert labc2 is not labc
  107. assert isinstance(pik, labc2)
  108. assert not isinstance(pik, labc)
  109. assert not isinstance(pik, LocalABC)
  110. assert pik.baz() == "My " + repr(pik)
  111. def test_meta_local_no_cache():
  112. """
  113. Test calling metaclass and cache registration
  114. """
  115. LocalMetaABC = abc.ABCMeta('LocalMetaABC', (), {})
  116. class ClassyClass:
  117. pass
  118. class KlassyClass:
  119. pass
  120. LocalMetaABC.register(ClassyClass)
  121. assert not issubclass(KlassyClass, LocalMetaABC)
  122. assert issubclass(ClassyClass, LocalMetaABC)
  123. res = dill.dumps((LocalMetaABC, ClassyClass, KlassyClass))
  124. lmabc, cc, kc = dill.loads(res)
  125. assert type(lmabc) == type(LocalMetaABC)
  126. assert not issubclass(kc, lmabc)
  127. assert issubclass(cc, lmabc)
  128. if __name__ == '__main__':
  129. test_abc_non_local()
  130. test_abc_local()
  131. test_meta_local_no_cache()