def test_trait_list_iter_observables_not_a_list_error(self):
        # Test when the given object is not a list
        instance = ClassWithList()

        observer = ListItemObserver(notify=True, optional=False)

        with self.assertRaises(ValueError) as exception_context:
            list(observer.iter_observables(instance.number))

        self.assertIn(
            "Expected a TraitList to be observed",
            str(exception_context.exception))
    def test_trait_list_iter_observables_not_a_trait_list_optional(self):
        # Test when the given object is a list but not an IObservable
        instance = ClassWithList()

        observer = ListItemObserver(notify=True, optional=True)

        self.assertIsNone(instance.not_a_trait_list)
        actual = list(observer.iter_observables(instance.not_a_trait_list))
        self.assertEqual(actual, [])

        instance.not_a_trait_list = CustomList()
        actual = list(observer.iter_observables(instance.not_a_trait_list))
        self.assertEqual(actual, [])
    def test_trait_list_iter_observables_error(self):
        # If the user chains a ListItemObserver after an observer that
        # does not produce a TraitList, raise an error

        instance = ClassWithList()
        instance.not_a_trait_list = CustomList()
        observer = ListItemObserver(notify=True, optional=False)

        with self.assertRaises(ValueError) as exception_context:
            next(observer.iter_observables(instance.not_a_trait_list))

        self.assertIn("Expected a TraitList to be observed",
                      str(exception_context.exception))
예제 #4
0
 def test_list_items_optional_true(self):
     expr = expression.list_items(optional=True)
     expected = [
         create_graph(ListItemObserver(notify=True, optional=True), ),
     ]
     actual = expr._as_graphs()
     self.assertEqual(actual, expected)
예제 #5
0
def list_items(notify=True, optional=False):
    """ Create a new expression for observing items inside a list.

    Events emitted (if any) will be instances of
    :class:`~traits.observation.events.ListChangeEvent`.

    e.g. ``trait("containers").list_items()`` for observing mutations
    to a list named ``containers``.

    e.g. ``trait("containers").list_items().trait("value")`` for observing
    the trait ``value`` on any items in the list ``containers``.

    Parameters
    ----------
    notify : bool, optional
        Whether to notify for changes. Default is to notify.
    optional : bool, optional
        Whether to ignore this if the upstream object is not a list.
        Default is false and an error will be raised if the object is not
        a list.

    Returns
    -------
    new_expression : ObserverExpression
    """
    observer = ListItemObserver(notify=notify, optional=optional)
    return SingleObserverExpression(observer)
    def test_maintain_notifier(self):
        # Test maintaining downstream notifier by
        # observing list of list

        instance = ClassWithListOfList()

        graph = create_graph(
            ListItemObserver(notify=False, optional=False),
            ListItemObserver(notify=True, optional=False),
        )
        handler = mock.Mock()
        call_add_or_remove_notifiers(
            object=instance.list_of_list,
            graph=graph,
            handler=handler,
        )

        # when
        instance.list_of_list.append([])

        # then
        # the first ListItemObserver has notify=False
        self.assertEqual(handler.call_count, 0)

        # but the second ListItemObserver is given to the nested list
        nested_list = instance.list_of_list[0]

        # when
        nested_list.append(1)

        # then
        ((event, ), _), = handler.call_args_list
        self.assertIs(event.object, nested_list)
        self.assertEqual(event.added, [1])
        self.assertEqual(event.removed, [])
        self.assertEqual(event.index, 0)
        handler.reset_mock()

        # when
        # the list is removed, it is not observed
        instance.list_of_list.pop()
        nested_list.append(1)

        # then
        self.assertEqual(handler.call_count, 0)
    def test_optional_observers(self):
        # ListItemObserver.optional is true, meaning it will ignore
        # incompatible incoming object.
        instance = ClassWithList()

        graph = create_graph(ListItemObserver(notify=True, optional=True), )
        handler = mock.Mock()
        call_add_or_remove_notifiers(
            object=instance.not_a_trait_list,
            graph=graph,
            handler=handler,
        )

        instance.not_a_trait_list = CustomList()
        instance.not_a_trait_list.append(1)

        self.assertEqual(handler.call_count, 0)
    def test_notifier_list_change(self):

        instance = ClassWithList(values=[])
        graph = create_graph(ListItemObserver(notify=True, optional=False), )
        handler = mock.Mock()
        call_add_or_remove_notifiers(
            object=instance.values,
            graph=graph,
            handler=handler,
        )

        # when
        instance.values.append(1)

        # then
        ((event, ), _), = handler.call_args_list
        self.assertIs(event.object, instance.values)
        self.assertEqual(event.added, [1])
        self.assertEqual(event.removed, [])
        self.assertEqual(event.index, 0)
    def test_notifier_custom_trait_list_change(self):
        # Test compatibility with any extension of TraitList, not just
        # TraitListObject
        instance = ClassWithList()
        instance.custom_trait_list = CustomTraitList()
        graph = create_graph(ListItemObserver(notify=True, optional=False), )
        handler = mock.Mock()
        call_add_or_remove_notifiers(
            object=instance.custom_trait_list,
            graph=graph,
            handler=handler,
        )

        # when
        instance.custom_trait_list.append(1)

        # then
        ((event, ), _), = handler.call_args_list
        self.assertIs(event.object, instance.custom_trait_list)
        self.assertEqual(event.added, [1])
        self.assertEqual(event.removed, [])
        self.assertEqual(event.index, 0)
예제 #10
0
 def test_equal_observers(self):
     observer1 = ListItemObserver(notify=False, optional=False)
     observer2 = ListItemObserver(notify=False, optional=False)
     self.assertEqual(observer1, observer2)
     self.assertEqual(hash(observer1), hash(observer2))
예제 #11
0
 def test_not_equal_different_type(self):
     observer1 = ListItemObserver(notify=False, optional=False)
     imposter = mock.Mock()
     imposter.notify = False
     imposter.optional = False
     self.assertNotEqual(observer1, imposter)
예제 #12
0
 def test_not_equal_optional(self):
     observer1 = ListItemObserver(notify=True, optional=True)
     observer2 = ListItemObserver(notify=True, optional=False)
     self.assertNotEqual(observer1, observer2)
예제 #13
0
 def test_trait_list_iter_objects_ignore_if_optional_and_not_list(self):
     observer = ListItemObserver(notify=True, optional=True)
     actual = list(observer.iter_objects(set([1])))
     self.assertEqual(actual, [])