Esempio n. 1
0
    def test_or_then_chained(self):
        observer1 = 1
        observer2 = 2
        observer3 = 3
        observer4 = 4
        expr1 = create_expression(observer1)
        expr2 = create_expression(observer2)
        expr3 = create_expression(observer3)
        expr4 = create_expression(observer4)

        expr = (expr1 | expr2).then(expr3 | expr4)

        expected = [
            ObserverGraph(
                node=observer1,
                children=[
                    create_graph(observer3),
                    create_graph(observer4),
                ],
            ),
            ObserverGraph(
                node=observer2,
                children=[
                    create_graph(observer3),
                    create_graph(observer4),
                ],
            ),
        ]
        actual = expr._as_graphs()
        self.assertEqual(actual, expected)
Esempio n. 2
0
    def test_add_notifiers_for_children_graphs(self):
        # Test adding notifiers using children graphs
        observable1 = DummyObservable()
        child_observer1 = DummyObserver(observables=[observable1], )
        observable2 = DummyObservable()
        child_observer2 = DummyObserver(observables=[observable2], )
        parent_observer = DummyObserver(next_objects=[mock.Mock()], )
        graph = ObserverGraph(
            node=parent_observer,
            children=[
                ObserverGraph(node=child_observer1, ),
                ObserverGraph(node=child_observer2, )
            ],
        )

        # when
        call_add_or_remove_notifiers(
            graph=graph,
            remove=False,
        )

        # then
        self.assertCountEqual(
            observable1.notifiers,
            [
                # For child1 observer
                child_observer1.notifier,
            ])
        self.assertCountEqual(
            observable2.notifiers,
            [
                # For child2 observer
                child_observer2.notifier,
            ])
Esempio n. 3
0
    def test_add_maintainers(self):
        # Test adding maintainers for children graphs
        observable = DummyObservable()
        maintainer = DummyNotifier()
        root_observer = DummyObserver(
            notify=False,
            observables=[observable],
            maintainer=maintainer,
        )
        # two children, each will have a maintainer
        graph = ObserverGraph(
            node=root_observer,
            children=[
                ObserverGraph(node=DummyObserver()),
                ObserverGraph(node=DummyObserver()),
            ],
        )

        # when
        call_add_or_remove_notifiers(
            graph=graph,
            remove=False,
        )

        # then
        # the dummy observer always return the same maintainer object.
        self.assertEqual(observable.notifiers, [maintainer, maintainer])
Esempio n. 4
0
    def test_remove_maintainers(self):
        observable = DummyObservable()
        maintainer = DummyNotifier()
        observable.notifiers = [maintainer, maintainer]

        root_observer = DummyObserver(
            notify=False,
            observables=[observable],
            maintainer=maintainer,
        )

        # for there are two children graphs
        # two maintainers will be removed.
        graph = ObserverGraph(
            node=root_observer,
            children=[
                ObserverGraph(node=DummyObserver()),
                ObserverGraph(node=DummyObserver()),
            ],
        )

        # when
        call_add_or_remove_notifiers(
            graph=graph,
            remove=True,
        )

        # then
        self.assertEqual(observable.notifiers, [])
 def test_children_ordered(self):
     child_graph = ObserverGraph(node=2)
     graph = ObserverGraph(
         node=1,
         children=[
             child_graph,
             ObserverGraph(node=3),
         ],
     )
     self.assertIs(graph.children[0], child_graph)
    def test_children_unique(self):
        child_graph = ObserverGraph(node=2)

        with self.assertRaises(ValueError) as exception_cm:
            ObserverGraph(
                node=1,
                children=[
                    child_graph,
                    ObserverGraph(node=2),
                ],
            )

        self.assertEqual(str(exception_cm.exception),
                         "Not all children are unique.")
 def test_equality_different_length_children(self):
     graph1 = ObserverGraph(
         node=1,
         children=[
             ObserverGraph(node=2),
             ObserverGraph(node=3),
         ],
     )
     graph2 = ObserverGraph(
         node=1,
         children=[
             ObserverGraph(node=2),
         ],
     )
     self.assertNotEqual(graph1, graph2)
Esempio n. 8
0
def create_graph(*nodes):
    """ Create an ObserverGraph with the given nodes joined one after another.
    Parameters
    ----------
    *nodes : hashable
        Items to be attached as nodes

    Returns
    -------
    ObserverGraph
    """
    node = nodes[-1]
    graph = ObserverGraph(node=node)
    for node in nodes[:-1][::-1]:
        graph = ObserverGraph(node=node, children=[graph])
    return graph
    def observer_change_handler(event, graph, handler, target, dispatcher):
        """ Handler for maintaining observers.

        Parameters
        ----------
        event : TraitChangeEvent
            Event triggered by add_trait.
        graph : ObserverGraph
            Description for the *downstream* observers, i.e. excluding self.
        handler : callable
            User handler.
        target : object
            Object seen by the user as the owner of the observer.
        dispatcher : callable
            Callable for dispatching the handler.
        """
        new_graph = ObserverGraph(node=_RestrictedNamedTraitObserver(
            name=event.new,
            wrapped_observer=graph.node,
        ),
                                  children=graph.children)
        add_or_remove_notifiers(
            object=event.object,
            graph=new_graph,
            handler=handler,
            target=target,
            dispatcher=dispatcher,
            remove=False,
        )
