deferred.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. # coding=utf-8
  2. #
  3. # This file is part of Hypothesis, which may be found at
  4. # https://github.com/HypothesisWorks/hypothesis-python
  5. #
  6. # Most of this work is copyright (C) 2013-2018 David R. MacIver
  7. # (david@drmaciver.com), but it contains contributions by others. See
  8. # CONTRIBUTING.rst for a full list of people who may hold copyright, and
  9. # consult the git log if you need to determine who owns an individual
  10. # contribution.
  11. #
  12. # This Source Code Form is subject to the terms of the Mozilla Public License,
  13. # v. 2.0. If a copy of the MPL was not distributed with this file, You can
  14. # obtain one at http://mozilla.org/MPL/2.0/.
  15. #
  16. # END HEADER
  17. from __future__ import division, print_function, absolute_import
  18. import inspect
  19. from hypothesis.errors import InvalidArgument
  20. from hypothesis.internal.reflection import get_pretty_function_description
  21. from hypothesis.searchstrategy.strategies import SearchStrategy
  22. class DeferredStrategy(SearchStrategy):
  23. """A strategy which may be used before it is fully defined."""
  24. def __init__(self, definition):
  25. SearchStrategy.__init__(self)
  26. self.__wrapped_strategy = None
  27. self.__in_repr = False
  28. self.__is_empty = None
  29. self.__definition = definition
  30. @property
  31. def wrapped_strategy(self):
  32. if self.__wrapped_strategy is None:
  33. if not inspect.isfunction(self.__definition):
  34. raise InvalidArgument((
  35. 'Excepted a definition to be a function but got %r of type'
  36. ' %s instead.') % (
  37. self.__definition, type(self.__definition).__name__))
  38. result = self.__definition()
  39. if result is self:
  40. raise InvalidArgument(
  41. 'Cannot define a deferred strategy to be itself')
  42. if not isinstance(result, SearchStrategy):
  43. raise InvalidArgument((
  44. 'Expected definition to return a SearchStrategy but '
  45. 'returned %r of type %s') % (
  46. result, type(result).__name__
  47. ))
  48. self.__wrapped_strategy = result
  49. del self.__definition
  50. return self.__wrapped_strategy
  51. @property
  52. def branches(self):
  53. return self.wrapped_strategy.branches
  54. @property
  55. def supports_find(self):
  56. return self.wrapped_strategy.supports_find
  57. def calc_is_empty(self, recur):
  58. return recur(self.wrapped_strategy)
  59. def calc_has_reusable_values(self, recur):
  60. return recur(self.wrapped_strategy)
  61. def __repr__(self):
  62. if self.__wrapped_strategy is not None:
  63. if self.__in_repr:
  64. return '(deferred@%r)' % (id(self),)
  65. try:
  66. self.__in_repr = True
  67. return repr(self.__wrapped_strategy)
  68. finally:
  69. self.__in_repr = False
  70. else:
  71. return 'deferred(%s)' % (
  72. get_pretty_function_description(self.__definition)
  73. )
  74. def do_draw(self, data):
  75. return data.draw(self.wrapped_strategy)