aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/traitlets
diff options
context:
space:
mode:
authordvshkurko <dvshkurko@yandex-team.ru>2022-02-10 16:45:52 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:52 +0300
commitc768a99151e47c3a4bb7b92c514d256abd301c4d (patch)
tree1a2c5ffcf89eb53ecd79dbc9bc0a195c27404d0c /contrib/python/traitlets
parent321ee9bce31ec6e238be26dbcbe539cffa2c3309 (diff)
downloadydb-c768a99151e47c3a4bb7b92c514d256abd301c4d.tar.gz
Restoring authorship annotation for <dvshkurko@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/traitlets')
-rw-r--r--contrib/python/traitlets/py2/tests/ya.make24
-rw-r--r--contrib/python/traitlets/py2/traitlets/tests/_warnings.py214
-rw-r--r--contrib/python/traitlets/py2/traitlets/tests/test_traitlets.py4836
-rw-r--r--contrib/python/traitlets/py2/traitlets/tests/test_traitlets_enum.py362
-rw-r--r--contrib/python/traitlets/py2/traitlets/tests/utils.py76
-rw-r--r--contrib/python/traitlets/py2/ya.make6
-rw-r--r--contrib/python/traitlets/py3/traitlets/tests/_warnings.py194
-rw-r--r--contrib/python/traitlets/py3/traitlets/tests/test_traitlets.py4608
-rw-r--r--contrib/python/traitlets/py3/traitlets/tests/test_traitlets_enum.py354
-rw-r--r--contrib/python/traitlets/py3/traitlets/tests/utils.py78
-rw-r--r--contrib/python/traitlets/py3/ya.make6
-rw-r--r--contrib/python/traitlets/ya.make4
12 files changed, 5381 insertions, 5381 deletions
diff --git a/contrib/python/traitlets/py2/tests/ya.make b/contrib/python/traitlets/py2/tests/ya.make
index 050f5d1cc0..d2d3e3b9bf 100644
--- a/contrib/python/traitlets/py2/tests/ya.make
+++ b/contrib/python/traitlets/py2/tests/ya.make
@@ -1,15 +1,15 @@
PY2TEST()
-
-OWNER(g:python-contrib borman nslus)
-
-PEERDIR(
+
+OWNER(g:python-contrib borman nslus)
+
+PEERDIR(
contrib/python/traitlets
-)
-
+)
+
ENV(
YA_PYTEST_DISABLE_DOCTEST=yes
)
-
+
SRCDIR(contrib/python/traitlets/py2/traitlets)
TEST_SRCS(
@@ -18,8 +18,8 @@ TEST_SRCS(
tests/test_traitlets.py
tests/test_traitlets_enum.py
tests/utils.py
-)
-
-NO_LINT()
-
-END()
+)
+
+NO_LINT()
+
+END()
diff --git a/contrib/python/traitlets/py2/traitlets/tests/_warnings.py b/contrib/python/traitlets/py2/traitlets/tests/_warnings.py
index beb3bf6ad5..f135d1f67e 100644
--- a/contrib/python/traitlets/py2/traitlets/tests/_warnings.py
+++ b/contrib/python/traitlets/py2/traitlets/tests/_warnings.py
@@ -1,107 +1,107 @@
-# From scikit-image: https://github.com/scikit-image/scikit-image/blob/c2f8c4ab123ebe5f7b827bc495625a32bb225c10/skimage/_shared/_warnings.py
-# Licensed under modified BSD license
-
-__all__ = ['all_warnings', 'expected_warnings']
-
-from contextlib import contextmanager
-import sys
-import warnings
-import inspect
-import re
-
-
-@contextmanager
-def all_warnings():
- """
- Context for use in testing to ensure that all warnings are raised.
- Examples
- --------
- >>> import warnings
- >>> def foo():
- ... warnings.warn(RuntimeWarning("bar"))
- We raise the warning once, while the warning filter is set to "once".
- Hereafter, the warning is invisible, even with custom filters:
- >>> with warnings.catch_warnings():
- ... warnings.simplefilter('once')
- ... foo()
- We can now run ``foo()`` without a warning being raised:
- >>> from numpy.testing import assert_warns
- >>> foo()
- To catch the warning, we call in the help of ``all_warnings``:
- >>> with all_warnings():
- ... assert_warns(RuntimeWarning, foo)
- """
-
- # Whenever a warning is triggered, Python adds a __warningregistry__
- # member to the *calling* module. The exercize here is to find
- # and eradicate all those breadcrumbs that were left lying around.
- #
- # We proceed by first searching all parent calling frames and explicitly
- # clearing their warning registries (necessary for the doctests above to
- # pass). Then, we search for all submodules of skimage and clear theirs
- # as well (necessary for the skimage test suite to pass).
-
- frame = inspect.currentframe()
- if frame:
- for f in inspect.getouterframes(frame):
- f[0].f_locals['__warningregistry__'] = {}
- del frame
-
- for mod_name, mod in list(sys.modules.items()):
- if 'six.moves' in mod_name:
- continue
- try:
- mod.__warningregistry__.clear()
- except AttributeError:
- pass
-
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter("always")
- yield w
-
-
-@contextmanager
-def expected_warnings(matching):
- """Context for use in testing to catch known warnings matching regexes
-
- Parameters
- ----------
- matching : list of strings or compiled regexes
- Regexes for the desired warning to catch
- Examples
- --------
- >>> from skimage import data, img_as_ubyte, img_as_float
- >>> with expected_warnings(['precision loss']):
- ... d = img_as_ubyte(img_as_float(data.coins()))
- Notes
- -----
- Uses `all_warnings` to ensure all warnings are raised.
- Upon exiting, it checks the recorded warnings for the desired matching
- pattern(s).
- Raises a ValueError if any match was not found or an unexpected
- warning was raised.
- Allows for three types of behaviors: "and", "or", and "optional" matches.
- This is done to accomodate different build enviroments or loop conditions
- that may produce different warnings. The behaviors can be combined.
- If you pass multiple patterns, you get an orderless "and", where all of the
- warnings must be raised.
- If you use the "|" operator in a pattern, you can catch one of several warnings.
- Finally, you can use "|\A\Z" in a pattern to signify it as optional.
- """
- with all_warnings() as w:
- # enter context
- yield w
- # exited user context, check the recorded warnings
- remaining = [m for m in matching if not '\A\Z' in m.split('|')]
- for warn in w:
- found = False
- for match in matching:
- if re.search(match, str(warn.message)) is not None:
- found = True
- if match in remaining:
- remaining.remove(match)
- if not found:
- raise ValueError('Unexpected warning: %s' % str(warn.message))
- if len(remaining) > 0:
- msg = 'No warning raised matching:\n%s' % '\n'.join(remaining)
- raise ValueError(msg)
+# From scikit-image: https://github.com/scikit-image/scikit-image/blob/c2f8c4ab123ebe5f7b827bc495625a32bb225c10/skimage/_shared/_warnings.py
+# Licensed under modified BSD license
+
+__all__ = ['all_warnings', 'expected_warnings']
+
+from contextlib import contextmanager
+import sys
+import warnings
+import inspect
+import re
+
+
+@contextmanager
+def all_warnings():
+ """
+ Context for use in testing to ensure that all warnings are raised.
+ Examples
+ --------
+ >>> import warnings
+ >>> def foo():
+ ... warnings.warn(RuntimeWarning("bar"))
+ We raise the warning once, while the warning filter is set to "once".
+ Hereafter, the warning is invisible, even with custom filters:
+ >>> with warnings.catch_warnings():
+ ... warnings.simplefilter('once')
+ ... foo()
+ We can now run ``foo()`` without a warning being raised:
+ >>> from numpy.testing import assert_warns
+ >>> foo()
+ To catch the warning, we call in the help of ``all_warnings``:
+ >>> with all_warnings():
+ ... assert_warns(RuntimeWarning, foo)
+ """
+
+ # Whenever a warning is triggered, Python adds a __warningregistry__
+ # member to the *calling* module. The exercize here is to find
+ # and eradicate all those breadcrumbs that were left lying around.
+ #
+ # We proceed by first searching all parent calling frames and explicitly
+ # clearing their warning registries (necessary for the doctests above to
+ # pass). Then, we search for all submodules of skimage and clear theirs
+ # as well (necessary for the skimage test suite to pass).
+
+ frame = inspect.currentframe()
+ if frame:
+ for f in inspect.getouterframes(frame):
+ f[0].f_locals['__warningregistry__'] = {}
+ del frame
+
+ for mod_name, mod in list(sys.modules.items()):
+ if 'six.moves' in mod_name:
+ continue
+ try:
+ mod.__warningregistry__.clear()
+ except AttributeError:
+ pass
+
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter("always")
+ yield w
+
+
+@contextmanager
+def expected_warnings(matching):
+ """Context for use in testing to catch known warnings matching regexes
+
+ Parameters
+ ----------
+ matching : list of strings or compiled regexes
+ Regexes for the desired warning to catch
+ Examples
+ --------
+ >>> from skimage import data, img_as_ubyte, img_as_float
+ >>> with expected_warnings(['precision loss']):
+ ... d = img_as_ubyte(img_as_float(data.coins()))
+ Notes
+ -----
+ Uses `all_warnings` to ensure all warnings are raised.
+ Upon exiting, it checks the recorded warnings for the desired matching
+ pattern(s).
+ Raises a ValueError if any match was not found or an unexpected
+ warning was raised.
+ Allows for three types of behaviors: "and", "or", and "optional" matches.
+ This is done to accomodate different build enviroments or loop conditions
+ that may produce different warnings. The behaviors can be combined.
+ If you pass multiple patterns, you get an orderless "and", where all of the
+ warnings must be raised.
+ If you use the "|" operator in a pattern, you can catch one of several warnings.
+ Finally, you can use "|\A\Z" in a pattern to signify it as optional.
+ """
+ with all_warnings() as w:
+ # enter context
+ yield w
+ # exited user context, check the recorded warnings
+ remaining = [m for m in matching if not '\A\Z' in m.split('|')]
+ for warn in w:
+ found = False
+ for match in matching:
+ if re.search(match, str(warn.message)) is not None:
+ found = True
+ if match in remaining:
+ remaining.remove(match)
+ if not found:
+ raise ValueError('Unexpected warning: %s' % str(warn.message))
+ if len(remaining) > 0:
+ msg = 'No warning raised matching:\n%s' % '\n'.join(remaining)
+ raise ValueError(msg)
diff --git a/contrib/python/traitlets/py2/traitlets/tests/test_traitlets.py b/contrib/python/traitlets/py2/traitlets/tests/test_traitlets.py
index 5c0440f9ba..11b334cb60 100644
--- a/contrib/python/traitlets/py2/traitlets/tests/test_traitlets.py
+++ b/contrib/python/traitlets/py2/traitlets/tests/test_traitlets.py
@@ -1,2419 +1,2419 @@
-# encoding: utf-8
-"""Tests for traitlets.traitlets."""
-
-# Copyright (c) IPython Development Team.
-# Distributed under the terms of the Modified BSD License.
-#
-# Adapted from enthought.traits, Copyright (c) Enthought, Inc.,
-# also under the terms of the Modified BSD License.
-
-import pickle
-import re
-import sys
+# encoding: utf-8
+"""Tests for traitlets.traitlets."""
+
+# Copyright (c) IPython Development Team.
+# Distributed under the terms of the Modified BSD License.
+#
+# Adapted from enthought.traits, Copyright (c) Enthought, Inc.,
+# also under the terms of the Modified BSD License.
+
+import pickle
+import re
+import sys
from ._warnings import expected_warnings
-
-from unittest import TestCase
-import pytest
-from pytest import mark
-
-from traitlets import (
- HasTraits, MetaHasTraits, TraitType, Any, Bool, CBytes, Dict, Enum,
- Int, CInt, Long, CLong, Integer, Float, CFloat, Complex, Bytes, Unicode,
- TraitError, Union, All, Undefined, Type, This, Instance, TCPAddress,
- List, Tuple, ObjectName, DottedObjectName, CRegExp, link, directional_link,
- ForwardDeclaredType, ForwardDeclaredInstance, validate, observe, default,
- observe_compat, BaseDescriptor, HasDescriptors,
-)
-
-import six
-
-def change_dict(*ordered_values):
- change_names = ('name', 'old', 'new', 'owner', 'type')
- return dict(zip(change_names, ordered_values))
-
-#-----------------------------------------------------------------------------
-# Helper classes for testing
-#-----------------------------------------------------------------------------
-
-
-class HasTraitsStub(HasTraits):
-
- def notify_change(self, change):
- self._notify_name = change['name']
- self._notify_old = change['old']
- self._notify_new = change['new']
- self._notify_type = change['type']
-
-
-#-----------------------------------------------------------------------------
-# Test classes
-#-----------------------------------------------------------------------------
-
-
-class TestTraitType(TestCase):
-
- def test_get_undefined(self):
- class A(HasTraits):
- a = TraitType
- a = A()
- with self.assertRaises(TraitError):
- a.a
-
- def test_set(self):
- class A(HasTraitsStub):
- a = TraitType
-
- a = A()
- a.a = 10
- self.assertEqual(a.a, 10)
- self.assertEqual(a._notify_name, 'a')
- self.assertEqual(a._notify_old, Undefined)
- self.assertEqual(a._notify_new, 10)
-
- def test_validate(self):
- class MyTT(TraitType):
- def validate(self, inst, value):
- return -1
- class A(HasTraitsStub):
- tt = MyTT
-
- a = A()
- a.tt = 10
- self.assertEqual(a.tt, -1)
-
- def test_default_validate(self):
- class MyIntTT(TraitType):
- def validate(self, obj, value):
- if isinstance(value, int):
- return value
- self.error(obj, value)
- class A(HasTraits):
- tt = MyIntTT(10)
- a = A()
- self.assertEqual(a.tt, 10)
-
- # Defaults are validated when the HasTraits is instantiated
- class B(HasTraits):
- tt = MyIntTT('bad default')
- self.assertRaises(TraitError, B)
-
- def test_info(self):
- class A(HasTraits):
- tt = TraitType
- a = A()
- self.assertEqual(A.tt.info(), 'any value')
-
- def test_error(self):
- class A(HasTraits):
- tt = TraitType
- a = A()
- self.assertRaises(TraitError, A.tt.error, a, 10)
-
- def test_deprecated_dynamic_initializer(self):
- class A(HasTraits):
- x = Int(10)
- def _x_default(self):
- return 11
- class B(A):
- x = Int(20)
- class C(A):
- def _x_default(self):
- return 21
-
- a = A()
- self.assertEqual(a._trait_values, {})
- self.assertEqual(a.x, 11)
- self.assertEqual(a._trait_values, {'x': 11})
- b = B()
- self.assertEqual(b.x, 20)
- self.assertEqual(b._trait_values, {'x': 20})
- c = C()
- self.assertEqual(c._trait_values, {})
- self.assertEqual(c.x, 21)
- self.assertEqual(c._trait_values, {'x': 21})
- # Ensure that the base class remains unmolested when the _default
- # initializer gets overridden in a subclass.
- a = A()
- c = C()
- self.assertEqual(a._trait_values, {})
- self.assertEqual(a.x, 11)
- self.assertEqual(a._trait_values, {'x': 11})
-
- def test_dynamic_initializer(self):
-
- class A(HasTraits):
- x = Int(10)
-
- @default('x')
- def _default_x(self):
- return 11
-
- class B(A):
- x = Int(20)
-
- class C(A):
-
- @default('x')
- def _default_x(self):
- return 21
-
- a = A()
- self.assertEqual(a._trait_values, {})
- self.assertEqual(a.x, 11)
- self.assertEqual(a._trait_values, {'x': 11})
- b = B()
- self.assertEqual(b.x, 20)
- self.assertEqual(b._trait_values, {'x': 20})
- c = C()
- self.assertEqual(c._trait_values, {})
- self.assertEqual(c.x, 21)
- self.assertEqual(c._trait_values, {'x': 21})
- # Ensure that the base class remains unmolested when the _default
- # initializer gets overridden in a subclass.
- a = A()
- c = C()
- self.assertEqual(a._trait_values, {})
- self.assertEqual(a.x, 11)
- self.assertEqual(a._trait_values, {'x': 11})
-
- def test_tag_metadata(self):
- class MyIntTT(TraitType):
- metadata = {'a': 1, 'b': 2}
- a = MyIntTT(10).tag(b=3, c=4)
- self.assertEqual(a.metadata, {'a': 1, 'b': 3, 'c': 4})
-
- def test_metadata_localized_instance(self):
- class MyIntTT(TraitType):
- metadata = {'a': 1, 'b': 2}
- a = MyIntTT(10)
- b = MyIntTT(10)
- a.metadata['c'] = 3
- # make sure that changing a's metadata didn't change b's metadata
- self.assertNotIn('c', b.metadata)
-
- def test_union_metadata(self):
- class Foo(HasTraits):
- bar = (Int().tag(ta=1) | Dict().tag(ta=2, ti='b')).tag(ti='a')
- foo = Foo()
- # At this point, no value has been set for bar, so value-specific
- # is not set.
- self.assertEqual(foo.trait_metadata('bar', 'ta'), None)
- self.assertEqual(foo.trait_metadata('bar', 'ti'), 'a')
- foo.bar = {}
- self.assertEqual(foo.trait_metadata('bar', 'ta'), 2)
- self.assertEqual(foo.trait_metadata('bar', 'ti'), 'b')
- foo.bar = 1
- self.assertEqual(foo.trait_metadata('bar', 'ta'), 1)
- self.assertEqual(foo.trait_metadata('bar', 'ti'), 'a')
-
- def test_union_default_value(self):
- class Foo(HasTraits):
- bar = Union([Dict(), Int()], default_value=1)
- foo = Foo()
- self.assertEqual(foo.bar, 1)
-
- def test_deprecated_metadata_access(self):
- class MyIntTT(TraitType):
- metadata = {'a': 1, 'b': 2}
- a = MyIntTT(10)
- with expected_warnings(["use the instance .metadata dictionary directly"]*2):
- a.set_metadata('key', 'value')
- v = a.get_metadata('key')
- self.assertEqual(v, 'value')
- with expected_warnings(["use the instance .help string directly"]*2):
- a.set_metadata('help', 'some help')
- v = a.get_metadata('help')
- self.assertEqual(v, 'some help')
-
- def test_trait_types_deprecated(self):
- with expected_warnings(["Traits should be given as instances"]):
- class C(HasTraits):
- t = Int
-
- def test_trait_types_list_deprecated(self):
- with expected_warnings(["Traits should be given as instances"]):
- class C(HasTraits):
- t = List(Int)
-
- def test_trait_types_tuple_deprecated(self):
- with expected_warnings(["Traits should be given as instances"]):
- class C(HasTraits):
- t = Tuple(Int)
-
- def test_trait_types_dict_deprecated(self):
- with expected_warnings(["Traits should be given as instances"]):
- class C(HasTraits):
- t = Dict(Int)
-
-class TestHasDescriptorsMeta(TestCase):
-
- def test_metaclass(self):
- self.assertEqual(type(HasTraits), MetaHasTraits)
-
- class A(HasTraits):
- a = Int()
-
- a = A()
- self.assertEqual(type(a.__class__), MetaHasTraits)
- self.assertEqual(a.a,0)
- a.a = 10
- self.assertEqual(a.a,10)
-
- class B(HasTraits):
- b = Int()
-
- b = B()
- self.assertEqual(b.b,0)
- b.b = 10
- self.assertEqual(b.b,10)
-
- class C(HasTraits):
- c = Int(30)
-
- c = C()
- self.assertEqual(c.c,30)
- c.c = 10
- self.assertEqual(c.c,10)
-
- def test_this_class(self):
- class A(HasTraits):
- t = This()
- tt = This()
- class B(A):
- tt = This()
- ttt = This()
- self.assertEqual(A.t.this_class, A)
- self.assertEqual(B.t.this_class, A)
- self.assertEqual(B.tt.this_class, B)
- self.assertEqual(B.ttt.this_class, B)
-
-class TestHasDescriptors(TestCase):
-
- def test_setup_instance(self):
-
- class FooDescriptor(BaseDescriptor):
-
- def instance_init(self, inst):
- foo = inst.foo # instance should have the attr
-
- class HasFooDescriptors(HasDescriptors):
-
- fd = FooDescriptor()
-
- def setup_instance(self, *args, **kwargs):
- self.foo = kwargs.get('foo', None)
- super(HasFooDescriptors, self).setup_instance(*args, **kwargs)
-
- hfd = HasFooDescriptors(foo='bar')
-
-class TestHasTraitsNotify(TestCase):
-
- def setUp(self):
- self._notify1 = []
- self._notify2 = []
-
- def notify1(self, name, old, new):
- self._notify1.append((name, old, new))
-
- def notify2(self, name, old, new):
- self._notify2.append((name, old, new))
-
- def test_notify_all(self):
-
- class A(HasTraits):
- a = Int()
- b = Float()
-
- a = A()
- a.on_trait_change(self.notify1)
- a.a = 0
- self.assertEqual(len(self._notify1),0)
- a.b = 0.0
- self.assertEqual(len(self._notify1),0)
- a.a = 10
- self.assertTrue(('a',0,10) in self._notify1)
- a.b = 10.0
- self.assertTrue(('b',0.0,10.0) in self._notify1)
- self.assertRaises(TraitError,setattr,a,'a','bad string')
- self.assertRaises(TraitError,setattr,a,'b','bad string')
- self._notify1 = []
- a.on_trait_change(self.notify1,remove=True)
- a.a = 20
- a.b = 20.0
- self.assertEqual(len(self._notify1),0)
-
- def test_notify_one(self):
-
- class A(HasTraits):
- a = Int()
- b = Float()
-
- a = A()
- a.on_trait_change(self.notify1, 'a')
- a.a = 0
- self.assertEqual(len(self._notify1),0)
- a.a = 10
- self.assertTrue(('a',0,10) in self._notify1)
- self.assertRaises(TraitError,setattr,a,'a','bad string')
-
- def test_subclass(self):
-
- class A(HasTraits):
- a = Int()
-
- class B(A):
- b = Float()
-
- b = B()
- self.assertEqual(b.a,0)
- self.assertEqual(b.b,0.0)
- b.a = 100
- b.b = 100.0
- self.assertEqual(b.a,100)
- self.assertEqual(b.b,100.0)
-
- def test_notify_subclass(self):
-
- class A(HasTraits):
- a = Int()
-
- class B(A):
- b = Float()
-
- b = B()
- b.on_trait_change(self.notify1, 'a')
- b.on_trait_change(self.notify2, 'b')
- b.a = 0
- b.b = 0.0
- self.assertEqual(len(self._notify1),0)
- self.assertEqual(len(self._notify2),0)
- b.a = 10
- b.b = 10.0
- self.assertTrue(('a',0,10) in self._notify1)
- self.assertTrue(('b',0.0,10.0) in self._notify2)
-
- def test_static_notify(self):
-
- class A(HasTraits):
- a = Int()
- _notify1 = []
- def _a_changed(self, name, old, new):
- self._notify1.append((name, old, new))
-
- a = A()
- a.a = 0
- # This is broken!!!
- self.assertEqual(len(a._notify1),0)
- a.a = 10
- self.assertTrue(('a',0,10) in a._notify1)
-
- class B(A):
- b = Float()
- _notify2 = []
- def _b_changed(self, name, old, new):
- self._notify2.append((name, old, new))
-
- b = B()
- b.a = 10
- b.b = 10.0
- self.assertTrue(('a',0,10) in b._notify1)
- self.assertTrue(('b',0.0,10.0) in b._notify2)
-
- def test_notify_args(self):
-
- def callback0():
- self.cb = ()
- def callback1(name):
- self.cb = (name,)
- def callback2(name, new):
- self.cb = (name, new)
- def callback3(name, old, new):
- self.cb = (name, old, new)
- def callback4(name, old, new, obj):
- self.cb = (name, old, new, obj)
-
- class A(HasTraits):
- a = Int()
-
- a = A()
- a.on_trait_change(callback0, 'a')
- a.a = 10
- self.assertEqual(self.cb,())
- a.on_trait_change(callback0, 'a', remove=True)
-
- a.on_trait_change(callback1, 'a')
- a.a = 100
- self.assertEqual(self.cb,('a',))
- a.on_trait_change(callback1, 'a', remove=True)
-
- a.on_trait_change(callback2, 'a')
- a.a = 1000
- self.assertEqual(self.cb,('a',1000))
- a.on_trait_change(callback2, 'a', remove=True)
-
- a.on_trait_change(callback3, 'a')
- a.a = 10000
- self.assertEqual(self.cb,('a',1000,10000))
- a.on_trait_change(callback3, 'a', remove=True)
-
- a.on_trait_change(callback4, 'a')
- a.a = 100000
- self.assertEqual(self.cb,('a',10000,100000,a))
- self.assertEqual(len(a._trait_notifiers['a']['change']), 1)
- a.on_trait_change(callback4, 'a', remove=True)
-
- self.assertEqual(len(a._trait_notifiers['a']['change']), 0)
-
- def test_notify_only_once(self):
-
- class A(HasTraits):
- listen_to = ['a']
-
- a = Int(0)
- b = 0
-
- def __init__(self, **kwargs):
- super(A, self).__init__(**kwargs)
- self.on_trait_change(self.listener1, ['a'])
-
- def listener1(self, name, old, new):
- self.b += 1
-
- class B(A):
-
- c = 0
- d = 0
-
- def __init__(self, **kwargs):
- super(B, self).__init__(**kwargs)
- self.on_trait_change(self.listener2)
-
- def listener2(self, name, old, new):
- self.c += 1
-
- def _a_changed(self, name, old, new):
- self.d += 1
-
- b = B()
- b.a += 1
- self.assertEqual(b.b, b.c)
- self.assertEqual(b.b, b.d)
- b.a += 1
- self.assertEqual(b.b, b.c)
- self.assertEqual(b.b, b.d)
-
-class TestObserveDecorator(TestCase):
-
- def setUp(self):
- self._notify1 = []
- self._notify2 = []
-
- def notify1(self, change):
- self._notify1.append(change)
-
- def notify2(self, change):
- self._notify2.append(change)
-
- def test_notify_all(self):
-
- class A(HasTraits):
- a = Int()
- b = Float()
-
- a = A()
- a.observe(self.notify1)
- a.a = 0
- self.assertEqual(len(self._notify1),0)
- a.b = 0.0
- self.assertEqual(len(self._notify1),0)
- a.a = 10
- change = change_dict('a', 0, 10, a, 'change')
- self.assertTrue(change in self._notify1)
- a.b = 10.0
- change = change_dict('b', 0.0, 10.0, a, 'change')
- self.assertTrue(change in self._notify1)
- self.assertRaises(TraitError,setattr,a,'a','bad string')
- self.assertRaises(TraitError,setattr,a,'b','bad string')
- self._notify1 = []
- a.unobserve(self.notify1)
- a.a = 20
- a.b = 20.0
- self.assertEqual(len(self._notify1),0)
-
- def test_notify_one(self):
-
- class A(HasTraits):
- a = Int()
- b = Float()
-
- a = A()
- a.observe(self.notify1, 'a')
- a.a = 0
- self.assertEqual(len(self._notify1),0)
- a.a = 10
- change = change_dict('a', 0, 10, a, 'change')
- self.assertTrue(change in self._notify1)
- self.assertRaises(TraitError,setattr,a,'a','bad string')
-
- def test_subclass(self):
-
- class A(HasTraits):
- a = Int()
-
- class B(A):
- b = Float()
-
- b = B()
- self.assertEqual(b.a,0)
- self.assertEqual(b.b,0.0)
- b.a = 100
- b.b = 100.0
- self.assertEqual(b.a,100)
- self.assertEqual(b.b,100.0)
-
- def test_notify_subclass(self):
-
- class A(HasTraits):
- a = Int()
-
- class B(A):
- b = Float()
-
- b = B()
- b.observe(self.notify1, 'a')
- b.observe(self.notify2, 'b')
- b.a = 0
- b.b = 0.0
- self.assertEqual(len(self._notify1),0)
- self.assertEqual(len(self._notify2),0)
- b.a = 10
- b.b = 10.0
- change = change_dict('a', 0, 10, b, 'change')
- self.assertTrue(change in self._notify1)
- change = change_dict('b', 0.0, 10.0, b, 'change')
- self.assertTrue(change in self._notify2)
-
- def test_static_notify(self):
-
- class A(HasTraits):
- a = Int()
- b = Int()
- _notify1 = []
- _notify_any = []
-
- @observe('a')
- def _a_changed(self, change):
- self._notify1.append(change)
-
- @observe(All)
- def _any_changed(self, change):
- self._notify_any.append(change)
-
- a = A()
- a.a = 0
- self.assertEqual(len(a._notify1),0)
- a.a = 10
- change = change_dict('a', 0, 10, a, 'change')
- self.assertTrue(change in a._notify1)
- a.b = 1
- self.assertEqual(len(a._notify_any), 2)
- change = change_dict('b', 0, 1, a, 'change')
- self.assertTrue(change in a._notify_any)
-
- class B(A):
- b = Float()
- _notify2 = []
- @observe('b')
- def _b_changed(self, change):
- self._notify2.append(change)
-
- b = B()
- b.a = 10
- b.b = 10.0
- change = change_dict('a', 0, 10, b, 'change')
- self.assertTrue(change in b._notify1)
- change = change_dict('b', 0.0, 10.0, b, 'change')
- self.assertTrue(change in b._notify2)
-
- def test_notify_args(self):
-
- def callback0():
- self.cb = ()
- def callback1(change):
- self.cb = change
-
- class A(HasTraits):
- a = Int()
-
- a = A()
- a.on_trait_change(callback0, 'a')
- a.a = 10
- self.assertEqual(self.cb,())
- a.unobserve(callback0, 'a')
-
- a.observe(callback1, 'a')
- a.a = 100
- change = change_dict('a', 10, 100, a, 'change')
- self.assertEqual(self.cb, change)
- self.assertEqual(len(a._trait_notifiers['a']['change']), 1)
- a.unobserve(callback1, 'a')
-
- self.assertEqual(len(a._trait_notifiers['a']['change']), 0)
-
- def test_notify_only_once(self):
-
- class A(HasTraits):
- listen_to = ['a']
-
- a = Int(0)
- b = 0
-
- def __init__(self, **kwargs):
- super(A, self).__init__(**kwargs)
- self.observe(self.listener1, ['a'])
-
- def listener1(self, change):
- self.b += 1
-
- class B(A):
-
- c = 0
- d = 0
-
- def __init__(self, **kwargs):
- super(B, self).__init__(**kwargs)
- self.observe(self.listener2)
-
- def listener2(self, change):
- self.c += 1
-
- @observe('a')
- def _a_changed(self, change):
- self.d += 1
-
- b = B()
- b.a += 1
- self.assertEqual(b.b, b.c)
- self.assertEqual(b.b, b.d)
- b.a += 1
- self.assertEqual(b.b, b.c)
- self.assertEqual(b.b, b.d)
-
-
-class TestHasTraits(TestCase):
-
- def test_trait_names(self):
- class A(HasTraits):
- i = Int()
- f = Float()
- a = A()
- self.assertEqual(sorted(a.trait_names()),['f','i'])
- self.assertEqual(sorted(A.class_trait_names()),['f','i'])
- self.assertTrue(a.has_trait('f'))
- self.assertFalse(a.has_trait('g'))
-
- def test_trait_metadata_deprecated(self):
- with expected_warnings(['metadata should be set using the \.tag\(\) method']):
- class A(HasTraits):
- i = Int(config_key='MY_VALUE')
- a = A()
- self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
-
- def test_trait_metadata(self):
- class A(HasTraits):
- i = Int().tag(config_key='MY_VALUE')
- a = A()
- self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
-
- def test_trait_metadata_default(self):
- class A(HasTraits):
- i = Int()
- a = A()
- self.assertEqual(a.trait_metadata('i', 'config_key'), None)
- self.assertEqual(a.trait_metadata('i', 'config_key', 'default'), 'default')
-
- def test_traits(self):
- class A(HasTraits):
- i = Int()
- f = Float()
- a = A()
- self.assertEqual(a.traits(), dict(i=A.i, f=A.f))
- self.assertEqual(A.class_traits(), dict(i=A.i, f=A.f))
-
- def test_traits_metadata(self):
- class A(HasTraits):
- i = Int().tag(config_key='VALUE1', other_thing='VALUE2')
- f = Float().tag(config_key='VALUE3', other_thing='VALUE2')
- j = Int(0)
- a = A()
- self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
- traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
- self.assertEqual(traits, dict(i=A.i))
-
- # This passes, but it shouldn't because I am replicating a bug in
- # traits.
- traits = a.traits(config_key=lambda v: True)
- self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
-
- def test_traits_metadata_deprecated(self):
- with expected_warnings(['metadata should be set using the \.tag\(\) method']*2):
- class A(HasTraits):
- i = Int(config_key='VALUE1', other_thing='VALUE2')
- f = Float(config_key='VALUE3', other_thing='VALUE2')
- j = Int(0)
- a = A()
- self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
- traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
- self.assertEqual(traits, dict(i=A.i))
-
- # This passes, but it shouldn't because I am replicating a bug in
- # traits.
- traits = a.traits(config_key=lambda v: True)
- self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
-
-
- def test_init(self):
- class A(HasTraits):
- i = Int()
- x = Float()
- a = A(i=1, x=10.0)
- self.assertEqual(a.i, 1)
- self.assertEqual(a.x, 10.0)
-
- def test_positional_args(self):
- class A(HasTraits):
- i = Int(0)
- def __init__(self, i):
- super(A, self).__init__()
- self.i = i
-
- a = A(5)
- self.assertEqual(a.i, 5)
- # should raise TypeError if no positional arg given
- self.assertRaises(TypeError, A)
-
-#-----------------------------------------------------------------------------
-# Tests for specific trait types
-#-----------------------------------------------------------------------------
-
-
-class TestType(TestCase):
-
- def test_default(self):
-
- class B(object): pass
- class A(HasTraits):
- klass = Type(allow_none=True)
-
- a = A()
- self.assertEqual(a.klass, object)
-
- a.klass = B
- self.assertEqual(a.klass, B)
- self.assertRaises(TraitError, setattr, a, 'klass', 10)
-
- def test_default_options(self):
-
- class B(object): pass
- class C(B): pass
- class A(HasTraits):
- # Different possible combinations of options for default_value
- # and klass. default_value=None is only valid with allow_none=True.
- k1 = Type()
- k2 = Type(None, allow_none=True)
- k3 = Type(B)
- k4 = Type(klass=B)
- k5 = Type(default_value=None, klass=B, allow_none=True)
- k6 = Type(default_value=C, klass=B)
-
- self.assertIs(A.k1.default_value, object)
- self.assertIs(A.k1.klass, object)
- self.assertIs(A.k2.default_value, None)
- self.assertIs(A.k2.klass, object)
- self.assertIs(A.k3.default_value, B)
- self.assertIs(A.k3.klass, B)
- self.assertIs(A.k4.default_value, B)
- self.assertIs(A.k4.klass, B)
- self.assertIs(A.k5.default_value, None)
- self.assertIs(A.k5.klass, B)
- self.assertIs(A.k6.default_value, C)
- self.assertIs(A.k6.klass, B)
-
- a = A()
- self.assertIs(a.k1, object)
- self.assertIs(a.k2, None)
- self.assertIs(a.k3, B)
- self.assertIs(a.k4, B)
- self.assertIs(a.k5, None)
- self.assertIs(a.k6, C)
-
- def test_value(self):
-
- class B(object): pass
- class C(object): pass
- class A(HasTraits):
- klass = Type(B)
-
- a = A()
- self.assertEqual(a.klass, B)
- self.assertRaises(TraitError, setattr, a, 'klass', C)
- self.assertRaises(TraitError, setattr, a, 'klass', object)
- a.klass = B
-
- def test_allow_none(self):
-
- class B(object): pass
- class C(B): pass
- class A(HasTraits):
- klass = Type(B)
-
- a = A()
- self.assertEqual(a.klass, B)
- self.assertRaises(TraitError, setattr, a, 'klass', None)
- a.klass = C
- self.assertEqual(a.klass, C)
-
- def test_validate_klass(self):
-
- class A(HasTraits):
- klass = Type('no strings allowed')
-
- self.assertRaises(ImportError, A)
-
- class A(HasTraits):
- klass = Type('rub.adub.Duck')
-
- self.assertRaises(ImportError, A)
-
- def test_validate_default(self):
-
- class B(object): pass
- class A(HasTraits):
- klass = Type('bad default', B)
-
- self.assertRaises(ImportError, A)
-
- class C(HasTraits):
- klass = Type(None, B)
-
- self.assertRaises(TraitError, C)
-
- def test_str_klass(self):
-
- class A(HasTraits):
- klass = Type('ipython_genutils.ipstruct.Struct')
-
- from ipython_genutils.ipstruct import Struct
- a = A()
- a.klass = Struct
- self.assertEqual(a.klass, Struct)
-
- self.assertRaises(TraitError, setattr, a, 'klass', 10)
-
- def test_set_str_klass(self):
-
- class A(HasTraits):
- klass = Type()
-
- a = A(klass='ipython_genutils.ipstruct.Struct')
- from ipython_genutils.ipstruct import Struct
- self.assertEqual(a.klass, Struct)
-
-class TestInstance(TestCase):
-
- def test_basic(self):
- class Foo(object): pass
- class Bar(Foo): pass
- class Bah(object): pass
-
- class A(HasTraits):
- inst = Instance(Foo, allow_none=True)
-
- a = A()
- self.assertTrue(a.inst is None)
- a.inst = Foo()
- self.assertTrue(isinstance(a.inst, Foo))
- a.inst = Bar()
- self.assertTrue(isinstance(a.inst, Foo))
- self.assertRaises(TraitError, setattr, a, 'inst', Foo)
- self.assertRaises(TraitError, setattr, a, 'inst', Bar)
- self.assertRaises(TraitError, setattr, a, 'inst', Bah())
-
- def test_default_klass(self):
- class Foo(object): pass
- class Bar(Foo): pass
- class Bah(object): pass
-
- class FooInstance(Instance):
- klass = Foo
-
- class A(HasTraits):
- inst = FooInstance(allow_none=True)
-
- a = A()
- self.assertTrue(a.inst is None)
- a.inst = Foo()
- self.assertTrue(isinstance(a.inst, Foo))
- a.inst = Bar()
- self.assertTrue(isinstance(a.inst, Foo))
- self.assertRaises(TraitError, setattr, a, 'inst', Foo)
- self.assertRaises(TraitError, setattr, a, 'inst', Bar)
- self.assertRaises(TraitError, setattr, a, 'inst', Bah())
-
- def test_unique_default_value(self):
- class Foo(object): pass
- class A(HasTraits):
- inst = Instance(Foo,(),{})
-
- a = A()
- b = A()
- self.assertTrue(a.inst is not b.inst)
-
- def test_args_kw(self):
- class Foo(object):
- def __init__(self, c): self.c = c
- class Bar(object): pass
- class Bah(object):
- def __init__(self, c, d):
- self.c = c; self.d = d
-
- class A(HasTraits):
- inst = Instance(Foo, (10,))
- a = A()
- self.assertEqual(a.inst.c, 10)
-
- class B(HasTraits):
- inst = Instance(Bah, args=(10,), kw=dict(d=20))
- b = B()
- self.assertEqual(b.inst.c, 10)
- self.assertEqual(b.inst.d, 20)
-
- class C(HasTraits):
- inst = Instance(Foo, allow_none=True)
- c = C()
- self.assertTrue(c.inst is None)
-
- def test_bad_default(self):
- class Foo(object): pass
-
- class A(HasTraits):
- inst = Instance(Foo)
-
- a = A()
- with self.assertRaises(TraitError):
- a.inst
-
- def test_instance(self):
- class Foo(object): pass
-
- def inner():
- class A(HasTraits):
- inst = Instance(Foo())
-
- self.assertRaises(TraitError, inner)
-
-
-class TestThis(TestCase):
-
- def test_this_class(self):
- class Foo(HasTraits):
- this = This()
-
- f = Foo()
- self.assertEqual(f.this, None)
- g = Foo()
- f.this = g
- self.assertEqual(f.this, g)
- self.assertRaises(TraitError, setattr, f, 'this', 10)
-
- def test_this_inst(self):
- class Foo(HasTraits):
- this = This()
-
- f = Foo()
- f.this = Foo()
- self.assertTrue(isinstance(f.this, Foo))
-
- def test_subclass(self):
- class Foo(HasTraits):
- t = This()
- class Bar(Foo):
- pass
- f = Foo()
- b = Bar()
- f.t = b
- b.t = f
- self.assertEqual(f.t, b)
- self.assertEqual(b.t, f)
-
- def test_subclass_override(self):
- class Foo(HasTraits):
- t = This()
- class Bar(Foo):
- t = This()
- f = Foo()
- b = Bar()
- f.t = b
- self.assertEqual(f.t, b)
- self.assertRaises(TraitError, setattr, b, 't', f)
-
- def test_this_in_container(self):
-
- class Tree(HasTraits):
- value = Unicode()
- leaves = List(This())
-
- tree = Tree(
- value='foo',
- leaves=[Tree(value='bar'), Tree(value='buzz')]
- )
-
- with self.assertRaises(TraitError):
- tree.leaves = [1, 2]
-
-class TraitTestBase(TestCase):
- """A best testing class for basic trait types."""
-
- def assign(self, value):
- self.obj.value = value
-
- def coerce(self, value):
- return value
-
- def test_good_values(self):
- if hasattr(self, '_good_values'):
- for value in self._good_values:
- self.assign(value)
- self.assertEqual(self.obj.value, self.coerce(value))
-
- def test_bad_values(self):
- if hasattr(self, '_bad_values'):
- for value in self._bad_values:
- try:
- self.assertRaises(TraitError, self.assign, value)
- except AssertionError:
- assert False, value
-
- def test_default_value(self):
- if hasattr(self, '_default_value'):
- self.assertEqual(self._default_value, self.obj.value)
-
- def test_allow_none(self):
- if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
- None in self._bad_values):
- trait=self.obj.traits()['value']
- try:
- trait.allow_none = True
- self._bad_values.remove(None)
- #skip coerce. Allow None casts None to None.
- self.assign(None)
- self.assertEqual(self.obj.value,None)
- self.test_good_values()
- self.test_bad_values()
- finally:
- #tear down
- trait.allow_none = False
- self._bad_values.append(None)
-
- def tearDown(self):
- # restore default value after tests, if set
- if hasattr(self, '_default_value'):
- self.obj.value = self._default_value
-
-
-class AnyTrait(HasTraits):
-
- value = Any()
-
-class AnyTraitTest(TraitTestBase):
-
- obj = AnyTrait()
-
- _default_value = None
- _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
- _bad_values = []
-
-class UnionTrait(HasTraits):
-
- value = Union([Type(), Bool()])
-
-class UnionTraitTest(TraitTestBase):
-
- obj = UnionTrait(value='ipython_genutils.ipstruct.Struct')
- _good_values = [int, float, True]
- _bad_values = [[], (0,), 1j]
-
-class OrTrait(HasTraits):
-
- value = Bool() | Unicode()
-
-class OrTraitTest(TraitTestBase):
-
- obj = OrTrait()
- _good_values = [True, False, 'ten']
- _bad_values = [[], (0,), 1j]
-
-class IntTrait(HasTraits):
-
- value = Int(99, min=-100)
-
-class TestInt(TraitTestBase):
-
- obj = IntTrait()
- _default_value = 99
- _good_values = [10, -10]
- _bad_values = ['ten', u'ten', [10], {'ten': 10}, (10,), None, 1j,
- 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
- u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', -200]
- if not six.PY3:
- _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
-
-
-class CIntTrait(HasTraits):
- value = CInt('5')
-
-class TestCInt(TraitTestBase):
- obj = CIntTrait()
-
- _default_value = 5
- _good_values = ['10', '-10', u'10', u'-10', 10, 10.0, -10.0, 10.1]
- _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
- None, 1j, '10.1', u'10.1']
-
- def coerce(self, n):
- return int(n)
-
-
-class MinBoundCIntTrait(HasTraits):
- value = CInt('5', min=3)
-
-class TestMinBoundCInt(TestCInt):
- obj = MinBoundCIntTrait()
-
- _default_value = 5
- _good_values = [3, 3.0, '3']
- _bad_values = [2.6, 2, -3, -3.0]
-
-
-class LongTrait(HasTraits):
-
- value = Long(99 if six.PY3 else long(99))
-
-class TestLong(TraitTestBase):
-
- obj = LongTrait()
-
- _default_value = 99 if six.PY3 else long(99)
- _good_values = [10, -10]
- _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
- None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
- '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
- u'-10.1']
- if not six.PY3:
- # maxint undefined on py3, because int == long
- _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
- _bad_values.extend([[long(10)], (long(10),)])
-
- @mark.skipif(six.PY3, reason="not relevant on py3")
- def test_cast_small(self):
- """Long casts ints to long"""
- self.obj.value = 10
- self.assertEqual(type(self.obj.value), long)
-
-
-class MinBoundLongTrait(HasTraits):
- value = Long(99 if six.PY3 else long(99), min=5)
-
-class TestMinBoundLong(TraitTestBase):
- obj = MinBoundLongTrait()
-
- _default_value = 99 if six.PY3 else long(99)
- _good_values = [5, 10]
- _bad_values = [4, -10]
-
-
-class MaxBoundLongTrait(HasTraits):
- value = Long(5 if six.PY3 else long(5), max=10)
-
-class TestMaxBoundLong(TraitTestBase):
- obj = MaxBoundLongTrait()
-
- _default_value = 5 if six.PY3 else long(5)
- _good_values = [10, -2]
- _bad_values = [11, 20]
-
-
-class CLongTrait(HasTraits):
- value = CLong('5')
-
-class TestCLong(TraitTestBase):
- obj = CLongTrait()
-
- _default_value = 5 if six.PY3 else long(5)
- _good_values = ['10', '-10', u'10', u'-10', 10, 10.0, -10.0, 10.1]
- _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
- None, 1j, '10.1', u'10.1']
-
- def coerce(self, n):
- return int(n) if six.PY3 else long(n)
-
-
-class MaxBoundCLongTrait(HasTraits):
- value = CLong('5', max=10)
-
-class TestMaxBoundCLong(TestCLong):
- obj = MaxBoundCLongTrait()
-
- _default_value = 5 if six.PY3 else long(5)
- _good_values = [10, '10', 10.3]
- _bad_values = [11.0, '11']
-
-
-class IntegerTrait(HasTraits):
- value = Integer(1)
-
-class TestInteger(TestLong):
- obj = IntegerTrait()
- _default_value = 1
-
- def coerce(self, n):
- return int(n)
-
- @mark.skipif(six.PY3, reason="not relevant on py3")
- def test_cast_small(self):
- """Integer casts small longs to int"""
-
- self.obj.value = long(100)
- self.assertEqual(type(self.obj.value), int)
-
-
-class MinBoundIntegerTrait(HasTraits):
- value = Integer(5, min=3)
-
-class TestMinBoundInteger(TraitTestBase):
- obj = MinBoundIntegerTrait()
-
- _default_value = 5
- _good_values = 3, 20
- _bad_values = [2, -10]
-
-
-class MaxBoundIntegerTrait(HasTraits):
- value = Integer(1, max=3)
-
-class TestMaxBoundInteger(TraitTestBase):
- obj = MaxBoundIntegerTrait()
-
- _default_value = 1
- _good_values = 3, -2
- _bad_values = [4, 10]
-
-
-class FloatTrait(HasTraits):
-
- value = Float(99.0, max=200.0)
-
-class TestFloat(TraitTestBase):
-
- obj = FloatTrait()
-
- _default_value = 99.0
- _good_values = [10, -10, 10.1, -10.1]
- _bad_values = ['ten', u'ten', [10], {'ten': 10}, (10,), None,
- 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
- u'-10', u'10L', u'-10L', u'10.1', u'-10.1', 201.0]
- if not six.PY3:
- _bad_values.extend([long(10), long(-10)])
-
-
-class CFloatTrait(HasTraits):
-
- value = CFloat('99.0', max=200.0)
-
-class TestCFloat(TraitTestBase):
-
- obj = CFloatTrait()
-
- _default_value = 99.0
- _good_values = [10, 10.0, 10.5, '10.0', '10', '-10', '10.0', u'10']
- _bad_values = ['ten', u'ten', [10], {'ten': 10}, (10,), None, 1j,
- 200.1, '200.1']
-
- def coerce(self, v):
- return float(v)
-
-
-class ComplexTrait(HasTraits):
-
- value = Complex(99.0-99.0j)
-
-class TestComplex(TraitTestBase):
-
- obj = ComplexTrait()
-
- _default_value = 99.0-99.0j
- _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
- 10.1j, 10.1+10.1j, 10.1-10.1j]
- _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
- if not six.PY3:
- _bad_values.extend([long(10), long(-10)])
-
-
-class BytesTrait(HasTraits):
-
- value = Bytes(b'string')
-
-class TestBytes(TraitTestBase):
-
- obj = BytesTrait()
-
- _default_value = b'string'
- _good_values = [b'10', b'-10', b'10L',
- b'-10L', b'10.1', b'-10.1', b'string']
- _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
- ['ten'],{'ten': 10},(10,), None, u'string']
- if not six.PY3:
- _bad_values.extend([long(10), long(-10)])
-
-
-class UnicodeTrait(HasTraits):
-
- value = Unicode(u'unicode')
-
-class TestUnicode(TraitTestBase):
-
- obj = UnicodeTrait()
-
- _default_value = u'unicode'
- _good_values = ['10', '-10', '10L', '-10L', '10.1',
- '-10.1', '', u'', 'string', u'string', u"€"]
- _bad_values = [10, -10, 10.1, -10.1, 1j,
- [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
- if not six.PY3:
- _bad_values.extend([long(10), long(-10)])
-
-
-class ObjectNameTrait(HasTraits):
- value = ObjectName("abc")
-
-class TestObjectName(TraitTestBase):
- obj = ObjectNameTrait()
-
- _default_value = "abc"
- _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
- _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
- None, object(), object]
- if sys.version_info[0] < 3:
- _bad_values.append(u"þ")
- else:
- _good_values.append(u"þ") # þ=1 is valid in Python 3 (PEP 3131).
-
-
-class DottedObjectNameTrait(HasTraits):
- value = DottedObjectName("a.b")
-
-class TestDottedObjectName(TraitTestBase):
- obj = DottedObjectNameTrait()
-
- _default_value = "a.b"
- _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
- _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
- if sys.version_info[0] < 3:
- _bad_values.append(u"t.þ")
- else:
- _good_values.append(u"t.þ")
-
-
-class TCPAddressTrait(HasTraits):
- value = TCPAddress()
-
-class TestTCPAddress(TraitTestBase):
-
- obj = TCPAddressTrait()
-
- _default_value = ('127.0.0.1',0)
- _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
- _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
-
-class ListTrait(HasTraits):
-
- value = List(Int())
-
-class TestList(TraitTestBase):
-
- obj = ListTrait()
-
- _default_value = []
- _good_values = [[], [1], list(range(10)), (1,2)]
- _bad_values = [10, [1,'a'], 'a']
-
- def coerce(self, value):
- if value is not None:
- value = list(value)
- return value
-
-class Foo(object):
- pass
-
-class NoneInstanceListTrait(HasTraits):
-
- value = List(Instance(Foo))
-
-class TestNoneInstanceList(TraitTestBase):
-
- obj = NoneInstanceListTrait()
-
- _default_value = []
- _good_values = [[Foo(), Foo()], []]
- _bad_values = [[None], [Foo(), None]]
-
-
-class InstanceListTrait(HasTraits):
-
- value = List(Instance(__name__+'.Foo'))
-
-class TestInstanceList(TraitTestBase):
-
- obj = InstanceListTrait()
-
- def test_klass(self):
- """Test that the instance klass is properly assigned."""
- self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
-
- _default_value = []
- _good_values = [[Foo(), Foo()], []]
- _bad_values = [['1', 2,], '1', [Foo], None]
-
-class UnionListTrait(HasTraits):
-
- value = List(Int() | Bool())
-
-class TestUnionListTrait(HasTraits):
-
- obj = UnionListTrait()
-
- _default_value = []
- _good_values = [[True, 1], [False, True]]
- _bad_values = [[1, 'True'], False]
-
-
-class LenListTrait(HasTraits):
-
- value = List(Int(), [0], minlen=1, maxlen=2)
-
-class TestLenList(TraitTestBase):
-
- obj = LenListTrait()
-
- _default_value = [0]
- _good_values = [[1], [1,2], (1,2)]
- _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
-
- def coerce(self, value):
- if value is not None:
- value = list(value)
- return value
-
-class TupleTrait(HasTraits):
-
- value = Tuple(Int(allow_none=True), default_value=(1,))
-
-class TestTupleTrait(TraitTestBase):
-
- obj = TupleTrait()
-
- _default_value = (1,)
- _good_values = [(1,), (0,), [1]]
- _bad_values = [10, (1, 2), ('a'), (), None]
-
- def coerce(self, value):
- if value is not None:
- value = tuple(value)
- return value
-
- def test_invalid_args(self):
- self.assertRaises(TypeError, Tuple, 5)
- self.assertRaises(TypeError, Tuple, default_value='hello')
- t = Tuple(Int(), CBytes(), default_value=(1,5))
-
-class LooseTupleTrait(HasTraits):
-
- value = Tuple((1,2,3))
-
-class TestLooseTupleTrait(TraitTestBase):
-
- obj = LooseTupleTrait()
-
- _default_value = (1,2,3)
- _good_values = [(1,), [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
- _bad_values = [10, 'hello', {}, None]
-
- def coerce(self, value):
- if value is not None:
- value = tuple(value)
- return value
-
- def test_invalid_args(self):
- self.assertRaises(TypeError, Tuple, 5)
- self.assertRaises(TypeError, Tuple, default_value='hello')
- t = Tuple(Int(), CBytes(), default_value=(1,5))
-
-
-class MultiTupleTrait(HasTraits):
-
- value = Tuple(Int(), Bytes(), default_value=[99,b'bottles'])
-
-class TestMultiTuple(TraitTestBase):
-
- obj = MultiTupleTrait()
-
- _default_value = (99,b'bottles')
- _good_values = [(1,b'a'), (2,b'b')]
- _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
-
-class CRegExpTrait(HasTraits):
-
- value = CRegExp(r'')
-
-class TestCRegExp(TraitTestBase):
-
- def coerce(self, value):
- return re.compile(value)
-
- obj = CRegExpTrait()
-
- _default_value = re.compile(r'')
- _good_values = [r'\d+', re.compile(r'\d+')]
- _bad_values = ['(', None, ()]
-
-class DictTrait(HasTraits):
- value = Dict()
-
-def test_dict_assignment():
- d = dict()
- c = DictTrait()
- c.value = d
- d['a'] = 5
- assert d == c.value
- assert c.value is d
-
-
-class UniformlyValidatedDictTrait(HasTraits):
-
- value = Dict(trait=Unicode(),
- default_value={'foo': '1'})
-
-
-class TestInstanceUniformlyValidatedDict(TraitTestBase):
-
- obj = UniformlyValidatedDictTrait()
-
- _default_value = {'foo': '1'}
- _good_values = [{'foo': '0', 'bar': '1'}]
- _bad_values = [{'foo': 0, 'bar': '1'}]
-
-
-class KeyValidatedDictTrait(HasTraits):
-
- value = Dict(traits={'foo': Int()},
- default_value={'foo': 1})
-
-
-class TestInstanceKeyValidatedDict(TraitTestBase):
-
- obj = KeyValidatedDictTrait()
-
- _default_value = {'foo': 1}
- _good_values = [{'foo': 0, 'bar': '1'}, {'foo': 0, 'bar': 1}]
- _bad_values = [{'foo': '0', 'bar': '1'}]
-
-
-class FullyValidatedDictTrait(HasTraits):
-
- value = Dict(trait=Unicode(),
- traits={'foo': Int()},
- default_value={'foo': 1})
-
-
-class TestInstanceFullyValidatedDict(TraitTestBase):
-
- obj = FullyValidatedDictTrait()
-
- _default_value = {'foo': 1}
- _good_values = [{'foo': 0, 'bar': '1'}, {'foo': 1, 'bar': '2'}]
- _bad_values = [{'foo': 0, 'bar': 1}, {'foo': '0', 'bar': '1'}]
-
-
-def test_dict_default_value():
- """Check that the `{}` default value of the Dict traitlet constructor is
- actually copied."""
-
- class Foo(HasTraits):
- d1 = Dict()
- d2 = Dict()
-
- foo = Foo()
- assert foo.d1 == {}
- assert foo.d2 == {}
- assert foo.d1 is not foo.d2
-
-
-class TestValidationHook(TestCase):
-
- def test_parity_trait(self):
- """Verify that the early validation hook is effective"""
-
- class Parity(HasTraits):
-
- value = Int(0)
- parity = Enum(['odd', 'even'], default_value='even')
-
- @validate('value')
- def _value_validate(self, proposal):
- value = proposal['value']
- if self.parity == 'even' and value % 2:
- raise TraitError('Expected an even number')
- if self.parity == 'odd' and (value % 2 == 0):
- raise TraitError('Expected an odd number')
- return value
-
- u = Parity()
- u.parity = 'odd'
- u.value = 1 # OK
- with self.assertRaises(TraitError):
- u.value = 2 # Trait Error
-
- u.parity = 'even'
- u.value = 2 # OK
-
- def test_multiple_validate(self):
- """Verify that we can register the same validator to multiple names"""
-
- class OddEven(HasTraits):
-
- odd = Int(1)
- even = Int(0)
-
- @validate('odd', 'even')
- def check_valid(self, proposal):
- if proposal['trait'].name == 'odd' and not proposal['value'] % 2:
- raise TraitError('odd should be odd')
- if proposal['trait'].name == 'even' and proposal['value'] % 2:
- raise TraitError('even should be even')
-
- u = OddEven()
- u.odd = 3 # OK
- with self.assertRaises(TraitError):
- u.odd = 2 # Trait Error
-
- u.even = 2 # OK
- with self.assertRaises(TraitError):
- u.even = 3 # Trait Error
-
-
-
-class TestLink(TestCase):
-
- def test_connect_same(self):
- """Verify two traitlets of the same type can be linked together using link."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- a = A(value=9)
- b = A(value=8)
-
- # Conenct the two classes.
- c = link((a, 'value'), (b, 'value'))
-
- # Make sure the values are the same at the point of linking.
- self.assertEqual(a.value, b.value)
-
- # Change one of the values to make sure they stay in sync.
- a.value = 5
- self.assertEqual(a.value, b.value)
- b.value = 6
- self.assertEqual(a.value, b.value)
-
- def test_link_different(self):
- """Verify two traitlets of different types can be linked together using link."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- class B(HasTraits):
- count = Int()
- a = A(value=9)
- b = B(count=8)
-
- # Conenct the two classes.
- c = link((a, 'value'), (b, 'count'))
-
- # Make sure the values are the same at the point of linking.
- self.assertEqual(a.value, b.count)
-
- # Change one of the values to make sure they stay in sync.
- a.value = 5
- self.assertEqual(a.value, b.count)
- b.count = 4
- self.assertEqual(a.value, b.count)
-
- def test_unlink(self):
- """Verify two linked traitlets can be unlinked."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- a = A(value=9)
- b = A(value=8)
-
- # Connect the two classes.
- c = link((a, 'value'), (b, 'value'))
- a.value = 4
- c.unlink()
-
- # Change one of the values to make sure they don't stay in sync.
- a.value = 5
- self.assertNotEqual(a.value, b.value)
-
- def test_callbacks(self):
- """Verify two linked traitlets have their callbacks called once."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- class B(HasTraits):
- count = Int()
- a = A(value=9)
- b = B(count=8)
-
- # Register callbacks that count.
- callback_count = []
- def a_callback(name, old, new):
- callback_count.append('a')
- a.on_trait_change(a_callback, 'value')
- def b_callback(name, old, new):
- callback_count.append('b')
- b.on_trait_change(b_callback, 'count')
-
- # Connect the two classes.
- c = link((a, 'value'), (b, 'count'))
-
- # Make sure b's count was set to a's value once.
- self.assertEqual(''.join(callback_count), 'b')
- del callback_count[:]
-
- # Make sure a's value was set to b's count once.
- b.count = 5
- self.assertEqual(''.join(callback_count), 'ba')
- del callback_count[:]
-
- # Make sure b's count was set to a's value once.
- a.value = 4
- self.assertEqual(''.join(callback_count), 'ab')
- del callback_count[:]
-
-class TestDirectionalLink(TestCase):
- def test_connect_same(self):
- """Verify two traitlets of the same type can be linked together using directional_link."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- a = A(value=9)
- b = A(value=8)
-
- # Conenct the two classes.
- c = directional_link((a, 'value'), (b, 'value'))
-
- # Make sure the values are the same at the point of linking.
- self.assertEqual(a.value, b.value)
-
- # Change one the value of the source and check that it synchronizes the target.
- a.value = 5
- self.assertEqual(b.value, 5)
- # Change one the value of the target and check that it has no impact on the source
- b.value = 6
- self.assertEqual(a.value, 5)
-
- def test_tranform(self):
- """Test transform link."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- a = A(value=9)
- b = A(value=8)
-
- # Conenct the two classes.
- c = directional_link((a, 'value'), (b, 'value'), lambda x: 2 * x)
-
- # Make sure the values are correct at the point of linking.
- self.assertEqual(b.value, 2 * a.value)
-
- # Change one the value of the source and check that it modifies the target.
- a.value = 5
- self.assertEqual(b.value, 10)
- # Change one the value of the target and check that it has no impact on the source
- b.value = 6
- self.assertEqual(a.value, 5)
-
- def test_link_different(self):
- """Verify two traitlets of different types can be linked together using link."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- class B(HasTraits):
- count = Int()
- a = A(value=9)
- b = B(count=8)
-
- # Conenct the two classes.
- c = directional_link((a, 'value'), (b, 'count'))
-
- # Make sure the values are the same at the point of linking.
- self.assertEqual(a.value, b.count)
-
- # Change one the value of the source and check that it synchronizes the target.
- a.value = 5
- self.assertEqual(b.count, 5)
- # Change one the value of the target and check that it has no impact on the source
- b.value = 6
- self.assertEqual(a.value, 5)
-
- def test_unlink(self):
- """Verify two linked traitlets can be unlinked."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- a = A(value=9)
- b = A(value=8)
-
- # Connect the two classes.
- c = directional_link((a, 'value'), (b, 'value'))
- a.value = 4
- c.unlink()
-
- # Change one of the values to make sure they don't stay in sync.
- a.value = 5
- self.assertNotEqual(a.value, b.value)
-
-class Pickleable(HasTraits):
-
- i = Int()
- @observe('i')
- def _i_changed(self, change): pass
- @validate('i')
- def _i_validate(self, commit):
- return commit['value']
-
- j = Int()
-
- def __init__(self):
- with self.hold_trait_notifications():
- self.i = 1
- self.on_trait_change(self._i_changed, 'i')
-
-def test_pickle_hastraits():
- c = Pickleable()
- for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
- p = pickle.dumps(c, protocol)
- c2 = pickle.loads(p)
- assert c2.i == c.i
- assert c2.j == c.j
-
- c.i = 5
- for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
- p = pickle.dumps(c, protocol)
- c2 = pickle.loads(p)
- assert c2.i == c.i
- assert c2.j == c.j
-
-
-def test_hold_trait_notifications():
- changes = []
-
- class Test(HasTraits):
- a = Integer(0)
- b = Integer(0)
-
- def _a_changed(self, name, old, new):
- changes.append((old, new))
-
- def _b_validate(self, value, trait):
- if value != 0:
- raise TraitError('Only 0 is a valid value')
- return value
-
- # Test context manager and nesting
- t = Test()
- with t.hold_trait_notifications():
- with t.hold_trait_notifications():
- t.a = 1
- assert t.a == 1
- assert changes == []
- t.a = 2
- assert t.a == 2
- with t.hold_trait_notifications():
- t.a = 3
- assert t.a == 3
- assert changes == []
- t.a = 4
- assert t.a == 4
- assert changes == []
- t.a = 4
- assert t.a == 4
- assert changes == []
-
- assert changes == [(0, 4)]
- # Test roll-back
- try:
- with t.hold_trait_notifications():
- t.b = 1 # raises a Trait error
- except:
- pass
- assert t.b == 0
-
-
-class RollBack(HasTraits):
- bar = Int()
- def _bar_validate(self, value, trait):
- if value:
- raise TraitError('foobar')
- return value
-
-
-class TestRollback(TestCase):
-
- def test_roll_back(self):
-
- def assign_rollback():
- RollBack(bar=1)
-
- self.assertRaises(TraitError, assign_rollback)
-
-
-class CacheModification(HasTraits):
- foo = Int()
- bar = Int()
-
- def _bar_validate(self, value, trait):
- self.foo = value
- return value
-
- def _foo_validate(self, value, trait):
- self.bar = value
- return value
-
-
-def test_cache_modification():
- CacheModification(foo=1)
- CacheModification(bar=1)
-
-
-class OrderTraits(HasTraits):
- notified = Dict()
-
- a = Unicode()
- b = Unicode()
- c = Unicode()
- d = Unicode()
- e = Unicode()
- f = Unicode()
- g = Unicode()
- h = Unicode()
- i = Unicode()
- j = Unicode()
- k = Unicode()
- l = Unicode()
-
- def _notify(self, name, old, new):
- """check the value of all traits when each trait change is triggered
-
- This verifies that the values are not sensitive
- to dict ordering when loaded from kwargs
- """
- # check the value of the other traits
- # when a given trait change notification fires
- self.notified[name] = {
- c: getattr(self, c) for c in 'abcdefghijkl'
- }
-
- def __init__(self, **kwargs):
- self.on_trait_change(self._notify)
- super(OrderTraits, self).__init__(**kwargs)
-
-def test_notification_order():
- d = {c:c for c in 'abcdefghijkl'}
- obj = OrderTraits()
- assert obj.notified == {}
- obj = OrderTraits(**d)
- notifications = {
- c: d for c in 'abcdefghijkl'
- }
- assert obj.notified == notifications
-
-
-
-###
-# Traits for Forward Declaration Tests
-###
-class ForwardDeclaredInstanceTrait(HasTraits):
-
- value = ForwardDeclaredInstance('ForwardDeclaredBar', allow_none=True)
-
-class ForwardDeclaredTypeTrait(HasTraits):
-
- value = ForwardDeclaredType('ForwardDeclaredBar', allow_none=True)
-
-class ForwardDeclaredInstanceListTrait(HasTraits):
-
- value = List(ForwardDeclaredInstance('ForwardDeclaredBar'))
-
-class ForwardDeclaredTypeListTrait(HasTraits):
-
- value = List(ForwardDeclaredType('ForwardDeclaredBar'))
-###
-# End Traits for Forward Declaration Tests
-###
-
-###
-# Classes for Forward Declaration Tests
-###
-class ForwardDeclaredBar(object):
- pass
-
-class ForwardDeclaredBarSub(ForwardDeclaredBar):
- pass
-###
-# End Classes for Forward Declaration Tests
-###
-
-###
-# Forward Declaration Tests
-###
-class TestForwardDeclaredInstanceTrait(TraitTestBase):
-
- obj = ForwardDeclaredInstanceTrait()
- _default_value = None
- _good_values = [None, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
- _bad_values = ['foo', 3, ForwardDeclaredBar, ForwardDeclaredBarSub]
-
-class TestForwardDeclaredTypeTrait(TraitTestBase):
-
- obj = ForwardDeclaredTypeTrait()
- _default_value = None
- _good_values = [None, ForwardDeclaredBar, ForwardDeclaredBarSub]
- _bad_values = ['foo', 3, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
-
-class TestForwardDeclaredInstanceList(TraitTestBase):
-
- obj = ForwardDeclaredInstanceListTrait()
-
- def test_klass(self):
- """Test that the instance klass is properly assigned."""
- self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
-
- _default_value = []
- _good_values = [
- [ForwardDeclaredBar(), ForwardDeclaredBarSub()],
- [],
- ]
- _bad_values = [
- ForwardDeclaredBar(),
- [ForwardDeclaredBar(), 3, None],
- '1',
- # Note that this is the type, not an instance.
- [ForwardDeclaredBar],
- [None],
- None,
- ]
-
-class TestForwardDeclaredTypeList(TraitTestBase):
-
- obj = ForwardDeclaredTypeListTrait()
-
- def test_klass(self):
- """Test that the instance klass is properly assigned."""
- self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
-
- _default_value = []
- _good_values = [
- [ForwardDeclaredBar, ForwardDeclaredBarSub],
- [],
- ]
- _bad_values = [
- ForwardDeclaredBar,
- [ForwardDeclaredBar, 3],
- '1',
- # Note that this is an instance, not the type.
- [ForwardDeclaredBar()],
- [None],
- None,
- ]
-###
-# End Forward Declaration Tests
-###
-
-class TestDynamicTraits(TestCase):
-
- def setUp(self):
- self._notify1 = []
-
- def notify1(self, name, old, new):
- self._notify1.append((name, old, new))
-
- def test_notify_all(self):
-
- class A(HasTraits):
- pass
-
- a = A()
- self.assertTrue(not hasattr(a, 'x'))
- self.assertTrue(not hasattr(a, 'y'))
-
- # Dynamically add trait x.
- a.add_traits(x=Int())
- self.assertTrue(hasattr(a, 'x'))
- self.assertTrue(isinstance(a, (A, )))
-
- # Dynamically add trait y.
- a.add_traits(y=Float())
- self.assertTrue(hasattr(a, 'y'))
- self.assertTrue(isinstance(a, (A, )))
- self.assertEqual(a.__class__.__name__, A.__name__)
-
- # Create a new instance and verify that x and y
- # aren't defined.
- b = A()
- self.assertTrue(not hasattr(b, 'x'))
- self.assertTrue(not hasattr(b, 'y'))
-
- # Verify that notification works like normal.
- a.on_trait_change(self.notify1)
- a.x = 0
- self.assertEqual(len(self._notify1), 0)
- a.y = 0.0
- self.assertEqual(len(self._notify1), 0)
- a.x = 10
- self.assertTrue(('x', 0, 10) in self._notify1)
- a.y = 10.0
- self.assertTrue(('y', 0.0, 10.0) in self._notify1)
- self.assertRaises(TraitError, setattr, a, 'x', 'bad string')
- self.assertRaises(TraitError, setattr, a, 'y', 'bad string')
- self._notify1 = []
- a.on_trait_change(self.notify1, remove=True)
- a.x = 20
- a.y = 20.0
- self.assertEqual(len(self._notify1), 0)
-
-
-def test_enum_no_default():
- class C(HasTraits):
- t = Enum(['a', 'b'])
-
- c = C()
- c.t = 'a'
- assert c.t == 'a'
-
- c = C()
-
- with pytest.raises(TraitError):
- t = c.t
-
- c = C(t='b')
- assert c.t == 'b'
-
-
-def test_default_value_repr():
- class C(HasTraits):
- t = Type('traitlets.HasTraits')
- t2 = Type(HasTraits)
- n = Integer(0)
- lis = List()
- d = Dict()
-
- assert C.t.default_value_repr() == "'traitlets.HasTraits'"
- assert C.t2.default_value_repr() == "'traitlets.traitlets.HasTraits'"
- assert C.n.default_value_repr() == '0'
- assert C.lis.default_value_repr() == '[]'
- assert C.d.default_value_repr() == '{}'
-
-
-class TransitionalClass(HasTraits):
-
- d = Any()
- @default('d')
- def _d_default(self):
- return TransitionalClass
-
- parent_super = False
- calls_super = Integer(0)
-
- @default('calls_super')
- def _calls_super_default(self):
- return -1
-
- @observe('calls_super')
- @observe_compat
- def _calls_super_changed(self, change):
- self.parent_super = change
-
- parent_override = False
- overrides = Integer(0)
-
- @observe('overrides')
- @observe_compat
- def _overrides_changed(self, change):
- self.parent_override = change
-
-
-class SubClass(TransitionalClass):
- def _d_default(self):
- return SubClass
-
- subclass_super = False
- def _calls_super_changed(self, name, old, new):
- self.subclass_super = True
- super(SubClass, self)._calls_super_changed(name, old, new)
-
- subclass_override = False
- def _overrides_changed(self, name, old, new):
- self.subclass_override = True
-
-
-def test_subclass_compat():
- obj = SubClass()
- obj.calls_super = 5
- assert obj.parent_super
- assert obj.subclass_super
- obj.overrides = 5
- assert obj.subclass_override
- assert not obj.parent_override
- assert obj.d is SubClass
-
-
-class DefinesHandler(HasTraits):
- parent_called = False
-
- trait = Integer()
- @observe('trait')
- def handler(self, change):
- self.parent_called = True
-
-
-class OverridesHandler(DefinesHandler):
- child_called = False
-
- @observe('trait')
- def handler(self, change):
- self.child_called = True
-
-
-def test_subclass_override_observer():
- obj = OverridesHandler()
- obj.trait = 5
- assert obj.child_called
- assert not obj.parent_called
-
-
-class DoesntRegisterHandler(DefinesHandler):
- child_called = False
-
- def handler(self, change):
- self.child_called = True
-
-
-def test_subclass_override_not_registered():
- """Subclass that overrides observer and doesn't re-register unregisters both"""
- obj = DoesntRegisterHandler()
- obj.trait = 5
- assert not obj.child_called
- assert not obj.parent_called
-
-
-class AddsHandler(DefinesHandler):
- child_called = False
-
- @observe('trait')
- def child_handler(self, change):
- self.child_called = True
-
-def test_subclass_add_observer():
- obj = AddsHandler()
- obj.trait = 5
- assert obj.child_called
- assert obj.parent_called
-
-
-def test_observe_iterables():
-
- class C(HasTraits):
- i = Integer()
- s = Unicode()
-
- c = C()
- recorded = {}
- def record(change):
- recorded['change'] = change
-
- # observe with names=set
- c.observe(record, names={'i', 's'})
- c.i = 5
- assert recorded['change'].name == 'i'
- assert recorded['change'].new == 5
- c.s = 'hi'
- assert recorded['change'].name == 's'
- assert recorded['change'].new == 'hi'
-
- # observe with names=custom container with iter, contains
- class MyContainer(object):
- def __init__(self, container):
- self.container = container
-
- def __iter__(self):
- return iter(self.container)
-
- def __contains__(self, key):
- return key in self.container
-
- c.observe(record, names=MyContainer({'i', 's'}))
- c.i = 10
- assert recorded['change'].name == 'i'
- assert recorded['change'].new == 10
- c.s = 'ok'
- assert recorded['change'].name == 's'
- assert recorded['change'].new == 'ok'
-
-
-def test_super_args():
- class SuperRecorder(object):
- def __init__(self, *args, **kwargs):
- self.super_args = args
- self.super_kwargs = kwargs
-
- class SuperHasTraits(HasTraits, SuperRecorder):
- i = Integer()
-
- obj = SuperHasTraits('a1', 'a2', b=10, i=5, c='x')
- assert obj.i == 5
- assert not hasattr(obj, 'b')
- assert not hasattr(obj, 'c')
- assert obj.super_args == ('a1' , 'a2')
- assert obj.super_kwargs == {'b': 10 , 'c': 'x'}
-
-def test_super_bad_args():
- class SuperHasTraits(HasTraits):
- a = Integer()
-
- if sys.version_info < (3,):
- # Legacy Python, object.__init__ warns itself, instead of raising
- w = ['object.__init__']
- else:
- w = ["Passing unrecoginized arguments"]
- with expected_warnings(w):
- obj = SuperHasTraits(a=1, b=2)
- assert obj.a == 1
- assert not hasattr(obj, 'b')
+
+from unittest import TestCase
+import pytest
+from pytest import mark
+
+from traitlets import (
+ HasTraits, MetaHasTraits, TraitType, Any, Bool, CBytes, Dict, Enum,
+ Int, CInt, Long, CLong, Integer, Float, CFloat, Complex, Bytes, Unicode,
+ TraitError, Union, All, Undefined, Type, This, Instance, TCPAddress,
+ List, Tuple, ObjectName, DottedObjectName, CRegExp, link, directional_link,
+ ForwardDeclaredType, ForwardDeclaredInstance, validate, observe, default,
+ observe_compat, BaseDescriptor, HasDescriptors,
+)
+
+import six
+
+def change_dict(*ordered_values):
+ change_names = ('name', 'old', 'new', 'owner', 'type')
+ return dict(zip(change_names, ordered_values))
+
+#-----------------------------------------------------------------------------
+# Helper classes for testing
+#-----------------------------------------------------------------------------
+
+
+class HasTraitsStub(HasTraits):
+
+ def notify_change(self, change):
+ self._notify_name = change['name']
+ self._notify_old = change['old']
+ self._notify_new = change['new']
+ self._notify_type = change['type']
+
+
+#-----------------------------------------------------------------------------
+# Test classes
+#-----------------------------------------------------------------------------
+
+
+class TestTraitType(TestCase):
+
+ def test_get_undefined(self):
+ class A(HasTraits):
+ a = TraitType
+ a = A()
+ with self.assertRaises(TraitError):
+ a.a
+
+ def test_set(self):
+ class A(HasTraitsStub):
+ a = TraitType
+
+ a = A()
+ a.a = 10
+ self.assertEqual(a.a, 10)
+ self.assertEqual(a._notify_name, 'a')
+ self.assertEqual(a._notify_old, Undefined)
+ self.assertEqual(a._notify_new, 10)
+
+ def test_validate(self):
+ class MyTT(TraitType):
+ def validate(self, inst, value):
+ return -1
+ class A(HasTraitsStub):
+ tt = MyTT
+
+ a = A()
+ a.tt = 10
+ self.assertEqual(a.tt, -1)
+
+ def test_default_validate(self):
+ class MyIntTT(TraitType):
+ def validate(self, obj, value):
+ if isinstance(value, int):
+ return value
+ self.error(obj, value)
+ class A(HasTraits):
+ tt = MyIntTT(10)
+ a = A()
+ self.assertEqual(a.tt, 10)
+
+ # Defaults are validated when the HasTraits is instantiated
+ class B(HasTraits):
+ tt = MyIntTT('bad default')
+ self.assertRaises(TraitError, B)
+
+ def test_info(self):
+ class A(HasTraits):
+ tt = TraitType
+ a = A()
+ self.assertEqual(A.tt.info(), 'any value')
+
+ def test_error(self):
+ class A(HasTraits):
+ tt = TraitType
+ a = A()
+ self.assertRaises(TraitError, A.tt.error, a, 10)
+
+ def test_deprecated_dynamic_initializer(self):
+ class A(HasTraits):
+ x = Int(10)
+ def _x_default(self):
+ return 11
+ class B(A):
+ x = Int(20)
+ class C(A):
+ def _x_default(self):
+ return 21
+
+ a = A()
+ self.assertEqual(a._trait_values, {})
+ self.assertEqual(a.x, 11)
+ self.assertEqual(a._trait_values, {'x': 11})
+ b = B()
+ self.assertEqual(b.x, 20)
+ self.assertEqual(b._trait_values, {'x': 20})
+ c = C()
+ self.assertEqual(c._trait_values, {})
+ self.assertEqual(c.x, 21)
+ self.assertEqual(c._trait_values, {'x': 21})
+ # Ensure that the base class remains unmolested when the _default
+ # initializer gets overridden in a subclass.
+ a = A()
+ c = C()
+ self.assertEqual(a._trait_values, {})
+ self.assertEqual(a.x, 11)
+ self.assertEqual(a._trait_values, {'x': 11})
+
+ def test_dynamic_initializer(self):
+
+ class A(HasTraits):
+ x = Int(10)
+
+ @default('x')
+ def _default_x(self):
+ return 11
+
+ class B(A):
+ x = Int(20)
+
+ class C(A):
+
+ @default('x')
+ def _default_x(self):
+ return 21
+
+ a = A()
+ self.assertEqual(a._trait_values, {})
+ self.assertEqual(a.x, 11)
+ self.assertEqual(a._trait_values, {'x': 11})
+ b = B()
+ self.assertEqual(b.x, 20)
+ self.assertEqual(b._trait_values, {'x': 20})
+ c = C()
+ self.assertEqual(c._trait_values, {})
+ self.assertEqual(c.x, 21)
+ self.assertEqual(c._trait_values, {'x': 21})
+ # Ensure that the base class remains unmolested when the _default
+ # initializer gets overridden in a subclass.
+ a = A()
+ c = C()
+ self.assertEqual(a._trait_values, {})
+ self.assertEqual(a.x, 11)
+ self.assertEqual(a._trait_values, {'x': 11})
+
+ def test_tag_metadata(self):
+ class MyIntTT(TraitType):
+ metadata = {'a': 1, 'b': 2}
+ a = MyIntTT(10).tag(b=3, c=4)
+ self.assertEqual(a.metadata, {'a': 1, 'b': 3, 'c': 4})
+
+ def test_metadata_localized_instance(self):
+ class MyIntTT(TraitType):
+ metadata = {'a': 1, 'b': 2}
+ a = MyIntTT(10)
+ b = MyIntTT(10)
+ a.metadata['c'] = 3
+ # make sure that changing a's metadata didn't change b's metadata
+ self.assertNotIn('c', b.metadata)
+
+ def test_union_metadata(self):
+ class Foo(HasTraits):
+ bar = (Int().tag(ta=1) | Dict().tag(ta=2, ti='b')).tag(ti='a')
+ foo = Foo()
+ # At this point, no value has been set for bar, so value-specific
+ # is not set.
+ self.assertEqual(foo.trait_metadata('bar', 'ta'), None)
+ self.assertEqual(foo.trait_metadata('bar', 'ti'), 'a')
+ foo.bar = {}
+ self.assertEqual(foo.trait_metadata('bar', 'ta'), 2)
+ self.assertEqual(foo.trait_metadata('bar', 'ti'), 'b')
+ foo.bar = 1
+ self.assertEqual(foo.trait_metadata('bar', 'ta'), 1)
+ self.assertEqual(foo.trait_metadata('bar', 'ti'), 'a')
+
+ def test_union_default_value(self):
+ class Foo(HasTraits):
+ bar = Union([Dict(), Int()], default_value=1)
+ foo = Foo()
+ self.assertEqual(foo.bar, 1)
+
+ def test_deprecated_metadata_access(self):
+ class MyIntTT(TraitType):
+ metadata = {'a': 1, 'b': 2}
+ a = MyIntTT(10)
+ with expected_warnings(["use the instance .metadata dictionary directly"]*2):
+ a.set_metadata('key', 'value')
+ v = a.get_metadata('key')
+ self.assertEqual(v, 'value')
+ with expected_warnings(["use the instance .help string directly"]*2):
+ a.set_metadata('help', 'some help')
+ v = a.get_metadata('help')
+ self.assertEqual(v, 'some help')
+
+ def test_trait_types_deprecated(self):
+ with expected_warnings(["Traits should be given as instances"]):
+ class C(HasTraits):
+ t = Int
+
+ def test_trait_types_list_deprecated(self):
+ with expected_warnings(["Traits should be given as instances"]):
+ class C(HasTraits):
+ t = List(Int)
+
+ def test_trait_types_tuple_deprecated(self):
+ with expected_warnings(["Traits should be given as instances"]):
+ class C(HasTraits):
+ t = Tuple(Int)
+
+ def test_trait_types_dict_deprecated(self):
+ with expected_warnings(["Traits should be given as instances"]):
+ class C(HasTraits):
+ t = Dict(Int)
+
+class TestHasDescriptorsMeta(TestCase):
+
+ def test_metaclass(self):
+ self.assertEqual(type(HasTraits), MetaHasTraits)
+
+ class A(HasTraits):
+ a = Int()
+
+ a = A()
+ self.assertEqual(type(a.__class__), MetaHasTraits)
+ self.assertEqual(a.a,0)
+ a.a = 10
+ self.assertEqual(a.a,10)
+
+ class B(HasTraits):
+ b = Int()
+
+ b = B()
+ self.assertEqual(b.b,0)
+ b.b = 10
+ self.assertEqual(b.b,10)
+
+ class C(HasTraits):
+ c = Int(30)
+
+ c = C()
+ self.assertEqual(c.c,30)
+ c.c = 10
+ self.assertEqual(c.c,10)
+
+ def test_this_class(self):
+ class A(HasTraits):
+ t = This()
+ tt = This()
+ class B(A):
+ tt = This()
+ ttt = This()
+ self.assertEqual(A.t.this_class, A)
+ self.assertEqual(B.t.this_class, A)
+ self.assertEqual(B.tt.this_class, B)
+ self.assertEqual(B.ttt.this_class, B)
+
+class TestHasDescriptors(TestCase):
+
+ def test_setup_instance(self):
+
+ class FooDescriptor(BaseDescriptor):
+
+ def instance_init(self, inst):
+ foo = inst.foo # instance should have the attr
+
+ class HasFooDescriptors(HasDescriptors):
+
+ fd = FooDescriptor()
+
+ def setup_instance(self, *args, **kwargs):
+ self.foo = kwargs.get('foo', None)
+ super(HasFooDescriptors, self).setup_instance(*args, **kwargs)
+
+ hfd = HasFooDescriptors(foo='bar')
+
+class TestHasTraitsNotify(TestCase):
+
+ def setUp(self):
+ self._notify1 = []
+ self._notify2 = []
+
+ def notify1(self, name, old, new):
+ self._notify1.append((name, old, new))
+
+ def notify2(self, name, old, new):
+ self._notify2.append((name, old, new))
+
+ def test_notify_all(self):
+
+ class A(HasTraits):
+ a = Int()
+ b = Float()
+
+ a = A()
+ a.on_trait_change(self.notify1)
+ a.a = 0
+ self.assertEqual(len(self._notify1),0)
+ a.b = 0.0
+ self.assertEqual(len(self._notify1),0)
+ a.a = 10
+ self.assertTrue(('a',0,10) in self._notify1)
+ a.b = 10.0
+ self.assertTrue(('b',0.0,10.0) in self._notify1)
+ self.assertRaises(TraitError,setattr,a,'a','bad string')
+ self.assertRaises(TraitError,setattr,a,'b','bad string')
+ self._notify1 = []
+ a.on_trait_change(self.notify1,remove=True)
+ a.a = 20
+ a.b = 20.0
+ self.assertEqual(len(self._notify1),0)
+
+ def test_notify_one(self):
+
+ class A(HasTraits):
+ a = Int()
+ b = Float()
+
+ a = A()
+ a.on_trait_change(self.notify1, 'a')
+ a.a = 0
+ self.assertEqual(len(self._notify1),0)
+ a.a = 10
+ self.assertTrue(('a',0,10) in self._notify1)
+ self.assertRaises(TraitError,setattr,a,'a','bad string')
+
+ def test_subclass(self):
+
+ class A(HasTraits):
+ a = Int()
+
+ class B(A):
+ b = Float()
+
+ b = B()
+ self.assertEqual(b.a,0)
+ self.assertEqual(b.b,0.0)
+ b.a = 100
+ b.b = 100.0
+ self.assertEqual(b.a,100)
+ self.assertEqual(b.b,100.0)
+
+ def test_notify_subclass(self):
+
+ class A(HasTraits):
+ a = Int()
+
+ class B(A):
+ b = Float()
+
+ b = B()
+ b.on_trait_change(self.notify1, 'a')
+ b.on_trait_change(self.notify2, 'b')
+ b.a = 0
+ b.b = 0.0
+ self.assertEqual(len(self._notify1),0)
+ self.assertEqual(len(self._notify2),0)
+ b.a = 10
+ b.b = 10.0
+ self.assertTrue(('a',0,10) in self._notify1)
+ self.assertTrue(('b',0.0,10.0) in self._notify2)
+
+ def test_static_notify(self):
+
+ class A(HasTraits):
+ a = Int()
+ _notify1 = []
+ def _a_changed(self, name, old, new):
+ self._notify1.append((name, old, new))
+
+ a = A()
+ a.a = 0
+ # This is broken!!!
+ self.assertEqual(len(a._notify1),0)
+ a.a = 10
+ self.assertTrue(('a',0,10) in a._notify1)
+
+ class B(A):
+ b = Float()
+ _notify2 = []
+ def _b_changed(self, name, old, new):
+ self._notify2.append((name, old, new))
+
+ b = B()
+ b.a = 10
+ b.b = 10.0
+ self.assertTrue(('a',0,10) in b._notify1)
+ self.assertTrue(('b',0.0,10.0) in b._notify2)
+
+ def test_notify_args(self):
+
+ def callback0():
+ self.cb = ()
+ def callback1(name):
+ self.cb = (name,)
+ def callback2(name, new):
+ self.cb = (name, new)
+ def callback3(name, old, new):
+ self.cb = (name, old, new)
+ def callback4(name, old, new, obj):
+ self.cb = (name, old, new, obj)
+
+ class A(HasTraits):
+ a = Int()
+
+ a = A()
+ a.on_trait_change(callback0, 'a')
+ a.a = 10
+ self.assertEqual(self.cb,())
+ a.on_trait_change(callback0, 'a', remove=True)
+
+ a.on_trait_change(callback1, 'a')
+ a.a = 100
+ self.assertEqual(self.cb,('a',))
+ a.on_trait_change(callback1, 'a', remove=True)
+
+ a.on_trait_change(callback2, 'a')
+ a.a = 1000
+ self.assertEqual(self.cb,('a',1000))
+ a.on_trait_change(callback2, 'a', remove=True)
+
+ a.on_trait_change(callback3, 'a')
+ a.a = 10000
+ self.assertEqual(self.cb,('a',1000,10000))
+ a.on_trait_change(callback3, 'a', remove=True)
+
+ a.on_trait_change(callback4, 'a')
+ a.a = 100000
+ self.assertEqual(self.cb,('a',10000,100000,a))
+ self.assertEqual(len(a._trait_notifiers['a']['change']), 1)
+ a.on_trait_change(callback4, 'a', remove=True)
+
+ self.assertEqual(len(a._trait_notifiers['a']['change']), 0)
+
+ def test_notify_only_once(self):
+
+ class A(HasTraits):
+ listen_to = ['a']
+
+ a = Int(0)
+ b = 0
+
+ def __init__(self, **kwargs):
+ super(A, self).__init__(**kwargs)
+ self.on_trait_change(self.listener1, ['a'])
+
+ def listener1(self, name, old, new):
+ self.b += 1
+
+ class B(A):
+
+ c = 0
+ d = 0
+
+ def __init__(self, **kwargs):
+ super(B, self).__init__(**kwargs)
+ self.on_trait_change(self.listener2)
+
+ def listener2(self, name, old, new):
+ self.c += 1
+
+ def _a_changed(self, name, old, new):
+ self.d += 1
+
+ b = B()
+ b.a += 1
+ self.assertEqual(b.b, b.c)
+ self.assertEqual(b.b, b.d)
+ b.a += 1
+ self.assertEqual(b.b, b.c)
+ self.assertEqual(b.b, b.d)
+
+class TestObserveDecorator(TestCase):
+
+ def setUp(self):
+ self._notify1 = []
+ self._notify2 = []
+
+ def notify1(self, change):
+ self._notify1.append(change)
+
+ def notify2(self, change):
+ self._notify2.append(change)
+
+ def test_notify_all(self):
+
+ class A(HasTraits):
+ a = Int()
+ b = Float()
+
+ a = A()
+ a.observe(self.notify1)
+ a.a = 0
+ self.assertEqual(len(self._notify1),0)
+ a.b = 0.0
+ self.assertEqual(len(self._notify1),0)
+ a.a = 10
+ change = change_dict('a', 0, 10, a, 'change')
+ self.assertTrue(change in self._notify1)
+ a.b = 10.0
+ change = change_dict('b', 0.0, 10.0, a, 'change')
+ self.assertTrue(change in self._notify1)
+ self.assertRaises(TraitError,setattr,a,'a','bad string')
+ self.assertRaises(TraitError,setattr,a,'b','bad string')
+ self._notify1 = []
+ a.unobserve(self.notify1)
+ a.a = 20
+ a.b = 20.0
+ self.assertEqual(len(self._notify1),0)
+
+ def test_notify_one(self):
+
+ class A(HasTraits):
+ a = Int()
+ b = Float()
+
+ a = A()
+ a.observe(self.notify1, 'a')
+ a.a = 0
+ self.assertEqual(len(self._notify1),0)
+ a.a = 10
+ change = change_dict('a', 0, 10, a, 'change')
+ self.assertTrue(change in self._notify1)
+ self.assertRaises(TraitError,setattr,a,'a','bad string')
+
+ def test_subclass(self):
+
+ class A(HasTraits):
+ a = Int()
+
+ class B(A):
+ b = Float()
+
+ b = B()
+ self.assertEqual(b.a,0)
+ self.assertEqual(b.b,0.0)
+ b.a = 100
+ b.b = 100.0
+ self.assertEqual(b.a,100)
+ self.assertEqual(b.b,100.0)
+
+ def test_notify_subclass(self):
+
+ class A(HasTraits):
+ a = Int()
+
+ class B(A):
+ b = Float()
+
+ b = B()
+ b.observe(self.notify1, 'a')
+ b.observe(self.notify2, 'b')
+ b.a = 0
+ b.b = 0.0
+ self.assertEqual(len(self._notify1),0)
+ self.assertEqual(len(self._notify2),0)
+ b.a = 10
+ b.b = 10.0
+ change = change_dict('a', 0, 10, b, 'change')
+ self.assertTrue(change in self._notify1)
+ change = change_dict('b', 0.0, 10.0, b, 'change')
+ self.assertTrue(change in self._notify2)
+
+ def test_static_notify(self):
+
+ class A(HasTraits):
+ a = Int()
+ b = Int()
+ _notify1 = []
+ _notify_any = []
+
+ @observe('a')
+ def _a_changed(self, change):
+ self._notify1.append(change)
+
+ @observe(All)
+ def _any_changed(self, change):
+ self._notify_any.append(change)
+
+ a = A()
+ a.a = 0
+ self.assertEqual(len(a._notify1),0)
+ a.a = 10
+ change = change_dict('a', 0, 10, a, 'change')
+ self.assertTrue(change in a._notify1)
+ a.b = 1
+ self.assertEqual(len(a._notify_any), 2)
+ change = change_dict('b', 0, 1, a, 'change')
+ self.assertTrue(change in a._notify_any)
+
+ class B(A):
+ b = Float()
+ _notify2 = []
+ @observe('b')
+ def _b_changed(self, change):
+ self._notify2.append(change)
+
+ b = B()
+ b.a = 10
+ b.b = 10.0
+ change = change_dict('a', 0, 10, b, 'change')
+ self.assertTrue(change in b._notify1)
+ change = change_dict('b', 0.0, 10.0, b, 'change')
+ self.assertTrue(change in b._notify2)
+
+ def test_notify_args(self):
+
+ def callback0():
+ self.cb = ()
+ def callback1(change):
+ self.cb = change
+
+ class A(HasTraits):
+ a = Int()
+
+ a = A()
+ a.on_trait_change(callback0, 'a')
+ a.a = 10
+ self.assertEqual(self.cb,())
+ a.unobserve(callback0, 'a')
+
+ a.observe(callback1, 'a')
+ a.a = 100
+ change = change_dict('a', 10, 100, a, 'change')
+ self.assertEqual(self.cb, change)
+ self.assertEqual(len(a._trait_notifiers['a']['change']), 1)
+ a.unobserve(callback1, 'a')
+
+ self.assertEqual(len(a._trait_notifiers['a']['change']), 0)
+
+ def test_notify_only_once(self):
+
+ class A(HasTraits):
+ listen_to = ['a']
+
+ a = Int(0)
+ b = 0
+
+ def __init__(self, **kwargs):
+ super(A, self).__init__(**kwargs)
+ self.observe(self.listener1, ['a'])
+
+ def listener1(self, change):
+ self.b += 1
+
+ class B(A):
+
+ c = 0
+ d = 0
+
+ def __init__(self, **kwargs):
+ super(B, self).__init__(**kwargs)
+ self.observe(self.listener2)
+
+ def listener2(self, change):
+ self.c += 1
+
+ @observe('a')
+ def _a_changed(self, change):
+ self.d += 1
+
+ b = B()
+ b.a += 1
+ self.assertEqual(b.b, b.c)
+ self.assertEqual(b.b, b.d)
+ b.a += 1
+ self.assertEqual(b.b, b.c)
+ self.assertEqual(b.b, b.d)
+
+
+class TestHasTraits(TestCase):
+
+ def test_trait_names(self):
+ class A(HasTraits):
+ i = Int()
+ f = Float()
+ a = A()
+ self.assertEqual(sorted(a.trait_names()),['f','i'])
+ self.assertEqual(sorted(A.class_trait_names()),['f','i'])
+ self.assertTrue(a.has_trait('f'))
+ self.assertFalse(a.has_trait('g'))
+
+ def test_trait_metadata_deprecated(self):
+ with expected_warnings(['metadata should be set using the \.tag\(\) method']):
+ class A(HasTraits):
+ i = Int(config_key='MY_VALUE')
+ a = A()
+ self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
+
+ def test_trait_metadata(self):
+ class A(HasTraits):
+ i = Int().tag(config_key='MY_VALUE')
+ a = A()
+ self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
+
+ def test_trait_metadata_default(self):
+ class A(HasTraits):
+ i = Int()
+ a = A()
+ self.assertEqual(a.trait_metadata('i', 'config_key'), None)
+ self.assertEqual(a.trait_metadata('i', 'config_key', 'default'), 'default')
+
+ def test_traits(self):
+ class A(HasTraits):
+ i = Int()
+ f = Float()
+ a = A()
+ self.assertEqual(a.traits(), dict(i=A.i, f=A.f))
+ self.assertEqual(A.class_traits(), dict(i=A.i, f=A.f))
+
+ def test_traits_metadata(self):
+ class A(HasTraits):
+ i = Int().tag(config_key='VALUE1', other_thing='VALUE2')
+ f = Float().tag(config_key='VALUE3', other_thing='VALUE2')
+ j = Int(0)
+ a = A()
+ self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
+ traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
+ self.assertEqual(traits, dict(i=A.i))
+
+ # This passes, but it shouldn't because I am replicating a bug in
+ # traits.
+ traits = a.traits(config_key=lambda v: True)
+ self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
+
+ def test_traits_metadata_deprecated(self):
+ with expected_warnings(['metadata should be set using the \.tag\(\) method']*2):
+ class A(HasTraits):
+ i = Int(config_key='VALUE1', other_thing='VALUE2')
+ f = Float(config_key='VALUE3', other_thing='VALUE2')
+ j = Int(0)
+ a = A()
+ self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
+ traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
+ self.assertEqual(traits, dict(i=A.i))
+
+ # This passes, but it shouldn't because I am replicating a bug in
+ # traits.
+ traits = a.traits(config_key=lambda v: True)
+ self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
+
+
+ def test_init(self):
+ class A(HasTraits):
+ i = Int()
+ x = Float()
+ a = A(i=1, x=10.0)
+ self.assertEqual(a.i, 1)
+ self.assertEqual(a.x, 10.0)
+
+ def test_positional_args(self):
+ class A(HasTraits):
+ i = Int(0)
+ def __init__(self, i):
+ super(A, self).__init__()
+ self.i = i
+
+ a = A(5)
+ self.assertEqual(a.i, 5)
+ # should raise TypeError if no positional arg given
+ self.assertRaises(TypeError, A)
+
+#-----------------------------------------------------------------------------
+# Tests for specific trait types
+#-----------------------------------------------------------------------------
+
+
+class TestType(TestCase):
+
+ def test_default(self):
+
+ class B(object): pass
+ class A(HasTraits):
+ klass = Type(allow_none=True)
+
+ a = A()
+ self.assertEqual(a.klass, object)
+
+ a.klass = B
+ self.assertEqual(a.klass, B)
+ self.assertRaises(TraitError, setattr, a, 'klass', 10)
+
+ def test_default_options(self):
+
+ class B(object): pass
+ class C(B): pass
+ class A(HasTraits):
+ # Different possible combinations of options for default_value
+ # and klass. default_value=None is only valid with allow_none=True.
+ k1 = Type()
+ k2 = Type(None, allow_none=True)
+ k3 = Type(B)
+ k4 = Type(klass=B)
+ k5 = Type(default_value=None, klass=B, allow_none=True)
+ k6 = Type(default_value=C, klass=B)
+
+ self.assertIs(A.k1.default_value, object)
+ self.assertIs(A.k1.klass, object)
+ self.assertIs(A.k2.default_value, None)
+ self.assertIs(A.k2.klass, object)
+ self.assertIs(A.k3.default_value, B)
+ self.assertIs(A.k3.klass, B)
+ self.assertIs(A.k4.default_value, B)
+ self.assertIs(A.k4.klass, B)
+ self.assertIs(A.k5.default_value, None)
+ self.assertIs(A.k5.klass, B)
+ self.assertIs(A.k6.default_value, C)
+ self.assertIs(A.k6.klass, B)
+
+ a = A()
+ self.assertIs(a.k1, object)
+ self.assertIs(a.k2, None)
+ self.assertIs(a.k3, B)
+ self.assertIs(a.k4, B)
+ self.assertIs(a.k5, None)
+ self.assertIs(a.k6, C)
+
+ def test_value(self):
+
+ class B(object): pass
+ class C(object): pass
+ class A(HasTraits):
+ klass = Type(B)
+
+ a = A()
+ self.assertEqual(a.klass, B)
+ self.assertRaises(TraitError, setattr, a, 'klass', C)
+ self.assertRaises(TraitError, setattr, a, 'klass', object)
+ a.klass = B
+
+ def test_allow_none(self):
+
+ class B(object): pass
+ class C(B): pass
+ class A(HasTraits):
+ klass = Type(B)
+
+ a = A()
+ self.assertEqual(a.klass, B)
+ self.assertRaises(TraitError, setattr, a, 'klass', None)
+ a.klass = C
+ self.assertEqual(a.klass, C)
+
+ def test_validate_klass(self):
+
+ class A(HasTraits):
+ klass = Type('no strings allowed')
+
+ self.assertRaises(ImportError, A)
+
+ class A(HasTraits):
+ klass = Type('rub.adub.Duck')
+
+ self.assertRaises(ImportError, A)
+
+ def test_validate_default(self):
+
+ class B(object): pass
+ class A(HasTraits):
+ klass = Type('bad default', B)
+
+ self.assertRaises(ImportError, A)
+
+ class C(HasTraits):
+ klass = Type(None, B)
+
+ self.assertRaises(TraitError, C)
+
+ def test_str_klass(self):
+
+ class A(HasTraits):
+ klass = Type('ipython_genutils.ipstruct.Struct')
+
+ from ipython_genutils.ipstruct import Struct
+ a = A()
+ a.klass = Struct
+ self.assertEqual(a.klass, Struct)
+
+ self.assertRaises(TraitError, setattr, a, 'klass', 10)
+
+ def test_set_str_klass(self):
+
+ class A(HasTraits):
+ klass = Type()
+
+ a = A(klass='ipython_genutils.ipstruct.Struct')
+ from ipython_genutils.ipstruct import Struct
+ self.assertEqual(a.klass, Struct)
+
+class TestInstance(TestCase):
+
+ def test_basic(self):
+ class Foo(object): pass
+ class Bar(Foo): pass
+ class Bah(object): pass
+
+ class A(HasTraits):
+ inst = Instance(Foo, allow_none=True)
+
+ a = A()
+ self.assertTrue(a.inst is None)
+ a.inst = Foo()
+ self.assertTrue(isinstance(a.inst, Foo))
+ a.inst = Bar()
+ self.assertTrue(isinstance(a.inst, Foo))
+ self.assertRaises(TraitError, setattr, a, 'inst', Foo)
+ self.assertRaises(TraitError, setattr, a, 'inst', Bar)
+ self.assertRaises(TraitError, setattr, a, 'inst', Bah())
+
+ def test_default_klass(self):
+ class Foo(object): pass
+ class Bar(Foo): pass
+ class Bah(object): pass
+
+ class FooInstance(Instance):
+ klass = Foo
+
+ class A(HasTraits):
+ inst = FooInstance(allow_none=True)
+
+ a = A()
+ self.assertTrue(a.inst is None)
+ a.inst = Foo()
+ self.assertTrue(isinstance(a.inst, Foo))
+ a.inst = Bar()
+ self.assertTrue(isinstance(a.inst, Foo))
+ self.assertRaises(TraitError, setattr, a, 'inst', Foo)
+ self.assertRaises(TraitError, setattr, a, 'inst', Bar)
+ self.assertRaises(TraitError, setattr, a, 'inst', Bah())
+
+ def test_unique_default_value(self):
+ class Foo(object): pass
+ class A(HasTraits):
+ inst = Instance(Foo,(),{})
+
+ a = A()
+ b = A()
+ self.assertTrue(a.inst is not b.inst)
+
+ def test_args_kw(self):
+ class Foo(object):
+ def __init__(self, c): self.c = c
+ class Bar(object): pass
+ class Bah(object):
+ def __init__(self, c, d):
+ self.c = c; self.d = d
+
+ class A(HasTraits):
+ inst = Instance(Foo, (10,))
+ a = A()
+ self.assertEqual(a.inst.c, 10)
+
+ class B(HasTraits):
+ inst = Instance(Bah, args=(10,), kw=dict(d=20))
+ b = B()
+ self.assertEqual(b.inst.c, 10)
+ self.assertEqual(b.inst.d, 20)
+
+ class C(HasTraits):
+ inst = Instance(Foo, allow_none=True)
+ c = C()
+ self.assertTrue(c.inst is None)
+
+ def test_bad_default(self):
+ class Foo(object): pass
+
+ class A(HasTraits):
+ inst = Instance(Foo)
+
+ a = A()
+ with self.assertRaises(TraitError):
+ a.inst
+
+ def test_instance(self):
+ class Foo(object): pass
+
+ def inner():
+ class A(HasTraits):
+ inst = Instance(Foo())
+
+ self.assertRaises(TraitError, inner)
+
+
+class TestThis(TestCase):
+
+ def test_this_class(self):
+ class Foo(HasTraits):
+ this = This()
+
+ f = Foo()
+ self.assertEqual(f.this, None)
+ g = Foo()
+ f.this = g
+ self.assertEqual(f.this, g)
+ self.assertRaises(TraitError, setattr, f, 'this', 10)
+
+ def test_this_inst(self):
+ class Foo(HasTraits):
+ this = This()
+
+ f = Foo()
+ f.this = Foo()
+ self.assertTrue(isinstance(f.this, Foo))
+
+ def test_subclass(self):
+ class Foo(HasTraits):
+ t = This()
+ class Bar(Foo):
+ pass
+ f = Foo()
+ b = Bar()
+ f.t = b
+ b.t = f
+ self.assertEqual(f.t, b)
+ self.assertEqual(b.t, f)
+
+ def test_subclass_override(self):
+ class Foo(HasTraits):
+ t = This()
+ class Bar(Foo):
+ t = This()
+ f = Foo()
+ b = Bar()
+ f.t = b
+ self.assertEqual(f.t, b)
+ self.assertRaises(TraitError, setattr, b, 't', f)
+
+ def test_this_in_container(self):
+
+ class Tree(HasTraits):
+ value = Unicode()
+ leaves = List(This())
+
+ tree = Tree(
+ value='foo',
+ leaves=[Tree(value='bar'), Tree(value='buzz')]
+ )
+
+ with self.assertRaises(TraitError):
+ tree.leaves = [1, 2]
+
+class TraitTestBase(TestCase):
+ """A best testing class for basic trait types."""
+
+ def assign(self, value):
+ self.obj.value = value
+
+ def coerce(self, value):
+ return value
+
+ def test_good_values(self):
+ if hasattr(self, '_good_values'):
+ for value in self._good_values:
+ self.assign(value)
+ self.assertEqual(self.obj.value, self.coerce(value))
+
+ def test_bad_values(self):
+ if hasattr(self, '_bad_values'):
+ for value in self._bad_values:
+ try:
+ self.assertRaises(TraitError, self.assign, value)
+ except AssertionError:
+ assert False, value
+
+ def test_default_value(self):
+ if hasattr(self, '_default_value'):
+ self.assertEqual(self._default_value, self.obj.value)
+
+ def test_allow_none(self):
+ if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
+ None in self._bad_values):
+ trait=self.obj.traits()['value']
+ try:
+ trait.allow_none = True
+ self._bad_values.remove(None)
+ #skip coerce. Allow None casts None to None.
+ self.assign(None)
+ self.assertEqual(self.obj.value,None)
+ self.test_good_values()
+ self.test_bad_values()
+ finally:
+ #tear down
+ trait.allow_none = False
+ self._bad_values.append(None)
+
+ def tearDown(self):
+ # restore default value after tests, if set
+ if hasattr(self, '_default_value'):
+ self.obj.value = self._default_value
+
+
+class AnyTrait(HasTraits):
+
+ value = Any()
+
+class AnyTraitTest(TraitTestBase):
+
+ obj = AnyTrait()
+
+ _default_value = None
+ _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
+ _bad_values = []
+
+class UnionTrait(HasTraits):
+
+ value = Union([Type(), Bool()])
+
+class UnionTraitTest(TraitTestBase):
+
+ obj = UnionTrait(value='ipython_genutils.ipstruct.Struct')
+ _good_values = [int, float, True]
+ _bad_values = [[], (0,), 1j]
+
+class OrTrait(HasTraits):
+
+ value = Bool() | Unicode()
+
+class OrTraitTest(TraitTestBase):
+
+ obj = OrTrait()
+ _good_values = [True, False, 'ten']
+ _bad_values = [[], (0,), 1j]
+
+class IntTrait(HasTraits):
+
+ value = Int(99, min=-100)
+
+class TestInt(TraitTestBase):
+
+ obj = IntTrait()
+ _default_value = 99
+ _good_values = [10, -10]
+ _bad_values = ['ten', u'ten', [10], {'ten': 10}, (10,), None, 1j,
+ 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
+ u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', -200]
+ if not six.PY3:
+ _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
+
+
+class CIntTrait(HasTraits):
+ value = CInt('5')
+
+class TestCInt(TraitTestBase):
+ obj = CIntTrait()
+
+ _default_value = 5
+ _good_values = ['10', '-10', u'10', u'-10', 10, 10.0, -10.0, 10.1]
+ _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
+ None, 1j, '10.1', u'10.1']
+
+ def coerce(self, n):
+ return int(n)
+
+
+class MinBoundCIntTrait(HasTraits):
+ value = CInt('5', min=3)
+
+class TestMinBoundCInt(TestCInt):
+ obj = MinBoundCIntTrait()
+
+ _default_value = 5
+ _good_values = [3, 3.0, '3']
+ _bad_values = [2.6, 2, -3, -3.0]
+
+
+class LongTrait(HasTraits):
+
+ value = Long(99 if six.PY3 else long(99))
+
+class TestLong(TraitTestBase):
+
+ obj = LongTrait()
+
+ _default_value = 99 if six.PY3 else long(99)
+ _good_values = [10, -10]
+ _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
+ None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
+ '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
+ u'-10.1']
+ if not six.PY3:
+ # maxint undefined on py3, because int == long
+ _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
+ _bad_values.extend([[long(10)], (long(10),)])
+
+ @mark.skipif(six.PY3, reason="not relevant on py3")
+ def test_cast_small(self):
+ """Long casts ints to long"""
+ self.obj.value = 10
+ self.assertEqual(type(self.obj.value), long)
+
+
+class MinBoundLongTrait(HasTraits):
+ value = Long(99 if six.PY3 else long(99), min=5)
+
+class TestMinBoundLong(TraitTestBase):
+ obj = MinBoundLongTrait()
+
+ _default_value = 99 if six.PY3 else long(99)
+ _good_values = [5, 10]
+ _bad_values = [4, -10]
+
+
+class MaxBoundLongTrait(HasTraits):
+ value = Long(5 if six.PY3 else long(5), max=10)
+
+class TestMaxBoundLong(TraitTestBase):
+ obj = MaxBoundLongTrait()
+
+ _default_value = 5 if six.PY3 else long(5)
+ _good_values = [10, -2]
+ _bad_values = [11, 20]
+
+
+class CLongTrait(HasTraits):
+ value = CLong('5')
+
+class TestCLong(TraitTestBase):
+ obj = CLongTrait()
+
+ _default_value = 5 if six.PY3 else long(5)
+ _good_values = ['10', '-10', u'10', u'-10', 10, 10.0, -10.0, 10.1]
+ _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
+ None, 1j, '10.1', u'10.1']
+
+ def coerce(self, n):
+ return int(n) if six.PY3 else long(n)
+
+
+class MaxBoundCLongTrait(HasTraits):
+ value = CLong('5', max=10)
+
+class TestMaxBoundCLong(TestCLong):
+ obj = MaxBoundCLongTrait()
+
+ _default_value = 5 if six.PY3 else long(5)
+ _good_values = [10, '10', 10.3]
+ _bad_values = [11.0, '11']
+
+
+class IntegerTrait(HasTraits):
+ value = Integer(1)
+
+class TestInteger(TestLong):
+ obj = IntegerTrait()
+ _default_value = 1
+
+ def coerce(self, n):
+ return int(n)
+
+ @mark.skipif(six.PY3, reason="not relevant on py3")
+ def test_cast_small(self):
+ """Integer casts small longs to int"""
+
+ self.obj.value = long(100)
+ self.assertEqual(type(self.obj.value), int)
+
+
+class MinBoundIntegerTrait(HasTraits):
+ value = Integer(5, min=3)
+
+class TestMinBoundInteger(TraitTestBase):
+ obj = MinBoundIntegerTrait()
+
+ _default_value = 5
+ _good_values = 3, 20
+ _bad_values = [2, -10]
+
+
+class MaxBoundIntegerTrait(HasTraits):
+ value = Integer(1, max=3)
+
+class TestMaxBoundInteger(TraitTestBase):
+ obj = MaxBoundIntegerTrait()
+
+ _default_value = 1
+ _good_values = 3, -2
+ _bad_values = [4, 10]
+
+
+class FloatTrait(HasTraits):
+
+ value = Float(99.0, max=200.0)
+
+class TestFloat(TraitTestBase):
+
+ obj = FloatTrait()
+
+ _default_value = 99.0
+ _good_values = [10, -10, 10.1, -10.1]
+ _bad_values = ['ten', u'ten', [10], {'ten': 10}, (10,), None,
+ 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
+ u'-10', u'10L', u'-10L', u'10.1', u'-10.1', 201.0]
+ if not six.PY3:
+ _bad_values.extend([long(10), long(-10)])
+
+
+class CFloatTrait(HasTraits):
+
+ value = CFloat('99.0', max=200.0)
+
+class TestCFloat(TraitTestBase):
+
+ obj = CFloatTrait()
+
+ _default_value = 99.0
+ _good_values = [10, 10.0, 10.5, '10.0', '10', '-10', '10.0', u'10']
+ _bad_values = ['ten', u'ten', [10], {'ten': 10}, (10,), None, 1j,
+ 200.1, '200.1']
+
+ def coerce(self, v):
+ return float(v)
+
+
+class ComplexTrait(HasTraits):
+
+ value = Complex(99.0-99.0j)
+
+class TestComplex(TraitTestBase):
+
+ obj = ComplexTrait()
+
+ _default_value = 99.0-99.0j
+ _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
+ 10.1j, 10.1+10.1j, 10.1-10.1j]
+ _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
+ if not six.PY3:
+ _bad_values.extend([long(10), long(-10)])
+
+
+class BytesTrait(HasTraits):
+
+ value = Bytes(b'string')
+
+class TestBytes(TraitTestBase):
+
+ obj = BytesTrait()
+
+ _default_value = b'string'
+ _good_values = [b'10', b'-10', b'10L',
+ b'-10L', b'10.1', b'-10.1', b'string']
+ _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
+ ['ten'],{'ten': 10},(10,), None, u'string']
+ if not six.PY3:
+ _bad_values.extend([long(10), long(-10)])
+
+
+class UnicodeTrait(HasTraits):
+
+ value = Unicode(u'unicode')
+
+class TestUnicode(TraitTestBase):
+
+ obj = UnicodeTrait()
+
+ _default_value = u'unicode'
+ _good_values = ['10', '-10', '10L', '-10L', '10.1',
+ '-10.1', '', u'', 'string', u'string', u"€"]
+ _bad_values = [10, -10, 10.1, -10.1, 1j,
+ [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
+ if not six.PY3:
+ _bad_values.extend([long(10), long(-10)])
+
+
+class ObjectNameTrait(HasTraits):
+ value = ObjectName("abc")
+
+class TestObjectName(TraitTestBase):
+ obj = ObjectNameTrait()
+
+ _default_value = "abc"
+ _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
+ _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
+ None, object(), object]
+ if sys.version_info[0] < 3:
+ _bad_values.append(u"þ")
+ else:
+ _good_values.append(u"þ") # þ=1 is valid in Python 3 (PEP 3131).
+
+
+class DottedObjectNameTrait(HasTraits):
+ value = DottedObjectName("a.b")
+
+class TestDottedObjectName(TraitTestBase):
+ obj = DottedObjectNameTrait()
+
+ _default_value = "a.b"
+ _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
+ _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
+ if sys.version_info[0] < 3:
+ _bad_values.append(u"t.þ")
+ else:
+ _good_values.append(u"t.þ")
+
+
+class TCPAddressTrait(HasTraits):
+ value = TCPAddress()
+
+class TestTCPAddress(TraitTestBase):
+
+ obj = TCPAddressTrait()
+
+ _default_value = ('127.0.0.1',0)
+ _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
+ _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
+
+class ListTrait(HasTraits):
+
+ value = List(Int())
+
+class TestList(TraitTestBase):
+
+ obj = ListTrait()
+
+ _default_value = []
+ _good_values = [[], [1], list(range(10)), (1,2)]
+ _bad_values = [10, [1,'a'], 'a']
+
+ def coerce(self, value):
+ if value is not None:
+ value = list(value)
+ return value
+
+class Foo(object):
+ pass
+
+class NoneInstanceListTrait(HasTraits):
+
+ value = List(Instance(Foo))
+
+class TestNoneInstanceList(TraitTestBase):
+
+ obj = NoneInstanceListTrait()
+
+ _default_value = []
+ _good_values = [[Foo(), Foo()], []]
+ _bad_values = [[None], [Foo(), None]]
+
+
+class InstanceListTrait(HasTraits):
+
+ value = List(Instance(__name__+'.Foo'))
+
+class TestInstanceList(TraitTestBase):
+
+ obj = InstanceListTrait()
+
+ def test_klass(self):
+ """Test that the instance klass is properly assigned."""
+ self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
+
+ _default_value = []
+ _good_values = [[Foo(), Foo()], []]
+ _bad_values = [['1', 2,], '1', [Foo], None]
+
+class UnionListTrait(HasTraits):
+
+ value = List(Int() | Bool())
+
+class TestUnionListTrait(HasTraits):
+
+ obj = UnionListTrait()
+
+ _default_value = []
+ _good_values = [[True, 1], [False, True]]
+ _bad_values = [[1, 'True'], False]
+
+
+class LenListTrait(HasTraits):
+
+ value = List(Int(), [0], minlen=1, maxlen=2)
+
+class TestLenList(TraitTestBase):
+
+ obj = LenListTrait()
+
+ _default_value = [0]
+ _good_values = [[1], [1,2], (1,2)]
+ _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
+
+ def coerce(self, value):
+ if value is not None:
+ value = list(value)
+ return value
+
+class TupleTrait(HasTraits):
+
+ value = Tuple(Int(allow_none=True), default_value=(1,))
+
+class TestTupleTrait(TraitTestBase):
+
+ obj = TupleTrait()
+
+ _default_value = (1,)
+ _good_values = [(1,), (0,), [1]]
+ _bad_values = [10, (1, 2), ('a'), (), None]
+
+ def coerce(self, value):
+ if value is not None:
+ value = tuple(value)
+ return value
+
+ def test_invalid_args(self):
+ self.assertRaises(TypeError, Tuple, 5)
+ self.assertRaises(TypeError, Tuple, default_value='hello')
+ t = Tuple(Int(), CBytes(), default_value=(1,5))
+
+class LooseTupleTrait(HasTraits):
+
+ value = Tuple((1,2,3))
+
+class TestLooseTupleTrait(TraitTestBase):
+
+ obj = LooseTupleTrait()
+
+ _default_value = (1,2,3)
+ _good_values = [(1,), [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
+ _bad_values = [10, 'hello', {}, None]
+
+ def coerce(self, value):
+ if value is not None:
+ value = tuple(value)
+ return value
+
+ def test_invalid_args(self):
+ self.assertRaises(TypeError, Tuple, 5)
+ self.assertRaises(TypeError, Tuple, default_value='hello')
+ t = Tuple(Int(), CBytes(), default_value=(1,5))
+
+
+class MultiTupleTrait(HasTraits):
+
+ value = Tuple(Int(), Bytes(), default_value=[99,b'bottles'])
+
+class TestMultiTuple(TraitTestBase):
+
+ obj = MultiTupleTrait()
+
+ _default_value = (99,b'bottles')
+ _good_values = [(1,b'a'), (2,b'b')]
+ _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
+
+class CRegExpTrait(HasTraits):
+
+ value = CRegExp(r'')
+
+class TestCRegExp(TraitTestBase):
+
+ def coerce(self, value):
+ return re.compile(value)
+
+ obj = CRegExpTrait()
+
+ _default_value = re.compile(r'')
+ _good_values = [r'\d+', re.compile(r'\d+')]
+ _bad_values = ['(', None, ()]
+
+class DictTrait(HasTraits):
+ value = Dict()
+
+def test_dict_assignment():
+ d = dict()
+ c = DictTrait()
+ c.value = d
+ d['a'] = 5
+ assert d == c.value
+ assert c.value is d
+
+
+class UniformlyValidatedDictTrait(HasTraits):
+
+ value = Dict(trait=Unicode(),
+ default_value={'foo': '1'})
+
+
+class TestInstanceUniformlyValidatedDict(TraitTestBase):
+
+ obj = UniformlyValidatedDictTrait()
+
+ _default_value = {'foo': '1'}
+ _good_values = [{'foo': '0', 'bar': '1'}]
+ _bad_values = [{'foo': 0, 'bar': '1'}]
+
+
+class KeyValidatedDictTrait(HasTraits):
+
+ value = Dict(traits={'foo': Int()},
+ default_value={'foo': 1})
+
+
+class TestInstanceKeyValidatedDict(TraitTestBase):
+
+ obj = KeyValidatedDictTrait()
+
+ _default_value = {'foo': 1}
+ _good_values = [{'foo': 0, 'bar': '1'}, {'foo': 0, 'bar': 1}]
+ _bad_values = [{'foo': '0', 'bar': '1'}]
+
+
+class FullyValidatedDictTrait(HasTraits):
+
+ value = Dict(trait=Unicode(),
+ traits={'foo': Int()},
+ default_value={'foo': 1})
+
+
+class TestInstanceFullyValidatedDict(TraitTestBase):
+
+ obj = FullyValidatedDictTrait()
+
+ _default_value = {'foo': 1}
+ _good_values = [{'foo': 0, 'bar': '1'}, {'foo': 1, 'bar': '2'}]
+ _bad_values = [{'foo': 0, 'bar': 1}, {'foo': '0', 'bar': '1'}]
+
+
+def test_dict_default_value():
+ """Check that the `{}` default value of the Dict traitlet constructor is
+ actually copied."""
+
+ class Foo(HasTraits):
+ d1 = Dict()
+ d2 = Dict()
+
+ foo = Foo()
+ assert foo.d1 == {}
+ assert foo.d2 == {}
+ assert foo.d1 is not foo.d2
+
+
+class TestValidationHook(TestCase):
+
+ def test_parity_trait(self):
+ """Verify that the early validation hook is effective"""
+
+ class Parity(HasTraits):
+
+ value = Int(0)
+ parity = Enum(['odd', 'even'], default_value='even')
+
+ @validate('value')
+ def _value_validate(self, proposal):
+ value = proposal['value']
+ if self.parity == 'even' and value % 2:
+ raise TraitError('Expected an even number')
+ if self.parity == 'odd' and (value % 2 == 0):
+ raise TraitError('Expected an odd number')
+ return value
+
+ u = Parity()
+ u.parity = 'odd'
+ u.value = 1 # OK
+ with self.assertRaises(TraitError):
+ u.value = 2 # Trait Error
+
+ u.parity = 'even'
+ u.value = 2 # OK
+
+ def test_multiple_validate(self):
+ """Verify that we can register the same validator to multiple names"""
+
+ class OddEven(HasTraits):
+
+ odd = Int(1)
+ even = Int(0)
+
+ @validate('odd', 'even')
+ def check_valid(self, proposal):
+ if proposal['trait'].name == 'odd' and not proposal['value'] % 2:
+ raise TraitError('odd should be odd')
+ if proposal['trait'].name == 'even' and proposal['value'] % 2:
+ raise TraitError('even should be even')
+
+ u = OddEven()
+ u.odd = 3 # OK
+ with self.assertRaises(TraitError):
+ u.odd = 2 # Trait Error
+
+ u.even = 2 # OK
+ with self.assertRaises(TraitError):
+ u.even = 3 # Trait Error
+
+
+
+class TestLink(TestCase):
+
+ def test_connect_same(self):
+ """Verify two traitlets of the same type can be linked together using link."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ a = A(value=9)
+ b = A(value=8)
+
+ # Conenct the two classes.
+ c = link((a, 'value'), (b, 'value'))
+
+ # Make sure the values are the same at the point of linking.
+ self.assertEqual(a.value, b.value)
+
+ # Change one of the values to make sure they stay in sync.
+ a.value = 5
+ self.assertEqual(a.value, b.value)
+ b.value = 6
+ self.assertEqual(a.value, b.value)
+
+ def test_link_different(self):
+ """Verify two traitlets of different types can be linked together using link."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ class B(HasTraits):
+ count = Int()
+ a = A(value=9)
+ b = B(count=8)
+
+ # Conenct the two classes.
+ c = link((a, 'value'), (b, 'count'))
+
+ # Make sure the values are the same at the point of linking.
+ self.assertEqual(a.value, b.count)
+
+ # Change one of the values to make sure they stay in sync.
+ a.value = 5
+ self.assertEqual(a.value, b.count)
+ b.count = 4
+ self.assertEqual(a.value, b.count)
+
+ def test_unlink(self):
+ """Verify two linked traitlets can be unlinked."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ a = A(value=9)
+ b = A(value=8)
+
+ # Connect the two classes.
+ c = link((a, 'value'), (b, 'value'))
+ a.value = 4
+ c.unlink()
+
+ # Change one of the values to make sure they don't stay in sync.
+ a.value = 5
+ self.assertNotEqual(a.value, b.value)
+
+ def test_callbacks(self):
+ """Verify two linked traitlets have their callbacks called once."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ class B(HasTraits):
+ count = Int()
+ a = A(value=9)
+ b = B(count=8)
+
+ # Register callbacks that count.
+ callback_count = []
+ def a_callback(name, old, new):
+ callback_count.append('a')
+ a.on_trait_change(a_callback, 'value')
+ def b_callback(name, old, new):
+ callback_count.append('b')
+ b.on_trait_change(b_callback, 'count')
+
+ # Connect the two classes.
+ c = link((a, 'value'), (b, 'count'))
+
+ # Make sure b's count was set to a's value once.
+ self.assertEqual(''.join(callback_count), 'b')
+ del callback_count[:]
+
+ # Make sure a's value was set to b's count once.
+ b.count = 5
+ self.assertEqual(''.join(callback_count), 'ba')
+ del callback_count[:]
+
+ # Make sure b's count was set to a's value once.
+ a.value = 4
+ self.assertEqual(''.join(callback_count), 'ab')
+ del callback_count[:]
+
+class TestDirectionalLink(TestCase):
+ def test_connect_same(self):
+ """Verify two traitlets of the same type can be linked together using directional_link."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ a = A(value=9)
+ b = A(value=8)
+
+ # Conenct the two classes.
+ c = directional_link((a, 'value'), (b, 'value'))
+
+ # Make sure the values are the same at the point of linking.
+ self.assertEqual(a.value, b.value)
+
+ # Change one the value of the source and check that it synchronizes the target.
+ a.value = 5
+ self.assertEqual(b.value, 5)
+ # Change one the value of the target and check that it has no impact on the source
+ b.value = 6
+ self.assertEqual(a.value, 5)
+
+ def test_tranform(self):
+ """Test transform link."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ a = A(value=9)
+ b = A(value=8)
+
+ # Conenct the two classes.
+ c = directional_link((a, 'value'), (b, 'value'), lambda x: 2 * x)
+
+ # Make sure the values are correct at the point of linking.
+ self.assertEqual(b.value, 2 * a.value)
+
+ # Change one the value of the source and check that it modifies the target.
+ a.value = 5
+ self.assertEqual(b.value, 10)
+ # Change one the value of the target and check that it has no impact on the source
+ b.value = 6
+ self.assertEqual(a.value, 5)
+
+ def test_link_different(self):
+ """Verify two traitlets of different types can be linked together using link."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ class B(HasTraits):
+ count = Int()
+ a = A(value=9)
+ b = B(count=8)
+
+ # Conenct the two classes.
+ c = directional_link((a, 'value'), (b, 'count'))
+
+ # Make sure the values are the same at the point of linking.
+ self.assertEqual(a.value, b.count)
+
+ # Change one the value of the source and check that it synchronizes the target.
+ a.value = 5
+ self.assertEqual(b.count, 5)
+ # Change one the value of the target and check that it has no impact on the source
+ b.value = 6
+ self.assertEqual(a.value, 5)
+
+ def test_unlink(self):
+ """Verify two linked traitlets can be unlinked."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ a = A(value=9)
+ b = A(value=8)
+
+ # Connect the two classes.
+ c = directional_link((a, 'value'), (b, 'value'))
+ a.value = 4
+ c.unlink()
+
+ # Change one of the values to make sure they don't stay in sync.
+ a.value = 5
+ self.assertNotEqual(a.value, b.value)
+
+class Pickleable(HasTraits):
+
+ i = Int()
+ @observe('i')
+ def _i_changed(self, change): pass
+ @validate('i')
+ def _i_validate(self, commit):
+ return commit['value']
+
+ j = Int()
+
+ def __init__(self):
+ with self.hold_trait_notifications():
+ self.i = 1
+ self.on_trait_change(self._i_changed, 'i')
+
+def test_pickle_hastraits():
+ c = Pickleable()
+ for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
+ p = pickle.dumps(c, protocol)
+ c2 = pickle.loads(p)
+ assert c2.i == c.i
+ assert c2.j == c.j
+
+ c.i = 5
+ for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
+ p = pickle.dumps(c, protocol)
+ c2 = pickle.loads(p)
+ assert c2.i == c.i
+ assert c2.j == c.j
+
+
+def test_hold_trait_notifications():
+ changes = []
+
+ class Test(HasTraits):
+ a = Integer(0)
+ b = Integer(0)
+
+ def _a_changed(self, name, old, new):
+ changes.append((old, new))
+
+ def _b_validate(self, value, trait):
+ if value != 0:
+ raise TraitError('Only 0 is a valid value')
+ return value
+
+ # Test context manager and nesting
+ t = Test()
+ with t.hold_trait_notifications():
+ with t.hold_trait_notifications():
+ t.a = 1
+ assert t.a == 1
+ assert changes == []
+ t.a = 2
+ assert t.a == 2
+ with t.hold_trait_notifications():
+ t.a = 3
+ assert t.a == 3
+ assert changes == []
+ t.a = 4
+ assert t.a == 4
+ assert changes == []
+ t.a = 4
+ assert t.a == 4
+ assert changes == []
+
+ assert changes == [(0, 4)]
+ # Test roll-back
+ try:
+ with t.hold_trait_notifications():
+ t.b = 1 # raises a Trait error
+ except:
+ pass
+ assert t.b == 0
+
+
+class RollBack(HasTraits):
+ bar = Int()
+ def _bar_validate(self, value, trait):
+ if value:
+ raise TraitError('foobar')
+ return value
+
+
+class TestRollback(TestCase):
+
+ def test_roll_back(self):
+
+ def assign_rollback():
+ RollBack(bar=1)
+
+ self.assertRaises(TraitError, assign_rollback)
+
+
+class CacheModification(HasTraits):
+ foo = Int()
+ bar = Int()
+
+ def _bar_validate(self, value, trait):
+ self.foo = value
+ return value
+
+ def _foo_validate(self, value, trait):
+ self.bar = value
+ return value
+
+
+def test_cache_modification():
+ CacheModification(foo=1)
+ CacheModification(bar=1)
+
+
+class OrderTraits(HasTraits):
+ notified = Dict()
+
+ a = Unicode()
+ b = Unicode()
+ c = Unicode()
+ d = Unicode()
+ e = Unicode()
+ f = Unicode()
+ g = Unicode()
+ h = Unicode()
+ i = Unicode()
+ j = Unicode()
+ k = Unicode()
+ l = Unicode()
+
+ def _notify(self, name, old, new):
+ """check the value of all traits when each trait change is triggered
+
+ This verifies that the values are not sensitive
+ to dict ordering when loaded from kwargs
+ """
+ # check the value of the other traits
+ # when a given trait change notification fires
+ self.notified[name] = {
+ c: getattr(self, c) for c in 'abcdefghijkl'
+ }
+
+ def __init__(self, **kwargs):
+ self.on_trait_change(self._notify)
+ super(OrderTraits, self).__init__(**kwargs)
+
+def test_notification_order():
+ d = {c:c for c in 'abcdefghijkl'}
+ obj = OrderTraits()
+ assert obj.notified == {}
+ obj = OrderTraits(**d)
+ notifications = {
+ c: d for c in 'abcdefghijkl'
+ }
+ assert obj.notified == notifications
+
+
+
+###
+# Traits for Forward Declaration Tests
+###
+class ForwardDeclaredInstanceTrait(HasTraits):
+
+ value = ForwardDeclaredInstance('ForwardDeclaredBar', allow_none=True)
+
+class ForwardDeclaredTypeTrait(HasTraits):
+
+ value = ForwardDeclaredType('ForwardDeclaredBar', allow_none=True)
+
+class ForwardDeclaredInstanceListTrait(HasTraits):
+
+ value = List(ForwardDeclaredInstance('ForwardDeclaredBar'))
+
+class ForwardDeclaredTypeListTrait(HasTraits):
+
+ value = List(ForwardDeclaredType('ForwardDeclaredBar'))
+###
+# End Traits for Forward Declaration Tests
+###
+
+###
+# Classes for Forward Declaration Tests
+###
+class ForwardDeclaredBar(object):
+ pass
+
+class ForwardDeclaredBarSub(ForwardDeclaredBar):
+ pass
+###
+# End Classes for Forward Declaration Tests
+###
+
+###
+# Forward Declaration Tests
+###
+class TestForwardDeclaredInstanceTrait(TraitTestBase):
+
+ obj = ForwardDeclaredInstanceTrait()
+ _default_value = None
+ _good_values = [None, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
+ _bad_values = ['foo', 3, ForwardDeclaredBar, ForwardDeclaredBarSub]
+
+class TestForwardDeclaredTypeTrait(TraitTestBase):
+
+ obj = ForwardDeclaredTypeTrait()
+ _default_value = None
+ _good_values = [None, ForwardDeclaredBar, ForwardDeclaredBarSub]
+ _bad_values = ['foo', 3, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
+
+class TestForwardDeclaredInstanceList(TraitTestBase):
+
+ obj = ForwardDeclaredInstanceListTrait()
+
+ def test_klass(self):
+ """Test that the instance klass is properly assigned."""
+ self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
+
+ _default_value = []
+ _good_values = [
+ [ForwardDeclaredBar(), ForwardDeclaredBarSub()],
+ [],
+ ]
+ _bad_values = [
+ ForwardDeclaredBar(),
+ [ForwardDeclaredBar(), 3, None],
+ '1',
+ # Note that this is the type, not an instance.
+ [ForwardDeclaredBar],
+ [None],
+ None,
+ ]
+
+class TestForwardDeclaredTypeList(TraitTestBase):
+
+ obj = ForwardDeclaredTypeListTrait()
+
+ def test_klass(self):
+ """Test that the instance klass is properly assigned."""
+ self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
+
+ _default_value = []
+ _good_values = [
+ [ForwardDeclaredBar, ForwardDeclaredBarSub],
+ [],
+ ]
+ _bad_values = [
+ ForwardDeclaredBar,
+ [ForwardDeclaredBar, 3],
+ '1',
+ # Note that this is an instance, not the type.
+ [ForwardDeclaredBar()],
+ [None],
+ None,
+ ]
+###
+# End Forward Declaration Tests
+###
+
+class TestDynamicTraits(TestCase):
+
+ def setUp(self):
+ self._notify1 = []
+
+ def notify1(self, name, old, new):
+ self._notify1.append((name, old, new))
+
+ def test_notify_all(self):
+
+ class A(HasTraits):
+ pass
+
+ a = A()
+ self.assertTrue(not hasattr(a, 'x'))
+ self.assertTrue(not hasattr(a, 'y'))
+
+ # Dynamically add trait x.
+ a.add_traits(x=Int())
+ self.assertTrue(hasattr(a, 'x'))
+ self.assertTrue(isinstance(a, (A, )))
+
+ # Dynamically add trait y.
+ a.add_traits(y=Float())
+ self.assertTrue(hasattr(a, 'y'))
+ self.assertTrue(isinstance(a, (A, )))
+ self.assertEqual(a.__class__.__name__, A.__name__)
+
+ # Create a new instance and verify that x and y
+ # aren't defined.
+ b = A()
+ self.assertTrue(not hasattr(b, 'x'))
+ self.assertTrue(not hasattr(b, 'y'))
+
+ # Verify that notification works like normal.
+ a.on_trait_change(self.notify1)
+ a.x = 0
+ self.assertEqual(len(self._notify1), 0)
+ a.y = 0.0
+ self.assertEqual(len(self._notify1), 0)
+ a.x = 10
+ self.assertTrue(('x', 0, 10) in self._notify1)
+ a.y = 10.0
+ self.assertTrue(('y', 0.0, 10.0) in self._notify1)
+ self.assertRaises(TraitError, setattr, a, 'x', 'bad string')
+ self.assertRaises(TraitError, setattr, a, 'y', 'bad string')
+ self._notify1 = []
+ a.on_trait_change(self.notify1, remove=True)
+ a.x = 20
+ a.y = 20.0
+ self.assertEqual(len(self._notify1), 0)
+
+
+def test_enum_no_default():
+ class C(HasTraits):
+ t = Enum(['a', 'b'])
+
+ c = C()
+ c.t = 'a'
+ assert c.t == 'a'
+
+ c = C()
+
+ with pytest.raises(TraitError):
+ t = c.t
+
+ c = C(t='b')
+ assert c.t == 'b'
+
+
+def test_default_value_repr():
+ class C(HasTraits):
+ t = Type('traitlets.HasTraits')
+ t2 = Type(HasTraits)
+ n = Integer(0)
+ lis = List()
+ d = Dict()
+
+ assert C.t.default_value_repr() == "'traitlets.HasTraits'"
+ assert C.t2.default_value_repr() == "'traitlets.traitlets.HasTraits'"
+ assert C.n.default_value_repr() == '0'
+ assert C.lis.default_value_repr() == '[]'
+ assert C.d.default_value_repr() == '{}'
+
+
+class TransitionalClass(HasTraits):
+
+ d = Any()
+ @default('d')
+ def _d_default(self):
+ return TransitionalClass
+
+ parent_super = False
+ calls_super = Integer(0)
+
+ @default('calls_super')
+ def _calls_super_default(self):
+ return -1
+
+ @observe('calls_super')
+ @observe_compat
+ def _calls_super_changed(self, change):
+ self.parent_super = change
+
+ parent_override = False
+ overrides = Integer(0)
+
+ @observe('overrides')
+ @observe_compat
+ def _overrides_changed(self, change):
+ self.parent_override = change
+
+
+class SubClass(TransitionalClass):
+ def _d_default(self):
+ return SubClass
+
+ subclass_super = False
+ def _calls_super_changed(self, name, old, new):
+ self.subclass_super = True
+ super(SubClass, self)._calls_super_changed(name, old, new)
+
+ subclass_override = False
+ def _overrides_changed(self, name, old, new):
+ self.subclass_override = True
+
+
+def test_subclass_compat():
+ obj = SubClass()
+ obj.calls_super = 5
+ assert obj.parent_super
+ assert obj.subclass_super
+ obj.overrides = 5
+ assert obj.subclass_override
+ assert not obj.parent_override
+ assert obj.d is SubClass
+
+
+class DefinesHandler(HasTraits):
+ parent_called = False
+
+ trait = Integer()
+ @observe('trait')
+ def handler(self, change):
+ self.parent_called = True
+
+
+class OverridesHandler(DefinesHandler):
+ child_called = False
+
+ @observe('trait')
+ def handler(self, change):
+ self.child_called = True
+
+
+def test_subclass_override_observer():
+ obj = OverridesHandler()
+ obj.trait = 5
+ assert obj.child_called
+ assert not obj.parent_called
+
+
+class DoesntRegisterHandler(DefinesHandler):
+ child_called = False
+
+ def handler(self, change):
+ self.child_called = True
+
+
+def test_subclass_override_not_registered():
+ """Subclass that overrides observer and doesn't re-register unregisters both"""
+ obj = DoesntRegisterHandler()
+ obj.trait = 5
+ assert not obj.child_called
+ assert not obj.parent_called
+
+
+class AddsHandler(DefinesHandler):
+ child_called = False
+
+ @observe('trait')
+ def child_handler(self, change):
+ self.child_called = True
+
+def test_subclass_add_observer():
+ obj = AddsHandler()
+ obj.trait = 5
+ assert obj.child_called
+ assert obj.parent_called
+
+
+def test_observe_iterables():
+
+ class C(HasTraits):
+ i = Integer()
+ s = Unicode()
+
+ c = C()
+ recorded = {}
+ def record(change):
+ recorded['change'] = change
+
+ # observe with names=set
+ c.observe(record, names={'i', 's'})
+ c.i = 5
+ assert recorded['change'].name == 'i'
+ assert recorded['change'].new == 5
+ c.s = 'hi'
+ assert recorded['change'].name == 's'
+ assert recorded['change'].new == 'hi'
+
+ # observe with names=custom container with iter, contains
+ class MyContainer(object):
+ def __init__(self, container):
+ self.container = container
+
+ def __iter__(self):
+ return iter(self.container)
+
+ def __contains__(self, key):
+ return key in self.container
+
+ c.observe(record, names=MyContainer({'i', 's'}))
+ c.i = 10
+ assert recorded['change'].name == 'i'
+ assert recorded['change'].new == 10
+ c.s = 'ok'
+ assert recorded['change'].name == 's'
+ assert recorded['change'].new == 'ok'
+
+
+def test_super_args():
+ class SuperRecorder(object):
+ def __init__(self, *args, **kwargs):
+ self.super_args = args
+ self.super_kwargs = kwargs
+
+ class SuperHasTraits(HasTraits, SuperRecorder):
+ i = Integer()
+
+ obj = SuperHasTraits('a1', 'a2', b=10, i=5, c='x')
+ assert obj.i == 5
+ assert not hasattr(obj, 'b')
+ assert not hasattr(obj, 'c')
+ assert obj.super_args == ('a1' , 'a2')
+ assert obj.super_kwargs == {'b': 10 , 'c': 'x'}
+
+def test_super_bad_args():
+ class SuperHasTraits(HasTraits):
+ a = Integer()
+
+ if sys.version_info < (3,):
+ # Legacy Python, object.__init__ warns itself, instead of raising
+ w = ['object.__init__']
+ else:
+ w = ["Passing unrecoginized arguments"]
+ with expected_warnings(w):
+ obj = SuperHasTraits(a=1, b=2)
+ assert obj.a == 1
+ assert not hasattr(obj, 'b')
diff --git a/contrib/python/traitlets/py2/traitlets/tests/test_traitlets_enum.py b/contrib/python/traitlets/py2/traitlets/tests/test_traitlets_enum.py
index 234466ac99..82259ae6c5 100644
--- a/contrib/python/traitlets/py2/traitlets/tests/test_traitlets_enum.py
+++ b/contrib/python/traitlets/py2/traitlets/tests/test_traitlets_enum.py
@@ -1,181 +1,181 @@
-# -*- coding: UTF-8 -*-
-# pylint: disable=missing-docstring, too-few-public-methods
-"""
-Test the trait-type ``UseEnum``.
-"""
-
-import unittest
-import enum
-from ipython_genutils.py3compat import string_types
-from traitlets import HasTraits, TraitError, UseEnum
-
-
-# -----------------------------------------------------------------------------
-# TEST SUPPORT:
-# -----------------------------------------------------------------------------
-class Color(enum.Enum):
- red = 1
- green = 2
- blue = 3
- yellow = 4
-
-class OtherColor(enum.Enum):
- red = 0
- green = 1
-
-
-# -----------------------------------------------------------------------------
-# TESTSUITE:
-# -----------------------------------------------------------------------------
-class TestUseEnum(unittest.TestCase):
- # pylint: disable=invalid-name
-
- class Example(HasTraits):
- color = UseEnum(Color, help="Color enum")
-
- def test_assign_enum_value(self):
- example = self.Example()
- example.color = Color.green
- self.assertEqual(example.color, Color.green)
-
- def test_assign_all_enum_values(self):
- # pylint: disable=no-member
- enum_values = [value for value in Color.__members__.values()]
- for value in enum_values:
- self.assertIsInstance(value, Color)
- example = self.Example()
- example.color = value
- self.assertEqual(example.color, value)
- self.assertIsInstance(value, Color)
-
- def test_assign_enum_value__with_other_enum_raises_error(self):
- example = self.Example()
- with self.assertRaises(TraitError):
- example.color = OtherColor.green
-
- def test_assign_enum_name_1(self):
- # -- CONVERT: string => Enum value (item)
- example = self.Example()
- example.color = "red"
- self.assertEqual(example.color, Color.red)
-
- def test_assign_enum_value_name(self):
- # -- CONVERT: string => Enum value (item)
- # pylint: disable=no-member
- enum_names = [enum_val.name for enum_val in Color.__members__.values()]
- for value in enum_names:
- self.assertIsInstance(value, string_types)
- example = self.Example()
- enum_value = Color.__members__.get(value)
- example.color = value
- self.assertIs(example.color, enum_value)
- self.assertEqual(example.color.name, value)
-
- def test_assign_scoped_enum_value_name(self):
- # -- CONVERT: string => Enum value (item)
- scoped_names = ["Color.red", "Color.green", "Color.blue", "Color.yellow"]
- for value in scoped_names:
- example = self.Example()
- example.color = value
- self.assertIsInstance(example.color, Color)
- self.assertEqual(str(example.color), value)
-
- def test_assign_bad_enum_value_name__raises_error(self):
- # -- CONVERT: string => Enum value (item)
- bad_enum_names = ["UNKNOWN_COLOR", "RED", "Green", "blue2"]
- for value in bad_enum_names:
- example = self.Example()
- with self.assertRaises(TraitError):
- example.color = value
-
- def test_assign_enum_value_number_1(self):
- # -- CONVERT: number => Enum value (item)
- example = self.Example()
- example.color = 1 # == Color.red.value
- example.color = Color.red.value
- self.assertEqual(example.color, Color.red)
-
- def test_assign_enum_value_number(self):
- # -- CONVERT: number => Enum value (item)
- # pylint: disable=no-member
- enum_numbers = [enum_val.value
- for enum_val in Color.__members__.values()]
- for value in enum_numbers:
- self.assertIsInstance(value, int)
- example = self.Example()
- example.color = value
- self.assertIsInstance(example.color, Color)
- self.assertEqual(example.color.value, value)
-
- def test_assign_bad_enum_value_number__raises_error(self):
- # -- CONVERT: number => Enum value (item)
- bad_numbers = [-1, 0, 5]
- for value in bad_numbers:
- self.assertIsInstance(value, int)
- assert UseEnum(Color).select_by_number(value, None) is None
- example = self.Example()
- with self.assertRaises(TraitError):
- example.color = value
-
- def test_ctor_without_default_value(self):
- # -- IMPLICIT: default_value = Color.red (first enum-value)
- class Example2(HasTraits):
- color = UseEnum(Color)
-
- example = Example2()
- self.assertEqual(example.color, Color.red)
-
- def test_ctor_with_default_value_as_enum_value(self):
- # -- CONVERT: number => Enum value (item)
- class Example2(HasTraits):
- color = UseEnum(Color, default_value=Color.green)
-
- example = Example2()
- self.assertEqual(example.color, Color.green)
-
-
- def test_ctor_with_default_value_none_and_not_allow_none(self):
- # -- IMPLICIT: default_value = Color.red (first enum-value)
- class Example2(HasTraits):
- color1 = UseEnum(Color, default_value=None, allow_none=False)
- color2 = UseEnum(Color, default_value=None)
- example = Example2()
- self.assertEqual(example.color1, Color.red)
- self.assertEqual(example.color2, Color.red)
-
- def test_ctor_with_default_value_none_and_allow_none(self):
- class Example2(HasTraits):
- color1 = UseEnum(Color, default_value=None, allow_none=True)
- color2 = UseEnum(Color, allow_none=True)
-
- example = Example2()
- self.assertIs(example.color1, None)
- self.assertIs(example.color2, None)
-
- def test_assign_none_without_allow_none_resets_to_default_value(self):
- class Example2(HasTraits):
- color1 = UseEnum(Color, allow_none=False)
- color2 = UseEnum(Color)
-
- example = Example2()
- example.color1 = None
- example.color2 = None
- self.assertIs(example.color1, Color.red)
- self.assertIs(example.color2, Color.red)
-
- def test_assign_none_to_enum_or_none(self):
- class Example2(HasTraits):
- color = UseEnum(Color, allow_none=True)
-
- example = Example2()
- example.color = None
- self.assertIs(example.color, None)
-
- def test_assign_bad_value_with_to_enum_or_none(self):
- class Example2(HasTraits):
- color = UseEnum(Color, allow_none=True)
-
- example = Example2()
- with self.assertRaises(TraitError):
- example.color = "BAD_VALUE"
-
+# -*- coding: UTF-8 -*-
+# pylint: disable=missing-docstring, too-few-public-methods
+"""
+Test the trait-type ``UseEnum``.
+"""
+
+import unittest
+import enum
+from ipython_genutils.py3compat import string_types
+from traitlets import HasTraits, TraitError, UseEnum
+
+
+# -----------------------------------------------------------------------------
+# TEST SUPPORT:
+# -----------------------------------------------------------------------------
+class Color(enum.Enum):
+ red = 1
+ green = 2
+ blue = 3
+ yellow = 4
+
+class OtherColor(enum.Enum):
+ red = 0
+ green = 1
+
+
+# -----------------------------------------------------------------------------
+# TESTSUITE:
+# -----------------------------------------------------------------------------
+class TestUseEnum(unittest.TestCase):
+ # pylint: disable=invalid-name
+
+ class Example(HasTraits):
+ color = UseEnum(Color, help="Color enum")
+
+ def test_assign_enum_value(self):
+ example = self.Example()
+ example.color = Color.green
+ self.assertEqual(example.color, Color.green)
+
+ def test_assign_all_enum_values(self):
+ # pylint: disable=no-member
+ enum_values = [value for value in Color.__members__.values()]
+ for value in enum_values:
+ self.assertIsInstance(value, Color)
+ example = self.Example()
+ example.color = value
+ self.assertEqual(example.color, value)
+ self.assertIsInstance(value, Color)
+
+ def test_assign_enum_value__with_other_enum_raises_error(self):
+ example = self.Example()
+ with self.assertRaises(TraitError):
+ example.color = OtherColor.green
+
+ def test_assign_enum_name_1(self):
+ # -- CONVERT: string => Enum value (item)
+ example = self.Example()
+ example.color = "red"
+ self.assertEqual(example.color, Color.red)
+
+ def test_assign_enum_value_name(self):
+ # -- CONVERT: string => Enum value (item)
+ # pylint: disable=no-member
+ enum_names = [enum_val.name for enum_val in Color.__members__.values()]
+ for value in enum_names:
+ self.assertIsInstance(value, string_types)
+ example = self.Example()
+ enum_value = Color.__members__.get(value)
+ example.color = value
+ self.assertIs(example.color, enum_value)
+ self.assertEqual(example.color.name, value)
+
+ def test_assign_scoped_enum_value_name(self):
+ # -- CONVERT: string => Enum value (item)
+ scoped_names = ["Color.red", "Color.green", "Color.blue", "Color.yellow"]
+ for value in scoped_names:
+ example = self.Example()
+ example.color = value
+ self.assertIsInstance(example.color, Color)
+ self.assertEqual(str(example.color), value)
+
+ def test_assign_bad_enum_value_name__raises_error(self):
+ # -- CONVERT: string => Enum value (item)
+ bad_enum_names = ["UNKNOWN_COLOR", "RED", "Green", "blue2"]
+ for value in bad_enum_names:
+ example = self.Example()
+ with self.assertRaises(TraitError):
+ example.color = value
+
+ def test_assign_enum_value_number_1(self):
+ # -- CONVERT: number => Enum value (item)
+ example = self.Example()
+ example.color = 1 # == Color.red.value
+ example.color = Color.red.value
+ self.assertEqual(example.color, Color.red)
+
+ def test_assign_enum_value_number(self):
+ # -- CONVERT: number => Enum value (item)
+ # pylint: disable=no-member
+ enum_numbers = [enum_val.value
+ for enum_val in Color.__members__.values()]
+ for value in enum_numbers:
+ self.assertIsInstance(value, int)
+ example = self.Example()
+ example.color = value
+ self.assertIsInstance(example.color, Color)
+ self.assertEqual(example.color.value, value)
+
+ def test_assign_bad_enum_value_number__raises_error(self):
+ # -- CONVERT: number => Enum value (item)
+ bad_numbers = [-1, 0, 5]
+ for value in bad_numbers:
+ self.assertIsInstance(value, int)
+ assert UseEnum(Color).select_by_number(value, None) is None
+ example = self.Example()
+ with self.assertRaises(TraitError):
+ example.color = value
+
+ def test_ctor_without_default_value(self):
+ # -- IMPLICIT: default_value = Color.red (first enum-value)
+ class Example2(HasTraits):
+ color = UseEnum(Color)
+
+ example = Example2()
+ self.assertEqual(example.color, Color.red)
+
+ def test_ctor_with_default_value_as_enum_value(self):
+ # -- CONVERT: number => Enum value (item)
+ class Example2(HasTraits):
+ color = UseEnum(Color, default_value=Color.green)
+
+ example = Example2()
+ self.assertEqual(example.color, Color.green)
+
+
+ def test_ctor_with_default_value_none_and_not_allow_none(self):
+ # -- IMPLICIT: default_value = Color.red (first enum-value)
+ class Example2(HasTraits):
+ color1 = UseEnum(Color, default_value=None, allow_none=False)
+ color2 = UseEnum(Color, default_value=None)
+ example = Example2()
+ self.assertEqual(example.color1, Color.red)
+ self.assertEqual(example.color2, Color.red)
+
+ def test_ctor_with_default_value_none_and_allow_none(self):
+ class Example2(HasTraits):
+ color1 = UseEnum(Color, default_value=None, allow_none=True)
+ color2 = UseEnum(Color, allow_none=True)
+
+ example = Example2()
+ self.assertIs(example.color1, None)
+ self.assertIs(example.color2, None)
+
+ def test_assign_none_without_allow_none_resets_to_default_value(self):
+ class Example2(HasTraits):
+ color1 = UseEnum(Color, allow_none=False)
+ color2 = UseEnum(Color)
+
+ example = Example2()
+ example.color1 = None
+ example.color2 = None
+ self.assertIs(example.color1, Color.red)
+ self.assertIs(example.color2, Color.red)
+
+ def test_assign_none_to_enum_or_none(self):
+ class Example2(HasTraits):
+ color = UseEnum(Color, allow_none=True)
+
+ example = Example2()
+ example.color = None
+ self.assertIs(example.color, None)
+
+ def test_assign_bad_value_with_to_enum_or_none(self):
+ class Example2(HasTraits):
+ color = UseEnum(Color, allow_none=True)
+
+ example = Example2()
+ with self.assertRaises(TraitError):
+ example.color = "BAD_VALUE"
+
diff --git a/contrib/python/traitlets/py2/traitlets/tests/utils.py b/contrib/python/traitlets/py2/traitlets/tests/utils.py
index 4efe85358a..88845d8519 100644
--- a/contrib/python/traitlets/py2/traitlets/tests/utils.py
+++ b/contrib/python/traitlets/py2/traitlets/tests/utils.py
@@ -1,39 +1,39 @@
-import sys
-
-from subprocess import Popen, PIPE
-
-def get_output_error_code(cmd):
- """Get stdout, stderr, and exit code from running a command"""
+import sys
+
+from subprocess import Popen, PIPE
+
+def get_output_error_code(cmd):
+ """Get stdout, stderr, and exit code from running a command"""
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
- out, err = p.communicate()
- out = out.decode('utf8', 'replace')
- err = err.decode('utf8', 'replace')
- return out, err, p.returncode
-
-
-def check_help_output(pkg, subcommand=None):
- """test that `python -m PKG [subcommand] -h` works"""
- cmd = [sys.executable, '-m', pkg]
- if subcommand:
- cmd.extend(subcommand)
- cmd.append('-h')
- out, err, rc = get_output_error_code(cmd)
- assert rc == 0, err
- assert "Traceback" not in err
- assert "Options" in out
- assert "--help-all" in out
- return out, err
-
-
-def check_help_all_output(pkg, subcommand=None):
- """test that `python -m PKG --help-all` works"""
- cmd = [sys.executable, '-m', pkg]
- if subcommand:
- cmd.extend(subcommand)
- cmd.append('--help-all')
- out, err, rc = get_output_error_code(cmd)
- assert rc == 0, err
- assert "Traceback" not in err
- assert "Options" in out
- assert "Class parameters" in out
- return out, err
+ out, err = p.communicate()
+ out = out.decode('utf8', 'replace')
+ err = err.decode('utf8', 'replace')
+ return out, err, p.returncode
+
+
+def check_help_output(pkg, subcommand=None):
+ """test that `python -m PKG [subcommand] -h` works"""
+ cmd = [sys.executable, '-m', pkg]
+ if subcommand:
+ cmd.extend(subcommand)
+ cmd.append('-h')
+ out, err, rc = get_output_error_code(cmd)
+ assert rc == 0, err
+ assert "Traceback" not in err
+ assert "Options" in out
+ assert "--help-all" in out
+ return out, err
+
+
+def check_help_all_output(pkg, subcommand=None):
+ """test that `python -m PKG --help-all` works"""
+ cmd = [sys.executable, '-m', pkg]
+ if subcommand:
+ cmd.extend(subcommand)
+ cmd.append('--help-all')
+ out, err, rc = get_output_error_code(cmd)
+ assert rc == 0, err
+ assert "Traceback" not in err
+ assert "Options" in out
+ assert "Class parameters" in out
+ return out, err
diff --git a/contrib/python/traitlets/py2/ya.make b/contrib/python/traitlets/py2/ya.make
index ed668b5d34..4a60107101 100644
--- a/contrib/python/traitlets/py2/ya.make
+++ b/contrib/python/traitlets/py2/ya.make
@@ -44,7 +44,7 @@ RESOURCE_FILES(
)
END()
-
-RECURSE_FOR_TESTS(
+
+RECURSE_FOR_TESTS(
tests
-)
+)
diff --git a/contrib/python/traitlets/py3/traitlets/tests/_warnings.py b/contrib/python/traitlets/py3/traitlets/tests/_warnings.py
index eb80d0a936..05e916806f 100644
--- a/contrib/python/traitlets/py3/traitlets/tests/_warnings.py
+++ b/contrib/python/traitlets/py3/traitlets/tests/_warnings.py
@@ -1,110 +1,110 @@
-# From scikit-image: https://github.com/scikit-image/scikit-image/blob/c2f8c4ab123ebe5f7b827bc495625a32bb225c10/skimage/_shared/_warnings.py
-# Licensed under modified BSD license
-
-__all__ = ['all_warnings', 'expected_warnings']
-
+# From scikit-image: https://github.com/scikit-image/scikit-image/blob/c2f8c4ab123ebe5f7b827bc495625a32bb225c10/skimage/_shared/_warnings.py
+# Licensed under modified BSD license
+
+__all__ = ['all_warnings', 'expected_warnings']
+
import inspect
import os
import re
-import sys
-import warnings
+import sys
+import warnings
from contextlib import contextmanager
from unittest import mock
-
-
-@contextmanager
-def all_warnings():
- """
- Context for use in testing to ensure that all warnings are raised.
- Examples
- --------
- >>> import warnings
- >>> def foo():
- ... warnings.warn(RuntimeWarning("bar"))
- We raise the warning once, while the warning filter is set to "once".
- Hereafter, the warning is invisible, even with custom filters:
- >>> with warnings.catch_warnings():
- ... warnings.simplefilter('once')
- ... foo()
- We can now run ``foo()`` without a warning being raised:
- >>> from numpy.testing import assert_warns
- >>> foo()
- To catch the warning, we call in the help of ``all_warnings``:
- >>> with all_warnings():
- ... assert_warns(RuntimeWarning, foo)
- """
-
- # Whenever a warning is triggered, Python adds a __warningregistry__
- # member to the *calling* module. The exercize here is to find
- # and eradicate all those breadcrumbs that were left lying around.
- #
- # We proceed by first searching all parent calling frames and explicitly
- # clearing their warning registries (necessary for the doctests above to
- # pass). Then, we search for all submodules of skimage and clear theirs
- # as well (necessary for the skimage test suite to pass).
-
- frame = inspect.currentframe()
- if frame:
- for f in inspect.getouterframes(frame):
- f[0].f_locals['__warningregistry__'] = {}
- del frame
-
- for mod_name, mod in list(sys.modules.items()):
- try:
- mod.__warningregistry__.clear()
- except AttributeError:
- pass
-
+
+
+@contextmanager
+def all_warnings():
+ """
+ Context for use in testing to ensure that all warnings are raised.
+ Examples
+ --------
+ >>> import warnings
+ >>> def foo():
+ ... warnings.warn(RuntimeWarning("bar"))
+ We raise the warning once, while the warning filter is set to "once".
+ Hereafter, the warning is invisible, even with custom filters:
+ >>> with warnings.catch_warnings():
+ ... warnings.simplefilter('once')
+ ... foo()
+ We can now run ``foo()`` without a warning being raised:
+ >>> from numpy.testing import assert_warns
+ >>> foo()
+ To catch the warning, we call in the help of ``all_warnings``:
+ >>> with all_warnings():
+ ... assert_warns(RuntimeWarning, foo)
+ """
+
+ # Whenever a warning is triggered, Python adds a __warningregistry__
+ # member to the *calling* module. The exercize here is to find
+ # and eradicate all those breadcrumbs that were left lying around.
+ #
+ # We proceed by first searching all parent calling frames and explicitly
+ # clearing their warning registries (necessary for the doctests above to
+ # pass). Then, we search for all submodules of skimage and clear theirs
+ # as well (necessary for the skimage test suite to pass).
+
+ frame = inspect.currentframe()
+ if frame:
+ for f in inspect.getouterframes(frame):
+ f[0].f_locals['__warningregistry__'] = {}
+ del frame
+
+ for mod_name, mod in list(sys.modules.items()):
+ try:
+ mod.__warningregistry__.clear()
+ except AttributeError:
+ pass
+
with warnings.catch_warnings(record=True) as w, \
mock.patch.dict(os.environ, {'TRAITLETS_ALL_DEPRECATIONS': '1'}):
- warnings.simplefilter("always")
- yield w
-
-
-@contextmanager
-def expected_warnings(matching):
+ warnings.simplefilter("always")
+ yield w
+
+
+@contextmanager
+def expected_warnings(matching):
r"""Context for use in testing to catch known warnings matching regexes
- Parameters
- ----------
- matching : list of strings or compiled regexes
- Regexes for the desired warning to catch
+ Parameters
+ ----------
+ matching : list of strings or compiled regexes
+ Regexes for the desired warning to catch
- Examples
- --------
- >>> from skimage import data, img_as_ubyte, img_as_float
+ Examples
+ --------
+ >>> from skimage import data, img_as_ubyte, img_as_float
>>> with expected_warnings(["precision loss"]):
- ... d = img_as_ubyte(img_as_float(data.coins()))
+ ... d = img_as_ubyte(img_as_float(data.coins()))
- Notes
- -----
- Uses `all_warnings` to ensure all warnings are raised.
- Upon exiting, it checks the recorded warnings for the desired matching
- pattern(s).
- Raises a ValueError if any match was not found or an unexpected
- warning was raised.
- Allows for three types of behaviors: "and", "or", and "optional" matches.
- This is done to accomodate different build enviroments or loop conditions
- that may produce different warnings. The behaviors can be combined.
- If you pass multiple patterns, you get an orderless "and", where all of the
- warnings must be raised.
- If you use the "|" operator in a pattern, you can catch one of several warnings.
- Finally, you can use "|\A\Z" in a pattern to signify it as optional.
- """
- with all_warnings() as w:
- # enter context
- yield w
- # exited user context, check the recorded warnings
+ Notes
+ -----
+ Uses `all_warnings` to ensure all warnings are raised.
+ Upon exiting, it checks the recorded warnings for the desired matching
+ pattern(s).
+ Raises a ValueError if any match was not found or an unexpected
+ warning was raised.
+ Allows for three types of behaviors: "and", "or", and "optional" matches.
+ This is done to accomodate different build enviroments or loop conditions
+ that may produce different warnings. The behaviors can be combined.
+ If you pass multiple patterns, you get an orderless "and", where all of the
+ warnings must be raised.
+ If you use the "|" operator in a pattern, you can catch one of several warnings.
+ Finally, you can use "|\A\Z" in a pattern to signify it as optional.
+ """
+ with all_warnings() as w:
+ # enter context
+ yield w
+ # exited user context, check the recorded warnings
remaining = [m for m in matching if not r'\A\Z' in m.split('|')]
- for warn in w:
- found = False
- for match in matching:
- if re.search(match, str(warn.message)) is not None:
- found = True
- if match in remaining:
- remaining.remove(match)
- if not found:
- raise ValueError('Unexpected warning: %s' % str(warn.message))
- if len(remaining) > 0:
- msg = 'No warning raised matching:\n%s' % '\n'.join(remaining)
- raise ValueError(msg)
+ for warn in w:
+ found = False
+ for match in matching:
+ if re.search(match, str(warn.message)) is not None:
+ found = True
+ if match in remaining:
+ remaining.remove(match)
+ if not found:
+ raise ValueError('Unexpected warning: %s' % str(warn.message))
+ if len(remaining) > 0:
+ msg = 'No warning raised matching:\n%s' % '\n'.join(remaining)
+ raise ValueError(msg)
diff --git a/contrib/python/traitlets/py3/traitlets/tests/test_traitlets.py b/contrib/python/traitlets/py3/traitlets/tests/test_traitlets.py
index ece95f6108..e42dbc01d0 100644
--- a/contrib/python/traitlets/py3/traitlets/tests/test_traitlets.py
+++ b/contrib/python/traitlets/py3/traitlets/tests/test_traitlets.py
@@ -1,20 +1,20 @@
-# encoding: utf-8
-"""Tests for traitlets.traitlets."""
-
-# Copyright (c) IPython Development Team.
-# Distributed under the terms of the Modified BSD License.
+# encoding: utf-8
+"""Tests for traitlets.traitlets."""
+
+# Copyright (c) IPython Development Team.
+# Distributed under the terms of the Modified BSD License.
#
-# Adapted from enthought.traits, Copyright (c) Enthought, Inc.,
-# also under the terms of the Modified BSD License.
-
-import pickle
-import re
+# Adapted from enthought.traits, Copyright (c) Enthought, Inc.,
+# also under the terms of the Modified BSD License.
+
+import pickle
+import re
from unittest import TestCase
-
-import pytest
-
+
+import pytest
+
from traitlets.tests._warnings import expected_warnings
-from traitlets import (
+from traitlets import (
HasTraits,
MetaHasTraits,
TraitType,
@@ -60,121 +60,121 @@ from traitlets import (
BaseDescriptor,
HasDescriptors,
CUnicode,
-)
+)
from traitlets.utils import cast_unicode
-
-
-def change_dict(*ordered_values):
- change_names = ('name', 'old', 'new', 'owner', 'type')
- return dict(zip(change_names, ordered_values))
-
-#-----------------------------------------------------------------------------
-# Helper classes for testing
-#-----------------------------------------------------------------------------
-
-
-class HasTraitsStub(HasTraits):
-
- def notify_change(self, change):
- self._notify_name = change['name']
- self._notify_old = change['old']
- self._notify_new = change['new']
- self._notify_type = change['type']
-
-
-#-----------------------------------------------------------------------------
-# Test classes
-#-----------------------------------------------------------------------------
-
-
-class TestTraitType(TestCase):
-
- def test_get_undefined(self):
- class A(HasTraits):
- a = TraitType
- a = A()
+
+
+def change_dict(*ordered_values):
+ change_names = ('name', 'old', 'new', 'owner', 'type')
+ return dict(zip(change_names, ordered_values))
+
+#-----------------------------------------------------------------------------
+# Helper classes for testing
+#-----------------------------------------------------------------------------
+
+
+class HasTraitsStub(HasTraits):
+
+ def notify_change(self, change):
+ self._notify_name = change['name']
+ self._notify_old = change['old']
+ self._notify_new = change['new']
+ self._notify_type = change['type']
+
+
+#-----------------------------------------------------------------------------
+# Test classes
+#-----------------------------------------------------------------------------
+
+
+class TestTraitType(TestCase):
+
+ def test_get_undefined(self):
+ class A(HasTraits):
+ a = TraitType
+ a = A()
assert a.a is Undefined
-
- def test_set(self):
- class A(HasTraitsStub):
- a = TraitType
-
- a = A()
- a.a = 10
- self.assertEqual(a.a, 10)
- self.assertEqual(a._notify_name, 'a')
- self.assertEqual(a._notify_old, Undefined)
- self.assertEqual(a._notify_new, 10)
-
- def test_validate(self):
- class MyTT(TraitType):
- def validate(self, inst, value):
- return -1
- class A(HasTraitsStub):
- tt = MyTT
-
- a = A()
- a.tt = 10
- self.assertEqual(a.tt, -1)
-
- def test_default_validate(self):
- class MyIntTT(TraitType):
- def validate(self, obj, value):
- if isinstance(value, int):
- return value
- self.error(obj, value)
- class A(HasTraits):
- tt = MyIntTT(10)
- a = A()
- self.assertEqual(a.tt, 10)
-
- # Defaults are validated when the HasTraits is instantiated
- class B(HasTraits):
- tt = MyIntTT('bad default')
+
+ def test_set(self):
+ class A(HasTraitsStub):
+ a = TraitType
+
+ a = A()
+ a.a = 10
+ self.assertEqual(a.a, 10)
+ self.assertEqual(a._notify_name, 'a')
+ self.assertEqual(a._notify_old, Undefined)
+ self.assertEqual(a._notify_new, 10)
+
+ def test_validate(self):
+ class MyTT(TraitType):
+ def validate(self, inst, value):
+ return -1
+ class A(HasTraitsStub):
+ tt = MyTT
+
+ a = A()
+ a.tt = 10
+ self.assertEqual(a.tt, -1)
+
+ def test_default_validate(self):
+ class MyIntTT(TraitType):
+ def validate(self, obj, value):
+ if isinstance(value, int):
+ return value
+ self.error(obj, value)
+ class A(HasTraits):
+ tt = MyIntTT(10)
+ a = A()
+ self.assertEqual(a.tt, 10)
+
+ # Defaults are validated when the HasTraits is instantiated
+ class B(HasTraits):
+ tt = MyIntTT('bad default')
self.assertRaises(TraitError, getattr, B(), 'tt')
-
- def test_info(self):
- class A(HasTraits):
- tt = TraitType
- a = A()
- self.assertEqual(A.tt.info(), 'any value')
-
- def test_error(self):
- class A(HasTraits):
+
+ def test_info(self):
+ class A(HasTraits):
+ tt = TraitType
+ a = A()
+ self.assertEqual(A.tt.info(), 'any value')
+
+ def test_error(self):
+ class A(HasTraits):
tt = TraitType()
- a = A()
- self.assertRaises(TraitError, A.tt.error, a, 10)
-
- def test_deprecated_dynamic_initializer(self):
- class A(HasTraits):
- x = Int(10)
- def _x_default(self):
- return 11
- class B(A):
- x = Int(20)
- class C(A):
- def _x_default(self):
- return 21
-
- a = A()
- self.assertEqual(a._trait_values, {})
- self.assertEqual(a.x, 11)
- self.assertEqual(a._trait_values, {'x': 11})
- b = B()
- self.assertEqual(b.x, 20)
- self.assertEqual(b._trait_values, {'x': 20})
- c = C()
- self.assertEqual(c._trait_values, {})
- self.assertEqual(c.x, 21)
- self.assertEqual(c._trait_values, {'x': 21})
- # Ensure that the base class remains unmolested when the _default
- # initializer gets overridden in a subclass.
- a = A()
- c = C()
- self.assertEqual(a._trait_values, {})
- self.assertEqual(a.x, 11)
- self.assertEqual(a._trait_values, {'x': 11})
-
+ a = A()
+ self.assertRaises(TraitError, A.tt.error, a, 10)
+
+ def test_deprecated_dynamic_initializer(self):
+ class A(HasTraits):
+ x = Int(10)
+ def _x_default(self):
+ return 11
+ class B(A):
+ x = Int(20)
+ class C(A):
+ def _x_default(self):
+ return 21
+
+ a = A()
+ self.assertEqual(a._trait_values, {})
+ self.assertEqual(a.x, 11)
+ self.assertEqual(a._trait_values, {'x': 11})
+ b = B()
+ self.assertEqual(b.x, 20)
+ self.assertEqual(b._trait_values, {'x': 20})
+ c = C()
+ self.assertEqual(c._trait_values, {})
+ self.assertEqual(c.x, 21)
+ self.assertEqual(c._trait_values, {'x': 21})
+ # Ensure that the base class remains unmolested when the _default
+ # initializer gets overridden in a subclass.
+ a = A()
+ c = C()
+ self.assertEqual(a._trait_values, {})
+ self.assertEqual(a.x, 11)
+ self.assertEqual(a._trait_values, {'x': 11})
+
def test_deprecated_method_warnings(self):
with expected_warnings([]):
@@ -215,79 +215,79 @@ class TestTraitType(TestCase):
assert obj.x == 5
- def test_dynamic_initializer(self):
-
- class A(HasTraits):
- x = Int(10)
-
- @default('x')
- def _default_x(self):
- return 11
-
- class B(A):
- x = Int(20)
-
- class C(A):
-
- @default('x')
- def _default_x(self):
- return 21
-
- a = A()
- self.assertEqual(a._trait_values, {})
- self.assertEqual(a.x, 11)
- self.assertEqual(a._trait_values, {'x': 11})
- b = B()
- self.assertEqual(b.x, 20)
- self.assertEqual(b._trait_values, {'x': 20})
- c = C()
- self.assertEqual(c._trait_values, {})
- self.assertEqual(c.x, 21)
- self.assertEqual(c._trait_values, {'x': 21})
- # Ensure that the base class remains unmolested when the _default
- # initializer gets overridden in a subclass.
- a = A()
- c = C()
- self.assertEqual(a._trait_values, {})
- self.assertEqual(a.x, 11)
- self.assertEqual(a._trait_values, {'x': 11})
-
- def test_tag_metadata(self):
- class MyIntTT(TraitType):
- metadata = {'a': 1, 'b': 2}
- a = MyIntTT(10).tag(b=3, c=4)
- self.assertEqual(a.metadata, {'a': 1, 'b': 3, 'c': 4})
-
- def test_metadata_localized_instance(self):
- class MyIntTT(TraitType):
- metadata = {'a': 1, 'b': 2}
- a = MyIntTT(10)
- b = MyIntTT(10)
- a.metadata['c'] = 3
- # make sure that changing a's metadata didn't change b's metadata
- self.assertNotIn('c', b.metadata)
-
- def test_union_metadata(self):
- class Foo(HasTraits):
- bar = (Int().tag(ta=1) | Dict().tag(ta=2, ti='b')).tag(ti='a')
- foo = Foo()
- # At this point, no value has been set for bar, so value-specific
- # is not set.
- self.assertEqual(foo.trait_metadata('bar', 'ta'), None)
- self.assertEqual(foo.trait_metadata('bar', 'ti'), 'a')
- foo.bar = {}
- self.assertEqual(foo.trait_metadata('bar', 'ta'), 2)
- self.assertEqual(foo.trait_metadata('bar', 'ti'), 'b')
- foo.bar = 1
- self.assertEqual(foo.trait_metadata('bar', 'ta'), 1)
- self.assertEqual(foo.trait_metadata('bar', 'ti'), 'a')
-
- def test_union_default_value(self):
- class Foo(HasTraits):
- bar = Union([Dict(), Int()], default_value=1)
- foo = Foo()
- self.assertEqual(foo.bar, 1)
-
+ def test_dynamic_initializer(self):
+
+ class A(HasTraits):
+ x = Int(10)
+
+ @default('x')
+ def _default_x(self):
+ return 11
+
+ class B(A):
+ x = Int(20)
+
+ class C(A):
+
+ @default('x')
+ def _default_x(self):
+ return 21
+
+ a = A()
+ self.assertEqual(a._trait_values, {})
+ self.assertEqual(a.x, 11)
+ self.assertEqual(a._trait_values, {'x': 11})
+ b = B()
+ self.assertEqual(b.x, 20)
+ self.assertEqual(b._trait_values, {'x': 20})
+ c = C()
+ self.assertEqual(c._trait_values, {})
+ self.assertEqual(c.x, 21)
+ self.assertEqual(c._trait_values, {'x': 21})
+ # Ensure that the base class remains unmolested when the _default
+ # initializer gets overridden in a subclass.
+ a = A()
+ c = C()
+ self.assertEqual(a._trait_values, {})
+ self.assertEqual(a.x, 11)
+ self.assertEqual(a._trait_values, {'x': 11})
+
+ def test_tag_metadata(self):
+ class MyIntTT(TraitType):
+ metadata = {'a': 1, 'b': 2}
+ a = MyIntTT(10).tag(b=3, c=4)
+ self.assertEqual(a.metadata, {'a': 1, 'b': 3, 'c': 4})
+
+ def test_metadata_localized_instance(self):
+ class MyIntTT(TraitType):
+ metadata = {'a': 1, 'b': 2}
+ a = MyIntTT(10)
+ b = MyIntTT(10)
+ a.metadata['c'] = 3
+ # make sure that changing a's metadata didn't change b's metadata
+ self.assertNotIn('c', b.metadata)
+
+ def test_union_metadata(self):
+ class Foo(HasTraits):
+ bar = (Int().tag(ta=1) | Dict().tag(ta=2, ti='b')).tag(ti='a')
+ foo = Foo()
+ # At this point, no value has been set for bar, so value-specific
+ # is not set.
+ self.assertEqual(foo.trait_metadata('bar', 'ta'), None)
+ self.assertEqual(foo.trait_metadata('bar', 'ti'), 'a')
+ foo.bar = {}
+ self.assertEqual(foo.trait_metadata('bar', 'ta'), 2)
+ self.assertEqual(foo.trait_metadata('bar', 'ti'), 'b')
+ foo.bar = 1
+ self.assertEqual(foo.trait_metadata('bar', 'ta'), 1)
+ self.assertEqual(foo.trait_metadata('bar', 'ti'), 'a')
+
+ def test_union_default_value(self):
+ class Foo(HasTraits):
+ bar = Union([Dict(), Int()], default_value=1)
+ foo = Foo()
+ self.assertEqual(foo.bar, 1)
+
def test_union_validation_priority(self):
class Foo(HasTraits):
bar = Union([CInt(), Unicode()])
@@ -301,506 +301,506 @@ class TestTraitType(TestCase):
bar = Union([Dict(), Int()])
self.assertEqual(Foo().bar, {})
- def test_deprecated_metadata_access(self):
- class MyIntTT(TraitType):
- metadata = {'a': 1, 'b': 2}
- a = MyIntTT(10)
- with expected_warnings(["use the instance .metadata dictionary directly"]*2):
- a.set_metadata('key', 'value')
- v = a.get_metadata('key')
- self.assertEqual(v, 'value')
- with expected_warnings(["use the instance .help string directly"]*2):
- a.set_metadata('help', 'some help')
- v = a.get_metadata('help')
- self.assertEqual(v, 'some help')
-
- def test_trait_types_deprecated(self):
- with expected_warnings(["Traits should be given as instances"]):
- class C(HasTraits):
- t = Int
-
- def test_trait_types_list_deprecated(self):
- with expected_warnings(["Traits should be given as instances"]):
- class C(HasTraits):
- t = List(Int)
-
- def test_trait_types_tuple_deprecated(self):
- with expected_warnings(["Traits should be given as instances"]):
- class C(HasTraits):
- t = Tuple(Int)
-
- def test_trait_types_dict_deprecated(self):
- with expected_warnings(["Traits should be given as instances"]):
- class C(HasTraits):
- t = Dict(Int)
-
-class TestHasDescriptorsMeta(TestCase):
-
- def test_metaclass(self):
- self.assertEqual(type(HasTraits), MetaHasTraits)
-
- class A(HasTraits):
- a = Int()
-
- a = A()
- self.assertEqual(type(a.__class__), MetaHasTraits)
- self.assertEqual(a.a,0)
- a.a = 10
- self.assertEqual(a.a,10)
-
- class B(HasTraits):
- b = Int()
-
- b = B()
- self.assertEqual(b.b,0)
- b.b = 10
- self.assertEqual(b.b,10)
-
- class C(HasTraits):
- c = Int(30)
-
- c = C()
- self.assertEqual(c.c,30)
- c.c = 10
- self.assertEqual(c.c,10)
-
- def test_this_class(self):
- class A(HasTraits):
- t = This()
- tt = This()
- class B(A):
- tt = This()
- ttt = This()
- self.assertEqual(A.t.this_class, A)
- self.assertEqual(B.t.this_class, A)
- self.assertEqual(B.tt.this_class, B)
- self.assertEqual(B.ttt.this_class, B)
-
-class TestHasDescriptors(TestCase):
-
- def test_setup_instance(self):
-
- class FooDescriptor(BaseDescriptor):
-
- def instance_init(self, inst):
- foo = inst.foo # instance should have the attr
-
- class HasFooDescriptors(HasDescriptors):
-
- fd = FooDescriptor()
-
- def setup_instance(self, *args, **kwargs):
- self.foo = kwargs.get('foo', None)
- super(HasFooDescriptors, self).setup_instance(*args, **kwargs)
-
- hfd = HasFooDescriptors(foo='bar')
-
-class TestHasTraitsNotify(TestCase):
-
- def setUp(self):
- self._notify1 = []
- self._notify2 = []
-
- def notify1(self, name, old, new):
- self._notify1.append((name, old, new))
-
- def notify2(self, name, old, new):
- self._notify2.append((name, old, new))
-
- def test_notify_all(self):
-
- class A(HasTraits):
- a = Int()
- b = Float()
-
- a = A()
- a.on_trait_change(self.notify1)
- a.a = 0
- self.assertEqual(len(self._notify1),0)
- a.b = 0.0
- self.assertEqual(len(self._notify1),0)
- a.a = 10
- self.assertTrue(('a',0,10) in self._notify1)
- a.b = 10.0
- self.assertTrue(('b',0.0,10.0) in self._notify1)
- self.assertRaises(TraitError,setattr,a,'a','bad string')
- self.assertRaises(TraitError,setattr,a,'b','bad string')
- self._notify1 = []
- a.on_trait_change(self.notify1,remove=True)
- a.a = 20
- a.b = 20.0
- self.assertEqual(len(self._notify1),0)
-
- def test_notify_one(self):
-
- class A(HasTraits):
- a = Int()
- b = Float()
-
- a = A()
- a.on_trait_change(self.notify1, 'a')
- a.a = 0
- self.assertEqual(len(self._notify1),0)
- a.a = 10
- self.assertTrue(('a',0,10) in self._notify1)
- self.assertRaises(TraitError,setattr,a,'a','bad string')
-
- def test_subclass(self):
-
- class A(HasTraits):
- a = Int()
-
- class B(A):
- b = Float()
-
- b = B()
- self.assertEqual(b.a,0)
- self.assertEqual(b.b,0.0)
- b.a = 100
- b.b = 100.0
- self.assertEqual(b.a,100)
- self.assertEqual(b.b,100.0)
-
- def test_notify_subclass(self):
-
- class A(HasTraits):
- a = Int()
-
- class B(A):
- b = Float()
-
- b = B()
- b.on_trait_change(self.notify1, 'a')
- b.on_trait_change(self.notify2, 'b')
- b.a = 0
- b.b = 0.0
- self.assertEqual(len(self._notify1),0)
- self.assertEqual(len(self._notify2),0)
- b.a = 10
- b.b = 10.0
- self.assertTrue(('a',0,10) in self._notify1)
- self.assertTrue(('b',0.0,10.0) in self._notify2)
-
- def test_static_notify(self):
-
- class A(HasTraits):
- a = Int()
- _notify1 = []
- def _a_changed(self, name, old, new):
- self._notify1.append((name, old, new))
-
- a = A()
- a.a = 0
- # This is broken!!!
- self.assertEqual(len(a._notify1),0)
- a.a = 10
- self.assertTrue(('a',0,10) in a._notify1)
-
- class B(A):
- b = Float()
- _notify2 = []
- def _b_changed(self, name, old, new):
- self._notify2.append((name, old, new))
-
- b = B()
- b.a = 10
- b.b = 10.0
- self.assertTrue(('a',0,10) in b._notify1)
- self.assertTrue(('b',0.0,10.0) in b._notify2)
-
- def test_notify_args(self):
-
- def callback0():
- self.cb = ()
- def callback1(name):
- self.cb = (name,)
- def callback2(name, new):
- self.cb = (name, new)
- def callback3(name, old, new):
- self.cb = (name, old, new)
- def callback4(name, old, new, obj):
- self.cb = (name, old, new, obj)
-
- class A(HasTraits):
- a = Int()
-
- a = A()
- a.on_trait_change(callback0, 'a')
- a.a = 10
- self.assertEqual(self.cb,())
- a.on_trait_change(callback0, 'a', remove=True)
-
- a.on_trait_change(callback1, 'a')
- a.a = 100
- self.assertEqual(self.cb,('a',))
- a.on_trait_change(callback1, 'a', remove=True)
-
- a.on_trait_change(callback2, 'a')
- a.a = 1000
- self.assertEqual(self.cb,('a',1000))
- a.on_trait_change(callback2, 'a', remove=True)
-
- a.on_trait_change(callback3, 'a')
- a.a = 10000
- self.assertEqual(self.cb,('a',1000,10000))
- a.on_trait_change(callback3, 'a', remove=True)
-
- a.on_trait_change(callback4, 'a')
- a.a = 100000
- self.assertEqual(self.cb,('a',10000,100000,a))
- self.assertEqual(len(a._trait_notifiers['a']['change']), 1)
- a.on_trait_change(callback4, 'a', remove=True)
-
- self.assertEqual(len(a._trait_notifiers['a']['change']), 0)
-
- def test_notify_only_once(self):
-
- class A(HasTraits):
- listen_to = ['a']
-
- a = Int(0)
- b = 0
-
- def __init__(self, **kwargs):
- super(A, self).__init__(**kwargs)
- self.on_trait_change(self.listener1, ['a'])
-
- def listener1(self, name, old, new):
- self.b += 1
-
- class B(A):
-
- c = 0
- d = 0
-
- def __init__(self, **kwargs):
- super(B, self).__init__(**kwargs)
- self.on_trait_change(self.listener2)
-
- def listener2(self, name, old, new):
- self.c += 1
-
- def _a_changed(self, name, old, new):
- self.d += 1
-
- b = B()
- b.a += 1
- self.assertEqual(b.b, b.c)
- self.assertEqual(b.b, b.d)
- b.a += 1
- self.assertEqual(b.b, b.c)
- self.assertEqual(b.b, b.d)
-
-class TestObserveDecorator(TestCase):
-
- def setUp(self):
- self._notify1 = []
- self._notify2 = []
-
- def notify1(self, change):
- self._notify1.append(change)
-
- def notify2(self, change):
- self._notify2.append(change)
-
- def test_notify_all(self):
-
- class A(HasTraits):
- a = Int()
- b = Float()
-
- a = A()
- a.observe(self.notify1)
- a.a = 0
- self.assertEqual(len(self._notify1),0)
- a.b = 0.0
- self.assertEqual(len(self._notify1),0)
- a.a = 10
- change = change_dict('a', 0, 10, a, 'change')
- self.assertTrue(change in self._notify1)
- a.b = 10.0
- change = change_dict('b', 0.0, 10.0, a, 'change')
- self.assertTrue(change in self._notify1)
- self.assertRaises(TraitError,setattr,a,'a','bad string')
- self.assertRaises(TraitError,setattr,a,'b','bad string')
- self._notify1 = []
- a.unobserve(self.notify1)
- a.a = 20
- a.b = 20.0
- self.assertEqual(len(self._notify1),0)
-
- def test_notify_one(self):
-
- class A(HasTraits):
- a = Int()
- b = Float()
-
- a = A()
- a.observe(self.notify1, 'a')
- a.a = 0
- self.assertEqual(len(self._notify1),0)
- a.a = 10
- change = change_dict('a', 0, 10, a, 'change')
- self.assertTrue(change in self._notify1)
- self.assertRaises(TraitError,setattr,a,'a','bad string')
-
- def test_subclass(self):
-
- class A(HasTraits):
- a = Int()
-
- class B(A):
- b = Float()
-
- b = B()
- self.assertEqual(b.a,0)
- self.assertEqual(b.b,0.0)
- b.a = 100
- b.b = 100.0
- self.assertEqual(b.a,100)
- self.assertEqual(b.b,100.0)
-
- def test_notify_subclass(self):
-
- class A(HasTraits):
- a = Int()
-
- class B(A):
- b = Float()
-
- b = B()
- b.observe(self.notify1, 'a')
- b.observe(self.notify2, 'b')
- b.a = 0
- b.b = 0.0
- self.assertEqual(len(self._notify1),0)
- self.assertEqual(len(self._notify2),0)
- b.a = 10
- b.b = 10.0
- change = change_dict('a', 0, 10, b, 'change')
- self.assertTrue(change in self._notify1)
- change = change_dict('b', 0.0, 10.0, b, 'change')
- self.assertTrue(change in self._notify2)
-
- def test_static_notify(self):
-
- class A(HasTraits):
- a = Int()
- b = Int()
- _notify1 = []
- _notify_any = []
-
- @observe('a')
- def _a_changed(self, change):
- self._notify1.append(change)
-
- @observe(All)
- def _any_changed(self, change):
- self._notify_any.append(change)
-
- a = A()
- a.a = 0
- self.assertEqual(len(a._notify1),0)
- a.a = 10
- change = change_dict('a', 0, 10, a, 'change')
- self.assertTrue(change in a._notify1)
- a.b = 1
- self.assertEqual(len(a._notify_any), 2)
- change = change_dict('b', 0, 1, a, 'change')
- self.assertTrue(change in a._notify_any)
-
- class B(A):
- b = Float()
- _notify2 = []
- @observe('b')
- def _b_changed(self, change):
- self._notify2.append(change)
-
- b = B()
- b.a = 10
- b.b = 10.0
- change = change_dict('a', 0, 10, b, 'change')
- self.assertTrue(change in b._notify1)
- change = change_dict('b', 0.0, 10.0, b, 'change')
- self.assertTrue(change in b._notify2)
-
- def test_notify_args(self):
-
- def callback0():
- self.cb = ()
- def callback1(change):
- self.cb = change
-
- class A(HasTraits):
- a = Int()
-
- a = A()
- a.on_trait_change(callback0, 'a')
- a.a = 10
- self.assertEqual(self.cb,())
- a.unobserve(callback0, 'a')
-
- a.observe(callback1, 'a')
- a.a = 100
- change = change_dict('a', 10, 100, a, 'change')
- self.assertEqual(self.cb, change)
- self.assertEqual(len(a._trait_notifiers['a']['change']), 1)
- a.unobserve(callback1, 'a')
-
- self.assertEqual(len(a._trait_notifiers['a']['change']), 0)
-
- def test_notify_only_once(self):
-
- class A(HasTraits):
- listen_to = ['a']
-
- a = Int(0)
- b = 0
-
- def __init__(self, **kwargs):
- super(A, self).__init__(**kwargs)
- self.observe(self.listener1, ['a'])
-
- def listener1(self, change):
- self.b += 1
-
- class B(A):
-
- c = 0
- d = 0
-
- def __init__(self, **kwargs):
- super(B, self).__init__(**kwargs)
- self.observe(self.listener2)
-
- def listener2(self, change):
- self.c += 1
-
- @observe('a')
- def _a_changed(self, change):
- self.d += 1
-
- b = B()
- b.a += 1
- self.assertEqual(b.b, b.c)
- self.assertEqual(b.b, b.d)
- b.a += 1
- self.assertEqual(b.b, b.c)
- self.assertEqual(b.b, b.d)
-
-
-class TestHasTraits(TestCase):
-
- def test_trait_names(self):
- class A(HasTraits):
- i = Int()
- f = Float()
- a = A()
- self.assertEqual(sorted(a.trait_names()),['f','i'])
- self.assertEqual(sorted(A.class_trait_names()),['f','i'])
- self.assertTrue(a.has_trait('f'))
- self.assertFalse(a.has_trait('g'))
-
+ def test_deprecated_metadata_access(self):
+ class MyIntTT(TraitType):
+ metadata = {'a': 1, 'b': 2}
+ a = MyIntTT(10)
+ with expected_warnings(["use the instance .metadata dictionary directly"]*2):
+ a.set_metadata('key', 'value')
+ v = a.get_metadata('key')
+ self.assertEqual(v, 'value')
+ with expected_warnings(["use the instance .help string directly"]*2):
+ a.set_metadata('help', 'some help')
+ v = a.get_metadata('help')
+ self.assertEqual(v, 'some help')
+
+ def test_trait_types_deprecated(self):
+ with expected_warnings(["Traits should be given as instances"]):
+ class C(HasTraits):
+ t = Int
+
+ def test_trait_types_list_deprecated(self):
+ with expected_warnings(["Traits should be given as instances"]):
+ class C(HasTraits):
+ t = List(Int)
+
+ def test_trait_types_tuple_deprecated(self):
+ with expected_warnings(["Traits should be given as instances"]):
+ class C(HasTraits):
+ t = Tuple(Int)
+
+ def test_trait_types_dict_deprecated(self):
+ with expected_warnings(["Traits should be given as instances"]):
+ class C(HasTraits):
+ t = Dict(Int)
+
+class TestHasDescriptorsMeta(TestCase):
+
+ def test_metaclass(self):
+ self.assertEqual(type(HasTraits), MetaHasTraits)
+
+ class A(HasTraits):
+ a = Int()
+
+ a = A()
+ self.assertEqual(type(a.__class__), MetaHasTraits)
+ self.assertEqual(a.a,0)
+ a.a = 10
+ self.assertEqual(a.a,10)
+
+ class B(HasTraits):
+ b = Int()
+
+ b = B()
+ self.assertEqual(b.b,0)
+ b.b = 10
+ self.assertEqual(b.b,10)
+
+ class C(HasTraits):
+ c = Int(30)
+
+ c = C()
+ self.assertEqual(c.c,30)
+ c.c = 10
+ self.assertEqual(c.c,10)
+
+ def test_this_class(self):
+ class A(HasTraits):
+ t = This()
+ tt = This()
+ class B(A):
+ tt = This()
+ ttt = This()
+ self.assertEqual(A.t.this_class, A)
+ self.assertEqual(B.t.this_class, A)
+ self.assertEqual(B.tt.this_class, B)
+ self.assertEqual(B.ttt.this_class, B)
+
+class TestHasDescriptors(TestCase):
+
+ def test_setup_instance(self):
+
+ class FooDescriptor(BaseDescriptor):
+
+ def instance_init(self, inst):
+ foo = inst.foo # instance should have the attr
+
+ class HasFooDescriptors(HasDescriptors):
+
+ fd = FooDescriptor()
+
+ def setup_instance(self, *args, **kwargs):
+ self.foo = kwargs.get('foo', None)
+ super(HasFooDescriptors, self).setup_instance(*args, **kwargs)
+
+ hfd = HasFooDescriptors(foo='bar')
+
+class TestHasTraitsNotify(TestCase):
+
+ def setUp(self):
+ self._notify1 = []
+ self._notify2 = []
+
+ def notify1(self, name, old, new):
+ self._notify1.append((name, old, new))
+
+ def notify2(self, name, old, new):
+ self._notify2.append((name, old, new))
+
+ def test_notify_all(self):
+
+ class A(HasTraits):
+ a = Int()
+ b = Float()
+
+ a = A()
+ a.on_trait_change(self.notify1)
+ a.a = 0
+ self.assertEqual(len(self._notify1),0)
+ a.b = 0.0
+ self.assertEqual(len(self._notify1),0)
+ a.a = 10
+ self.assertTrue(('a',0,10) in self._notify1)
+ a.b = 10.0
+ self.assertTrue(('b',0.0,10.0) in self._notify1)
+ self.assertRaises(TraitError,setattr,a,'a','bad string')
+ self.assertRaises(TraitError,setattr,a,'b','bad string')
+ self._notify1 = []
+ a.on_trait_change(self.notify1,remove=True)
+ a.a = 20
+ a.b = 20.0
+ self.assertEqual(len(self._notify1),0)
+
+ def test_notify_one(self):
+
+ class A(HasTraits):
+ a = Int()
+ b = Float()
+
+ a = A()
+ a.on_trait_change(self.notify1, 'a')
+ a.a = 0
+ self.assertEqual(len(self._notify1),0)
+ a.a = 10
+ self.assertTrue(('a',0,10) in self._notify1)
+ self.assertRaises(TraitError,setattr,a,'a','bad string')
+
+ def test_subclass(self):
+
+ class A(HasTraits):
+ a = Int()
+
+ class B(A):
+ b = Float()
+
+ b = B()
+ self.assertEqual(b.a,0)
+ self.assertEqual(b.b,0.0)
+ b.a = 100
+ b.b = 100.0
+ self.assertEqual(b.a,100)
+ self.assertEqual(b.b,100.0)
+
+ def test_notify_subclass(self):
+
+ class A(HasTraits):
+ a = Int()
+
+ class B(A):
+ b = Float()
+
+ b = B()
+ b.on_trait_change(self.notify1, 'a')
+ b.on_trait_change(self.notify2, 'b')
+ b.a = 0
+ b.b = 0.0
+ self.assertEqual(len(self._notify1),0)
+ self.assertEqual(len(self._notify2),0)
+ b.a = 10
+ b.b = 10.0
+ self.assertTrue(('a',0,10) in self._notify1)
+ self.assertTrue(('b',0.0,10.0) in self._notify2)
+
+ def test_static_notify(self):
+
+ class A(HasTraits):
+ a = Int()
+ _notify1 = []
+ def _a_changed(self, name, old, new):
+ self._notify1.append((name, old, new))
+
+ a = A()
+ a.a = 0
+ # This is broken!!!
+ self.assertEqual(len(a._notify1),0)
+ a.a = 10
+ self.assertTrue(('a',0,10) in a._notify1)
+
+ class B(A):
+ b = Float()
+ _notify2 = []
+ def _b_changed(self, name, old, new):
+ self._notify2.append((name, old, new))
+
+ b = B()
+ b.a = 10
+ b.b = 10.0
+ self.assertTrue(('a',0,10) in b._notify1)
+ self.assertTrue(('b',0.0,10.0) in b._notify2)
+
+ def test_notify_args(self):
+
+ def callback0():
+ self.cb = ()
+ def callback1(name):
+ self.cb = (name,)
+ def callback2(name, new):
+ self.cb = (name, new)
+ def callback3(name, old, new):
+ self.cb = (name, old, new)
+ def callback4(name, old, new, obj):
+ self.cb = (name, old, new, obj)
+
+ class A(HasTraits):
+ a = Int()
+
+ a = A()
+ a.on_trait_change(callback0, 'a')
+ a.a = 10
+ self.assertEqual(self.cb,())
+ a.on_trait_change(callback0, 'a', remove=True)
+
+ a.on_trait_change(callback1, 'a')
+ a.a = 100
+ self.assertEqual(self.cb,('a',))
+ a.on_trait_change(callback1, 'a', remove=True)
+
+ a.on_trait_change(callback2, 'a')
+ a.a = 1000
+ self.assertEqual(self.cb,('a',1000))
+ a.on_trait_change(callback2, 'a', remove=True)
+
+ a.on_trait_change(callback3, 'a')
+ a.a = 10000
+ self.assertEqual(self.cb,('a',1000,10000))
+ a.on_trait_change(callback3, 'a', remove=True)
+
+ a.on_trait_change(callback4, 'a')
+ a.a = 100000
+ self.assertEqual(self.cb,('a',10000,100000,a))
+ self.assertEqual(len(a._trait_notifiers['a']['change']), 1)
+ a.on_trait_change(callback4, 'a', remove=True)
+
+ self.assertEqual(len(a._trait_notifiers['a']['change']), 0)
+
+ def test_notify_only_once(self):
+
+ class A(HasTraits):
+ listen_to = ['a']
+
+ a = Int(0)
+ b = 0
+
+ def __init__(self, **kwargs):
+ super(A, self).__init__(**kwargs)
+ self.on_trait_change(self.listener1, ['a'])
+
+ def listener1(self, name, old, new):
+ self.b += 1
+
+ class B(A):
+
+ c = 0
+ d = 0
+
+ def __init__(self, **kwargs):
+ super(B, self).__init__(**kwargs)
+ self.on_trait_change(self.listener2)
+
+ def listener2(self, name, old, new):
+ self.c += 1
+
+ def _a_changed(self, name, old, new):
+ self.d += 1
+
+ b = B()
+ b.a += 1
+ self.assertEqual(b.b, b.c)
+ self.assertEqual(b.b, b.d)
+ b.a += 1
+ self.assertEqual(b.b, b.c)
+ self.assertEqual(b.b, b.d)
+
+class TestObserveDecorator(TestCase):
+
+ def setUp(self):
+ self._notify1 = []
+ self._notify2 = []
+
+ def notify1(self, change):
+ self._notify1.append(change)
+
+ def notify2(self, change):
+ self._notify2.append(change)
+
+ def test_notify_all(self):
+
+ class A(HasTraits):
+ a = Int()
+ b = Float()
+
+ a = A()
+ a.observe(self.notify1)
+ a.a = 0
+ self.assertEqual(len(self._notify1),0)
+ a.b = 0.0
+ self.assertEqual(len(self._notify1),0)
+ a.a = 10
+ change = change_dict('a', 0, 10, a, 'change')
+ self.assertTrue(change in self._notify1)
+ a.b = 10.0
+ change = change_dict('b', 0.0, 10.0, a, 'change')
+ self.assertTrue(change in self._notify1)
+ self.assertRaises(TraitError,setattr,a,'a','bad string')
+ self.assertRaises(TraitError,setattr,a,'b','bad string')
+ self._notify1 = []
+ a.unobserve(self.notify1)
+ a.a = 20
+ a.b = 20.0
+ self.assertEqual(len(self._notify1),0)
+
+ def test_notify_one(self):
+
+ class A(HasTraits):
+ a = Int()
+ b = Float()
+
+ a = A()
+ a.observe(self.notify1, 'a')
+ a.a = 0
+ self.assertEqual(len(self._notify1),0)
+ a.a = 10
+ change = change_dict('a', 0, 10, a, 'change')
+ self.assertTrue(change in self._notify1)
+ self.assertRaises(TraitError,setattr,a,'a','bad string')
+
+ def test_subclass(self):
+
+ class A(HasTraits):
+ a = Int()
+
+ class B(A):
+ b = Float()
+
+ b = B()
+ self.assertEqual(b.a,0)
+ self.assertEqual(b.b,0.0)
+ b.a = 100
+ b.b = 100.0
+ self.assertEqual(b.a,100)
+ self.assertEqual(b.b,100.0)
+
+ def test_notify_subclass(self):
+
+ class A(HasTraits):
+ a = Int()
+
+ class B(A):
+ b = Float()
+
+ b = B()
+ b.observe(self.notify1, 'a')
+ b.observe(self.notify2, 'b')
+ b.a = 0
+ b.b = 0.0
+ self.assertEqual(len(self._notify1),0)
+ self.assertEqual(len(self._notify2),0)
+ b.a = 10
+ b.b = 10.0
+ change = change_dict('a', 0, 10, b, 'change')
+ self.assertTrue(change in self._notify1)
+ change = change_dict('b', 0.0, 10.0, b, 'change')
+ self.assertTrue(change in self._notify2)
+
+ def test_static_notify(self):
+
+ class A(HasTraits):
+ a = Int()
+ b = Int()
+ _notify1 = []
+ _notify_any = []
+
+ @observe('a')
+ def _a_changed(self, change):
+ self._notify1.append(change)
+
+ @observe(All)
+ def _any_changed(self, change):
+ self._notify_any.append(change)
+
+ a = A()
+ a.a = 0
+ self.assertEqual(len(a._notify1),0)
+ a.a = 10
+ change = change_dict('a', 0, 10, a, 'change')
+ self.assertTrue(change in a._notify1)
+ a.b = 1
+ self.assertEqual(len(a._notify_any), 2)
+ change = change_dict('b', 0, 1, a, 'change')
+ self.assertTrue(change in a._notify_any)
+
+ class B(A):
+ b = Float()
+ _notify2 = []
+ @observe('b')
+ def _b_changed(self, change):
+ self._notify2.append(change)
+
+ b = B()
+ b.a = 10
+ b.b = 10.0
+ change = change_dict('a', 0, 10, b, 'change')
+ self.assertTrue(change in b._notify1)
+ change = change_dict('b', 0.0, 10.0, b, 'change')
+ self.assertTrue(change in b._notify2)
+
+ def test_notify_args(self):
+
+ def callback0():
+ self.cb = ()
+ def callback1(change):
+ self.cb = change
+
+ class A(HasTraits):
+ a = Int()
+
+ a = A()
+ a.on_trait_change(callback0, 'a')
+ a.a = 10
+ self.assertEqual(self.cb,())
+ a.unobserve(callback0, 'a')
+
+ a.observe(callback1, 'a')
+ a.a = 100
+ change = change_dict('a', 10, 100, a, 'change')
+ self.assertEqual(self.cb, change)
+ self.assertEqual(len(a._trait_notifiers['a']['change']), 1)
+ a.unobserve(callback1, 'a')
+
+ self.assertEqual(len(a._trait_notifiers['a']['change']), 0)
+
+ def test_notify_only_once(self):
+
+ class A(HasTraits):
+ listen_to = ['a']
+
+ a = Int(0)
+ b = 0
+
+ def __init__(self, **kwargs):
+ super(A, self).__init__(**kwargs)
+ self.observe(self.listener1, ['a'])
+
+ def listener1(self, change):
+ self.b += 1
+
+ class B(A):
+
+ c = 0
+ d = 0
+
+ def __init__(self, **kwargs):
+ super(B, self).__init__(**kwargs)
+ self.observe(self.listener2)
+
+ def listener2(self, change):
+ self.c += 1
+
+ @observe('a')
+ def _a_changed(self, change):
+ self.d += 1
+
+ b = B()
+ b.a += 1
+ self.assertEqual(b.b, b.c)
+ self.assertEqual(b.b, b.d)
+ b.a += 1
+ self.assertEqual(b.b, b.c)
+ self.assertEqual(b.b, b.d)
+
+
+class TestHasTraits(TestCase):
+
+ def test_trait_names(self):
+ class A(HasTraits):
+ i = Int()
+ f = Float()
+ a = A()
+ self.assertEqual(sorted(a.trait_names()),['f','i'])
+ self.assertEqual(sorted(A.class_trait_names()),['f','i'])
+ self.assertTrue(a.has_trait('f'))
+ self.assertFalse(a.has_trait('g'))
+
def test_trait_has_value(self):
class A(HasTraits):
i = Int()
@@ -813,438 +813,438 @@ class TestHasTraits(TestCase):
self.assertTrue(a.trait_has_value('i'))
self.assertTrue(a.trait_has_value('f'))
- def test_trait_metadata_deprecated(self):
+ def test_trait_metadata_deprecated(self):
with expected_warnings([r'metadata should be set using the \.tag\(\) method']):
- class A(HasTraits):
- i = Int(config_key='MY_VALUE')
- a = A()
- self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
-
- def test_trait_metadata(self):
- class A(HasTraits):
- i = Int().tag(config_key='MY_VALUE')
- a = A()
- self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
-
- def test_trait_metadata_default(self):
- class A(HasTraits):
- i = Int()
- a = A()
- self.assertEqual(a.trait_metadata('i', 'config_key'), None)
- self.assertEqual(a.trait_metadata('i', 'config_key', 'default'), 'default')
-
- def test_traits(self):
- class A(HasTraits):
- i = Int()
- f = Float()
- a = A()
- self.assertEqual(a.traits(), dict(i=A.i, f=A.f))
- self.assertEqual(A.class_traits(), dict(i=A.i, f=A.f))
-
- def test_traits_metadata(self):
- class A(HasTraits):
- i = Int().tag(config_key='VALUE1', other_thing='VALUE2')
- f = Float().tag(config_key='VALUE3', other_thing='VALUE2')
- j = Int(0)
- a = A()
- self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
- traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
- self.assertEqual(traits, dict(i=A.i))
-
- # This passes, but it shouldn't because I am replicating a bug in
- # traits.
- traits = a.traits(config_key=lambda v: True)
- self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
-
- def test_traits_metadata_deprecated(self):
+ class A(HasTraits):
+ i = Int(config_key='MY_VALUE')
+ a = A()
+ self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
+
+ def test_trait_metadata(self):
+ class A(HasTraits):
+ i = Int().tag(config_key='MY_VALUE')
+ a = A()
+ self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
+
+ def test_trait_metadata_default(self):
+ class A(HasTraits):
+ i = Int()
+ a = A()
+ self.assertEqual(a.trait_metadata('i', 'config_key'), None)
+ self.assertEqual(a.trait_metadata('i', 'config_key', 'default'), 'default')
+
+ def test_traits(self):
+ class A(HasTraits):
+ i = Int()
+ f = Float()
+ a = A()
+ self.assertEqual(a.traits(), dict(i=A.i, f=A.f))
+ self.assertEqual(A.class_traits(), dict(i=A.i, f=A.f))
+
+ def test_traits_metadata(self):
+ class A(HasTraits):
+ i = Int().tag(config_key='VALUE1', other_thing='VALUE2')
+ f = Float().tag(config_key='VALUE3', other_thing='VALUE2')
+ j = Int(0)
+ a = A()
+ self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
+ traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
+ self.assertEqual(traits, dict(i=A.i))
+
+ # This passes, but it shouldn't because I am replicating a bug in
+ # traits.
+ traits = a.traits(config_key=lambda v: True)
+ self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
+
+ def test_traits_metadata_deprecated(self):
with expected_warnings([r'metadata should be set using the \.tag\(\) method']*2):
- class A(HasTraits):
- i = Int(config_key='VALUE1', other_thing='VALUE2')
- f = Float(config_key='VALUE3', other_thing='VALUE2')
- j = Int(0)
- a = A()
- self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
- traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
- self.assertEqual(traits, dict(i=A.i))
-
- # This passes, but it shouldn't because I am replicating a bug in
- # traits.
- traits = a.traits(config_key=lambda v: True)
- self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
-
-
- def test_init(self):
- class A(HasTraits):
- i = Int()
- x = Float()
- a = A(i=1, x=10.0)
- self.assertEqual(a.i, 1)
- self.assertEqual(a.x, 10.0)
-
- def test_positional_args(self):
- class A(HasTraits):
- i = Int(0)
- def __init__(self, i):
- super(A, self).__init__()
- self.i = i
-
- a = A(5)
- self.assertEqual(a.i, 5)
- # should raise TypeError if no positional arg given
- self.assertRaises(TypeError, A)
-
-#-----------------------------------------------------------------------------
-# Tests for specific trait types
-#-----------------------------------------------------------------------------
-
-
-class TestType(TestCase):
-
- def test_default(self):
-
- class B(object): pass
- class A(HasTraits):
- klass = Type(allow_none=True)
-
- a = A()
- self.assertEqual(a.klass, object)
-
- a.klass = B
- self.assertEqual(a.klass, B)
- self.assertRaises(TraitError, setattr, a, 'klass', 10)
-
- def test_default_options(self):
-
- class B(object): pass
- class C(B): pass
- class A(HasTraits):
- # Different possible combinations of options for default_value
- # and klass. default_value=None is only valid with allow_none=True.
- k1 = Type()
- k2 = Type(None, allow_none=True)
- k3 = Type(B)
- k4 = Type(klass=B)
- k5 = Type(default_value=None, klass=B, allow_none=True)
- k6 = Type(default_value=C, klass=B)
-
- self.assertIs(A.k1.default_value, object)
- self.assertIs(A.k1.klass, object)
- self.assertIs(A.k2.default_value, None)
- self.assertIs(A.k2.klass, object)
- self.assertIs(A.k3.default_value, B)
- self.assertIs(A.k3.klass, B)
- self.assertIs(A.k4.default_value, B)
- self.assertIs(A.k4.klass, B)
- self.assertIs(A.k5.default_value, None)
- self.assertIs(A.k5.klass, B)
- self.assertIs(A.k6.default_value, C)
- self.assertIs(A.k6.klass, B)
-
- a = A()
- self.assertIs(a.k1, object)
- self.assertIs(a.k2, None)
- self.assertIs(a.k3, B)
- self.assertIs(a.k4, B)
- self.assertIs(a.k5, None)
- self.assertIs(a.k6, C)
-
- def test_value(self):
-
- class B(object): pass
- class C(object): pass
- class A(HasTraits):
- klass = Type(B)
-
- a = A()
- self.assertEqual(a.klass, B)
- self.assertRaises(TraitError, setattr, a, 'klass', C)
- self.assertRaises(TraitError, setattr, a, 'klass', object)
- a.klass = B
-
- def test_allow_none(self):
-
- class B(object): pass
- class C(B): pass
- class A(HasTraits):
- klass = Type(B)
-
- a = A()
- self.assertEqual(a.klass, B)
- self.assertRaises(TraitError, setattr, a, 'klass', None)
- a.klass = C
- self.assertEqual(a.klass, C)
-
- def test_validate_klass(self):
-
- class A(HasTraits):
- klass = Type('no strings allowed')
-
- self.assertRaises(ImportError, A)
-
- class A(HasTraits):
- klass = Type('rub.adub.Duck')
-
- self.assertRaises(ImportError, A)
-
- def test_validate_default(self):
-
- class B(object): pass
- class A(HasTraits):
- klass = Type('bad default', B)
-
- self.assertRaises(ImportError, A)
-
- class C(HasTraits):
- klass = Type(None, B)
-
+ class A(HasTraits):
+ i = Int(config_key='VALUE1', other_thing='VALUE2')
+ f = Float(config_key='VALUE3', other_thing='VALUE2')
+ j = Int(0)
+ a = A()
+ self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
+ traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
+ self.assertEqual(traits, dict(i=A.i))
+
+ # This passes, but it shouldn't because I am replicating a bug in
+ # traits.
+ traits = a.traits(config_key=lambda v: True)
+ self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
+
+
+ def test_init(self):
+ class A(HasTraits):
+ i = Int()
+ x = Float()
+ a = A(i=1, x=10.0)
+ self.assertEqual(a.i, 1)
+ self.assertEqual(a.x, 10.0)
+
+ def test_positional_args(self):
+ class A(HasTraits):
+ i = Int(0)
+ def __init__(self, i):
+ super(A, self).__init__()
+ self.i = i
+
+ a = A(5)
+ self.assertEqual(a.i, 5)
+ # should raise TypeError if no positional arg given
+ self.assertRaises(TypeError, A)
+
+#-----------------------------------------------------------------------------
+# Tests for specific trait types
+#-----------------------------------------------------------------------------
+
+
+class TestType(TestCase):
+
+ def test_default(self):
+
+ class B(object): pass
+ class A(HasTraits):
+ klass = Type(allow_none=True)
+
+ a = A()
+ self.assertEqual(a.klass, object)
+
+ a.klass = B
+ self.assertEqual(a.klass, B)
+ self.assertRaises(TraitError, setattr, a, 'klass', 10)
+
+ def test_default_options(self):
+
+ class B(object): pass
+ class C(B): pass
+ class A(HasTraits):
+ # Different possible combinations of options for default_value
+ # and klass. default_value=None is only valid with allow_none=True.
+ k1 = Type()
+ k2 = Type(None, allow_none=True)
+ k3 = Type(B)
+ k4 = Type(klass=B)
+ k5 = Type(default_value=None, klass=B, allow_none=True)
+ k6 = Type(default_value=C, klass=B)
+
+ self.assertIs(A.k1.default_value, object)
+ self.assertIs(A.k1.klass, object)
+ self.assertIs(A.k2.default_value, None)
+ self.assertIs(A.k2.klass, object)
+ self.assertIs(A.k3.default_value, B)
+ self.assertIs(A.k3.klass, B)
+ self.assertIs(A.k4.default_value, B)
+ self.assertIs(A.k4.klass, B)
+ self.assertIs(A.k5.default_value, None)
+ self.assertIs(A.k5.klass, B)
+ self.assertIs(A.k6.default_value, C)
+ self.assertIs(A.k6.klass, B)
+
+ a = A()
+ self.assertIs(a.k1, object)
+ self.assertIs(a.k2, None)
+ self.assertIs(a.k3, B)
+ self.assertIs(a.k4, B)
+ self.assertIs(a.k5, None)
+ self.assertIs(a.k6, C)
+
+ def test_value(self):
+
+ class B(object): pass
+ class C(object): pass
+ class A(HasTraits):
+ klass = Type(B)
+
+ a = A()
+ self.assertEqual(a.klass, B)
+ self.assertRaises(TraitError, setattr, a, 'klass', C)
+ self.assertRaises(TraitError, setattr, a, 'klass', object)
+ a.klass = B
+
+ def test_allow_none(self):
+
+ class B(object): pass
+ class C(B): pass
+ class A(HasTraits):
+ klass = Type(B)
+
+ a = A()
+ self.assertEqual(a.klass, B)
+ self.assertRaises(TraitError, setattr, a, 'klass', None)
+ a.klass = C
+ self.assertEqual(a.klass, C)
+
+ def test_validate_klass(self):
+
+ class A(HasTraits):
+ klass = Type('no strings allowed')
+
+ self.assertRaises(ImportError, A)
+
+ class A(HasTraits):
+ klass = Type('rub.adub.Duck')
+
+ self.assertRaises(ImportError, A)
+
+ def test_validate_default(self):
+
+ class B(object): pass
+ class A(HasTraits):
+ klass = Type('bad default', B)
+
+ self.assertRaises(ImportError, A)
+
+ class C(HasTraits):
+ klass = Type(None, B)
+
self.assertRaises(TraitError, getattr, C(), 'klass')
-
- def test_str_klass(self):
-
- class A(HasTraits):
+
+ def test_str_klass(self):
+
+ class A(HasTraits):
klass = Type("traitlets.config.Config")
-
+
from traitlets.config import Config
- a = A()
+ a = A()
a.klass = Config
self.assertEqual(a.klass, Config)
-
- self.assertRaises(TraitError, setattr, a, 'klass', 10)
-
- def test_set_str_klass(self):
-
- class A(HasTraits):
- klass = Type()
-
+
+ self.assertRaises(TraitError, setattr, a, 'klass', 10)
+
+ def test_set_str_klass(self):
+
+ class A(HasTraits):
+ klass = Type()
+
a = A(klass="traitlets.config.Config")
from traitlets.config import Config
-
+
self.assertEqual(a.klass, Config)
-class TestInstance(TestCase):
-
- def test_basic(self):
- class Foo(object): pass
- class Bar(Foo): pass
- class Bah(object): pass
-
- class A(HasTraits):
- inst = Instance(Foo, allow_none=True)
-
- a = A()
- self.assertTrue(a.inst is None)
- a.inst = Foo()
- self.assertTrue(isinstance(a.inst, Foo))
- a.inst = Bar()
- self.assertTrue(isinstance(a.inst, Foo))
- self.assertRaises(TraitError, setattr, a, 'inst', Foo)
- self.assertRaises(TraitError, setattr, a, 'inst', Bar)
- self.assertRaises(TraitError, setattr, a, 'inst', Bah())
-
- def test_default_klass(self):
- class Foo(object): pass
- class Bar(Foo): pass
- class Bah(object): pass
-
- class FooInstance(Instance):
- klass = Foo
-
- class A(HasTraits):
- inst = FooInstance(allow_none=True)
-
- a = A()
- self.assertTrue(a.inst is None)
- a.inst = Foo()
- self.assertTrue(isinstance(a.inst, Foo))
- a.inst = Bar()
- self.assertTrue(isinstance(a.inst, Foo))
- self.assertRaises(TraitError, setattr, a, 'inst', Foo)
- self.assertRaises(TraitError, setattr, a, 'inst', Bar)
- self.assertRaises(TraitError, setattr, a, 'inst', Bah())
-
- def test_unique_default_value(self):
- class Foo(object): pass
- class A(HasTraits):
- inst = Instance(Foo,(),{})
-
- a = A()
- b = A()
- self.assertTrue(a.inst is not b.inst)
-
- def test_args_kw(self):
- class Foo(object):
- def __init__(self, c): self.c = c
- class Bar(object): pass
- class Bah(object):
- def __init__(self, c, d):
- self.c = c; self.d = d
-
- class A(HasTraits):
- inst = Instance(Foo, (10,))
- a = A()
- self.assertEqual(a.inst.c, 10)
-
- class B(HasTraits):
- inst = Instance(Bah, args=(10,), kw=dict(d=20))
- b = B()
- self.assertEqual(b.inst.c, 10)
- self.assertEqual(b.inst.d, 20)
-
- class C(HasTraits):
- inst = Instance(Foo, allow_none=True)
- c = C()
- self.assertTrue(c.inst is None)
-
- def test_bad_default(self):
- class Foo(object): pass
-
- class A(HasTraits):
- inst = Instance(Foo)
-
- a = A()
- with self.assertRaises(TraitError):
- a.inst
-
- def test_instance(self):
- class Foo(object): pass
-
- def inner():
- class A(HasTraits):
- inst = Instance(Foo())
-
- self.assertRaises(TraitError, inner)
-
-
-class TestThis(TestCase):
-
- def test_this_class(self):
- class Foo(HasTraits):
- this = This()
-
- f = Foo()
- self.assertEqual(f.this, None)
- g = Foo()
- f.this = g
- self.assertEqual(f.this, g)
- self.assertRaises(TraitError, setattr, f, 'this', 10)
-
- def test_this_inst(self):
- class Foo(HasTraits):
- this = This()
-
- f = Foo()
- f.this = Foo()
- self.assertTrue(isinstance(f.this, Foo))
-
- def test_subclass(self):
- class Foo(HasTraits):
- t = This()
- class Bar(Foo):
- pass
- f = Foo()
- b = Bar()
- f.t = b
- b.t = f
- self.assertEqual(f.t, b)
- self.assertEqual(b.t, f)
-
- def test_subclass_override(self):
- class Foo(HasTraits):
- t = This()
- class Bar(Foo):
- t = This()
- f = Foo()
- b = Bar()
- f.t = b
- self.assertEqual(f.t, b)
- self.assertRaises(TraitError, setattr, b, 't', f)
-
- def test_this_in_container(self):
-
- class Tree(HasTraits):
- value = Unicode()
- leaves = List(This())
-
- tree = Tree(
- value='foo',
- leaves=[Tree(value='bar'), Tree(value='buzz')]
- )
-
- with self.assertRaises(TraitError):
- tree.leaves = [1, 2]
-
-class TraitTestBase(TestCase):
- """A best testing class for basic trait types."""
-
- def assign(self, value):
- self.obj.value = value
-
- def coerce(self, value):
- return value
-
- def test_good_values(self):
- if hasattr(self, '_good_values'):
- for value in self._good_values:
- self.assign(value)
- self.assertEqual(self.obj.value, self.coerce(value))
-
- def test_bad_values(self):
- if hasattr(self, '_bad_values'):
- for value in self._bad_values:
- try:
- self.assertRaises(TraitError, self.assign, value)
- except AssertionError:
- assert False, value
-
- def test_default_value(self):
- if hasattr(self, '_default_value'):
- self.assertEqual(self._default_value, self.obj.value)
-
- def test_allow_none(self):
- if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
- None in self._bad_values):
- trait=self.obj.traits()['value']
- try:
- trait.allow_none = True
- self._bad_values.remove(None)
- #skip coerce. Allow None casts None to None.
- self.assign(None)
- self.assertEqual(self.obj.value,None)
- self.test_good_values()
- self.test_bad_values()
- finally:
- #tear down
- trait.allow_none = False
- self._bad_values.append(None)
-
- def tearDown(self):
- # restore default value after tests, if set
- if hasattr(self, '_default_value'):
- self.obj.value = self._default_value
-
-
-class AnyTrait(HasTraits):
-
- value = Any()
-
-class AnyTraitTest(TraitTestBase):
-
- obj = AnyTrait()
-
- _default_value = None
+class TestInstance(TestCase):
+
+ def test_basic(self):
+ class Foo(object): pass
+ class Bar(Foo): pass
+ class Bah(object): pass
+
+ class A(HasTraits):
+ inst = Instance(Foo, allow_none=True)
+
+ a = A()
+ self.assertTrue(a.inst is None)
+ a.inst = Foo()
+ self.assertTrue(isinstance(a.inst, Foo))
+ a.inst = Bar()
+ self.assertTrue(isinstance(a.inst, Foo))
+ self.assertRaises(TraitError, setattr, a, 'inst', Foo)
+ self.assertRaises(TraitError, setattr, a, 'inst', Bar)
+ self.assertRaises(TraitError, setattr, a, 'inst', Bah())
+
+ def test_default_klass(self):
+ class Foo(object): pass
+ class Bar(Foo): pass
+ class Bah(object): pass
+
+ class FooInstance(Instance):
+ klass = Foo
+
+ class A(HasTraits):
+ inst = FooInstance(allow_none=True)
+
+ a = A()
+ self.assertTrue(a.inst is None)
+ a.inst = Foo()
+ self.assertTrue(isinstance(a.inst, Foo))
+ a.inst = Bar()
+ self.assertTrue(isinstance(a.inst, Foo))
+ self.assertRaises(TraitError, setattr, a, 'inst', Foo)
+ self.assertRaises(TraitError, setattr, a, 'inst', Bar)
+ self.assertRaises(TraitError, setattr, a, 'inst', Bah())
+
+ def test_unique_default_value(self):
+ class Foo(object): pass
+ class A(HasTraits):
+ inst = Instance(Foo,(),{})
+
+ a = A()
+ b = A()
+ self.assertTrue(a.inst is not b.inst)
+
+ def test_args_kw(self):
+ class Foo(object):
+ def __init__(self, c): self.c = c
+ class Bar(object): pass
+ class Bah(object):
+ def __init__(self, c, d):
+ self.c = c; self.d = d
+
+ class A(HasTraits):
+ inst = Instance(Foo, (10,))
+ a = A()
+ self.assertEqual(a.inst.c, 10)
+
+ class B(HasTraits):
+ inst = Instance(Bah, args=(10,), kw=dict(d=20))
+ b = B()
+ self.assertEqual(b.inst.c, 10)
+ self.assertEqual(b.inst.d, 20)
+
+ class C(HasTraits):
+ inst = Instance(Foo, allow_none=True)
+ c = C()
+ self.assertTrue(c.inst is None)
+
+ def test_bad_default(self):
+ class Foo(object): pass
+
+ class A(HasTraits):
+ inst = Instance(Foo)
+
+ a = A()
+ with self.assertRaises(TraitError):
+ a.inst
+
+ def test_instance(self):
+ class Foo(object): pass
+
+ def inner():
+ class A(HasTraits):
+ inst = Instance(Foo())
+
+ self.assertRaises(TraitError, inner)
+
+
+class TestThis(TestCase):
+
+ def test_this_class(self):
+ class Foo(HasTraits):
+ this = This()
+
+ f = Foo()
+ self.assertEqual(f.this, None)
+ g = Foo()
+ f.this = g
+ self.assertEqual(f.this, g)
+ self.assertRaises(TraitError, setattr, f, 'this', 10)
+
+ def test_this_inst(self):
+ class Foo(HasTraits):
+ this = This()
+
+ f = Foo()
+ f.this = Foo()
+ self.assertTrue(isinstance(f.this, Foo))
+
+ def test_subclass(self):
+ class Foo(HasTraits):
+ t = This()
+ class Bar(Foo):
+ pass
+ f = Foo()
+ b = Bar()
+ f.t = b
+ b.t = f
+ self.assertEqual(f.t, b)
+ self.assertEqual(b.t, f)
+
+ def test_subclass_override(self):
+ class Foo(HasTraits):
+ t = This()
+ class Bar(Foo):
+ t = This()
+ f = Foo()
+ b = Bar()
+ f.t = b
+ self.assertEqual(f.t, b)
+ self.assertRaises(TraitError, setattr, b, 't', f)
+
+ def test_this_in_container(self):
+
+ class Tree(HasTraits):
+ value = Unicode()
+ leaves = List(This())
+
+ tree = Tree(
+ value='foo',
+ leaves=[Tree(value='bar'), Tree(value='buzz')]
+ )
+
+ with self.assertRaises(TraitError):
+ tree.leaves = [1, 2]
+
+class TraitTestBase(TestCase):
+ """A best testing class for basic trait types."""
+
+ def assign(self, value):
+ self.obj.value = value
+
+ def coerce(self, value):
+ return value
+
+ def test_good_values(self):
+ if hasattr(self, '_good_values'):
+ for value in self._good_values:
+ self.assign(value)
+ self.assertEqual(self.obj.value, self.coerce(value))
+
+ def test_bad_values(self):
+ if hasattr(self, '_bad_values'):
+ for value in self._bad_values:
+ try:
+ self.assertRaises(TraitError, self.assign, value)
+ except AssertionError:
+ assert False, value
+
+ def test_default_value(self):
+ if hasattr(self, '_default_value'):
+ self.assertEqual(self._default_value, self.obj.value)
+
+ def test_allow_none(self):
+ if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
+ None in self._bad_values):
+ trait=self.obj.traits()['value']
+ try:
+ trait.allow_none = True
+ self._bad_values.remove(None)
+ #skip coerce. Allow None casts None to None.
+ self.assign(None)
+ self.assertEqual(self.obj.value,None)
+ self.test_good_values()
+ self.test_bad_values()
+ finally:
+ #tear down
+ trait.allow_none = False
+ self._bad_values.append(None)
+
+ def tearDown(self):
+ # restore default value after tests, if set
+ if hasattr(self, '_default_value'):
+ self.obj.value = self._default_value
+
+
+class AnyTrait(HasTraits):
+
+ value = Any()
+
+class AnyTraitTest(TraitTestBase):
+
+ obj = AnyTrait()
+
+ _default_value = None
_good_values = [10.0, 'ten', [10], {'ten': 10},(10,), None, 1j]
- _bad_values = []
-
-class UnionTrait(HasTraits):
-
- value = Union([Type(), Bool()])
-
-class UnionTraitTest(TraitTestBase):
-
+ _bad_values = []
+
+class UnionTrait(HasTraits):
+
+ value = Union([Type(), Bool()])
+
+class UnionTraitTest(TraitTestBase):
+
obj = UnionTrait(value="traitlets.config.Config")
- _good_values = [int, float, True]
- _bad_values = [[], (0,), 1j]
-
+ _good_values = [int, float, True]
+ _bad_values = [[], (0,), 1j]
+
class CallableTrait(HasTraits):
value = Callable()
@@ -1255,407 +1255,407 @@ class CallableTraitTest(TraitTestBase):
_good_values = [int, sorted, lambda x: print(x)]
_bad_values = [[], 1, '']
-class OrTrait(HasTraits):
-
- value = Bool() | Unicode()
-
-class OrTraitTest(TraitTestBase):
-
- obj = OrTrait()
- _good_values = [True, False, 'ten']
- _bad_values = [[], (0,), 1j]
-
-class IntTrait(HasTraits):
-
- value = Int(99, min=-100)
-
-class TestInt(TraitTestBase):
-
- obj = IntTrait()
- _default_value = 99
- _good_values = [10, -10]
+class OrTrait(HasTraits):
+
+ value = Bool() | Unicode()
+
+class OrTraitTest(TraitTestBase):
+
+ obj = OrTrait()
+ _good_values = [True, False, 'ten']
+ _bad_values = [[], (0,), 1j]
+
+class IntTrait(HasTraits):
+
+ value = Int(99, min=-100)
+
+class TestInt(TraitTestBase):
+
+ obj = IntTrait()
+ _default_value = 99
+ _good_values = [10, -10]
_bad_values = ['ten', [10], {'ten': 10}, (10,), None, 1j,
10.1, -10.1, '10L', '-10L', '10.1', '-10.1',
'10', '-10', -200]
-
-
-class CIntTrait(HasTraits):
- value = CInt('5')
-
-class TestCInt(TraitTestBase):
- obj = CIntTrait()
-
- _default_value = 5
+
+
+class CIntTrait(HasTraits):
+ value = CInt('5')
+
+class TestCInt(TraitTestBase):
+ obj = CIntTrait()
+
+ _default_value = 5
_good_values = ['10', '-10', 10, 10.0, -10.0, 10.1]
_bad_values = ['ten', [10], {'ten': 10},(10,),
None, 1j, '10.1']
-
- def coerce(self, n):
- return int(n)
-
-
-class MinBoundCIntTrait(HasTraits):
- value = CInt('5', min=3)
-
-class TestMinBoundCInt(TestCInt):
- obj = MinBoundCIntTrait()
-
- _default_value = 5
- _good_values = [3, 3.0, '3']
- _bad_values = [2.6, 2, -3, -3.0]
-
-
-class LongTrait(HasTraits):
-
+
+ def coerce(self, n):
+ return int(n)
+
+
+class MinBoundCIntTrait(HasTraits):
+ value = CInt('5', min=3)
+
+class TestMinBoundCInt(TestCInt):
+ obj = MinBoundCIntTrait()
+
+ _default_value = 5
+ _good_values = [3, 3.0, '3']
+ _bad_values = [2.6, 2, -3, -3.0]
+
+
+class LongTrait(HasTraits):
+
value = Long(99)
-
-class TestLong(TraitTestBase):
-
- obj = LongTrait()
-
+
+class TestLong(TraitTestBase):
+
+ obj = LongTrait()
+
_default_value = 99
- _good_values = [10, -10]
+ _good_values = [10, -10]
_bad_values = ['ten', [10], {'ten': 10},(10,),
- None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
+ None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
'-10.1']
-
-
-class MinBoundLongTrait(HasTraits):
+
+
+class MinBoundLongTrait(HasTraits):
value = Long(99, min=5)
-
-class TestMinBoundLong(TraitTestBase):
- obj = MinBoundLongTrait()
-
+
+class TestMinBoundLong(TraitTestBase):
+ obj = MinBoundLongTrait()
+
_default_value = 99
- _good_values = [5, 10]
- _bad_values = [4, -10]
-
-
-class MaxBoundLongTrait(HasTraits):
+ _good_values = [5, 10]
+ _bad_values = [4, -10]
+
+
+class MaxBoundLongTrait(HasTraits):
value = Long(5, max=10)
-
-class TestMaxBoundLong(TraitTestBase):
- obj = MaxBoundLongTrait()
-
+
+class TestMaxBoundLong(TraitTestBase):
+ obj = MaxBoundLongTrait()
+
_default_value = 5
- _good_values = [10, -2]
- _bad_values = [11, 20]
-
-
-class CLongTrait(HasTraits):
- value = CLong('5')
-
-class TestCLong(TraitTestBase):
- obj = CLongTrait()
-
+ _good_values = [10, -2]
+ _bad_values = [11, 20]
+
+
+class CLongTrait(HasTraits):
+ value = CLong('5')
+
+class TestCLong(TraitTestBase):
+ obj = CLongTrait()
+
_default_value = 5
_good_values = ['10', '-10', 10, 10.0, -10.0, 10.1]
_bad_values = ['ten', [10], {'ten': 10},(10,),
None, 1j, '10.1']
-
- def coerce(self, n):
+
+ def coerce(self, n):
return int(n)
-
-
-class MaxBoundCLongTrait(HasTraits):
- value = CLong('5', max=10)
-
-class TestMaxBoundCLong(TestCLong):
- obj = MaxBoundCLongTrait()
-
+
+
+class MaxBoundCLongTrait(HasTraits):
+ value = CLong('5', max=10)
+
+class TestMaxBoundCLong(TestCLong):
+ obj = MaxBoundCLongTrait()
+
+ _default_value = 5
+ _good_values = [10, '10', 10.3]
+ _bad_values = [11.0, '11']
+
+
+class IntegerTrait(HasTraits):
+ value = Integer(1)
+
+class TestInteger(TestLong):
+ obj = IntegerTrait()
+ _default_value = 1
+
+ def coerce(self, n):
+ return int(n)
+
+
+class MinBoundIntegerTrait(HasTraits):
+ value = Integer(5, min=3)
+
+class TestMinBoundInteger(TraitTestBase):
+ obj = MinBoundIntegerTrait()
+
_default_value = 5
- _good_values = [10, '10', 10.3]
- _bad_values = [11.0, '11']
-
-
-class IntegerTrait(HasTraits):
- value = Integer(1)
-
-class TestInteger(TestLong):
- obj = IntegerTrait()
- _default_value = 1
-
- def coerce(self, n):
- return int(n)
-
-
-class MinBoundIntegerTrait(HasTraits):
- value = Integer(5, min=3)
-
-class TestMinBoundInteger(TraitTestBase):
- obj = MinBoundIntegerTrait()
-
- _default_value = 5
- _good_values = 3, 20
- _bad_values = [2, -10]
-
-
-class MaxBoundIntegerTrait(HasTraits):
- value = Integer(1, max=3)
-
-class TestMaxBoundInteger(TraitTestBase):
- obj = MaxBoundIntegerTrait()
-
- _default_value = 1
- _good_values = 3, -2
- _bad_values = [4, 10]
-
-
-class FloatTrait(HasTraits):
-
- value = Float(99.0, max=200.0)
-
-class TestFloat(TraitTestBase):
-
- obj = FloatTrait()
-
- _default_value = 99.0
- _good_values = [10, -10, 10.1, -10.1]
+ _good_values = 3, 20
+ _bad_values = [2, -10]
+
+
+class MaxBoundIntegerTrait(HasTraits):
+ value = Integer(1, max=3)
+
+class TestMaxBoundInteger(TraitTestBase):
+ obj = MaxBoundIntegerTrait()
+
+ _default_value = 1
+ _good_values = 3, -2
+ _bad_values = [4, 10]
+
+
+class FloatTrait(HasTraits):
+
+ value = Float(99.0, max=200.0)
+
+class TestFloat(TraitTestBase):
+
+ obj = FloatTrait()
+
+ _default_value = 99.0
+ _good_values = [10, -10, 10.1, -10.1]
_bad_values = ['ten', [10], {'ten': 10}, (10,), None,
1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', 201.0]
-
-
-class CFloatTrait(HasTraits):
-
- value = CFloat('99.0', max=200.0)
-
-class TestCFloat(TraitTestBase):
-
- obj = CFloatTrait()
-
- _default_value = 99.0
+
+
+class CFloatTrait(HasTraits):
+
+ value = CFloat('99.0', max=200.0)
+
+class TestCFloat(TraitTestBase):
+
+ obj = CFloatTrait()
+
+ _default_value = 99.0
_good_values = [10, 10.0, 10.5, '10.0', '10', '-10']
_bad_values = ['ten', [10], {'ten': 10}, (10,), None, 1j,
- 200.1, '200.1']
-
- def coerce(self, v):
- return float(v)
-
-
-class ComplexTrait(HasTraits):
-
- value = Complex(99.0-99.0j)
-
-class TestComplex(TraitTestBase):
-
- obj = ComplexTrait()
-
- _default_value = 99.0-99.0j
- _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
- 10.1j, 10.1+10.1j, 10.1-10.1j]
+ 200.1, '200.1']
+
+ def coerce(self, v):
+ return float(v)
+
+
+class ComplexTrait(HasTraits):
+
+ value = Complex(99.0-99.0j)
+
+class TestComplex(TraitTestBase):
+
+ obj = ComplexTrait()
+
+ _default_value = 99.0-99.0j
+ _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
+ 10.1j, 10.1+10.1j, 10.1-10.1j]
_bad_values = ['10L', '-10L', 'ten', [10], {'ten': 10},(10,), None]
-
-
-class BytesTrait(HasTraits):
-
- value = Bytes(b'string')
-
-class TestBytes(TraitTestBase):
-
- obj = BytesTrait()
-
- _default_value = b'string'
- _good_values = [b'10', b'-10', b'10L',
- b'-10L', b'10.1', b'-10.1', b'string']
- _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
+
+
+class BytesTrait(HasTraits):
+
+ value = Bytes(b'string')
+
+class TestBytes(TraitTestBase):
+
+ obj = BytesTrait()
+
+ _default_value = b'string'
+ _good_values = [b'10', b'-10', b'10L',
+ b'-10L', b'10.1', b'-10.1', b'string']
+ _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
['ten'],{'ten': 10},(10,), None, 'string']
-
-
-class UnicodeTrait(HasTraits):
-
+
+
+class UnicodeTrait(HasTraits):
+
value = Unicode('unicode')
-
-class TestUnicode(TraitTestBase):
-
- obj = UnicodeTrait()
-
+
+class TestUnicode(TraitTestBase):
+
+ obj = UnicodeTrait()
+
_default_value = 'unicode'
- _good_values = ['10', '-10', '10L', '-10L', '10.1',
+ _good_values = ['10', '-10', '10L', '-10L', '10.1',
'-10.1', '', 'string', "€", b"bytestring"]
- _bad_values = [10, -10, 10.1, -10.1, 1j,
+ _bad_values = [10, -10, 10.1, -10.1, 1j,
[10], ['ten'], {'ten': 10},(10,), None]
-
+
def coerce(self, v):
return cast_unicode(v)
-
-
-class ObjectNameTrait(HasTraits):
- value = ObjectName("abc")
-
-class TestObjectName(TraitTestBase):
- obj = ObjectNameTrait()
-
- _default_value = "abc"
+
+
+class ObjectNameTrait(HasTraits):
+ value = ObjectName("abc")
+
+class TestObjectName(TraitTestBase):
+ obj = ObjectNameTrait()
+
+ _default_value = "abc"
_good_values = ["a", "gh", "g9", "g_", "_G", "a345_"]
_bad_values = [1, "", "€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
- None, object(), object]
+ None, object(), object]
_good_values.append("þ") # þ=1 is valid in Python 3 (PEP 3131).
-
-
-class DottedObjectNameTrait(HasTraits):
- value = DottedObjectName("a.b")
-
-class TestDottedObjectName(TraitTestBase):
- obj = DottedObjectNameTrait()
-
- _default_value = "a.b"
+
+
+class DottedObjectNameTrait(HasTraits):
+ value = DottedObjectName("a.b")
+
+class TestDottedObjectName(TraitTestBase):
+ obj = DottedObjectNameTrait()
+
+ _default_value = "a.b"
_good_values = ["A", "y.t", "y765.__repr__", "os.path.join"]
_bad_values = [1, "abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
-
+
_good_values.append("t.þ")
-
-
-class TCPAddressTrait(HasTraits):
- value = TCPAddress()
-
-class TestTCPAddress(TraitTestBase):
-
- obj = TCPAddressTrait()
-
- _default_value = ('127.0.0.1',0)
- _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
- _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
-
-
-class ListTrait(HasTraits):
-
- value = List(Int())
-
-
-class TestList(TraitTestBase):
-
- obj = ListTrait()
-
- _default_value = []
- _good_values = [[], [1], list(range(10)), (1,2)]
- _bad_values = [10, [1,'a'], 'a']
-
- def coerce(self, value):
- if value is not None:
- value = list(value)
- return value
-
-
-class Foo(object):
- pass
-
-class NoneInstanceListTrait(HasTraits):
-
- value = List(Instance(Foo))
-
-class TestNoneInstanceList(TraitTestBase):
-
- obj = NoneInstanceListTrait()
-
- _default_value = []
- _good_values = [[Foo(), Foo()], []]
- _bad_values = [[None], [Foo(), None]]
-
-
-class InstanceListTrait(HasTraits):
-
- value = List(Instance(__name__+'.Foo'))
-
-class TestInstanceList(TraitTestBase):
-
- obj = InstanceListTrait()
-
- def test_klass(self):
- """Test that the instance klass is properly assigned."""
- self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
-
- _default_value = []
- _good_values = [[Foo(), Foo()], []]
- _bad_values = [['1', 2,], '1', [Foo], None]
-
-class UnionListTrait(HasTraits):
-
- value = List(Int() | Bool())
-
+
+
+class TCPAddressTrait(HasTraits):
+ value = TCPAddress()
+
+class TestTCPAddress(TraitTestBase):
+
+ obj = TCPAddressTrait()
+
+ _default_value = ('127.0.0.1',0)
+ _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
+ _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
+
+
+class ListTrait(HasTraits):
+
+ value = List(Int())
+
+
+class TestList(TraitTestBase):
+
+ obj = ListTrait()
+
+ _default_value = []
+ _good_values = [[], [1], list(range(10)), (1,2)]
+ _bad_values = [10, [1,'a'], 'a']
+
+ def coerce(self, value):
+ if value is not None:
+ value = list(value)
+ return value
+
+
+class Foo(object):
+ pass
+
+class NoneInstanceListTrait(HasTraits):
+
+ value = List(Instance(Foo))
+
+class TestNoneInstanceList(TraitTestBase):
+
+ obj = NoneInstanceListTrait()
+
+ _default_value = []
+ _good_values = [[Foo(), Foo()], []]
+ _bad_values = [[None], [Foo(), None]]
+
+
+class InstanceListTrait(HasTraits):
+
+ value = List(Instance(__name__+'.Foo'))
+
+class TestInstanceList(TraitTestBase):
+
+ obj = InstanceListTrait()
+
+ def test_klass(self):
+ """Test that the instance klass is properly assigned."""
+ self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
+
+ _default_value = []
+ _good_values = [[Foo(), Foo()], []]
+ _bad_values = [['1', 2,], '1', [Foo], None]
+
+class UnionListTrait(HasTraits):
+
+ value = List(Int() | Bool())
+
class TestUnionListTrait(TraitTestBase):
-
- obj = UnionListTrait()
-
- _default_value = []
- _good_values = [[True, 1], [False, True]]
- _bad_values = [[1, 'True'], False]
-
-
-class LenListTrait(HasTraits):
-
- value = List(Int(), [0], minlen=1, maxlen=2)
-
-class TestLenList(TraitTestBase):
-
- obj = LenListTrait()
-
- _default_value = [0]
- _good_values = [[1], [1,2], (1,2)]
- _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
-
- def coerce(self, value):
- if value is not None:
- value = list(value)
- return value
-
-class TupleTrait(HasTraits):
-
- value = Tuple(Int(allow_none=True), default_value=(1,))
-
-class TestTupleTrait(TraitTestBase):
-
- obj = TupleTrait()
-
+
+ obj = UnionListTrait()
+
+ _default_value = []
+ _good_values = [[True, 1], [False, True]]
+ _bad_values = [[1, 'True'], False]
+
+
+class LenListTrait(HasTraits):
+
+ value = List(Int(), [0], minlen=1, maxlen=2)
+
+class TestLenList(TraitTestBase):
+
+ obj = LenListTrait()
+
+ _default_value = [0]
+ _good_values = [[1], [1,2], (1,2)]
+ _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
+
+ def coerce(self, value):
+ if value is not None:
+ value = list(value)
+ return value
+
+class TupleTrait(HasTraits):
+
+ value = Tuple(Int(allow_none=True), default_value=(1,))
+
+class TestTupleTrait(TraitTestBase):
+
+ obj = TupleTrait()
+
_default_value = (1,)
- _good_values = [(1,), (0,), [1]]
- _bad_values = [10, (1, 2), ('a'), (), None]
-
- def coerce(self, value):
- if value is not None:
- value = tuple(value)
- return value
-
- def test_invalid_args(self):
- self.assertRaises(TypeError, Tuple, 5)
- self.assertRaises(TypeError, Tuple, default_value='hello')
- t = Tuple(Int(), CBytes(), default_value=(1,5))
-
-class LooseTupleTrait(HasTraits):
-
- value = Tuple((1,2,3))
-
-class TestLooseTupleTrait(TraitTestBase):
-
- obj = LooseTupleTrait()
-
- _default_value = (1,2,3)
- _good_values = [(1,), [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
- _bad_values = [10, 'hello', {}, None]
-
- def coerce(self, value):
- if value is not None:
- value = tuple(value)
- return value
-
- def test_invalid_args(self):
- self.assertRaises(TypeError, Tuple, 5)
- self.assertRaises(TypeError, Tuple, default_value='hello')
- t = Tuple(Int(), CBytes(), default_value=(1,5))
-
-
-class MultiTupleTrait(HasTraits):
-
- value = Tuple(Int(), Bytes(), default_value=[99,b'bottles'])
-
-class TestMultiTuple(TraitTestBase):
-
- obj = MultiTupleTrait()
-
- _default_value = (99,b'bottles')
- _good_values = [(1,b'a'), (2,b'b')]
+ _good_values = [(1,), (0,), [1]]
+ _bad_values = [10, (1, 2), ('a'), (), None]
+
+ def coerce(self, value):
+ if value is not None:
+ value = tuple(value)
+ return value
+
+ def test_invalid_args(self):
+ self.assertRaises(TypeError, Tuple, 5)
+ self.assertRaises(TypeError, Tuple, default_value='hello')
+ t = Tuple(Int(), CBytes(), default_value=(1,5))
+
+class LooseTupleTrait(HasTraits):
+
+ value = Tuple((1,2,3))
+
+class TestLooseTupleTrait(TraitTestBase):
+
+ obj = LooseTupleTrait()
+
+ _default_value = (1,2,3)
+ _good_values = [(1,), [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
+ _bad_values = [10, 'hello', {}, None]
+
+ def coerce(self, value):
+ if value is not None:
+ value = tuple(value)
+ return value
+
+ def test_invalid_args(self):
+ self.assertRaises(TypeError, Tuple, 5)
+ self.assertRaises(TypeError, Tuple, default_value='hello')
+ t = Tuple(Int(), CBytes(), default_value=(1,5))
+
+
+class MultiTupleTrait(HasTraits):
+
+ value = Tuple(Int(), Bytes(), default_value=[99,b'bottles'])
+
+class TestMultiTuple(TraitTestBase):
+
+ obj = MultiTupleTrait()
+
+ _default_value = (99,b'bottles')
+ _good_values = [(1,b'a'), (2,b'b')]
_bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, 'a'))
-
+
@pytest.mark.parametrize(
"Trait", (List, Tuple, Set, Dict, Integer, Unicode,),
@@ -1707,64 +1707,64 @@ def test_subclass_default_value(Trait, default_value):
assert c.t == default_value
-class CRegExpTrait(HasTraits):
-
- value = CRegExp(r'')
-
-
-class TestCRegExp(TraitTestBase):
-
- def coerce(self, value):
- return re.compile(value)
-
- obj = CRegExpTrait()
-
- _default_value = re.compile(r'')
- _good_values = [r'\d+', re.compile(r'\d+')]
- _bad_values = ['(', None, ()]
-
-class DictTrait(HasTraits):
- value = Dict()
-
-def test_dict_assignment():
- d = dict()
- c = DictTrait()
- c.value = d
- d['a'] = 5
+class CRegExpTrait(HasTraits):
+
+ value = CRegExp(r'')
+
+
+class TestCRegExp(TraitTestBase):
+
+ def coerce(self, value):
+ return re.compile(value)
+
+ obj = CRegExpTrait()
+
+ _default_value = re.compile(r'')
+ _good_values = [r'\d+', re.compile(r'\d+')]
+ _bad_values = ['(', None, ()]
+
+class DictTrait(HasTraits):
+ value = Dict()
+
+def test_dict_assignment():
+ d = dict()
+ c = DictTrait()
+ c.value = d
+ d['a'] = 5
assert d == c.value
- assert c.value is d
-
-
+ assert c.value is d
+
+
class UniformlyValueValidatedDictTrait(HasTraits):
-
- value = Dict(trait=Unicode(),
- default_value={'foo': '1'})
-
-
+
+ value = Dict(trait=Unicode(),
+ default_value={'foo': '1'})
+
+
class TestInstanceUniformlyValueValidatedDict(TraitTestBase):
-
+
obj = UniformlyValueValidatedDictTrait()
-
- _default_value = {'foo': '1'}
- _good_values = [{'foo': '0', 'bar': '1'}]
- _bad_values = [{'foo': 0, 'bar': '1'}]
-
-
+
+ _default_value = {'foo': '1'}
+ _good_values = [{'foo': '0', 'bar': '1'}]
+ _bad_values = [{'foo': 0, 'bar': '1'}]
+
+
class NonuniformlyValueValidatedDictTrait(HasTraits):
-
- value = Dict(traits={'foo': Int()},
- default_value={'foo': 1})
-
-
+
+ value = Dict(traits={'foo': Int()},
+ default_value={'foo': 1})
+
+
class TestInstanceNonuniformlyValueValidatedDict(TraitTestBase):
-
+
obj = NonuniformlyValueValidatedDictTrait()
-
- _default_value = {'foo': 1}
- _good_values = [{'foo': 0, 'bar': '1'}, {'foo': 0, 'bar': 1}]
- _bad_values = [{'foo': '0', 'bar': '1'}]
-
-
+
+ _default_value = {'foo': 1}
+ _good_values = [{'foo': 0, 'bar': '1'}, {'foo': 0, 'bar': 1}]
+ _bad_values = [{'foo': '0', 'bar': '1'}]
+
+
class KeyValidatedDictTrait(HasTraits):
value = Dict(key_trait=Unicode(),
@@ -1780,196 +1780,196 @@ class TestInstanceKeyValidatedDict(TraitTestBase):
_bad_values = [{'foo': '0', 0: '1'}]
-class FullyValidatedDictTrait(HasTraits):
-
- value = Dict(trait=Unicode(),
+class FullyValidatedDictTrait(HasTraits):
+
+ value = Dict(trait=Unicode(),
key_trait=Unicode(),
- traits={'foo': Int()},
- default_value={'foo': 1})
-
-
-class TestInstanceFullyValidatedDict(TraitTestBase):
-
- obj = FullyValidatedDictTrait()
-
- _default_value = {'foo': 1}
- _good_values = [{'foo': 0, 'bar': '1'}, {'foo': 1, 'bar': '2'}]
+ traits={'foo': Int()},
+ default_value={'foo': 1})
+
+
+class TestInstanceFullyValidatedDict(TraitTestBase):
+
+ obj = FullyValidatedDictTrait()
+
+ _default_value = {'foo': 1}
+ _good_values = [{'foo': 0, 'bar': '1'}, {'foo': 1, 'bar': '2'}]
_bad_values = [{'foo': 0, 'bar': 1}, {'foo': '0', 'bar': '1'}, {'foo': 0, 0: '1'}]
-
-
-def test_dict_default_value():
- """Check that the `{}` default value of the Dict traitlet constructor is
- actually copied."""
-
- class Foo(HasTraits):
- d1 = Dict()
- d2 = Dict()
-
- foo = Foo()
- assert foo.d1 == {}
- assert foo.d2 == {}
- assert foo.d1 is not foo.d2
-
-
-class TestValidationHook(TestCase):
-
- def test_parity_trait(self):
- """Verify that the early validation hook is effective"""
-
- class Parity(HasTraits):
-
- value = Int(0)
- parity = Enum(['odd', 'even'], default_value='even')
-
- @validate('value')
- def _value_validate(self, proposal):
- value = proposal['value']
- if self.parity == 'even' and value % 2:
- raise TraitError('Expected an even number')
- if self.parity == 'odd' and (value % 2 == 0):
- raise TraitError('Expected an odd number')
- return value
-
- u = Parity()
- u.parity = 'odd'
- u.value = 1 # OK
- with self.assertRaises(TraitError):
- u.value = 2 # Trait Error
-
- u.parity = 'even'
- u.value = 2 # OK
-
- def test_multiple_validate(self):
- """Verify that we can register the same validator to multiple names"""
-
- class OddEven(HasTraits):
-
- odd = Int(1)
- even = Int(0)
-
- @validate('odd', 'even')
- def check_valid(self, proposal):
- if proposal['trait'].name == 'odd' and not proposal['value'] % 2:
- raise TraitError('odd should be odd')
- if proposal['trait'].name == 'even' and proposal['value'] % 2:
- raise TraitError('even should be even')
-
- u = OddEven()
- u.odd = 3 # OK
- with self.assertRaises(TraitError):
- u.odd = 2 # Trait Error
-
- u.even = 2 # OK
- with self.assertRaises(TraitError):
- u.even = 3 # Trait Error
-
-
-
-class TestLink(TestCase):
-
- def test_connect_same(self):
- """Verify two traitlets of the same type can be linked together using link."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- a = A(value=9)
- b = A(value=8)
-
- # Conenct the two classes.
- c = link((a, 'value'), (b, 'value'))
-
- # Make sure the values are the same at the point of linking.
- self.assertEqual(a.value, b.value)
-
- # Change one of the values to make sure they stay in sync.
- a.value = 5
- self.assertEqual(a.value, b.value)
- b.value = 6
- self.assertEqual(a.value, b.value)
-
- def test_link_different(self):
- """Verify two traitlets of different types can be linked together using link."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- class B(HasTraits):
- count = Int()
- a = A(value=9)
- b = B(count=8)
-
- # Conenct the two classes.
- c = link((a, 'value'), (b, 'count'))
-
- # Make sure the values are the same at the point of linking.
- self.assertEqual(a.value, b.count)
-
- # Change one of the values to make sure they stay in sync.
- a.value = 5
- self.assertEqual(a.value, b.count)
- b.count = 4
- self.assertEqual(a.value, b.count)
-
+
+
+def test_dict_default_value():
+ """Check that the `{}` default value of the Dict traitlet constructor is
+ actually copied."""
+
+ class Foo(HasTraits):
+ d1 = Dict()
+ d2 = Dict()
+
+ foo = Foo()
+ assert foo.d1 == {}
+ assert foo.d2 == {}
+ assert foo.d1 is not foo.d2
+
+
+class TestValidationHook(TestCase):
+
+ def test_parity_trait(self):
+ """Verify that the early validation hook is effective"""
+
+ class Parity(HasTraits):
+
+ value = Int(0)
+ parity = Enum(['odd', 'even'], default_value='even')
+
+ @validate('value')
+ def _value_validate(self, proposal):
+ value = proposal['value']
+ if self.parity == 'even' and value % 2:
+ raise TraitError('Expected an even number')
+ if self.parity == 'odd' and (value % 2 == 0):
+ raise TraitError('Expected an odd number')
+ return value
+
+ u = Parity()
+ u.parity = 'odd'
+ u.value = 1 # OK
+ with self.assertRaises(TraitError):
+ u.value = 2 # Trait Error
+
+ u.parity = 'even'
+ u.value = 2 # OK
+
+ def test_multiple_validate(self):
+ """Verify that we can register the same validator to multiple names"""
+
+ class OddEven(HasTraits):
+
+ odd = Int(1)
+ even = Int(0)
+
+ @validate('odd', 'even')
+ def check_valid(self, proposal):
+ if proposal['trait'].name == 'odd' and not proposal['value'] % 2:
+ raise TraitError('odd should be odd')
+ if proposal['trait'].name == 'even' and proposal['value'] % 2:
+ raise TraitError('even should be even')
+
+ u = OddEven()
+ u.odd = 3 # OK
+ with self.assertRaises(TraitError):
+ u.odd = 2 # Trait Error
+
+ u.even = 2 # OK
+ with self.assertRaises(TraitError):
+ u.even = 3 # Trait Error
+
+
+
+class TestLink(TestCase):
+
+ def test_connect_same(self):
+ """Verify two traitlets of the same type can be linked together using link."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ a = A(value=9)
+ b = A(value=8)
+
+ # Conenct the two classes.
+ c = link((a, 'value'), (b, 'value'))
+
+ # Make sure the values are the same at the point of linking.
+ self.assertEqual(a.value, b.value)
+
+ # Change one of the values to make sure they stay in sync.
+ a.value = 5
+ self.assertEqual(a.value, b.value)
+ b.value = 6
+ self.assertEqual(a.value, b.value)
+
+ def test_link_different(self):
+ """Verify two traitlets of different types can be linked together using link."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ class B(HasTraits):
+ count = Int()
+ a = A(value=9)
+ b = B(count=8)
+
+ # Conenct the two classes.
+ c = link((a, 'value'), (b, 'count'))
+
+ # Make sure the values are the same at the point of linking.
+ self.assertEqual(a.value, b.count)
+
+ # Change one of the values to make sure they stay in sync.
+ a.value = 5
+ self.assertEqual(a.value, b.count)
+ b.count = 4
+ self.assertEqual(a.value, b.count)
+
def test_unlink_link(self):
"""Verify two linked traitlets can be unlinked and relinked."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- a = A(value=9)
- b = A(value=8)
-
- # Connect the two classes.
- c = link((a, 'value'), (b, 'value'))
- a.value = 4
- c.unlink()
-
- # Change one of the values to make sure they don't stay in sync.
- a.value = 5
- self.assertNotEqual(a.value, b.value)
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ a = A(value=9)
+ b = A(value=8)
+
+ # Connect the two classes.
+ c = link((a, 'value'), (b, 'value'))
+ a.value = 4
+ c.unlink()
+
+ # Change one of the values to make sure they don't stay in sync.
+ a.value = 5
+ self.assertNotEqual(a.value, b.value)
c.link()
self.assertEqual(a.value, b.value)
a.value += 1
self.assertEqual(a.value, b.value)
-
- def test_callbacks(self):
- """Verify two linked traitlets have their callbacks called once."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- class B(HasTraits):
- count = Int()
- a = A(value=9)
- b = B(count=8)
-
- # Register callbacks that count.
- callback_count = []
- def a_callback(name, old, new):
- callback_count.append('a')
- a.on_trait_change(a_callback, 'value')
- def b_callback(name, old, new):
- callback_count.append('b')
- b.on_trait_change(b_callback, 'count')
-
- # Connect the two classes.
- c = link((a, 'value'), (b, 'count'))
-
- # Make sure b's count was set to a's value once.
- self.assertEqual(''.join(callback_count), 'b')
- del callback_count[:]
-
- # Make sure a's value was set to b's count once.
- b.count = 5
- self.assertEqual(''.join(callback_count), 'ba')
- del callback_count[:]
-
- # Make sure b's count was set to a's value once.
- a.value = 4
- self.assertEqual(''.join(callback_count), 'ab')
- del callback_count[:]
-
+
+ def test_callbacks(self):
+ """Verify two linked traitlets have their callbacks called once."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ class B(HasTraits):
+ count = Int()
+ a = A(value=9)
+ b = B(count=8)
+
+ # Register callbacks that count.
+ callback_count = []
+ def a_callback(name, old, new):
+ callback_count.append('a')
+ a.on_trait_change(a_callback, 'value')
+ def b_callback(name, old, new):
+ callback_count.append('b')
+ b.on_trait_change(b_callback, 'count')
+
+ # Connect the two classes.
+ c = link((a, 'value'), (b, 'count'))
+
+ # Make sure b's count was set to a's value once.
+ self.assertEqual(''.join(callback_count), 'b')
+ del callback_count[:]
+
+ # Make sure a's value was set to b's count once.
+ b.count = 5
+ self.assertEqual(''.join(callback_count), 'ba')
+ del callback_count[:]
+
+ # Make sure b's count was set to a's value once.
+ a.value = 4
+ self.assertEqual(''.join(callback_count), 'ab')
+ del callback_count[:]
+
def test_tranform(self):
"""Test transform link."""
@@ -2020,610 +2020,610 @@ class TestLink(TestCase):
l = link((mc, "i"), (mc, "j"))
self.assertRaises(TraitError, setattr, mc, 'j', 2)
-class TestDirectionalLink(TestCase):
- def test_connect_same(self):
- """Verify two traitlets of the same type can be linked together using directional_link."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- a = A(value=9)
- b = A(value=8)
-
- # Conenct the two classes.
- c = directional_link((a, 'value'), (b, 'value'))
-
- # Make sure the values are the same at the point of linking.
- self.assertEqual(a.value, b.value)
-
- # Change one the value of the source and check that it synchronizes the target.
- a.value = 5
- self.assertEqual(b.value, 5)
- # Change one the value of the target and check that it has no impact on the source
- b.value = 6
- self.assertEqual(a.value, 5)
-
- def test_tranform(self):
- """Test transform link."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- a = A(value=9)
- b = A(value=8)
-
- # Conenct the two classes.
- c = directional_link((a, 'value'), (b, 'value'), lambda x: 2 * x)
-
- # Make sure the values are correct at the point of linking.
- self.assertEqual(b.value, 2 * a.value)
-
- # Change one the value of the source and check that it modifies the target.
- a.value = 5
- self.assertEqual(b.value, 10)
- # Change one the value of the target and check that it has no impact on the source
- b.value = 6
- self.assertEqual(a.value, 5)
-
- def test_link_different(self):
- """Verify two traitlets of different types can be linked together using link."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- class B(HasTraits):
- count = Int()
- a = A(value=9)
- b = B(count=8)
-
- # Conenct the two classes.
- c = directional_link((a, 'value'), (b, 'count'))
-
- # Make sure the values are the same at the point of linking.
- self.assertEqual(a.value, b.count)
-
- # Change one the value of the source and check that it synchronizes the target.
- a.value = 5
- self.assertEqual(b.count, 5)
- # Change one the value of the target and check that it has no impact on the source
- b.value = 6
- self.assertEqual(a.value, 5)
-
+class TestDirectionalLink(TestCase):
+ def test_connect_same(self):
+ """Verify two traitlets of the same type can be linked together using directional_link."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ a = A(value=9)
+ b = A(value=8)
+
+ # Conenct the two classes.
+ c = directional_link((a, 'value'), (b, 'value'))
+
+ # Make sure the values are the same at the point of linking.
+ self.assertEqual(a.value, b.value)
+
+ # Change one the value of the source and check that it synchronizes the target.
+ a.value = 5
+ self.assertEqual(b.value, 5)
+ # Change one the value of the target and check that it has no impact on the source
+ b.value = 6
+ self.assertEqual(a.value, 5)
+
+ def test_tranform(self):
+ """Test transform link."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ a = A(value=9)
+ b = A(value=8)
+
+ # Conenct the two classes.
+ c = directional_link((a, 'value'), (b, 'value'), lambda x: 2 * x)
+
+ # Make sure the values are correct at the point of linking.
+ self.assertEqual(b.value, 2 * a.value)
+
+ # Change one the value of the source and check that it modifies the target.
+ a.value = 5
+ self.assertEqual(b.value, 10)
+ # Change one the value of the target and check that it has no impact on the source
+ b.value = 6
+ self.assertEqual(a.value, 5)
+
+ def test_link_different(self):
+ """Verify two traitlets of different types can be linked together using link."""
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ class B(HasTraits):
+ count = Int()
+ a = A(value=9)
+ b = B(count=8)
+
+ # Conenct the two classes.
+ c = directional_link((a, 'value'), (b, 'count'))
+
+ # Make sure the values are the same at the point of linking.
+ self.assertEqual(a.value, b.count)
+
+ # Change one the value of the source and check that it synchronizes the target.
+ a.value = 5
+ self.assertEqual(b.count, 5)
+ # Change one the value of the target and check that it has no impact on the source
+ b.value = 6
+ self.assertEqual(a.value, 5)
+
def test_unlink_link(self):
"""Verify two linked traitlets can be unlinked and relinked."""
-
- # Create two simple classes with Int traitlets.
- class A(HasTraits):
- value = Int()
- a = A(value=9)
- b = A(value=8)
-
- # Connect the two classes.
- c = directional_link((a, 'value'), (b, 'value'))
- a.value = 4
- c.unlink()
-
- # Change one of the values to make sure they don't stay in sync.
- a.value = 5
- self.assertNotEqual(a.value, b.value)
+
+ # Create two simple classes with Int traitlets.
+ class A(HasTraits):
+ value = Int()
+ a = A(value=9)
+ b = A(value=8)
+
+ # Connect the two classes.
+ c = directional_link((a, 'value'), (b, 'value'))
+ a.value = 4
+ c.unlink()
+
+ # Change one of the values to make sure they don't stay in sync.
+ a.value = 5
+ self.assertNotEqual(a.value, b.value)
c.link()
self.assertEqual(a.value, b.value)
a.value += 1
self.assertEqual(a.value, b.value)
-
-class Pickleable(HasTraits):
-
- i = Int()
- @observe('i')
- def _i_changed(self, change): pass
- @validate('i')
- def _i_validate(self, commit):
- return commit['value']
-
- j = Int()
-
- def __init__(self):
- with self.hold_trait_notifications():
- self.i = 1
- self.on_trait_change(self._i_changed, 'i')
-
-def test_pickle_hastraits():
- c = Pickleable()
- for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
- p = pickle.dumps(c, protocol)
- c2 = pickle.loads(p)
- assert c2.i == c.i
- assert c2.j == c.j
-
- c.i = 5
- for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
- p = pickle.dumps(c, protocol)
- c2 = pickle.loads(p)
- assert c2.i == c.i
- assert c2.j == c.j
-
-
-def test_hold_trait_notifications():
- changes = []
-
- class Test(HasTraits):
- a = Integer(0)
- b = Integer(0)
-
- def _a_changed(self, name, old, new):
- changes.append((old, new))
-
- def _b_validate(self, value, trait):
- if value != 0:
- raise TraitError('Only 0 is a valid value')
- return value
-
- # Test context manager and nesting
- t = Test()
- with t.hold_trait_notifications():
- with t.hold_trait_notifications():
- t.a = 1
- assert t.a == 1
- assert changes == []
- t.a = 2
- assert t.a == 2
- with t.hold_trait_notifications():
- t.a = 3
- assert t.a == 3
- assert changes == []
- t.a = 4
- assert t.a == 4
- assert changes == []
- t.a = 4
- assert t.a == 4
- assert changes == []
-
- assert changes == [(0, 4)]
- # Test roll-back
- try:
- with t.hold_trait_notifications():
- t.b = 1 # raises a Trait error
- except:
- pass
- assert t.b == 0
-
-
-class RollBack(HasTraits):
- bar = Int()
- def _bar_validate(self, value, trait):
- if value:
- raise TraitError('foobar')
- return value
-
-
-class TestRollback(TestCase):
-
- def test_roll_back(self):
-
- def assign_rollback():
- RollBack(bar=1)
-
- self.assertRaises(TraitError, assign_rollback)
-
-
-class CacheModification(HasTraits):
- foo = Int()
- bar = Int()
-
- def _bar_validate(self, value, trait):
- self.foo = value
- return value
-
- def _foo_validate(self, value, trait):
- self.bar = value
- return value
-
-
-def test_cache_modification():
- CacheModification(foo=1)
- CacheModification(bar=1)
-
-
-class OrderTraits(HasTraits):
- notified = Dict()
-
- a = Unicode()
- b = Unicode()
- c = Unicode()
- d = Unicode()
- e = Unicode()
- f = Unicode()
- g = Unicode()
- h = Unicode()
- i = Unicode()
- j = Unicode()
- k = Unicode()
- l = Unicode()
-
- def _notify(self, name, old, new):
- """check the value of all traits when each trait change is triggered
-
- This verifies that the values are not sensitive
- to dict ordering when loaded from kwargs
- """
- # check the value of the other traits
- # when a given trait change notification fires
- self.notified[name] = {
- c: getattr(self, c) for c in 'abcdefghijkl'
- }
-
- def __init__(self, **kwargs):
- self.on_trait_change(self._notify)
- super(OrderTraits, self).__init__(**kwargs)
-
-def test_notification_order():
- d = {c:c for c in 'abcdefghijkl'}
- obj = OrderTraits()
- assert obj.notified == {}
- obj = OrderTraits(**d)
- notifications = {
- c: d for c in 'abcdefghijkl'
- }
- assert obj.notified == notifications
-
-
-
-###
-# Traits for Forward Declaration Tests
-###
-class ForwardDeclaredInstanceTrait(HasTraits):
-
- value = ForwardDeclaredInstance('ForwardDeclaredBar', allow_none=True)
-
-class ForwardDeclaredTypeTrait(HasTraits):
-
- value = ForwardDeclaredType('ForwardDeclaredBar', allow_none=True)
-
-class ForwardDeclaredInstanceListTrait(HasTraits):
-
- value = List(ForwardDeclaredInstance('ForwardDeclaredBar'))
-
-class ForwardDeclaredTypeListTrait(HasTraits):
-
- value = List(ForwardDeclaredType('ForwardDeclaredBar'))
-###
-# End Traits for Forward Declaration Tests
-###
-
-###
-# Classes for Forward Declaration Tests
-###
-class ForwardDeclaredBar(object):
- pass
-
-class ForwardDeclaredBarSub(ForwardDeclaredBar):
- pass
-###
-# End Classes for Forward Declaration Tests
-###
-
-###
-# Forward Declaration Tests
-###
-class TestForwardDeclaredInstanceTrait(TraitTestBase):
-
- obj = ForwardDeclaredInstanceTrait()
- _default_value = None
- _good_values = [None, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
- _bad_values = ['foo', 3, ForwardDeclaredBar, ForwardDeclaredBarSub]
-
-class TestForwardDeclaredTypeTrait(TraitTestBase):
-
- obj = ForwardDeclaredTypeTrait()
- _default_value = None
- _good_values = [None, ForwardDeclaredBar, ForwardDeclaredBarSub]
- _bad_values = ['foo', 3, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
-
-class TestForwardDeclaredInstanceList(TraitTestBase):
-
- obj = ForwardDeclaredInstanceListTrait()
-
- def test_klass(self):
- """Test that the instance klass is properly assigned."""
- self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
-
- _default_value = []
- _good_values = [
- [ForwardDeclaredBar(), ForwardDeclaredBarSub()],
- [],
- ]
- _bad_values = [
- ForwardDeclaredBar(),
- [ForwardDeclaredBar(), 3, None],
- '1',
- # Note that this is the type, not an instance.
- [ForwardDeclaredBar],
- [None],
- None,
- ]
-
-class TestForwardDeclaredTypeList(TraitTestBase):
-
- obj = ForwardDeclaredTypeListTrait()
-
- def test_klass(self):
- """Test that the instance klass is properly assigned."""
- self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
-
- _default_value = []
- _good_values = [
- [ForwardDeclaredBar, ForwardDeclaredBarSub],
- [],
- ]
- _bad_values = [
- ForwardDeclaredBar,
- [ForwardDeclaredBar, 3],
- '1',
- # Note that this is an instance, not the type.
- [ForwardDeclaredBar()],
- [None],
- None,
- ]
-###
-# End Forward Declaration Tests
-###
-
-class TestDynamicTraits(TestCase):
-
- def setUp(self):
- self._notify1 = []
-
- def notify1(self, name, old, new):
- self._notify1.append((name, old, new))
-
- def test_notify_all(self):
-
- class A(HasTraits):
- pass
-
- a = A()
- self.assertTrue(not hasattr(a, 'x'))
- self.assertTrue(not hasattr(a, 'y'))
-
- # Dynamically add trait x.
- a.add_traits(x=Int())
- self.assertTrue(hasattr(a, 'x'))
- self.assertTrue(isinstance(a, (A, )))
-
- # Dynamically add trait y.
- a.add_traits(y=Float())
- self.assertTrue(hasattr(a, 'y'))
- self.assertTrue(isinstance(a, (A, )))
- self.assertEqual(a.__class__.__name__, A.__name__)
-
- # Create a new instance and verify that x and y
- # aren't defined.
- b = A()
- self.assertTrue(not hasattr(b, 'x'))
- self.assertTrue(not hasattr(b, 'y'))
-
- # Verify that notification works like normal.
- a.on_trait_change(self.notify1)
- a.x = 0
- self.assertEqual(len(self._notify1), 0)
- a.y = 0.0
- self.assertEqual(len(self._notify1), 0)
- a.x = 10
- self.assertTrue(('x', 0, 10) in self._notify1)
- a.y = 10.0
- self.assertTrue(('y', 0.0, 10.0) in self._notify1)
- self.assertRaises(TraitError, setattr, a, 'x', 'bad string')
- self.assertRaises(TraitError, setattr, a, 'y', 'bad string')
- self._notify1 = []
- a.on_trait_change(self.notify1, remove=True)
- a.x = 20
- a.y = 20.0
- self.assertEqual(len(self._notify1), 0)
-
-
-def test_enum_no_default():
- class C(HasTraits):
- t = Enum(['a', 'b'])
-
- c = C()
- c.t = 'a'
- assert c.t == 'a'
-
- c = C()
-
- with pytest.raises(TraitError):
- t = c.t
-
- c = C(t='b')
- assert c.t == 'b'
-
-
-def test_default_value_repr():
- class C(HasTraits):
- t = Type('traitlets.HasTraits')
- t2 = Type(HasTraits)
- n = Integer(0)
- lis = List()
- d = Dict()
-
- assert C.t.default_value_repr() == "'traitlets.HasTraits'"
- assert C.t2.default_value_repr() == "'traitlets.traitlets.HasTraits'"
- assert C.n.default_value_repr() == '0'
- assert C.lis.default_value_repr() == '[]'
- assert C.d.default_value_repr() == '{}'
-
-
-class TransitionalClass(HasTraits):
-
- d = Any()
- @default('d')
- def _d_default(self):
- return TransitionalClass
-
- parent_super = False
- calls_super = Integer(0)
-
- @default('calls_super')
- def _calls_super_default(self):
- return -1
-
- @observe('calls_super')
- @observe_compat
- def _calls_super_changed(self, change):
- self.parent_super = change
-
- parent_override = False
- overrides = Integer(0)
-
- @observe('overrides')
- @observe_compat
- def _overrides_changed(self, change):
- self.parent_override = change
-
-
-class SubClass(TransitionalClass):
- def _d_default(self):
- return SubClass
-
- subclass_super = False
- def _calls_super_changed(self, name, old, new):
- self.subclass_super = True
- super(SubClass, self)._calls_super_changed(name, old, new)
-
- subclass_override = False
- def _overrides_changed(self, name, old, new):
- self.subclass_override = True
-
-
-def test_subclass_compat():
- obj = SubClass()
- obj.calls_super = 5
- assert obj.parent_super
- assert obj.subclass_super
- obj.overrides = 5
- assert obj.subclass_override
- assert not obj.parent_override
- assert obj.d is SubClass
-
-
-class DefinesHandler(HasTraits):
- parent_called = False
-
- trait = Integer()
- @observe('trait')
- def handler(self, change):
- self.parent_called = True
-
-
-class OverridesHandler(DefinesHandler):
- child_called = False
-
- @observe('trait')
- def handler(self, change):
- self.child_called = True
-
-
-def test_subclass_override_observer():
- obj = OverridesHandler()
- obj.trait = 5
- assert obj.child_called
- assert not obj.parent_called
-
-
-class DoesntRegisterHandler(DefinesHandler):
- child_called = False
-
- def handler(self, change):
- self.child_called = True
-
-
-def test_subclass_override_not_registered():
- """Subclass that overrides observer and doesn't re-register unregisters both"""
- obj = DoesntRegisterHandler()
- obj.trait = 5
- assert not obj.child_called
- assert not obj.parent_called
-
-
-class AddsHandler(DefinesHandler):
- child_called = False
-
- @observe('trait')
- def child_handler(self, change):
- self.child_called = True
-
-def test_subclass_add_observer():
- obj = AddsHandler()
- obj.trait = 5
- assert obj.child_called
- assert obj.parent_called
-
-
-def test_observe_iterables():
-
- class C(HasTraits):
- i = Integer()
- s = Unicode()
-
- c = C()
- recorded = {}
- def record(change):
- recorded['change'] = change
-
- # observe with names=set
- c.observe(record, names={'i', 's'})
- c.i = 5
- assert recorded['change'].name == 'i'
- assert recorded['change'].new == 5
- c.s = 'hi'
- assert recorded['change'].name == 's'
- assert recorded['change'].new == 'hi'
-
- # observe with names=custom container with iter, contains
- class MyContainer(object):
- def __init__(self, container):
- self.container = container
-
- def __iter__(self):
- return iter(self.container)
-
- def __contains__(self, key):
- return key in self.container
-
- c.observe(record, names=MyContainer({'i', 's'}))
- c.i = 10
- assert recorded['change'].name == 'i'
- assert recorded['change'].new == 10
- c.s = 'ok'
- assert recorded['change'].name == 's'
- assert recorded['change'].new == 'ok'
-
-
-def test_super_args():
- class SuperRecorder(object):
- def __init__(self, *args, **kwargs):
- self.super_args = args
- self.super_kwargs = kwargs
-
- class SuperHasTraits(HasTraits, SuperRecorder):
- i = Integer()
-
- obj = SuperHasTraits('a1', 'a2', b=10, i=5, c='x')
- assert obj.i == 5
- assert not hasattr(obj, 'b')
- assert not hasattr(obj, 'c')
- assert obj.super_args == ('a1' , 'a2')
- assert obj.super_kwargs == {'b': 10 , 'c': 'x'}
-
-def test_super_bad_args():
- class SuperHasTraits(HasTraits):
- a = Integer()
+
+class Pickleable(HasTraits):
+
+ i = Int()
+ @observe('i')
+ def _i_changed(self, change): pass
+ @validate('i')
+ def _i_validate(self, commit):
+ return commit['value']
+
+ j = Int()
+
+ def __init__(self):
+ with self.hold_trait_notifications():
+ self.i = 1
+ self.on_trait_change(self._i_changed, 'i')
+
+def test_pickle_hastraits():
+ c = Pickleable()
+ for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
+ p = pickle.dumps(c, protocol)
+ c2 = pickle.loads(p)
+ assert c2.i == c.i
+ assert c2.j == c.j
+
+ c.i = 5
+ for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
+ p = pickle.dumps(c, protocol)
+ c2 = pickle.loads(p)
+ assert c2.i == c.i
+ assert c2.j == c.j
+
+
+def test_hold_trait_notifications():
+ changes = []
+
+ class Test(HasTraits):
+ a = Integer(0)
+ b = Integer(0)
+
+ def _a_changed(self, name, old, new):
+ changes.append((old, new))
+
+ def _b_validate(self, value, trait):
+ if value != 0:
+ raise TraitError('Only 0 is a valid value')
+ return value
+
+ # Test context manager and nesting
+ t = Test()
+ with t.hold_trait_notifications():
+ with t.hold_trait_notifications():
+ t.a = 1
+ assert t.a == 1
+ assert changes == []
+ t.a = 2
+ assert t.a == 2
+ with t.hold_trait_notifications():
+ t.a = 3
+ assert t.a == 3
+ assert changes == []
+ t.a = 4
+ assert t.a == 4
+ assert changes == []
+ t.a = 4
+ assert t.a == 4
+ assert changes == []
+
+ assert changes == [(0, 4)]
+ # Test roll-back
+ try:
+ with t.hold_trait_notifications():
+ t.b = 1 # raises a Trait error
+ except:
+ pass
+ assert t.b == 0
+
+
+class RollBack(HasTraits):
+ bar = Int()
+ def _bar_validate(self, value, trait):
+ if value:
+ raise TraitError('foobar')
+ return value
+
+
+class TestRollback(TestCase):
+
+ def test_roll_back(self):
+
+ def assign_rollback():
+ RollBack(bar=1)
+
+ self.assertRaises(TraitError, assign_rollback)
+
+
+class CacheModification(HasTraits):
+ foo = Int()
+ bar = Int()
+
+ def _bar_validate(self, value, trait):
+ self.foo = value
+ return value
+
+ def _foo_validate(self, value, trait):
+ self.bar = value
+ return value
+
+
+def test_cache_modification():
+ CacheModification(foo=1)
+ CacheModification(bar=1)
+
+
+class OrderTraits(HasTraits):
+ notified = Dict()
+
+ a = Unicode()
+ b = Unicode()
+ c = Unicode()
+ d = Unicode()
+ e = Unicode()
+ f = Unicode()
+ g = Unicode()
+ h = Unicode()
+ i = Unicode()
+ j = Unicode()
+ k = Unicode()
+ l = Unicode()
+
+ def _notify(self, name, old, new):
+ """check the value of all traits when each trait change is triggered
+
+ This verifies that the values are not sensitive
+ to dict ordering when loaded from kwargs
+ """
+ # check the value of the other traits
+ # when a given trait change notification fires
+ self.notified[name] = {
+ c: getattr(self, c) for c in 'abcdefghijkl'
+ }
+
+ def __init__(self, **kwargs):
+ self.on_trait_change(self._notify)
+ super(OrderTraits, self).__init__(**kwargs)
+
+def test_notification_order():
+ d = {c:c for c in 'abcdefghijkl'}
+ obj = OrderTraits()
+ assert obj.notified == {}
+ obj = OrderTraits(**d)
+ notifications = {
+ c: d for c in 'abcdefghijkl'
+ }
+ assert obj.notified == notifications
+
+
+
+###
+# Traits for Forward Declaration Tests
+###
+class ForwardDeclaredInstanceTrait(HasTraits):
+
+ value = ForwardDeclaredInstance('ForwardDeclaredBar', allow_none=True)
+
+class ForwardDeclaredTypeTrait(HasTraits):
+
+ value = ForwardDeclaredType('ForwardDeclaredBar', allow_none=True)
+
+class ForwardDeclaredInstanceListTrait(HasTraits):
+
+ value = List(ForwardDeclaredInstance('ForwardDeclaredBar'))
+
+class ForwardDeclaredTypeListTrait(HasTraits):
+
+ value = List(ForwardDeclaredType('ForwardDeclaredBar'))
+###
+# End Traits for Forward Declaration Tests
+###
+
+###
+# Classes for Forward Declaration Tests
+###
+class ForwardDeclaredBar(object):
+ pass
+
+class ForwardDeclaredBarSub(ForwardDeclaredBar):
+ pass
+###
+# End Classes for Forward Declaration Tests
+###
+
+###
+# Forward Declaration Tests
+###
+class TestForwardDeclaredInstanceTrait(TraitTestBase):
+
+ obj = ForwardDeclaredInstanceTrait()
+ _default_value = None
+ _good_values = [None, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
+ _bad_values = ['foo', 3, ForwardDeclaredBar, ForwardDeclaredBarSub]
+
+class TestForwardDeclaredTypeTrait(TraitTestBase):
+
+ obj = ForwardDeclaredTypeTrait()
+ _default_value = None
+ _good_values = [None, ForwardDeclaredBar, ForwardDeclaredBarSub]
+ _bad_values = ['foo', 3, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
+
+class TestForwardDeclaredInstanceList(TraitTestBase):
+
+ obj = ForwardDeclaredInstanceListTrait()
+
+ def test_klass(self):
+ """Test that the instance klass is properly assigned."""
+ self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
+
+ _default_value = []
+ _good_values = [
+ [ForwardDeclaredBar(), ForwardDeclaredBarSub()],
+ [],
+ ]
+ _bad_values = [
+ ForwardDeclaredBar(),
+ [ForwardDeclaredBar(), 3, None],
+ '1',
+ # Note that this is the type, not an instance.
+ [ForwardDeclaredBar],
+ [None],
+ None,
+ ]
+
+class TestForwardDeclaredTypeList(TraitTestBase):
+
+ obj = ForwardDeclaredTypeListTrait()
+
+ def test_klass(self):
+ """Test that the instance klass is properly assigned."""
+ self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
+
+ _default_value = []
+ _good_values = [
+ [ForwardDeclaredBar, ForwardDeclaredBarSub],
+ [],
+ ]
+ _bad_values = [
+ ForwardDeclaredBar,
+ [ForwardDeclaredBar, 3],
+ '1',
+ # Note that this is an instance, not the type.
+ [ForwardDeclaredBar()],
+ [None],
+ None,
+ ]
+###
+# End Forward Declaration Tests
+###
+
+class TestDynamicTraits(TestCase):
+
+ def setUp(self):
+ self._notify1 = []
+
+ def notify1(self, name, old, new):
+ self._notify1.append((name, old, new))
+
+ def test_notify_all(self):
+
+ class A(HasTraits):
+ pass
+
+ a = A()
+ self.assertTrue(not hasattr(a, 'x'))
+ self.assertTrue(not hasattr(a, 'y'))
+
+ # Dynamically add trait x.
+ a.add_traits(x=Int())
+ self.assertTrue(hasattr(a, 'x'))
+ self.assertTrue(isinstance(a, (A, )))
+
+ # Dynamically add trait y.
+ a.add_traits(y=Float())
+ self.assertTrue(hasattr(a, 'y'))
+ self.assertTrue(isinstance(a, (A, )))
+ self.assertEqual(a.__class__.__name__, A.__name__)
+
+ # Create a new instance and verify that x and y
+ # aren't defined.
+ b = A()
+ self.assertTrue(not hasattr(b, 'x'))
+ self.assertTrue(not hasattr(b, 'y'))
+
+ # Verify that notification works like normal.
+ a.on_trait_change(self.notify1)
+ a.x = 0
+ self.assertEqual(len(self._notify1), 0)
+ a.y = 0.0
+ self.assertEqual(len(self._notify1), 0)
+ a.x = 10
+ self.assertTrue(('x', 0, 10) in self._notify1)
+ a.y = 10.0
+ self.assertTrue(('y', 0.0, 10.0) in self._notify1)
+ self.assertRaises(TraitError, setattr, a, 'x', 'bad string')
+ self.assertRaises(TraitError, setattr, a, 'y', 'bad string')
+ self._notify1 = []
+ a.on_trait_change(self.notify1, remove=True)
+ a.x = 20
+ a.y = 20.0
+ self.assertEqual(len(self._notify1), 0)
+
+
+def test_enum_no_default():
+ class C(HasTraits):
+ t = Enum(['a', 'b'])
+
+ c = C()
+ c.t = 'a'
+ assert c.t == 'a'
+
+ c = C()
+
+ with pytest.raises(TraitError):
+ t = c.t
+
+ c = C(t='b')
+ assert c.t == 'b'
+
+
+def test_default_value_repr():
+ class C(HasTraits):
+ t = Type('traitlets.HasTraits')
+ t2 = Type(HasTraits)
+ n = Integer(0)
+ lis = List()
+ d = Dict()
+
+ assert C.t.default_value_repr() == "'traitlets.HasTraits'"
+ assert C.t2.default_value_repr() == "'traitlets.traitlets.HasTraits'"
+ assert C.n.default_value_repr() == '0'
+ assert C.lis.default_value_repr() == '[]'
+ assert C.d.default_value_repr() == '{}'
+
+
+class TransitionalClass(HasTraits):
+
+ d = Any()
+ @default('d')
+ def _d_default(self):
+ return TransitionalClass
+
+ parent_super = False
+ calls_super = Integer(0)
+
+ @default('calls_super')
+ def _calls_super_default(self):
+ return -1
+
+ @observe('calls_super')
+ @observe_compat
+ def _calls_super_changed(self, change):
+ self.parent_super = change
+
+ parent_override = False
+ overrides = Integer(0)
+
+ @observe('overrides')
+ @observe_compat
+ def _overrides_changed(self, change):
+ self.parent_override = change
+
+
+class SubClass(TransitionalClass):
+ def _d_default(self):
+ return SubClass
+
+ subclass_super = False
+ def _calls_super_changed(self, name, old, new):
+ self.subclass_super = True
+ super(SubClass, self)._calls_super_changed(name, old, new)
+
+ subclass_override = False
+ def _overrides_changed(self, name, old, new):
+ self.subclass_override = True
+
+
+def test_subclass_compat():
+ obj = SubClass()
+ obj.calls_super = 5
+ assert obj.parent_super
+ assert obj.subclass_super
+ obj.overrides = 5
+ assert obj.subclass_override
+ assert not obj.parent_override
+ assert obj.d is SubClass
+
+
+class DefinesHandler(HasTraits):
+ parent_called = False
+
+ trait = Integer()
+ @observe('trait')
+ def handler(self, change):
+ self.parent_called = True
+
+
+class OverridesHandler(DefinesHandler):
+ child_called = False
+
+ @observe('trait')
+ def handler(self, change):
+ self.child_called = True
+
+
+def test_subclass_override_observer():
+ obj = OverridesHandler()
+ obj.trait = 5
+ assert obj.child_called
+ assert not obj.parent_called
+
+
+class DoesntRegisterHandler(DefinesHandler):
+ child_called = False
+
+ def handler(self, change):
+ self.child_called = True
+
+
+def test_subclass_override_not_registered():
+ """Subclass that overrides observer and doesn't re-register unregisters both"""
+ obj = DoesntRegisterHandler()
+ obj.trait = 5
+ assert not obj.child_called
+ assert not obj.parent_called
+
+
+class AddsHandler(DefinesHandler):
+ child_called = False
+
+ @observe('trait')
+ def child_handler(self, change):
+ self.child_called = True
+
+def test_subclass_add_observer():
+ obj = AddsHandler()
+ obj.trait = 5
+ assert obj.child_called
+ assert obj.parent_called
+
+
+def test_observe_iterables():
+
+ class C(HasTraits):
+ i = Integer()
+ s = Unicode()
+
+ c = C()
+ recorded = {}
+ def record(change):
+ recorded['change'] = change
+
+ # observe with names=set
+ c.observe(record, names={'i', 's'})
+ c.i = 5
+ assert recorded['change'].name == 'i'
+ assert recorded['change'].new == 5
+ c.s = 'hi'
+ assert recorded['change'].name == 's'
+ assert recorded['change'].new == 'hi'
+
+ # observe with names=custom container with iter, contains
+ class MyContainer(object):
+ def __init__(self, container):
+ self.container = container
+
+ def __iter__(self):
+ return iter(self.container)
+
+ def __contains__(self, key):
+ return key in self.container
+
+ c.observe(record, names=MyContainer({'i', 's'}))
+ c.i = 10
+ assert recorded['change'].name == 'i'
+ assert recorded['change'].new == 10
+ c.s = 'ok'
+ assert recorded['change'].name == 's'
+ assert recorded['change'].new == 'ok'
+
+
+def test_super_args():
+ class SuperRecorder(object):
+ def __init__(self, *args, **kwargs):
+ self.super_args = args
+ self.super_kwargs = kwargs
+
+ class SuperHasTraits(HasTraits, SuperRecorder):
+ i = Integer()
+
+ obj = SuperHasTraits('a1', 'a2', b=10, i=5, c='x')
+ assert obj.i == 5
+ assert not hasattr(obj, 'b')
+ assert not hasattr(obj, 'c')
+ assert obj.super_args == ('a1' , 'a2')
+ assert obj.super_kwargs == {'b': 10 , 'c': 'x'}
+
+def test_super_bad_args():
+ class SuperHasTraits(HasTraits):
+ a = Integer()
w = ["Passing unrecognized arguments"]
- with expected_warnings(w):
- obj = SuperHasTraits(a=1, b=2)
+ with expected_warnings(w):
+ obj = SuperHasTraits(a=1, b=2)
assert obj.a == 1
- assert not hasattr(obj, 'b')
+ assert not hasattr(obj, 'b')
def test_default_mro():
diff --git a/contrib/python/traitlets/py3/traitlets/tests/test_traitlets_enum.py b/contrib/python/traitlets/py3/traitlets/tests/test_traitlets_enum.py
index 6a074aadfb..769e830b33 100644
--- a/contrib/python/traitlets/py3/traitlets/tests/test_traitlets_enum.py
+++ b/contrib/python/traitlets/py3/traitlets/tests/test_traitlets_enum.py
@@ -1,28 +1,28 @@
-# pylint: disable=missing-docstring, too-few-public-methods
-"""
-Test the trait-type ``UseEnum``.
-"""
-
-import unittest
-import enum
+# pylint: disable=missing-docstring, too-few-public-methods
+"""
+Test the trait-type ``UseEnum``.
+"""
+
+import unittest
+import enum
from traitlets import HasTraits, TraitError, Enum, UseEnum, CaselessStrEnum, FuzzyEnum
-
-
-# -----------------------------------------------------------------------------
-# TEST SUPPORT:
-# -----------------------------------------------------------------------------
-
-class Color(enum.Enum):
- red = 1
- green = 2
- blue = 3
- yellow = 4
-
-class OtherColor(enum.Enum):
- red = 0
- green = 1
-
-
+
+
+# -----------------------------------------------------------------------------
+# TEST SUPPORT:
+# -----------------------------------------------------------------------------
+
+class Color(enum.Enum):
+ red = 1
+ green = 2
+ blue = 3
+ yellow = 4
+
+class OtherColor(enum.Enum):
+ red = 0
+ green = 1
+
+
class CSColor(enum.Enum):
red = 1
Green = 2
@@ -33,161 +33,161 @@ class CSColor(enum.Enum):
color_choices = 'red Green BLUE YeLLoW'.split()
-# -----------------------------------------------------------------------------
-# TESTSUITE:
-# -----------------------------------------------------------------------------
-class TestUseEnum(unittest.TestCase):
- # pylint: disable=invalid-name
-
- class Example(HasTraits):
- color = UseEnum(Color, help="Color enum")
-
- def test_assign_enum_value(self):
- example = self.Example()
- example.color = Color.green
- self.assertEqual(example.color, Color.green)
-
- def test_assign_all_enum_values(self):
- # pylint: disable=no-member
- enum_values = [value for value in Color.__members__.values()]
- for value in enum_values:
- self.assertIsInstance(value, Color)
- example = self.Example()
- example.color = value
- self.assertEqual(example.color, value)
- self.assertIsInstance(value, Color)
-
- def test_assign_enum_value__with_other_enum_raises_error(self):
- example = self.Example()
- with self.assertRaises(TraitError):
- example.color = OtherColor.green
-
- def test_assign_enum_name_1(self):
- # -- CONVERT: string => Enum value (item)
- example = self.Example()
- example.color = "red"
- self.assertEqual(example.color, Color.red)
-
- def test_assign_enum_value_name(self):
- # -- CONVERT: string => Enum value (item)
- # pylint: disable=no-member
- enum_names = [enum_val.name for enum_val in Color.__members__.values()]
- for value in enum_names:
+# -----------------------------------------------------------------------------
+# TESTSUITE:
+# -----------------------------------------------------------------------------
+class TestUseEnum(unittest.TestCase):
+ # pylint: disable=invalid-name
+
+ class Example(HasTraits):
+ color = UseEnum(Color, help="Color enum")
+
+ def test_assign_enum_value(self):
+ example = self.Example()
+ example.color = Color.green
+ self.assertEqual(example.color, Color.green)
+
+ def test_assign_all_enum_values(self):
+ # pylint: disable=no-member
+ enum_values = [value for value in Color.__members__.values()]
+ for value in enum_values:
+ self.assertIsInstance(value, Color)
+ example = self.Example()
+ example.color = value
+ self.assertEqual(example.color, value)
+ self.assertIsInstance(value, Color)
+
+ def test_assign_enum_value__with_other_enum_raises_error(self):
+ example = self.Example()
+ with self.assertRaises(TraitError):
+ example.color = OtherColor.green
+
+ def test_assign_enum_name_1(self):
+ # -- CONVERT: string => Enum value (item)
+ example = self.Example()
+ example.color = "red"
+ self.assertEqual(example.color, Color.red)
+
+ def test_assign_enum_value_name(self):
+ # -- CONVERT: string => Enum value (item)
+ # pylint: disable=no-member
+ enum_names = [enum_val.name for enum_val in Color.__members__.values()]
+ for value in enum_names:
self.assertIsInstance(value, str)
- example = self.Example()
- enum_value = Color.__members__.get(value)
- example.color = value
- self.assertIs(example.color, enum_value)
- self.assertEqual(example.color.name, value)
-
- def test_assign_scoped_enum_value_name(self):
- # -- CONVERT: string => Enum value (item)
- scoped_names = ["Color.red", "Color.green", "Color.blue", "Color.yellow"]
- for value in scoped_names:
- example = self.Example()
- example.color = value
- self.assertIsInstance(example.color, Color)
+ example = self.Example()
+ enum_value = Color.__members__.get(value)
+ example.color = value
+ self.assertIs(example.color, enum_value)
+ self.assertEqual(example.color.name, value)
+
+ def test_assign_scoped_enum_value_name(self):
+ # -- CONVERT: string => Enum value (item)
+ scoped_names = ["Color.red", "Color.green", "Color.blue", "Color.yellow"]
+ for value in scoped_names:
+ example = self.Example()
+ example.color = value
+ self.assertIsInstance(example.color, Color)
self.assertEqual(str(example.color), value)
-
- def test_assign_bad_enum_value_name__raises_error(self):
- # -- CONVERT: string => Enum value (item)
- bad_enum_names = ["UNKNOWN_COLOR", "RED", "Green", "blue2"]
- for value in bad_enum_names:
- example = self.Example()
- with self.assertRaises(TraitError):
- example.color = value
-
- def test_assign_enum_value_number_1(self):
- # -- CONVERT: number => Enum value (item)
- example = self.Example()
- example.color = 1 # == Color.red.value
- example.color = Color.red.value
- self.assertEqual(example.color, Color.red)
-
- def test_assign_enum_value_number(self):
- # -- CONVERT: number => Enum value (item)
- # pylint: disable=no-member
- enum_numbers = [enum_val.value
- for enum_val in Color.__members__.values()]
- for value in enum_numbers:
- self.assertIsInstance(value, int)
- example = self.Example()
- example.color = value
- self.assertIsInstance(example.color, Color)
- self.assertEqual(example.color.value, value)
-
- def test_assign_bad_enum_value_number__raises_error(self):
- # -- CONVERT: number => Enum value (item)
- bad_numbers = [-1, 0, 5]
- for value in bad_numbers:
- self.assertIsInstance(value, int)
- assert UseEnum(Color).select_by_number(value, None) is None
- example = self.Example()
- with self.assertRaises(TraitError):
- example.color = value
-
- def test_ctor_without_default_value(self):
- # -- IMPLICIT: default_value = Color.red (first enum-value)
- class Example2(HasTraits):
- color = UseEnum(Color)
-
- example = Example2()
- self.assertEqual(example.color, Color.red)
-
- def test_ctor_with_default_value_as_enum_value(self):
- # -- CONVERT: number => Enum value (item)
- class Example2(HasTraits):
- color = UseEnum(Color, default_value=Color.green)
-
- example = Example2()
- self.assertEqual(example.color, Color.green)
-
-
- def test_ctor_with_default_value_none_and_not_allow_none(self):
- # -- IMPLICIT: default_value = Color.red (first enum-value)
- class Example2(HasTraits):
- color1 = UseEnum(Color, default_value=None, allow_none=False)
- color2 = UseEnum(Color, default_value=None)
- example = Example2()
- self.assertEqual(example.color1, Color.red)
- self.assertEqual(example.color2, Color.red)
-
- def test_ctor_with_default_value_none_and_allow_none(self):
- class Example2(HasTraits):
- color1 = UseEnum(Color, default_value=None, allow_none=True)
- color2 = UseEnum(Color, allow_none=True)
-
- example = Example2()
- self.assertIs(example.color1, None)
- self.assertIs(example.color2, None)
-
- def test_assign_none_without_allow_none_resets_to_default_value(self):
- class Example2(HasTraits):
- color1 = UseEnum(Color, allow_none=False)
- color2 = UseEnum(Color)
-
- example = Example2()
- example.color1 = None
- example.color2 = None
- self.assertIs(example.color1, Color.red)
- self.assertIs(example.color2, Color.red)
-
- def test_assign_none_to_enum_or_none(self):
- class Example2(HasTraits):
- color = UseEnum(Color, allow_none=True)
-
- example = Example2()
- example.color = None
- self.assertIs(example.color, None)
-
- def test_assign_bad_value_with_to_enum_or_none(self):
- class Example2(HasTraits):
- color = UseEnum(Color, allow_none=True)
-
- example = Example2()
- with self.assertRaises(TraitError):
- example.color = "BAD_VALUE"
-
+
+ def test_assign_bad_enum_value_name__raises_error(self):
+ # -- CONVERT: string => Enum value (item)
+ bad_enum_names = ["UNKNOWN_COLOR", "RED", "Green", "blue2"]
+ for value in bad_enum_names:
+ example = self.Example()
+ with self.assertRaises(TraitError):
+ example.color = value
+
+ def test_assign_enum_value_number_1(self):
+ # -- CONVERT: number => Enum value (item)
+ example = self.Example()
+ example.color = 1 # == Color.red.value
+ example.color = Color.red.value
+ self.assertEqual(example.color, Color.red)
+
+ def test_assign_enum_value_number(self):
+ # -- CONVERT: number => Enum value (item)
+ # pylint: disable=no-member
+ enum_numbers = [enum_val.value
+ for enum_val in Color.__members__.values()]
+ for value in enum_numbers:
+ self.assertIsInstance(value, int)
+ example = self.Example()
+ example.color = value
+ self.assertIsInstance(example.color, Color)
+ self.assertEqual(example.color.value, value)
+
+ def test_assign_bad_enum_value_number__raises_error(self):
+ # -- CONVERT: number => Enum value (item)
+ bad_numbers = [-1, 0, 5]
+ for value in bad_numbers:
+ self.assertIsInstance(value, int)
+ assert UseEnum(Color).select_by_number(value, None) is None
+ example = self.Example()
+ with self.assertRaises(TraitError):
+ example.color = value
+
+ def test_ctor_without_default_value(self):
+ # -- IMPLICIT: default_value = Color.red (first enum-value)
+ class Example2(HasTraits):
+ color = UseEnum(Color)
+
+ example = Example2()
+ self.assertEqual(example.color, Color.red)
+
+ def test_ctor_with_default_value_as_enum_value(self):
+ # -- CONVERT: number => Enum value (item)
+ class Example2(HasTraits):
+ color = UseEnum(Color, default_value=Color.green)
+
+ example = Example2()
+ self.assertEqual(example.color, Color.green)
+
+
+ def test_ctor_with_default_value_none_and_not_allow_none(self):
+ # -- IMPLICIT: default_value = Color.red (first enum-value)
+ class Example2(HasTraits):
+ color1 = UseEnum(Color, default_value=None, allow_none=False)
+ color2 = UseEnum(Color, default_value=None)
+ example = Example2()
+ self.assertEqual(example.color1, Color.red)
+ self.assertEqual(example.color2, Color.red)
+
+ def test_ctor_with_default_value_none_and_allow_none(self):
+ class Example2(HasTraits):
+ color1 = UseEnum(Color, default_value=None, allow_none=True)
+ color2 = UseEnum(Color, allow_none=True)
+
+ example = Example2()
+ self.assertIs(example.color1, None)
+ self.assertIs(example.color2, None)
+
+ def test_assign_none_without_allow_none_resets_to_default_value(self):
+ class Example2(HasTraits):
+ color1 = UseEnum(Color, allow_none=False)
+ color2 = UseEnum(Color)
+
+ example = Example2()
+ example.color1 = None
+ example.color2 = None
+ self.assertIs(example.color1, Color.red)
+ self.assertIs(example.color2, Color.red)
+
+ def test_assign_none_to_enum_or_none(self):
+ class Example2(HasTraits):
+ color = UseEnum(Color, allow_none=True)
+
+ example = Example2()
+ example.color = None
+ self.assertIs(example.color, None)
+
+ def test_assign_bad_value_with_to_enum_or_none(self):
+ class Example2(HasTraits):
+ color = UseEnum(Color, allow_none=True)
+
+ example = Example2()
+ with self.assertRaises(TraitError):
+ example.color = "BAD_VALUE"
+
def test_info(self):
import sys
diff --git a/contrib/python/traitlets/py3/traitlets/tests/utils.py b/contrib/python/traitlets/py3/traitlets/tests/utils.py
index 7cb76bfa2c..c5ac591435 100644
--- a/contrib/python/traitlets/py3/traitlets/tests/utils.py
+++ b/contrib/python/traitlets/py3/traitlets/tests/utils.py
@@ -1,42 +1,42 @@
from subprocess import Popen, PIPE
import sys
-import os
-
-
-def get_output_error_code(cmd):
- """Get stdout, stderr, and exit code from running a command"""
- env = os.environ.copy()
- env['Y_PYTHON_ENTRY_POINT'] = ':main'
- p = Popen(cmd, stdout=PIPE, stderr=PIPE, env=env)
- out, err = p.communicate()
- out = out.decode('utf8', 'replace')
- err = err.decode('utf8', 'replace')
- return out, err, p.returncode
-
-
-def check_help_output(pkg, subcommand=None):
- """test that `python -m PKG [subcommand] -h` works"""
- cmd = [sys.executable, '-m', pkg]
- if subcommand:
- cmd.extend(subcommand)
- cmd.append('-h')
- out, err, rc = get_output_error_code(cmd)
- assert rc == 0, err
- assert "Traceback" not in err
- assert "Options" in out
- assert "--help-all" in out
- return out, err
-
-
-def check_help_all_output(pkg, subcommand=None):
- """test that `python -m PKG --help-all` works"""
- cmd = [sys.executable, '-m', pkg]
- if subcommand:
- cmd.extend(subcommand)
- cmd.append('--help-all')
- out, err, rc = get_output_error_code(cmd)
- assert rc == 0, err
- assert "Traceback" not in err
- assert "Options" in out
+import os
+
+
+def get_output_error_code(cmd):
+ """Get stdout, stderr, and exit code from running a command"""
+ env = os.environ.copy()
+ env['Y_PYTHON_ENTRY_POINT'] = ':main'
+ p = Popen(cmd, stdout=PIPE, stderr=PIPE, env=env)
+ out, err = p.communicate()
+ out = out.decode('utf8', 'replace')
+ err = err.decode('utf8', 'replace')
+ return out, err, p.returncode
+
+
+def check_help_output(pkg, subcommand=None):
+ """test that `python -m PKG [subcommand] -h` works"""
+ cmd = [sys.executable, '-m', pkg]
+ if subcommand:
+ cmd.extend(subcommand)
+ cmd.append('-h')
+ out, err, rc = get_output_error_code(cmd)
+ assert rc == 0, err
+ assert "Traceback" not in err
+ assert "Options" in out
+ assert "--help-all" in out
+ return out, err
+
+
+def check_help_all_output(pkg, subcommand=None):
+ """test that `python -m PKG --help-all` works"""
+ cmd = [sys.executable, '-m', pkg]
+ if subcommand:
+ cmd.extend(subcommand)
+ cmd.append('--help-all')
+ out, err, rc = get_output_error_code(cmd)
+ assert rc == 0, err
+ assert "Traceback" not in err
+ assert "Options" in out
assert "Class options" in out
- return out, err
+ return out, err
diff --git a/contrib/python/traitlets/py3/ya.make b/contrib/python/traitlets/py3/ya.make
index ea546d53e4..46980f21b3 100644
--- a/contrib/python/traitlets/py3/ya.make
+++ b/contrib/python/traitlets/py3/ya.make
@@ -44,7 +44,7 @@ RESOURCE_FILES(
)
END()
-
-RECURSE_FOR_TESTS(
+
+RECURSE_FOR_TESTS(
tests
-)
+)
diff --git a/contrib/python/traitlets/ya.make b/contrib/python/traitlets/ya.make
index 97655f153c..3156aae8c5 100644
--- a/contrib/python/traitlets/ya.make
+++ b/contrib/python/traitlets/ya.make
@@ -13,8 +13,8 @@ ENDIF()
NO_LINT()
END()
-
+
RECURSE(
py2
py3
-)
+)