def test_observe_with_expression(self): foo = ClassWithNumber() handler = mock.Mock() observe( object=foo, expression=trait("number"), handler=handler, ) # when foo.number += 1 # then self.assertEqual(handler.call_count, 1) handler.reset_mock() # when observe( object=foo, expression=trait("number"), handler=handler, remove=True, ) foo.number += 1 # then self.assertEqual(handler.call_count, 0)
def test_observe_different_target(self): # Test the result of setting target to be the same as object parent1 = ClassWithInstance() parent2 = ClassWithInstance() # the instance is shared instance = ClassWithNumber() parent1.instance = instance parent2.instance = instance handler = mock.Mock() # when observe( object=parent1, expression=trait("instance").trait("number"), handler=handler, ) observe( object=parent2, expression=trait("instance").trait("number"), handler=handler, ) instance.number += 1 # then # the handler should be called twice as the targets are different. self.assertEqual(handler.call_count, 2)
def test_items(self): actual = parse("items") expected = (trait("items", optional=True) | dict_items(optional=True) | list_items(optional=True) | set_items(optional=True)) self.assertEqual(actual, expected)
def test_set_equality_comparison_mode_prevent_change_event(self): # Justification for the warning: Reassess if the warning is still # needed if this test fails. instance = ObjectWithEqualityComparisonMode() instance.set_values = {1} handler = mock.Mock() with warnings.catch_warnings(): warnings.simplefilter("ignore") observe( object=instance, expression=expression.trait("set_values").set_items(), handler=handler, ) # New set, but equals to the previous instance.set_values = {1} handler.reset_mock() # when instance.set_values.add(2) # The expected value is 1. # If this fails with 1 != 0, consider removing the warning. self.assertEqual(handler.call_count, 0)
def test_any_value_followed_by_list_items_old_bad_value(self): # see enthought/traits#1277 foo = Foo() foo.any_value = CannotCompare() handler = mock.Mock() # list_items(optional=True) will excuse the CannotCompare which isn't # a TraitList observe( object=foo, expression=expression.trait("any_value").list_items(optional=True), handler=handler, ) # when # this triggers observer_change_handler foo.any_value = foo.list_of_int # a TraitList # then # no errors # when handler.reset_mock() foo.any_value.append(1) # then self.assertEqual(handler.call_count, 1)
def _handle_items(trees, default_notifies): """ Handle keyword "items". Parameters ---------- trees : list of lark.tree.Tree The children tree for the "items" rule. It should be empty. default_notifies : list of boolean The notify flag stack. Returns ------- expression : ObserverExpression """ if trees: # Nothing should be wrapped in items raise ValueError("Unexpected tree: {!r}".format(trees)) notify = default_notifies[-1] return reduce(operator.or_, ( expression_module.trait("items", notify=notify, optional=True), expression_module.dict_items(notify=notify, optional=True), expression_module.list_items(notify=notify, optional=True), expression_module.set_items(notify=notify, optional=True), ))
def test_items_not_notify(self): actual = parse("items:attr") expected = (trait("items", notify=False, optional=True) | dict_items(notify=False, optional=True) | list_items(notify=False, optional=True) | set_items(notify=False, optional=True)).trait("attr") self.assertEqual(actual, expected)
def test_trait_name_optional_true(self): # Test the top-level function expr = expression.trait("name", optional=True) expected = [ create_graph( NamedTraitObserver(name="name", notify=True, optional=True)), ] actual = expr._as_graphs() self.assertEqual(actual, expected)
def test_trait_method_optional_true(self): # Test the instance method calls the top-level function correctly. expr = expression.trait("name").trait("attr", optional=True) expected = [ create_graph( NamedTraitObserver(name="name", notify=True, optional=False), NamedTraitObserver(name="attr", notify=True, optional=True), ), ] actual = expr._as_graphs() self.assertEqual(actual, expected)
def test_property_equality_no_effect(self): instance = ObjectWithEqualityComparisonMode() instance.number = 1 handler = mock.Mock() observe( object=instance, expression=expression.trait("calculated"), handler=handler, ) # when instance.number = 2 # then self.assertEqual(handler.call_count, 1)
def test_any_value_followed_by_list_items_new_bad_value(self): # see enthought/traits#1277 foo = Foo() handler = mock.Mock() # list_items(optional=True) will excuse the CannotCompare which isn't # a TraitList observe( object=foo, expression=expression.trait("any_value").list_items(optional=True), handler=handler, ) # when # this triggers observer_change_handler foo.any_value = CannotCompare()
def _handle_trait(trees, default_notifies): """ Handle an element for a named trait. Parameters ---------- trees : list of lark.tree.Tree The children tree for the "trait" rule. It contains only one item. default_notifies : list of boolean The notify flag stack. Returns ------- expression : ObserverExpression """ token, = trees name = token.value notify = default_notifies[-1] return expression_module.trait(name, notify=notify)
def test_observe_different_dispatcher(self): self.dispatch_records = [] def dispatcher(handler, event): self.dispatch_records.append((handler, event)) foo = ClassWithNumber() handler = mock.Mock() # when observe( object=foo, expression=trait("number"), handler=handler, dispatcher=dispatcher, ) foo.number += 1 # then # the dispatcher is called. self.assertEqual(len(self.dispatch_records), 1)
def test_list_equality_prevent_change_event(self): instance = ObjectWithEqualityComparisonMode() instance.list_values = [1] handler = mock.Mock() observe( object=instance, expression=expression.trait("list_values").list_items(), handler=handler, ) # New list, but equals to the previous instance.list_values = [1] # then self.assertEqual(handler.call_count, 0) # when instance.list_values.append(2) # then self.assertEqual(handler.call_count, 1)
def test_dict_equality_prevent_change_event(self): instance = ObjectWithEqualityComparisonMode() instance.dict_values = {"1": 1} handler = mock.Mock() observe( object=instance, expression=expression.trait("dict_values").dict_items(), handler=handler, ) # New dict, but equals to the previous instance.dict_values = {"1": 1} # then self.assertEqual(handler.call_count, 0) # when instance.dict_values["2"] = 2 # then self.assertEqual(handler.call_count, 1)
def test_basic_trait_equality_prevent_change_event(self): instance = ObjectWithEqualityComparisonMode() instance.number = 1 handler = mock.Mock() observe( object=instance, expression=expression.trait("number"), handler=handler, ) # when instance.number = 1.0 # then self.assertEqual(handler.call_count, 0) # when instance.number = True # then self.assertEqual(handler.call_count, 0) # when instance.number = 2.0 # then self.assertEqual(handler.call_count, 1) handler.reset_mock() # when # This instance cannot be compared with 2.0 for equality. instance.number = CannotCompare() # then self.assertEqual(handler.call_count, 1)
def test_trait_not_notifiy(self): actual = parse("a:b") expected = trait("a", notify=False).trait("b") self.assertEqual(actual, expected)
def test_simple_trait(self): actual = parse("a") expected = trait("a") self.assertEqual(actual, expected)
def test_multi_branch_then_or_apply_notify_flag_to_last_item(self): actual = parse("root.[a.b.c.d,value]:g") expected = (trait("root").then( trait("a").trait("b").trait("c").trait("d", False) | trait("value", False)).trait("g")) self.assertEqual(actual, expected)
def test_grouped_or_extended(self): actual = parse("root.[left,right].value") expected = (trait("root").then(trait("left") | trait("right")).trait("value")) self.assertEqual(actual, expected)
def test_grouped_or(self): actual = parse("root.[left,right]") expected = trait("root").then(trait("left") | trait("right")) self.assertEqual(actual, expected)
def test_or_with_join_nested(self): actual = parse("a.b.c,d.e") expected = (trait("a").trait("b").trait("c") | trait("d").trait("e")) self.assertEqual(actual, expected)
def test_or_with_commas(self): actual = parse("a,b,c") expected = trait("a") | trait("b") | trait("c") self.assertEqual(actual, expected)
def test_join_with_colon(self): actual = parse("a:b:c") expected = trait("a", False).trait("b", False).trait("c") self.assertEqual(actual, expected)
def test_join(self): actual = parse("a.b.c") expected = trait("a").trait("b").trait("c") self.assertEqual(actual, expected)