Esempio n. 10
0
    def test_observer_graph_hash_with_named_listener(self):
        # Test equality + hashing using set passes.

        path1 = ObserverGraph(
            node=create_observer(name="foo"),
            children=[
                ObserverGraph(node=create_observer(name="bar")),
            ],
        )
        path2 = ObserverGraph(
            node=create_observer(name="foo"),
            children=[
                ObserverGraph(node=create_observer(name="bar")),
            ],
        )
        # This tests __eq__ and __hash__
        self.assertEqual(path1, path2)
Esempio n. 11
0
    def test_add_notifiers_for_extra_graph(self):
        observable = DummyObservable()
        extra_notifier = DummyNotifier()
        extra_observer = DummyObserver(
            observables=[observable],
            notifier=extra_notifier,
        )
        extra_graph = ObserverGraph(node=extra_observer, )
        observer = DummyObserver(extra_graphs=[extra_graph], )
        graph = ObserverGraph(node=observer)

        # when
        call_add_or_remove_notifiers(
            graph=graph,
            remove=False,
        )

        # then
        self.assertEqual(observable.notifiers, [extra_notifier])
Esempio n. 12
0
    def test_remove_notifiers_for_extra_graph(self):
        observable = DummyObservable()
        extra_notifier = DummyNotifier()
        extra_observer = DummyObserver(
            observables=[observable],
            notifier=extra_notifier,
        )
        extra_graph = ObserverGraph(node=extra_observer, )
        observer = DummyObserver(extra_graphs=[extra_graph], )
        graph = ObserverGraph(node=observer)

        # suppose the notifier was added before
        observable.notifiers = [extra_notifier]

        # when
        call_add_or_remove_notifiers(
            graph=graph,
            remove=True,
        )

        # then
        self.assertEqual(observable.notifiers, [])
Esempio n. 13
0
    def test_remove_notifier_raises_let_error_propagate(self):
        # Test if the notifier remove_from raises, the error will
        # be propagated.

        # DummyNotifier.remove_from raises if the notifier is not found.
        observer = DummyObserver(
            observables=[DummyObservable()],
            notifier=DummyNotifier(),
        )

        with self.assertRaises(NotifierNotFound):
            call_add_or_remove_notifiers(
                graph=ObserverGraph(node=observer),
                remove=True,
            )
Esempio n. 14
0
    def test_remove_notifiers_for_children_graphs(self):
        observable1 = DummyObservable()
        notifier1 = DummyNotifier()
        child_observer1 = DummyObserver(
            observables=[observable1],
            notifier=notifier1,
        )
        observable2 = DummyObservable()
        notifier2 = DummyNotifier()
        child_observer2 = DummyObserver(
            observables=[observable2],
            notifier=notifier2,
        )
        parent_observer = DummyObserver(next_objects=[mock.Mock()], )

        graph = ObserverGraph(
            node=parent_observer,
            children=[
                ObserverGraph(node=child_observer1, ),
                ObserverGraph(node=child_observer2, )
            ],
        )

        # suppose notifiers were added
        observable1.notifiers = [notifier1]
        observable2.notifiers = [notifier2]

        # when
        call_add_or_remove_notifiers(
            graph=graph,
            remove=True,
        )

        # then
        self.assertEqual(observable1.notifiers, [])
        self.assertEqual(observable2.notifiers, [])
Esempio n. 15
0
    def test_add_trait_notifiers(self):
        observable = DummyObservable()
        notifier = DummyNotifier()
        observer = DummyObserver(
            notify=True,
            observables=[observable],
            notifier=notifier,
        )
        graph = ObserverGraph(node=observer)

        # when
        call_add_or_remove_notifiers(
            graph=graph,
            remove=False,
        )

        # then
        self.assertEqual(observable.notifiers, [notifier])
Esempio n. 16
0
    def iter_extra_graphs(self, graph):
        """ Yield new ObserverGraph to be contributed by this observer.

        Parameters
        ----------
        graph : ObserverGraph
            The graph this observer is part of.

        Yields
        ------
        ObserverGraph
        """
        yield ObserverGraph(
            node=TraitAddedObserver(
                match_func=self.filter,
                optional=False,
            ),
            children=[graph],
        )
Esempio n. 17
0
def call_add_or_remove_notifiers(**kwargs):
    """ Convenience function for calling add_or_remove_notifiers with default
    values.

    Parameters
    ----------
    **kwargs
        New argument values to use instead.
    """
    values = dict(
        object=mock.Mock(),
        graph=ObserverGraph(node=None),
        handler=mock.Mock(),
        target=_DEFAULT_TARGET,
        dispatcher=dispatch_same,
        remove=False,
    )
    values.update(kwargs)
    add_or_remove_notifiers(**values)
