Skip to content

Commit

Permalink
Merge pull request #39 from takluyver/type-default-sentinel
Browse files Browse the repository at this point in the history
Use NoDefaultSpecified as sentinel for Type default
  • Loading branch information
minrk committed Jun 17, 2015
2 parents 0daacdf + d539e96 commit 2b8b540
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 8 deletions.
35 changes: 35 additions & 0 deletions traitlets/tests/test_traitlets.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,41 @@ class A(HasTraits):
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
Expand Down
21 changes: 13 additions & 8 deletions traitlets/traitlets.py
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ def error(self, obj, value):
class Type(ClassBasedTraitType):
"""A trait whose value must be a subclass of a specified class."""

def __init__ (self, default_value=None, klass=None, **metadata):
def __init__ (self, default_value=NoDefaultSpecified, klass=None, **metadata):
"""Construct a Type trait
A Type trait specifies that its values must be subclasses of
Expand All @@ -919,26 +919,31 @@ def __init__ (self, default_value=None, klass=None, **metadata):
the str must be a fully specified class name, like 'foo.bar.Bah'.
The string is resolved into real class, when the parent
:class:`HasTraits` class is instantiated.
klass : class, str, None
klass : class, str [ default object ]
Values of this trait must be a subclass of klass. The klass
may be specified in a string like: 'foo.bar.MyClass'.
The string is resolved into real class, when the parent
:class:`HasTraits` class is instantiated.
allow_none : bool [ default False ]
Indicates whether None is allowed as an assignable value.
"""
if default_value is None:
if klass is None:
default_value = klass = object
elif klass is None:
klass = default_value
if default_value is NoDefaultSpecified:
new_default_value = object if (klass is None) else klass
else:
new_default_value = default_value

if klass is None:
if (default_value is None) or (default_value is NoDefaultSpecified):
klass = object
else:
klass = default_value

if not (inspect.isclass(klass) or isinstance(klass, py3compat.string_types)):
raise TraitError("A Type trait must specify a class.")

self.klass = klass

super(Type, self).__init__(default_value, **metadata)
super(Type, self).__init__(new_default_value, **metadata)

def validate(self, obj, value):
"""Validates that the value is a valid object instance."""
Expand Down

0 comments on commit 2b8b540

Please sign in to comment.