test_detect.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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-2023 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. from dill.detect import baditems, badobjects, badtypes, errors, parent, at, globalvars
  9. from dill import settings
  10. from dill._dill import IS_PYPY
  11. from pickle import PicklingError
  12. import inspect
  13. import sys
  14. import os
  15. def test_bad_things():
  16. f = inspect.currentframe()
  17. assert baditems(f) == [f]
  18. #assert baditems(globals()) == [f] #XXX
  19. assert badobjects(f) is f
  20. assert badtypes(f) == type(f)
  21. assert type(errors(f)) is TypeError
  22. d = badtypes(f, 1)
  23. assert isinstance(d, dict)
  24. assert list(badobjects(f, 1).keys()) == list(d.keys())
  25. assert list(errors(f, 1).keys()) == list(d.keys())
  26. s = set([(err.__class__.__name__,err.args[0]) for err in list(errors(f, 1).values())])
  27. a = dict(s)
  28. if not os.environ.get('COVERAGE'): #XXX: travis-ci
  29. assert len(s) is len(a) # TypeError (and possibly PicklingError)
  30. n = 2
  31. assert len(a) is n if 'PicklingError' in a.keys() else n-1
  32. def test_parent():
  33. x = [4,5,6,7]
  34. listiter = iter(x)
  35. obj = parent(listiter, list)
  36. assert obj is x
  37. if IS_PYPY: assert parent(obj, int) is None
  38. else: assert parent(obj, int) is x[-1] # python oddly? finds last int
  39. assert at(id(at)) is at
  40. a, b, c = 1, 2, 3
  41. def squared(x):
  42. return a+x**2
  43. def foo(x):
  44. def bar(y):
  45. return squared(x)+y
  46. return bar
  47. class _class:
  48. def _method(self):
  49. pass
  50. def ok(self):
  51. return True
  52. def test_globals():
  53. def f():
  54. a
  55. def g():
  56. b
  57. def h():
  58. c
  59. assert globalvars(f) == dict(a=1, b=2, c=3)
  60. res = globalvars(foo, recurse=True)
  61. assert set(res) == set(['squared', 'a'])
  62. res = globalvars(foo, recurse=False)
  63. assert res == {}
  64. zap = foo(2)
  65. res = globalvars(zap, recurse=True)
  66. assert set(res) == set(['squared', 'a'])
  67. res = globalvars(zap, recurse=False)
  68. assert set(res) == set(['squared'])
  69. del zap
  70. res = globalvars(squared)
  71. assert set(res) == set(['a'])
  72. # FIXME: should find referenced __builtins__
  73. #res = globalvars(_class, recurse=True)
  74. #assert set(res) == set(['True'])
  75. #res = globalvars(_class, recurse=False)
  76. #assert res == {}
  77. #res = globalvars(_class.ok, recurse=True)
  78. #assert set(res) == set(['True'])
  79. #res = globalvars(_class.ok, recurse=False)
  80. #assert set(res) == set(['True'])
  81. #98 dill ignores __getstate__ in interactive lambdas
  82. bar = [0]
  83. class Foo(object):
  84. def __init__(self):
  85. pass
  86. def __getstate__(self):
  87. bar[0] = bar[0]+1
  88. return {}
  89. def __setstate__(self, data):
  90. pass
  91. f = Foo()
  92. def test_getstate():
  93. from dill import dumps, loads
  94. dumps(f)
  95. b = bar[0]
  96. dumps(lambda: f, recurse=False) # doesn't call __getstate__
  97. assert bar[0] == b
  98. dumps(lambda: f, recurse=True) # calls __getstate__
  99. assert bar[0] == b + 1
  100. #97 serialize lambdas in test files
  101. def test_deleted():
  102. global sin
  103. from dill import dumps, loads
  104. from math import sin, pi
  105. def sinc(x):
  106. return sin(x)/x
  107. settings['recurse'] = True
  108. _sinc = dumps(sinc)
  109. sin = globals().pop('sin')
  110. sin = 1
  111. del sin
  112. sinc_ = loads(_sinc) # no NameError... pickling preserves 'sin'
  113. res = sinc_(1)
  114. from math import sin
  115. assert sinc(1) == res
  116. def test_lambdify():
  117. try:
  118. from sympy import symbols, lambdify
  119. except ImportError:
  120. return
  121. settings['recurse'] = True
  122. x = symbols("x")
  123. y = x**2
  124. f = lambdify([x], y)
  125. z = min
  126. d = globals()
  127. globalvars(f, recurse=True, builtin=True)
  128. assert z is min
  129. assert d is globals()
  130. if __name__ == '__main__':
  131. test_bad_things()
  132. test_parent()
  133. test_globals()
  134. test_getstate()
  135. test_deleted()
  136. test_lambdify()