Esempio n. 18
0
    def iter_extra_graphs(self, graph):
        """ Yield additional ObserverGraph for adding/removing notifiers when
        this observer is encountered in a given ObserverGraph.

        Parameters
        ----------
        graph : ObserverGraph
            The graph where this observer is the root node.

        Yields
        ------
        graph : ObserverGraph
        """
        yield ObserverGraph(
            node=TraitAddedObserver(
                match_func=lambda name, trait: name == self.name,
                optional=self.optional,
            ),
            children=[graph],
        )
Esempio n. 19
0
    def test_add_trait_notifiers_notify_flag_is_false(self):
        # Test when the notify flag is false, the notifier is not
        # added.
        observable = DummyObservable()
        notifier = DummyNotifier()
        observer = DummyObserver(
            notify=False,
            observables=[observable],
            notifier=notifier,
        )
        graph = ObserverGraph(node=observer)

        # when
        call_add_or_remove_notifiers(
            graph=graph,
            remove=False,
        )

        # then
        self.assertEqual(observable.notifiers, [])
Esempio n. 20
0
    def test_remove_notifiers_skip_if_notify_flag_is_false(self):
        observable = DummyObservable()
        notifier = DummyNotifier()
        observable.notifiers = [notifier]

        observer = DummyObserver(
            notify=False,
            observables=[observable],
            notifier=notifier,
        )
        graph = ObserverGraph(node=observer, )

        # when
        call_add_or_remove_notifiers(
            graph=graph,
            remove=True,
        )

        # then
        # notify is false, remove does nothing.
        self.assertEqual(observable.notifiers, [notifier])
 def test_equality_order_of_children(self):
     # The order of items in children does not matter
     graph1 = ObserverGraph(
         node=1,
         children=[
             ObserverGraph(node=2),
             ObserverGraph(node=3),
         ],
     )
     graph2 = ObserverGraph(
         node=1,
         children=[
             ObserverGraph(node=3),
             ObserverGraph(node=2),
         ],
     )
     self.assertEqual(graph1, graph2)
     self.assertEqual(hash(graph1), hash(graph2))
def graph_from_nodes(*nodes):
    nodes = nodes[::-1]
    graph = ObserverGraph(node=nodes[0])
    for node in nodes[1:]:
        graph = ObserverGraph(node=node, children=[graph])
    return graph
Esempio n. 23
0
 def _create_graphs(self, branches):
     return [
         ObserverGraph(node=self.observer, children=branches),
     ]
Esempio n. 24
0
    def test_basic_instance_change(self):
        class Bar(HasTraits):
            value = Int()

        class Foo(HasTraits):
            bar = Instance(Bar)

        on_bar_value_changed = self.handler

        bar = Bar()
        foo1 = Foo(bar=bar)
        foo2 = Foo(bar=bar)

        def observer_handler(event, graph, handler, target, dispatcher):
            # Very stupid handler for maintaining notifiers.
            old_notifiers = event.old._trait("value", 2)._notifiers(True)
            old_notifiers.remove(handler)
            new_notifiers = event.new._trait("value", 2)._notifiers(True)
            new_notifiers.append(handler)
            # Ignore graph, which would have been used for propagating
            # notifiers in nested objects.
            # Ignore target, which would have been used as the context
            # for the user handler.
            # Ignore dispatcher, which would otherwise wrap the user handler.

        # Two notifiers are added to bar
        # One "belongs" to foo1, the second one "belongs" to foo2
        bar._trait("value", 2)._notifiers(True).extend([
            on_bar_value_changed,
            on_bar_value_changed,
        ])

        # this is for maintaining notifiers that belong to foo1
        notifier_foo1 = create_notifier(
            observer_handler=observer_handler,
            event_factory=self.event_factory,
            graph=ObserverGraph(node=None),
            handler=on_bar_value_changed,
            target=foo1,
            dispatcher=dispatch_here,
        )
        notifier_foo1.add_to(foo1._trait("bar", 2))

        # this is for maintaining notifiers that belong to foo2
        notifier_foo2 = create_notifier(
            observer_handler=observer_handler,
            event_factory=self.event_factory,
            graph=ObserverGraph(node=None),
            handler=on_bar_value_changed,
            target=foo2,
            dispatcher=dispatch_here,
        )
        notifier_foo2.add_to(foo2._trait("bar", 2))

        # when
        # the bar is changed, the ObserverChangeNotifier is fired so that
        # user handler on Bar.value is maintained.
        self.event_args_list.clear()
        new_bar = Bar(value=1)
        foo1.bar = new_bar
        foo2.bar = new_bar
        new_bar.value += 1

        # then
        self.assertEqual(len(self.event_args_list), 2)

        # when
        # changes on the old bar will not be captured
        self.event_args_list.clear()
        bar.value += 1

        # then
        self.assertEqual(len(self.event_args_list), 0)