Show More
@@ -1330,6 +1330,50 b' def test_pickle_hastraits():' | |||
|
1330 | 1330 | nt.assert_equal(c2.i, c.i) |
|
1331 | 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 | 1377 | class TestEventful(TestCase): |
|
1334 | 1378 | |
|
1335 | 1379 | def test_list(self): |
@@ -575,8 +575,31 b' class HasTraits(py3compat.with_metaclass(MetaHasTraits, object)):' | |||
|
575 | 575 | # Allow trait values to be set using keyword arguments. |
|
576 | 576 | # We need to use setattr for this to trigger validation and |
|
577 | 577 | # notifications. |
|
578 | for key, value in iteritems(kw): | |
|
579 | setattr(self, key, value) | |
|
578 | ||
|
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 | 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