def assertEventuallyTrue(self, obj, trait, condition, timeout=5.0): """Assert that the given condition is eventually true. Fail if the condition is not satisfied within the given timeout. `condition` takes `obj` as an argument, and should return a Boolean indicating whether the condition is satisfied or not. `timeout` gives the maximum time (in seconds) to wait for the condition to become true. Default is 5.0 seconds. A value of `None` can be used to indicate no timeout. (obj, trait) give an object and trait to listen to for indication of a possible change: whenever the trait changes, the condition is re-evaluated. """ try: wait_for_condition( condition=condition, obj=obj, trait=trait, timeout=timeout, ) except RuntimeError: # Helpful to know whether we timed out because the # condition never became true, or because the expected # event was never issued. condition_at_timeout = condition(obj) self.fail( "Timed out waiting for condition. " "At timeout, condition was {0}.".format(condition_at_timeout))
def assertEventuallyTrue(self, obj, trait, condition, timeout=5.0): """ Assert that the given condition is eventually true. Parameters ---------- obj : HasTraits The HasTraits class instance who's traits will change. trait : str The extended trait name of trait changes to listen to. condition : callable A function that will be called when the specified trait changes. This should accept ``obj`` and should return a Boolean indicating whether the condition is satisfied or not. timeout : float or None, optional The amount of time in seconds to wait for the condition to become true. None can be used to indicate no timeout. """ try: wait_for_condition( condition=condition, obj=obj, trait=trait, timeout=timeout ) except RuntimeError: # Helpful to know whether we timed out because the # condition never became true, or because the expected # event was never issued. condition_at_timeout = condition(obj) self.fail( "Timed out waiting for condition. " "At timeout, condition was {0}.".format(condition_at_timeout) )
def testPlot(self): self.workflow.wi_sync(self.wi, 'view_error', 'waiting') self.wi.current_view = self.wi.default_view self.workflow.wi_waitfor(self.wi, 'view_error', '') self.workflow.wi_sync(self.wi, 'view_error', 'waiting') self.wi.default_view.current_plot = "Autofluorescence" self.workflow.wi_waitfor(self.wi, 'view_error', '') self.workflow.wi_sync(self.wi, 'view_error', 'waiting') self.wi.default_view.current_plot = "Bleedthrough" self.workflow.wi_waitfor(self.wi, 'view_error', '') self.workflow.wi_sync(self.wi, 'view_error', 'waiting') self.wi.default_view.current_plot = "Bead Calibration" self.workflow.wi_waitfor(self.wi, 'view_error', '') self.workflow.remote_exec("pass") self.op.to_channel = "FITC-A" self.op.do_color_translation = True wait_for_condition(lambda v: v.valid_model == False, self.op, 'valid_model', 30) self.op.translation_list[0].file = self.cwd + "/../../cytoflow/tests/data/tasbe/rby.fcs" self.op.translation_list[1].file = self.cwd + "/../../cytoflow/tests/data/tasbe/rby.fcs" self.workflow.remote_exec("pass") self.op.do_estimate = 1 wait_for_condition(lambda v: v.valid_model == True, self.op, 'valid_model', 30) self.workflow.wi_sync(self.wi, 'view_error', 'waiting') self.wi.default_view.current_plot = "Color Translation" self.workflow.wi_waitfor(self.wi, 'view_error', '')
def assertEventuallyTrue(self, obj, trait, condition, timeout=5.0): """ Assert that the given condition is eventually true. Parameters ---------- obj : HasTraits The HasTraits class instance who's traits will change. trait : str The extended trait name of trait changes to listen to. condition : callable A function that will be called when the specified trait changes. This should accept ``obj`` and should return a Boolean indicating whether the condition is satisfied or not. timeout : float or None, optional The amount of time in seconds to wait for the condition to become true. None can be used to indicate no timeout. """ try: wait_for_condition(condition=condition, obj=obj, trait=trait, timeout=timeout) except RuntimeError: # Helpful to know whether we timed out because the # condition never became true, or because the expected # event was never issued. condition_at_timeout = condition(obj) self.fail( "Timed out waiting for condition. " "At timeout, condition was {0}.".format(condition_at_timeout))
def assertTraitChangesAsync(self, obj, trait, count=1, timeout=5.0): """ Assert an object trait eventually changes. Context manager used to assert that the given trait changes at least `count` times within the given timeout, as a result of execution of the body of the corresponding with block. The trait changes are permitted to occur asynchronously. **Example usage**:: with self.assertTraitChangesAsync(my_object, 'SomeEvent', count=4): <do stuff that should cause my_object.SomeEvent to be fired at least 4 times within the next 5 seconds> Parameters ---------- obj : HasTraits The HasTraits class instance whose class trait will change. trait : str The extended trait name of trait changes to listen to. count : int, optional The expected number of times the event should be fired. timeout : float or None, optional The amount of time in seconds to wait for the specified number of changes. None can be used to indicate no timeout. """ collector = _TraitsChangeCollector(obj=obj, trait_name=trait) # Pass control to body of the with statement. collector.start_collecting() try: yield collector # Wait for the expected number of events to arrive. try: wait_for_condition( condition=lambda obj: obj.event_count >= count, obj=collector, trait="event_count_updated", timeout=timeout, ) except RuntimeError: actual_event_count = collector.event_count msg = ( "Expected {0} event on {1} to be fired at least {2} " "times, but the event was only fired {3} times " "before timeout ({4} seconds)." ).format(trait, obj, count, actual_event_count, timeout) self.fail(msg) finally: collector.stop_collecting()
def tearDown(self): # setting the output files self.op.input_files = [self.cwd + "/../../cytoflow/tests/data/tasbe/rby.fcs"] wait_for_condition(lambda v: v.status == 'Done converting!', self.op, 'status', 30) shutil.rmtree(self.op.output_directory) WorkflowTest.tearDown(self)
def testChangeChannels(self): self.workflow.remote_exec("pass") self.op.channels = ["FITC-A", "Pacific Blue-A"] wait_for_condition(lambda v: v.valid_model == False, self.op, 'valid_model', 60) self.assertTrue(len(self.op.units_list) == 2) self.assertTrue(len(self.op.bleedthrough_list) == 2) self.workflow.remote_exec("pass") self.op.do_estimate = True wait_for_condition(lambda v: v.valid_model == True, self.op, 'valid_model', 60)
def test_wait_for_condition_success(self): lights = TrafficLights(colour="Green") t = threading.Thread(target=lights.make_random_changes, args=(2, )) t.start() wait_for_condition(condition=lambda l: l.colour == "Red", obj=lights, trait="colour") self.assertEqual(lights.colour, "Red") t.join()
def setUp(self): super().setUp() self.op = op = TasbeCalibrationOp() self.cwd = os.path.dirname(os.path.abspath(__file__)) self.wi = wi = WorkflowItem(operation=op, status='waiting', view_error="Not yet plotted") wi.default_view = self.op.default_view() wi.views.append(self.wi.default_view) self.workflow.workflow.append(wi) self.workflow.selected = self.wi op.blank_file = self.cwd + "/../../cytoflow/tests/data/tasbe/blank.fcs" op.fsc_channel = "FSC-A" op.ssc_channel = "SSC-A" op._polygon_op.vertices = [(72417, 499), (74598, 1499), (118743, 3376), (216547, 6166), (246258, 4543), (237880, 1973), (139102, 872), (87822, 519)] op.channels = ["FITC-A", "Pacific Blue-A", "PE-Tx-Red-YG-A"] op.bleedthrough_list = [ _BleedthroughControl(channel="FITC-A", file=self.cwd + "/../../cytoflow/tests/data/tasbe/eyfp.fcs"), _BleedthroughControl(channel="Pacific Blue-A", file=self.cwd + "/../../cytoflow/tests/data/tasbe/ebfp.fcs"), _BleedthroughControl(channel="PE-Tx-Red-YG-A", file=self.cwd + "/../../cytoflow/tests/data/tasbe/mkate.fcs") ] op.beads_name = "Spherotech RCP-30-5A Lot AG01, AF02, AD04 and AAE01" op.beads_file = self.cwd + "/../../cytoflow/tests/data/tasbe/beads.fcs" op.units_list = [ _Unit(channel="FITC-A", unit="MEFL"), _Unit(channel="Pacific Blue-A", unit="MEBFP"), _Unit(channel="PE-Tx-Red-YG-A", unit="MEPTR") ] op.do_color_translation = False op.output_directory = tempfile.mkdtemp() # run the estimate self.workflow.remote_exec("pass") op.valid_model = False op.do_estimate = True wait_for_condition(lambda v: v.valid_model == True, self.op, 'valid_model', 30)
def test_wait_for_condition_success(self): lights = TrafficLights(colour='Green') t = threading.Thread(target=lights.make_random_changes, args=(2,)) t.start() wait_for_condition( condition=lambda l: l.colour == 'Red', obj=lights, trait='colour', ) self.assertEqual(lights.colour, 'Red') t.join()
def assertTraitChangesAsync(self, obj, trait, count=1, timeout=5.0): """Assert an object trait eventually changes. Context manager used to assert that the given trait changes at least `count` times within the given timeout, as a result of execution of the body of the corresponding with block. The trait changes are permitted to occur asynchronously. Example usage: with self.assertTraitChangesAsync(my_object, 'SomeEvent', count=4): <do stuff that should cause my_object.SomeEvent to be fired at least 4 times within the next 5 seconds> """ collector = _TraitsChangeCollector(obj=obj, trait=trait) # Pass control to body of the with statement. collector.start_collecting() try: yield collector # Wait for the expected number of events to arrive. try: wait_for_condition( condition=lambda obj: obj.event_count >= count, obj=collector, trait='event_count_updated', timeout=timeout, ) except RuntimeError: actual_event_count = collector.event_count msg = ("Expected {0} event on {1} to be fired at least {2} " "times, but the event was only fired {3} times " "before timeout ({4} seconds).").format( trait, obj, count, actual_event_count, timeout, ) self.fail(msg) finally: collector.stop_collecting()
def testDoTranslation(self): self.workflow.remote_exec("pass") self.op.to_channel = "FITC-A" self.op.do_color_translation = True wait_for_condition(lambda v: v.valid_model == False, self.op, 'valid_model', 30) self.assertEqual(len(self.op.units_list), 1) self.assertEqual(self.op.units_list[0].channel, "FITC-A") self.assertEqual(self.op.units_list[0].unit, "MEFL") self.assertEqual(len(self.op.translation_list), 2) self.op.translation_list[0].file = self.cwd + "/../../cytoflow/tests/data/tasbe/rby.fcs" self.op.translation_list[1].file = self.cwd + "/../../cytoflow/tests/data/tasbe/rby.fcs" self.workflow.remote_exec("pass") self.op.do_estimate = True wait_for_condition(lambda v: v.valid_model == True, self.op, 'valid_model', 30)
def wi_waitfor(self, wi, variable, value, timeout = 30): """Waits a configurable amount of time for wi's status to change to status""" from traits.util.async_trait_wait import wait_for_condition try: wait_for_condition(lambda v: v.trait_get([variable])[variable] == value, wi, variable, timeout) except RuntimeError: logger.error("Timed out after {} seconds waiting for {} to become {}.\n" "Current value: {}\n" "WorkflowItem.op_error: {}\n" "WorkflowItem.estimate_error: {}\n" "WorkflowItem.view_error: {}" .format(timeout, variable, value, wi.trait_get([variable])[variable], wi.op_error, wi.estimate_error, wi.view_error)) raise
def test_traits_handler_cleaned_up(self): # An older version of wait_for_condition failed to clean up # the trait handler, leading to possibly evaluation of the # condition after the 'wait_for_condition' call had returned. self.lights = TrafficLights(colour='Green') t = threading.Thread(target=self.lights.make_random_changes, args=(3,)) t.start() wait_for_condition( condition=lambda l: self.lights.colour == 'Red', obj=self.lights, trait='colour', ) del self.lights # If the condition gets evaluated again past this point, we'll # see an AttributeError from the failed self.lights lookup. # assertSucceeds! t.join()