From 18d47dd168b02f9c61f2beaf408437017c1d2959 Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Thu, 31 Jan 2019 16:01:17 +0100 Subject: [PATCH 01/10] Update to hypothesis 4.4.3 --- hypothesis_trio/stateful.py | 165 ++++++++++++++++++++++-------------- 1 file changed, 100 insertions(+), 65 deletions(-) diff --git a/hypothesis_trio/stateful.py b/hypothesis_trio/stateful.py index 9b949b0..402a68f 100644 --- a/hypothesis_trio/stateful.py +++ b/hypothesis_trio/stateful.py @@ -1,59 +1,99 @@ import trio from trio.testing import trio_test -import hypothesis.internal.conjecture.utils as cu -from hypothesis._settings import Verbosity -from hypothesis.reporting import current_verbosity + + from hypothesis.stateful import ( - VarReference, + # Needed for run_state_machine_as_test copy-paste + check_type, + cu, + current_verbosity, + Verbosity, + Settings, + HealthCheck, GenericStateMachine, - StateMachineRunner, - run_state_machine_as_test, - Bundle, - rule, - initialize, - precondition, - invariant, + given, + st, + current_build_context, + function_digest, + # Needed for TrioRuleBasedStateMachine RuleBasedStateMachine, + VarReference, + MultipleResults, ) -def monkey_patch_hypothesis(): - def run(self, state_machine, print_steps=None): - if print_steps is None: - print_steps = current_verbosity() >= Verbosity.debug - self.data.hypothesis_runner = state_machine +# This is an ugly copy-paste since it's currently no possible to plug a special +# runner into run_state_machine_as_test +def run_state_machine_as_test(state_machine_factory, settings=None): + """Run a state machine definition as a test, either silently doing nothing + or printing a minimal breaking program and raising an exception. + state_machine_factory is anything which returns an instance of + GenericStateMachine when called with no arguments - it can be a class or a + function. settings will be used to control the execution of the test. + """ + if settings is None: + try: + settings = state_machine_factory.TestCase.settings + check_type(Settings, settings, "state_machine_factory.TestCase.settings") + except AttributeError: + settings = Settings(deadline=None, suppress_health_check=HealthCheck.all()) + check_type(Settings, settings, "settings") + + @settings + @given(st.data()) + def run_state_machine(factory, data): + machine = factory() + check_type(GenericStateMachine, machine, "state_machine_factory()") + data.conjecture_data.hypothesis_runner = machine + + n_steps = settings.stateful_step_count should_continue = cu.many( - self.data, - min_size=1, - max_size=self.n_steps, - average_size=self.n_steps, + data.conjecture_data, min_size=1, max_size=n_steps, average_size=n_steps ) - def _default_runner(data, print_steps, should_continue): - try: - if print_steps: - state_machine.print_start() - state_machine.check_invariants() + print_steps = ( + current_build_context().is_final or current_verbosity() >= Verbosity.debug + ) - while should_continue.more(): - value = data.draw(state_machine.steps()) - if print_steps: - state_machine.print_step(value) - state_machine.execute_step(value) - state_machine.check_invariants() - finally: + # Plug a custom machinery + # This block is not in the original copy-paste + try: + machine._custom_runner + except AttributeError: + pass + else: + return machine._custom_runner(data, print_steps, should_continue) + + try: + if print_steps: + machine.print_start() + machine.check_invariants() + + while should_continue.more(): + value = data.conjecture_data.draw(machine.steps()) if print_steps: - state_machine.print_end() - state_machine.teardown() - - runner = getattr(state_machine, '_custom_runner', _default_runner) - runner(self.data, print_steps, should_continue) - - StateMachineRunner.run = run - - -monkey_patch_hypothesis() + machine.print_step(value) + machine.execute_step(value) + machine.check_invariants() + finally: + if print_steps: + machine.print_end() + machine.teardown() + + # Use a machine digest to identify stateful tests in the example database + run_state_machine.hypothesis.inner_test._hypothesis_internal_add_digest = function_digest( + state_machine_factory + ) + # Copy some attributes so @seed and @reproduce_failure "just work" + run_state_machine._hypothesis_internal_use_seed = getattr( + state_machine_factory, "_hypothesis_internal_use_seed", None + ) + run_state_machine._hypothesis_internal_use_reproduce_failure = getattr( + state_machine_factory, "_hypothesis_internal_use_reproduce_failure", None + ) + + run_state_machine(state_machine_factory) class TrioGenericStateMachine(GenericStateMachine): @@ -102,7 +142,7 @@ async def _run(**kwargs): await self.check_invariants() while should_continue.more(): - value = data.draw(self.steps()) + value = data.conjecture_data.draw(self.steps()) if print_steps: self.print_step(value) await self.execute_step(value) @@ -152,14 +192,11 @@ async def execute_step(self, step): data[k] = self.names_to_values[v.name] result = await rule.function(self, **data) if rule.targets: - name = self.new_name() - self.names_to_values[name] = result - # TODO: not really elegant to access __printer this way... - self._RuleBasedStateMachine__printer.singleton_pprinters.setdefault( - id(result), lambda obj, p, cycle: p.text(name) - ) - for target in rule.targets: - self.bundle(target).append(VarReference(name)) + if isinstance(result, MultipleResults): + for single_result in result.values: + self._add_result_to_targets(rule.targets, single_result) + else: + self._add_result_to_targets(rule.targets, result) if self._initialize_rules_to_run: self._initialize_rules_to_run.remove(rule) @@ -170,17 +207,15 @@ async def check_invariants(self): await invar.function(self) -__all__ = ( - 'VarReference', - 'GenericStateMachine', - 'StateMachineRunner', - 'run_state_machine_as_test', - 'Bundle', - 'rule', - 'initialize', - 'precondition', - 'invariant', - 'RuleBasedStateMachine', - 'TrioGenericStateMachine', - 'TrioRuleBasedStateMachine', -) +# Monkey patching + +def monkey_patch_hypothesis(): + from hypothesis import stateful + stateful._old_run_state_machine_as_test = stateful.run_state_machine_as_test + stateful.run_state_machine_as_test = run_state_machine_as_test + + +monkey_patch_hypothesis() + +# Expose all objects from original stateful module +from hypothesis.stateful import * From c3554c82b934fdf5dcfa1cb4a851ba202612dabf Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Fri, 1 Feb 2019 12:11:25 +0100 Subject: [PATCH 02/10] Remove TrioGenericStateMachine --- hypothesis_trio/_tests/test_async_stateful.py | 40 +------------------ hypothesis_trio/stateful.py | 18 +-------- 2 files changed, 3 insertions(+), 55 deletions(-) diff --git a/hypothesis_trio/_tests/test_async_stateful.py b/hypothesis_trio/_tests/test_async_stateful.py index f505d17..4941677 100644 --- a/hypothesis_trio/_tests/test_async_stateful.py +++ b/hypothesis_trio/_tests/test_async_stateful.py @@ -3,49 +3,11 @@ from trio.abc import Instrument from trio.testing import MockClock -from hypothesis_trio.stateful import TrioGenericStateMachine, TrioRuleBasedStateMachine +from hypothesis_trio.stateful import TrioRuleBasedStateMachine from hypothesis.stateful import initialize, rule, invariant, run_state_machine_as_test from hypothesis.strategies import just, integers, lists, tuples -def test_triggers(): - class LogEventsStateMachine(TrioGenericStateMachine): - events = [] - - async def teardown(self): - await trio.sleep(0) - self.events.append('teardown') - - def steps(self): - return just(42) - - async def execute_step(self, step): - await trio.sleep(0) - assert step is 42 - self.events.append('execute_step') - - async def check_invariants(self): - await trio.sleep(0) - self.events.append('check_invariants') - - run_state_machine_as_test(LogEventsStateMachine) - - per_run_events = [] - current_run_events = [] - for event in LogEventsStateMachine.events: - current_run_events.append(event) - if event == 'teardown': - per_run_events.append(current_run_events) - current_run_events = [] - - for run_events in per_run_events: - expected_events = ['check_invariants'] - expected_events += ['execute_step', 'check_invariants' - ] * ((len(run_events) - 2) // 2) - expected_events.append('teardown') - assert run_events == expected_events - - def test_rule_based(): class LogEventsRuleBasedStateMachine(TrioRuleBasedStateMachine): events = [] diff --git a/hypothesis_trio/stateful.py b/hypothesis_trio/stateful.py index 402a68f..7689bf9 100644 --- a/hypothesis_trio/stateful.py +++ b/hypothesis_trio/stateful.py @@ -96,8 +96,8 @@ def run_state_machine(factory, data): run_state_machine(state_machine_factory) -class TrioGenericStateMachine(GenericStateMachine): - """Trio compatible version of `hypothesis.stateful.GenericStateMachine` +class TrioRuleBasedStateMachine(RuleBasedStateMachine): + """Trio compatible version of `hypothesis.stateful.RuleBasedStateMachine`. """ def __init__(self): @@ -162,10 +162,6 @@ async def _run(**kwargs): kwargs['clock'] = self.__clock trio_test(_run)(**kwargs) - async def execute_step(self, step): - """Execute a step that has been previously drawn from self.steps()""" - raise NotImplementedError(u'%r.execute_step()' % (self,)) - async def teardown(self): """Called after a run has finished executing to clean up any necessary state. @@ -174,16 +170,6 @@ async def teardown(self): """ pass - async def check_invariants(self): - """Called after initializing and after executing each step.""" - pass - - -class TrioRuleBasedStateMachine(TrioGenericStateMachine, - RuleBasedStateMachine): - """Trio compatible version of `hypothesis.stateful.RuleBasedStateMachine`. - """ - async def execute_step(self, step): rule, data = step data = dict(data) From c9c25970134ea83c8fcb37bf6ba45effe49ad2e8 Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Thu, 31 Jan 2019 17:07:50 +0100 Subject: [PATCH 03/10] Replace trio.Queue with trio.open_memory_channel in the tests --- hypothesis_trio/_tests/test_async_stateful.py | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/hypothesis_trio/_tests/test_async_stateful.py b/hypothesis_trio/_tests/test_async_stateful.py index 4941677..37010a1 100644 --- a/hypothesis_trio/_tests/test_async_stateful.py +++ b/hypothesis_trio/_tests/test_async_stateful.py @@ -112,44 +112,42 @@ async def teardown(self): def test_trio_style(): - async def _consumer( - in_queue, out_queue, *, task_status=trio.TASK_STATUS_IGNORED + async def consumer( + receive_job, send_result, *, task_status=trio.TASK_STATUS_IGNORED ): with trio.open_cancel_scope() as cancel_scope: task_status.started(cancel_scope) - while True: - x, y = await in_queue.get() + async for x, y in receive_job: await trio.sleep(0) result = x + y - await out_queue.put('%s + %s = %s' % (x, y, result)) + await send_result.send('%s + %s = %s' % (x, y, result)) class TrioStyleStateMachine(TrioRuleBasedStateMachine): @initialize() async def initialize(self): - self.job_queue = trio.Queue(100) - self.result_queue = trio.Queue(100) - self.consumer_cancel_scope = await self.get_root_nursery().start( - _consumer, self.job_queue, self.result_queue - ) + self.send_job, receive_job = trio.open_memory_channel(100) + send_result, self.receive_result = trio.open_memory_channel(100) + self.consumer_args = consumer, receive_job, send_result + self.consumer_cancel_scope = await self.get_root_nursery( + ).start(*self.consumer_args) @rule(work=lists(tuples(integers(), integers()))) async def generate_work(self, work): await trio.sleep(0) for x, y in work: - await self.job_queue.put((x, y)) + await self.send_job.send((x, y)) @rule() async def restart_consumer(self): self.consumer_cancel_scope.cancel() - self.consumer_cancel_scope = await self.get_root_nursery().start( - _consumer, self.job_queue, self.result_queue - ) + self.consumer_cancel_scope = await self.get_root_nursery( + ).start(*self.consumer_args) @invariant() async def check_results(self): while True: try: - job = self.result_queue.get_nowait() + job = self.receive_result.receive_nowait() assert isinstance(job, str) except (trio.WouldBlock, AttributeError): break From 55eedbd15b3103e14154b22379d57df38ae3809a Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Thu, 31 Jan 2019 16:04:02 +0100 Subject: [PATCH 04/10] Run 'yapf -rpi setup.py hypothesis_trio' --- hypothesis_trio/stateful.py | 23 ++++++++++++++++------- setup.py | 4 +--- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/hypothesis_trio/stateful.py b/hypothesis_trio/stateful.py index 7689bf9..e7272f1 100644 --- a/hypothesis_trio/stateful.py +++ b/hypothesis_trio/stateful.py @@ -1,7 +1,6 @@ import trio from trio.testing import trio_test - from hypothesis.stateful import ( # Needed for run_state_machine_as_test copy-paste check_type, @@ -21,10 +20,10 @@ MultipleResults, ) - # This is an ugly copy-paste since it's currently no possible to plug a special # runner into run_state_machine_as_test + def run_state_machine_as_test(state_machine_factory, settings=None): """Run a state machine definition as a test, either silently doing nothing or printing a minimal breaking program and raising an exception. @@ -35,9 +34,13 @@ def run_state_machine_as_test(state_machine_factory, settings=None): if settings is None: try: settings = state_machine_factory.TestCase.settings - check_type(Settings, settings, "state_machine_factory.TestCase.settings") + check_type( + Settings, settings, "state_machine_factory.TestCase.settings" + ) except AttributeError: - settings = Settings(deadline=None, suppress_health_check=HealthCheck.all()) + settings = Settings( + deadline=None, suppress_health_check=HealthCheck.all() + ) check_type(Settings, settings, "settings") @settings @@ -49,11 +52,15 @@ def run_state_machine(factory, data): n_steps = settings.stateful_step_count should_continue = cu.many( - data.conjecture_data, min_size=1, max_size=n_steps, average_size=n_steps + data.conjecture_data, + min_size=1, + max_size=n_steps, + average_size=n_steps ) print_steps = ( - current_build_context().is_final or current_verbosity() >= Verbosity.debug + current_build_context().is_final + or current_verbosity() >= Verbosity.debug ) # Plug a custom machinery @@ -90,7 +97,8 @@ def run_state_machine(factory, data): state_machine_factory, "_hypothesis_internal_use_seed", None ) run_state_machine._hypothesis_internal_use_reproduce_failure = getattr( - state_machine_factory, "_hypothesis_internal_use_reproduce_failure", None + state_machine_factory, "_hypothesis_internal_use_reproduce_failure", + None ) run_state_machine(state_machine_factory) @@ -195,6 +203,7 @@ async def check_invariants(self): # Monkey patching + def monkey_patch_hypothesis(): from hypothesis import stateful stateful._old_run_state_machine_as_test = stateful.run_state_machine_as_test diff --git a/setup.py b/setup.py index 4832df8..5678a6c 100644 --- a/setup.py +++ b/setup.py @@ -14,9 +14,7 @@ author_email="emmanuel.leblond@gmail.com", license="MIT -or- Apache License 2.0", packages=find_packages(), - install_requires=[ - "trio", - ], + install_requires=["trio"], keywords=[ 'async', 'hypothesis', From 84948d8973b4152357cbf318d502fc7fada15781 Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Tue, 5 Feb 2019 17:19:13 +0100 Subject: [PATCH 05/10] Make regular state machine use the actual hypothesis runner --- hypothesis_trio/stateful.py | 60 +++++++++++++++---------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/hypothesis_trio/stateful.py b/hypothesis_trio/stateful.py index e7272f1..4eedbb4 100644 --- a/hypothesis_trio/stateful.py +++ b/hypothesis_trio/stateful.py @@ -1,6 +1,8 @@ import trio from trio.testing import trio_test +import hypothesis + from hypothesis.stateful import ( # Needed for run_state_machine_as_test copy-paste check_type, @@ -24,13 +26,7 @@ # runner into run_state_machine_as_test -def run_state_machine_as_test(state_machine_factory, settings=None): - """Run a state machine definition as a test, either silently doing nothing - or printing a minimal breaking program and raising an exception. - state_machine_factory is anything which returns an instance of - GenericStateMachine when called with no arguments - it can be a class or a - function. settings will be used to control the execution of the test. - """ +def run_custom_state_machine_as_test(state_machine_factory, settings=None): if settings is None: try: settings = state_machine_factory.TestCase.settings @@ -63,30 +59,7 @@ def run_state_machine(factory, data): or current_verbosity() >= Verbosity.debug ) - # Plug a custom machinery - # This block is not in the original copy-paste - try: - machine._custom_runner - except AttributeError: - pass - else: - return machine._custom_runner(data, print_steps, should_continue) - - try: - if print_steps: - machine.print_start() - machine.check_invariants() - - while should_continue.more(): - value = data.conjecture_data.draw(machine.steps()) - if print_steps: - machine.print_step(value) - machine.execute_step(value) - machine.check_invariants() - finally: - if print_steps: - machine.print_end() - machine.teardown() + return machine._custom_runner(data, print_steps, should_continue) # Use a machine digest to identify stateful tests in the example database run_state_machine.hypothesis.inner_test._hypothesis_internal_add_digest = function_digest( @@ -205,12 +178,27 @@ async def check_invariants(self): def monkey_patch_hypothesis(): - from hypothesis import stateful - stateful._old_run_state_machine_as_test = stateful.run_state_machine_as_test - stateful.run_state_machine_as_test = run_state_machine_as_test + if hasattr(hypothesis.stateful, "original_run_state_machine_as_test"): + return + original = hypothesis.stateful.run_state_machine_as_test + + def run_state_machine_as_test(state_machine_factory, settings=None): + """Run a state machine definition as a test, either silently doing nothing + or printing a minimal breaking program and raising an exception. + state_machine_factory is anything which returns an instance of + GenericStateMachine when called with no arguments - it can be a class or a + function. settings will be used to control the execution of the test. + """ + if hasattr(state_machine_factory, '_custom_runner'): + return run_custom_state_machine_as_test( + state_machine_factory, settings=settings + ) + return original(state_machine_factory, settings=settings) + hypothesis.stateful.original_run_state_machine_as_test = original + hypothesis.stateful.run_state_machine_as_test = run_state_machine_as_test -monkey_patch_hypothesis() -# Expose all objects from original stateful module +# Monkey patch and expose all objects from original stateful module +monkey_patch_hypothesis() from hypothesis.stateful import * From 0d0bbfdd491caf13ce6721f0c6a6f53f9dbf6fd0 Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Fri, 8 Feb 2019 15:25:52 +0100 Subject: [PATCH 06/10] Add proper reporting for async steps --- hypothesis_trio/stateful.py | 67 ++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/hypothesis_trio/stateful.py b/hypothesis_trio/stateful.py index 4eedbb4..e57588b 100644 --- a/hypothesis_trio/stateful.py +++ b/hypothesis_trio/stateful.py @@ -20,6 +20,7 @@ RuleBasedStateMachine, VarReference, MultipleResults, + report, ) # This is an ugly copy-paste since it's currently no possible to plug a special @@ -114,25 +115,33 @@ def push_instrument(self, instrument): raise RuntimeError('Can only add instrument during `__init__`') self.__instruments.append(instrument) + # Runner logic + def _custom_runner(self, data, print_steps, should_continue): + async def runner(machine): + try: + if print_steps: + machine.print_start() + await machine.check_invariants() + + while should_continue.more(): + value = data.conjecture_data.draw(machine.steps()) + if print_steps: + machine.print_step(value) + await machine.execute_step(value) + await machine.check_invariants() + finally: + if print_steps: + self.print_end() + await self.teardown() + + self.trio_run(runner, self) + + def trio_run(self, corofn, *args): async def _run(**kwargs): async with trio.open_nursery() as self._nursery: - try: - if print_steps: - self.print_start() - await self.check_invariants() - - while should_continue.more(): - value = data.conjecture_data.draw(self.steps()) - if print_steps: - self.print_step(value) - await self.execute_step(value) - await self.check_invariants() - finally: - if print_steps: - self.print_end() - await self.teardown() - self._nursery.cancel_scope.cancel() + await corofn(*args) + self._nursery.cancel_scope.cancel() self.__started = True kwargs = { @@ -143,6 +152,8 @@ async def _run(**kwargs): kwargs['clock'] = self.__clock trio_test(_run)(**kwargs) + # Async methods + async def teardown(self): """Called after a run has finished executing to clean up any necessary state. @@ -173,6 +184,30 @@ async def check_invariants(self): continue await invar.function(self) + # Reporting + + def print_start(self): + report("state = %s()" % (self.__class__.__name__,)) + report("async def steps():") + + def print_end(self): + report(" await state.teardown()") + report("state.trio_run(steps)") + + def print_step(self, step): + rule, data = step + data_repr = {} + for k, v in data.items(): + data_repr[k] = self._RuleBasedStateMachine__pretty(v) + self.step_count = getattr(self, "step_count", 0) + 1 + report( + " %sawait state.%s(%s)" % ( + "%s = " % (self.upcoming_name(),) if rule.targets else "", + rule.function.__name__, + ", ".join("%s=%s" % kv for kv in data_repr.items()), + ) + ) + # Monkey patching From fad9a239cd253cb79994d7b722a43c82764e37fd Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Fri, 8 Feb 2019 15:26:10 +0100 Subject: [PATCH 07/10] Add a test for failing trio state machine --- hypothesis_trio/_tests/test_async_stateful.py | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/hypothesis_trio/_tests/test_async_stateful.py b/hypothesis_trio/_tests/test_async_stateful.py index 37010a1..2869ea2 100644 --- a/hypothesis_trio/_tests/test_async_stateful.py +++ b/hypothesis_trio/_tests/test_async_stateful.py @@ -3,9 +3,11 @@ from trio.abc import Instrument from trio.testing import MockClock +import hypothesis +from hypothesis import Verbosity from hypothesis_trio.stateful import TrioRuleBasedStateMachine -from hypothesis.stateful import initialize, rule, invariant, run_state_machine_as_test -from hypothesis.strategies import just, integers, lists, tuples +from hypothesis.stateful import Bundle, initialize, rule, invariant, run_state_machine_as_test +from hypothesis.strategies import integers, lists, tuples def test_rule_based(): @@ -153,3 +155,51 @@ async def check_results(self): break run_state_machine_as_test(TrioStyleStateMachine) + + +def test_trio_style_failing(capsys): + + # Failing state machine + + class TrioStyleStateMachine(TrioRuleBasedStateMachine): + Values = Bundle('value') + + @initialize(target=Values) + async def initialize(self): + return 1 + + @rule(value=Values) + async def do_work(self, value): + assert value == 2 + + # Check failure + + settings = hypothesis.settings(max_examples=10, verbosity=Verbosity.debug) + with pytest.raises(AssertionError) as record: + run_state_machine_as_test(TrioStyleStateMachine, settings=settings) + captured = capsys.readouterr() + assert 'assert 1 == 2' in str(record.value) + + # Check steps + + with pytest.raises(AssertionError) as record: + state = TrioStyleStateMachine() + + async def steps(): + v1 = await state.initialize() + await state.do_work(value=v1) + await state.teardown() + + state.trio_run(steps) + assert 'assert 1 == 2' in str(record.value) + + # Check steps printout + + assert """\ +state = TrioStyleStateMachine() +async def steps(): + v1 = await state.initialize() + await state.do_work(value=v1) + await state.teardown() +state.trio_run(steps) +""" in captured.out From 5743b21cb98e01d47431cc6cd60ff494f4958e33 Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Thu, 31 Jan 2019 17:42:52 +0100 Subject: [PATCH 08/10] Update Travis matrix --- .travis.yml | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index c37a900..4e792ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,14 @@ language: python python: -- 3.5.0 -- 3.5.2 -- 3.5-dev +- 3.5 +- pypy3.5 - 3.6 -- 3.6-dev -- 3.7-dev +- 3.7 +- 3.8-dev sudo: false -dist: trusty +dist: xenial matrix: include: - - os: linux - language: generic - env: USE_PYPY_RELEASE_VERSION=5.9-beta - # Python3.5 on MacOS doesn't currently support TLSv1.2 needed to use pip :( - # http://pyfound.blogspot.fr/2017/01/time-to-upgrade-your-python-tls-v12.html - # - os: osx - # language: generic - # env: MACPYTHON=3.5.4 - os: osx language: generic env: MACPYTHON=3.6.3 From 11c0db8a2911f3b4d386f176e63ce279f98ae621 Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Thu, 31 Jan 2019 16:01:25 +0100 Subject: [PATCH 09/10] Pin hypothesis to releases compatible with 4.0 (i.e. >= 4.0, ==4.*) We have to, since the stateful module relies on a dangerous copy-paste --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5678a6c..82b27ad 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ author_email="emmanuel.leblond@gmail.com", license="MIT -or- Apache License 2.0", packages=find_packages(), - install_requires=["trio"], + install_requires=["trio", "hypothesis~=4.0"], keywords=[ 'async', 'hypothesis', From d2561e1d0af969da51d960a0d32b0bc4d8daab7e Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Thu, 31 Jan 2019 16:07:00 +0100 Subject: [PATCH 10/10] Bump version 0.3.0 --- hypothesis_trio/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypothesis_trio/_version.py b/hypothesis_trio/_version.py index 0a92cf7..f879b44 100644 --- a/hypothesis_trio/_version.py +++ b/hypothesis_trio/_version.py @@ -1,3 +1,3 @@ # This file is imported from __init__.py and exec'd from setup.py -__version__ = "0.2.2" +__version__ = "0.3.0"