Hello community, here is the log from the commit of package python-hypothesis for openSUSE:Factory checked in at 2017-11-30 12:38:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-hypothesis (Old) and /work/SRC/openSUSE:Factory/.python-hypothesis.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-hypothesis" Thu Nov 30 12:38:19 2017 rev:12 rq:545893 version:3.38.5 Changes: -------- --- /work/SRC/openSUSE:Factory/python-hypothesis/python-hypothesis.changes 2017-11-21 15:28:52.588811435 +0100 +++ /work/SRC/openSUSE:Factory/.python-hypothesis.new/python-hypothesis.changes 2017-11-30 12:38:20.629292841 +0100 @@ -1,0 +2,37 @@ +Sun Nov 26 21:26:33 UTC 2017 - a...@gmx.de + +- update to version 3.38.5: + * This fixes the repr of strategies using lambda that are defined + inside decorators to include the lambda source. + This would mostly have been visible when using the statistics + functionality - lambdas used for e.g. filtering would have shown + up with a <unknown> as their body. This can still happen, but it + should happen less often now. + +------------------------------------------------------------------- +Wed Nov 22 19:42:32 UTC 2017 - a...@gmx.de + +- update to version 3.38.4: + * This release updates the reported statistics so that they show + approximately what fraction of your test run time is spent in data + generation (as opposed to test execution). + +- changes from version 3.38.3: + * This is a documentation release, which ensures code examples are + up to date by running them as doctests in CI (issue #711). + +- changes from version 3.38.2: + * This release changes the behaviour of the deadline setting when + used with data(): Time spent inside calls to data.draw will no + longer be counted towards the deadline time. + * As a side effect of some refactoring required for this work, the + way flaky tests are handled has changed slightly. You are unlikely + to see much difference from this, but some error messages will + have changed. + +- changes from version 3.38.1: + * This patch has a variety of non-user-visible refactorings, + removing various minor warts ranging from indirect imports to + typos in comments. + +------------------------------------------------------------------- Old: ---- hypothesis-3.38.0.tar.gz New: ---- hypothesis-3.38.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-hypothesis.spec ++++++ --- /var/tmp/diff_new_pack.xO0uBE/_old 2017-11-30 12:38:21.265269715 +0100 +++ /var/tmp/diff_new_pack.xO0uBE/_new 2017-11-30 12:38:21.269269570 +0100 @@ -24,7 +24,7 @@ %endif %bcond_with test Name: python-hypothesis -Version: 3.38.0 +Version: 3.38.5 Release: 0 Summary: A library for property based testing License: MPL-2.0 ++++++ hypothesis-3.38.0.tar.gz -> hypothesis-3.38.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/PKG-INFO new/hypothesis-3.38.5/PKG-INFO --- old/hypothesis-3.38.0/PKG-INFO 2017-11-18 11:27:46.000000000 +0100 +++ new/hypothesis-3.38.5/PKG-INFO 2017-11-23 20:40:32.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: hypothesis -Version: 3.38.0 +Version: 3.38.5 Summary: A library for property based testing Home-page: https://github.com/HypothesisWorks/hypothesis-python Author: David R. MacIver diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/core.py new/hypothesis-3.38.5/src/hypothesis/core.py --- old/hypothesis-3.38.0/src/hypothesis/core.py 2017-11-18 11:26:22.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/core.py 2017-11-23 20:40:05.000000000 +0100 @@ -23,7 +23,6 @@ import os import sys import time -import functools import traceback from random import Random @@ -45,7 +44,7 @@ from hypothesis.reporting import report, verbose_report, current_verbosity from hypothesis.statistics import note_engine_for_statistics from hypothesis.internal.compat import ceil, str_to_bytes, \ - get_type_hints, getfullargspec, encoded_filepath + benchmark_time, get_type_hints, getfullargspec, encoded_filepath from hypothesis.internal.coverage import IN_COVERAGE_TESTS from hypothesis.utils.conventions import infer, not_set from hypothesis.internal.escalation import is_hypothesis_file, \ @@ -76,18 +75,6 @@ return random.Random(random.getrandbits(128)) -def test_is_flaky(test, expected_repr): - @functools.wraps(test) - def test_or_flaky(*args, **kwargs): - text_repr = arg_string(test, args, kwargs) - raise Flaky( - ( - 'Hypothesis %s(%s) produces unreliable results: Falsified' - ' on the first call but did not on a subsequent one' - ) % (test.__name__, text_repr,)) - return test_or_flaky - - @attr.s() class Example(object): args = attr.ib() @@ -113,37 +100,6 @@ return accept -def reify_and_execute( - search_strategy, test, - print_example=False, - is_final=False, collector=None -): - def run(data): - with BuildContext(data, is_final=is_final): - import random as rnd_module - rnd_module.seed(0) - args, kwargs = data.draw(search_strategy) - - if print_example: - report( - lambda: 'Falsifying example: %s(%s)' % ( - test.__name__, arg_string(test, args, kwargs))) - elif current_verbosity() >= Verbosity.verbose: - report( - lambda: 'Trying example: %s(%s)' % ( - test.__name__, arg_string(test, args, kwargs))) - if collector is None: - return test(*args, **kwargs) - else: # pragma: no cover - try: - collector.start() - return test(*args, **kwargs) - finally: - collector.stop() - - return run - - def seed(seed): """seed: Start the test execution from a specific seed. @@ -438,44 +394,14 @@ self.settings = settings self.at_least_one_success = False self.last_exception = None - self.repr_for_last_exception = None self.falsifying_examples = () self.__was_flaky = False self.random = random self.__warned_deadline = False self.__existing_collector = None self.__test_runtime = None - self.__in_final_replay = False - if self.settings.deadline is None: - self.test = test - else: - @proxies(test) - def timed_test(*args, **kwargs): - self.__test_runtime = None - start = time.time() - result = test(*args, **kwargs) - runtime = (time.time() - start) * 1000 - self.__test_runtime = runtime - if self.settings.deadline is not_set: - if ( - not self.__warned_deadline and - runtime >= 200 - ): - self.__warned_deadline = True - note_deprecation(( - 'Test took %.2fms to run. In future the default ' - 'deadline setting will be 200ms, which will ' - 'make this an error. You can set deadline to ' - 'an explicit value of e.g. %d to turn tests ' - 'slower than this into an error, or you can set ' - 'it to None to disable this check entirely.') % ( - runtime, ceil(runtime / 100) * 100, - )) - elif runtime >= self.current_deadline: - raise DeadlineExceeded(runtime, self.settings.deadline) - return result - self.test = timed_test + self.test = test self.coverage_data = CoverageData() self.files_to_propagate = set() @@ -501,13 +427,106 @@ else: self.collector = None - @property - def current_deadline(self): - base = self.settings.deadline - if self.__in_final_replay: - return base + def execute( + self, data, + print_example=False, + is_final=False, + expected_failure=None, collect=False, + ): + text_repr = [None] + if self.settings.deadline is None: + test = self.test else: - return base * 1.25 + @proxies(self.test) + def test(*args, **kwargs): + self.__test_runtime = None + initial_draws = len(data.draw_times) + start = benchmark_time() + result = self.test(*args, **kwargs) + finish = benchmark_time() + internal_draw_time = sum(data.draw_times[initial_draws:]) + runtime = (finish - start - internal_draw_time) * 1000 + self.__test_runtime = runtime + if self.settings.deadline is not_set: + if ( + not self.__warned_deadline and + runtime >= 200 + ): + self.__warned_deadline = True + note_deprecation(( + 'Test took %.2fms to run. In future the default ' + 'deadline setting will be 200ms, which will ' + 'make this an error. You can set deadline to ' + 'an explicit value of e.g. %d to turn tests ' + 'slower than this into an error, or you can set ' + 'it to None to disable this check entirely.') % ( + runtime, ceil(runtime / 100) * 100, + )) + else: + current_deadline = self.settings.deadline + if not is_final: + current_deadline *= 1.25 + if runtime >= current_deadline: + raise DeadlineExceeded(runtime, self.settings.deadline) + return result + + def run(data): + with self.settings: + with BuildContext(data, is_final=is_final): + import random as rnd_module + rnd_module.seed(0) + args, kwargs = data.draw(self.search_strategy) + if expected_failure is not None: + text_repr[0] = arg_string(test, args, kwargs) + + if print_example: + report( + lambda: 'Falsifying example: %s(%s)' % ( + test.__name__, arg_string(test, args, kwargs))) + elif current_verbosity() >= Verbosity.verbose: + report( + lambda: 'Trying example: %s(%s)' % ( + test.__name__, arg_string(test, args, kwargs))) + + if self.collector is None or not collect: + return test(*args, **kwargs) + else: # pragma: no cover + try: + self.collector.start() + return test(*args, **kwargs) + finally: + self.collector.stop() + + result = self.test_runner(data, run) + if expected_failure is not None: + exception, traceback = expected_failure + if ( + isinstance( + exception, + DeadlineExceeded + ) and self.__test_runtime is not None + ): + report(( + 'Unreliable test timings! On an initial run, this ' + 'test took %.2fms, which exceeded the deadline of ' + '%.2fms, but on a subsequent run it took %.2f ms, ' + 'which did not. If you expect this sort of ' + 'variability in your test timings, consider turning ' + 'deadlines off for this test by setting deadline=None.' + ) % ( + exception.runtime, + self.settings.deadline, self.__test_runtime + )) + else: + report( + 'Failed to reproduce exception. Expected: \n' + + traceback, + ) + self.__flaky(( + 'Hypothesis %s(%s) produces unreliable results: Falsified' + ' on the first call but did not on a subsequent one' + ) % (test.__name__, text_repr[0],)) + return result def should_trace(self, original_filename, frame): # pragma: no cover disp = FileDisposition() @@ -555,9 +574,7 @@ def evaluate_test_data(self, data): try: if self.collector is None: - result = self.test_runner(data, reify_and_execute( - self.search_strategy, self.test, - )) + result = self.execute(data) else: # pragma: no cover # This should always be a no-op, but the coverage tracer has # a bad habit of resurrecting itself. @@ -565,10 +582,7 @@ sys.settrace(None) try: self.collector.data = {} - result = self.test_runner(data, reify_and_execute( - self.search_strategy, self.test, - collector=self.collector - )) + result = self.execute(data, collect=True) finally: sys.settrace(original) covdata = CoverageData() @@ -686,18 +700,18 @@ flaky = 0 - self.__in_final_replay = True - for falsifying_example in self.falsifying_examples: self.__was_flaky = False + assert falsifying_example.__expected_exception is not None try: - with self.settings: - self.test_runner( - ConjectureData.for_buffer(falsifying_example.buffer), - reify_and_execute( - self.search_strategy, self.test, - print_example=True, is_final=True - )) + self.execute( + ConjectureData.for_buffer(falsifying_example.buffer), + print_example=True, is_final=True, + expected_failure=( + falsifying_example.__expected_exception, + falsifying_example.__expected_traceback, + ) + ) except (UnsatisfiedAssumption, StopTest): report(traceback.format_exc()) self.__flaky( @@ -708,56 +722,6 @@ if len(self.falsifying_examples) <= 1: raise report(traceback.format_exc()) - else: - if ( - isinstance( - falsifying_example.__expected_exception, - DeadlineExceeded - ) and self.__test_runtime is not None - ): - report(( - 'Unreliable test timings! On an initial run, this ' - 'test took %.2fms, which exceeded the deadline of ' - '%.2fms, but on a subsequent run it took %.2f ms, ' - 'which did not. If you expect this sort of ' - 'variability in your test timings, consider turning ' - 'deadlines off for this test by setting deadline=None.' - ) % ( - falsifying_example.__expected_exception.runtime, - self.settings.deadline, self.__test_runtime - )) - else: - report( - 'Failed to reproduce exception. Expected: \n' + - falsifying_example.__expected_traceback, - ) - - filter_message = ( - 'Unreliable test data: Failed to reproduce a failure ' - 'and then when it came to recreating the example in ' - 'order to print the test data with a flaky result ' - 'the example was filtered out (by e.g. a ' - 'call to filter in your strategy) when we didn\'t ' - 'expect it to be.' - ) - - try: - self.test_runner( - ConjectureData.for_buffer(falsifying_example.buffer), - reify_and_execute( - self.search_strategy, - test_is_flaky( - self.test, self.repr_for_last_exception), - print_example=True, is_final=True - )) - except (UnsatisfiedAssumption, StopTest): - self.__flaky(filter_message) - except Flaky as e: - if len(self.falsifying_examples) > 1: - self.__flaky(e.args[0]) - else: - raise - if self.__was_flaky: flaky += 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/extra/pytestplugin.py new/hypothesis-3.38.5/src/hypothesis/extra/pytestplugin.py --- old/hypothesis-3.38.0/src/hypothesis/extra/pytestplugin.py 2017-11-18 11:26:22.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/extra/pytestplugin.py 2017-11-23 20:40:05.000000000 +0100 @@ -135,6 +135,9 @@ ' - Typical runtimes: %s' % (statistics.runtimes,) ) terminalreporter.write_line( + ' - Fraction of time spent in data generation: %s' % ( + statistics.draw_time_percentage,)) + terminalreporter.write_line( ' - Stopped because %s' % (statistics.exit_reason,) ) if statistics.events: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/internal/cache.py new/hypothesis-3.38.5/src/hypothesis/internal/cache.py --- old/hypothesis-3.38.0/src/hypothesis/internal/cache.py 2017-11-18 11:26:22.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/internal/cache.py 2017-11-23 20:40:05.000000000 +0100 @@ -55,7 +55,7 @@ self.max_size = max_size # Implementation: We store a binary heap of Entry objects in self.data, - # with the heap property requirnig that a parent's score is <= that of + # with the heap property requiring that a parent's score is <= that of # its children. keys_to_index then maps keys to their index in the # heap. We keep these two in sync automatically - the heap is never # reordered without updating the index. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/internal/charmap.py new/hypothesis-3.38.5/src/hypothesis/internal/charmap.py --- old/hypothesis-3.38.0/src/hypothesis/internal/charmap.py 2017-11-18 11:26:22.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/internal/charmap.py 2017-11-23 20:40:05.000000000 +0100 @@ -65,8 +65,8 @@ rs[-1][-1] += 1 else: rs.append([i, i]) - _charmap = {k: tuple((map(tuple, v))) - for k, v in tmp_charmap.items()} + _charmap = {k: tuple(tuple(pair) for pair in pairs) + for k, pairs in tmp_charmap.items()} try: # Write the Unicode table atomically @@ -87,10 +87,10 @@ def categories(): - """Return a list of Unicode categories in a normalised order. + """Return a tuple of Unicode categories in a normalised order. >>> categories() # doctest: +ELLIPSIS - ['Zl', 'Zp', 'Co', 'Me', 'Pc', ..., 'Cc', 'Cs'] + ('Zl', 'Zp', 'Co', 'Me', 'Pc', ..., 'Cc', 'Cs') """ global _categories @@ -103,7 +103,7 @@ _categories.remove('Cs') # Other, Surrogate _categories.append('Cc') _categories.append('Cs') - return _categories + return tuple(_categories) def _union_intervals(x, y): @@ -149,7 +149,7 @@ ((48, 57), (97, 102)) """ - intervals = [(ord(c), ord(c)) for c in sorted(s)] + intervals = tuple((ord(c), ord(c)) for c in sorted(s)) return _union_intervals(intervals, intervals) @@ -184,8 +184,7 @@ """Return a tuple of codepoint intervals covering characters that match one or more categories in the tuple of categories `key`. - >>> all_categories = tuple(categories()) - >>> _query_for_key(all_categories) + >>> _query_for_key(categories()) ((0, 1114111),) >>> _query_for_key(('Zl', 'Zp', 'Co')) ((8232, 8233), (57344, 63743), (983040, 1048573), (1048576, 1114109)) @@ -196,8 +195,7 @@ except KeyError: pass assert key - cs = categories() - if len(key) == len(cs): + if set(key) == set(categories()): result = ((0, sys.maxunicode),) else: result = _union_intervals( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/internal/conjecture/engine.py new/hypothesis-3.38.5/src/hypothesis/internal/conjecture/engine.py --- old/hypothesis-3.38.0/src/hypothesis/internal/conjecture/engine.py 2017-11-18 11:26:22.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/internal/conjecture/engine.py 2017-11-23 20:40:05.000000000 +0100 @@ -83,6 +83,10 @@ self.random = random or Random(getrandbits(128)) self.database_key = database_key self.status_runtimes = {} + + self.all_drawtimes = [] + self.all_runtimes = [] + self.events_to_strings = WeakKeyDictionary() self.target_selector = TargetSelector(self.random) @@ -381,6 +385,8 @@ else: self.save_buffer(data.buffer, self.secondary_key) runtime = max(data.finish_time - data.start_time, 0.0) + self.all_runtimes.append(runtime) + self.all_drawtimes.extend(data.draw_times) self.status_runtimes.setdefault(data.status, []).append(runtime) for event in set(map(self.event_to_string, data.events)): self.event_call_counts[event] += 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/internal/reflection.py new/hypothesis-3.38.5/src/hypothesis/internal/reflection.py --- old/hypothesis-3.38.0/src/hypothesis/internal/reflection.py 2017-11-18 11:26:22.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/internal/reflection.py 2017-11-23 20:40:05.000000000 +0100 @@ -282,6 +282,9 @@ source = LINE_CONTINUATION.sub(' ', source) source = WHITESPACE.sub(' ', source) source = source.strip() + assert 'lambda' in source + + tree = None try: tree = ast.parse(source) @@ -289,15 +292,32 @@ for i in hrange(len(source) - 1, len('lambda'), -1): prefix = source[:i] if 'lambda' not in prefix: - return if_confused + break try: tree = ast.parse(prefix) source = prefix break except SyntaxError: continue - else: - return if_confused + if tree is None: + if source.startswith('@'): + # This will always eventually find a valid expression because + # the decorator must be a valid Python function call, so will + # eventually be syntactically valid and break out of the loop. Thus + # this loop can never terminate normally, so a no branch pragma is + # appropriate. + for i in hrange(len(source) + 1): # pragma: no branch + p = source[1:i] + if 'lambda' in p: + try: + tree = ast.parse(p) + source = p + break + except SyntaxError: + pass + + if tree is None: + return if_confused all_lambdas = extract_all_lambdas(tree) aligned_lambdas = [ @@ -316,10 +336,9 @@ parsed = ast.parse(source[:i]) assert len(parsed.body) == 1 assert parsed.body - if not isinstance(parsed.body[0].value, ast.Lambda): - continue - source = source[:i] - break + if isinstance(parsed.body[0].value, ast.Lambda): + source = source[:i] + break except SyntaxError: pass lines = source.split('\n') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/searchstrategy/lazy.py new/hypothesis-3.38.5/src/hypothesis/searchstrategy/lazy.py --- old/hypothesis-3.38.0/src/hypothesis/searchstrategy/lazy.py 2017-11-18 11:26:22.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/searchstrategy/lazy.py 2017-11-23 20:40:05.000000000 +0100 @@ -17,7 +17,7 @@ from __future__ import division, print_function, absolute_import -from hypothesis.internal.compat import hrange, getfullargspec +from hypothesis.internal.compat import getfullargspec from hypothesis.internal.reflection import arg_string, \ convert_keyword_arguments, convert_positional_arguments from hypothesis.searchstrategy.strategies import SearchStrategy @@ -144,8 +144,9 @@ argspec = getfullargspec(self.__function) defaults = dict(argspec.kwonlydefaults or {}) if argspec.defaults is not None: - for k in hrange(1, len(argspec.defaults) + 1): - defaults[argspec.args[-k]] = argspec.defaults[-k] + for name, value in zip(reversed(argspec.args), + reversed(argspec.defaults)): + defaults[name] = value if len(argspec.args) > 1 or argspec.defaults: _args, _kwargs = convert_positional_arguments( self.__function, _args, _kwargs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/searchstrategy/regex.py new/hypothesis-3.38.5/src/hypothesis/searchstrategy/regex.py --- old/hypothesis-3.38.0/src/hypothesis/searchstrategy/regex.py 2017-11-18 11:26:22.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/searchstrategy/regex.py 2017-11-23 20:40:05.000000000 +0100 @@ -20,7 +20,8 @@ import re import sys import operator -import sre_parse as sre +import sre_parse +import sre_constants as sre import hypothesis.strategies as st from hypothesis import reject @@ -231,7 +232,7 @@ def base_regex_strategy(regex, parsed=None): if parsed is None: - parsed = sre.parse(regex.pattern) + parsed = sre_parse.parse(regex.pattern) return clear_cache_after_draw(_strategy( parsed, Context(flags=regex.flags), @@ -245,7 +246,7 @@ is_unicode = isinstance(regex.pattern, text_type) - parsed = sre.parse(regex.pattern) + parsed = sre_parse.parse(regex.pattern) if not parsed: if is_unicode: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/statistics.py new/hypothesis-3.38.5/src/hypothesis/statistics.py --- old/hypothesis-3.38.0/src/hypothesis/statistics.py 2017-11-18 11:26:22.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/statistics.py 2017-11-23 20:40:05.000000000 +0100 @@ -77,6 +77,18 @@ engine.event_call_counts.items(), key=lambda x: -x[1]) ] + total_runtime = math.fsum(engine.all_runtimes) + total_drawtime = math.fsum(engine.all_drawtimes) + + if total_drawtime == 0.0: + self.draw_time_percentage = '~ 0%' + else: + draw_time_percentage = 100.0 * min( + 1, total_drawtime / total_runtime) + + self.draw_time_percentage = '~ %d%%' % ( + round(draw_time_percentage),) + def note_engine_for_statistics(engine): callback = collector.value diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/strategies.py new/hypothesis-3.38.5/src/hypothesis/strategies.py --- old/hypothesis-3.38.0/src/hypothesis/strategies.py 2017-11-18 11:26:22.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/strategies.py 2017-11-23 20:40:05.000000000 +0100 @@ -1671,18 +1671,18 @@ >>> import hypothesis.strategies as st >>> x = st.deferred(lambda: st.booleans() | st.tuples(x, x)) >>> x.example() - (False, (False, True)) + (((False, (True, True)), (False, True)), (True, True)) >>> x.example() - True + (True, True) Mutual recursion also works fine: >>> a = st.deferred(lambda: st.booleans() | b) >>> b = st.deferred(lambda: st.tuples(a, a)) >>> a.example() - (((True, True), False), True) + (True, (True, False)) >>> b.example() - (((( False, ((True, False), (True, True))), True), False), True) + (False, True) """ from hypothesis.searchstrategy.deferred import DeferredStrategy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis/version.py new/hypothesis-3.38.5/src/hypothesis/version.py --- old/hypothesis-3.38.0/src/hypothesis/version.py 2017-11-18 11:27:45.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis/version.py 2017-11-23 20:40:32.000000000 +0100 @@ -17,5 +17,5 @@ from __future__ import division, print_function, absolute_import -__version_info__ = (3, 38, 0) +__version_info__ = (3, 38, 5) __version__ = '.'.join(map(str, __version_info__)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-3.38.0/src/hypothesis.egg-info/PKG-INFO new/hypothesis-3.38.5/src/hypothesis.egg-info/PKG-INFO --- old/hypothesis-3.38.0/src/hypothesis.egg-info/PKG-INFO 2017-11-18 11:27:46.000000000 +0100 +++ new/hypothesis-3.38.5/src/hypothesis.egg-info/PKG-INFO 2017-11-23 20:40:32.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: hypothesis -Version: 3.38.0 +Version: 3.38.5 Summary: A library for property based testing Home-page: https://github.com/HypothesisWorks/hypothesis-python Author: David R. MacIver