test_detect.py 4.0 KB

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