Show More
@@ -1330,6 +1330,50 b' def test_pickle_hastraits():' | |||||
1330 | nt.assert_equal(c2.i, c.i) |
|
1330 | nt.assert_equal(c2.i, c.i) | |
1331 | nt.assert_equal(c2.j, c.j) |
|
1331 | nt.assert_equal(c2.j, c.j) | |
1332 |
|
1332 | |||
|
1333 | ||||
|
1334 | class OrderTraits(HasTraits): | |||
|
1335 | notified = Dict() | |||
|
1336 | ||||
|
1337 | a = Unicode() | |||
|
1338 | b = Unicode() | |||
|
1339 | c = Unicode() | |||
|
1340 | d = Unicode() | |||
|
1341 | e = Unicode() | |||
|
1342 | f = Unicode() | |||
|
1343 | g = Unicode() | |||
|
1344 | h = Unicode() | |||
|
1345 | i = Unicode() | |||
|
1346 | j = Unicode() | |||
|
1347 | k = Unicode() | |||
|
1348 | l = Unicode() | |||
|
1349 | ||||
|
1350 | def _notify(self, name, old, new): | |||
|
1351 | """check the value of all traits when each trait change is triggered | |||
|
1352 | ||||
|
1353 | This verifies that the values are not sensitive | |||
|
1354 | to dict ordering when loaded from kwargs | |||
|
1355 | """ | |||
|
1356 | # check the value of the other traits | |||
|
1357 | # when a given trait change notification fires | |||
|
1358 | self.notified[name] = { | |||
|
1359 | c: getattr(self, c) for c in 'abcdefghijkl' | |||
|
1360 | } | |||
|
1361 | ||||
|
1362 | def __init__(self, **kwargs): | |||
|
1363 | self.on_trait_change(self._notify) | |||
|
1364 | super(OrderTraits, self).__init__(**kwargs) | |||
|
1365 | ||||
|
1366 | def test_notification_order(): | |||
|
1367 | d = {c:c for c in 'abcdefghijkl'} | |||
|
1368 | obj = OrderTraits() | |||
|
1369 | nt.assert_equal(obj.notified, {}) | |||
|
1370 | obj = OrderTraits(**d) | |||
|
1371 | notifications = { | |||
|
1372 | c: d for c in 'abcdefghijkl' | |||
|
1373 | } | |||
|
1374 | nt.assert_equal(obj.notified, notifications) | |||
|
1375 | ||||
|
1376 | ||||
1333 | class TestEventful(TestCase): |
|
1377 | class TestEventful(TestCase): | |
1334 |
|
1378 | |||
1335 | def test_list(self): |
|
1379 | def test_list(self): |
@@ -575,8 +575,31 b' class HasTraits(py3compat.with_metaclass(MetaHasTraits, object)):' | |||||
575 | # Allow trait values to be set using keyword arguments. |
|
575 | # Allow trait values to be set using keyword arguments. | |
576 | # We need to use setattr for this to trigger validation and |
|
576 | # We need to use setattr for this to trigger validation and | |
577 | # notifications. |
|
577 | # notifications. | |
578 | for key, value in iteritems(kw): |
|
578 | ||
579 | setattr(self, key, value) |
|
579 | with self.delay_trait_notifications(): | |
|
580 | for key, value in iteritems(kw): | |||
|
581 | setattr(self, key, value) | |||
|
582 | ||||
|
583 | @contextlib.contextmanager | |||
|
584 | def delay_trait_notifications(self): | |||
|
585 | """Context manager for bundling trait change notifications | |||
|
586 | ||||
|
587 | Use this when doing multiple trait assignments (init, config), | |||
|
588 | to avoid race conditions in trait notifiers requesting other trait values. | |||
|
589 | All trait notifications will fire after all values have been assigned. | |||
|
590 | """ | |||
|
591 | _notify_trait = self._notify_trait | |||
|
592 | notifications = [] | |||
|
593 | self._notify_trait = lambda *a: notifications.append(a) | |||
|
594 | ||||
|
595 | try: | |||
|
596 | yield | |||
|
597 | finally: | |||
|
598 | self._notify_trait = _notify_trait | |||
|
599 | ||||
|
600 | # trigger delayed notifications | |||
|
601 | for args in notifications: | |||
|
602 | self._notify_trait(*args) | |||
580 |
|
603 | |||
581 | def _notify_trait(self, name, old_value, new_value): |
|
604 | def _notify_trait(self, name, old_value, new_value): | |
582 |
|
605 |
General Comments 0
You need to be logged in to leave comments.
Login now