Skip to content

Commit

Permalink
update following rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
rmorshea committed Feb 1, 2017
1 parent dfef2fa commit 751b750
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 80 deletions.
23 changes: 22 additions & 1 deletion traitlets/tests/test_traitlets.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
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,
observe_compat, BaseDescriptor, HasDescriptors, parse_notifier_name,
parse_notifier_tags, TraitEventHandler
)

import six
Expand All @@ -31,6 +32,7 @@ def change_dict(*ordered_values):
change_names = ('name', 'old', 'new', 'owner', 'type')
return dict(zip(change_names, ordered_values))


#-----------------------------------------------------------------------------
# Helper classes for testing
#-----------------------------------------------------------------------------
Expand Down Expand Up @@ -567,6 +569,10 @@ def notify1(self, change):
def notify2(self, change):
self._notify2.append(change)

def test_raise_on_no_names(self):
with pytest.raises(TypeError):
observe()

def test_notify_all(self):

class A(HasTraits):
Expand Down Expand Up @@ -2637,3 +2643,18 @@ def __init__(__self, cls, self):
pass

x = X(cls=None, self=None)


#-----------------------------------------------------------------------------
# Misc testing for improved coverage
#-----------------------------------------------------------------------------


def test_notifier_parsing():
with pytest.raises(TypeError):
parse_notifier_name([0])

with pytest.raises(TypeError):
parse_notifier_tags(0, {"type": None})


97 changes: 18 additions & 79 deletions traitlets/traitlets.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def parse_notifier_name(names):
else:
for n in names:
if not isinstance(n, six.string_types):
raise TypeError("names must be strings, not %s" % n)
raise TypeError("names must be strings or All, not %s" % n)
return list(names)


Expand Down Expand Up @@ -805,13 +805,8 @@ def observe(*names, **kwargs):
type: str, kwarg-only
The type of event to observe (e.g. 'change')
"""
if not names:
raise TypeError("Please specify at least one trait name to observe.")
for name in names:
if name is not All and not isinstance(name, six.string_types):
raise TypeError("trait names to observe must be strings or All, not %r" % name)
return ObserveHandler(names, tags=kwargs.get('tags', {}),
type=kwargs.get('type', 'change'))
type=kwargs.get('type', 'change'))


def observe_compat(func):
Expand Down Expand Up @@ -869,11 +864,6 @@ def validate(*names, **kwargs):
exiting the ``hold_trait_notifications`` context, and such changes may not
commute.
"""
if not names:
raise TypeError("Please specify at least one trait name to validate.")
for name in names:
if name is not All and not isinstance(name, six.string_types):
raise TypeError("trait names to validate must be strings or All, not %r" % name)
return ValidateHandler(names, tags=kwargs.get('tags', {}))


Expand Down Expand Up @@ -915,11 +905,6 @@ def some_other_default(self): # This default generator should not be
return 3.0 # ignored since it is defined in a
# class derived from B.a.this_class.
"""
if not names:
raise TypeError("Please specify at least one trait name to validate.")
for name in names:
if name is not All and not isinstance(name, six.string_types):
raise TypeError("trait names to validate must be strings or All, not %r" % name)
return DefaultHandler(names, tags=kwargs.get('tags', {}))


Expand Down Expand Up @@ -950,12 +935,14 @@ class TraitEventHandler(EventHandler):
trait_names = []

def __init__(self, names, tags):
if names: self.trait_names = parse_notifier_name(names)
if tags: self.metadata = tags
if (not names and names is not None) and not tags:
raise TypeError("Please specify at least one trait name or tag.")
self.trait_names = parse_notifier_name(names)
self.metadata = tags or {}

def register(self, inst):
def register(self, obj):
"""Associate this event with traits on an instance"""
pass
raise NotImplementedError()

def event_of(self, obj, names=None):
"""Get the object's trait names this instance is an event of
Expand Down Expand Up @@ -998,18 +985,8 @@ def __init__(self, names, type, tags):
def instance_init(self, inst):
self.register(inst)

def register(self, inst, names=None):
if names is not None:
matched = self.event_of(inst, names)
if len(matched)!=len(names):
diff = set(names).difference(matched)
m = "Not handling events for %r"
raise TraitError(m % list(diff))
else:
names = list(matched)
else:
names = self.event_of(inst)
inst.observe(self, names, type=self.type)
def register(self, inst):
inst.observe(self, self.event_of(inst), type=self.type)


class ValidateHandler(TraitEventHandler):
Expand All @@ -1020,17 +997,7 @@ def instance_init(self, inst):
self.register(inst)

def register(self, inst, names=None):
if names is not None:
matched = self.event_of(inst, names)
if len(matched)!=names:
diff = set(names).difference(matched)
m = "Not handling events for %r"
raise TraitError(m % diff)
else:
names = list(matched)
else:
names = self.event_of(inst)
inst._register_validator(self, names)
inst._register_validator(self, self.event_of(inst))


class DefaultHandler(TraitEventHandler):
Expand All @@ -1041,33 +1008,10 @@ def class_init(self, cls, name):
super(DefaultHandler, self).class_init(cls, name)
self.register(cls)

def register(self, cls, names=None):
def register(self, cls):
"""Associate this event with traits on a class"""
if not issubclass(cls, HasTraits):
raise TypeError("Expected a HasTraits subclass")
elif names is not None:
matched = self.event_of(cls, names)
if len(matched)!=names:
diff = set(names).difference(matched)
m = "Not handling events for %r"
raise TraitError(m % diff)
else:
names = list(matched)
else:
names = self.event_of(cls)
self._register(cls, names)

def _register(self, cls, names):
# Class creation prevents registration logic from being
# properly overridden if done on the class, because super
# fails. Thus the event is registered here, through the
# descriptor, so super can be used when overriding it.
for n in names:
if n in cls._trait_default_generators:
raise TraitError("%s has a conflicting default"
" generator for '%s'" % (cls.__name__, n))
else:
cls._trait_default_generators[n] = self
for n in self.event_of(cls):
cls._trait_default_generators[n] = self


class HasDescriptors(six.with_metaclass(MetaHasDescriptors, object)):
Expand Down Expand Up @@ -1339,7 +1283,7 @@ def _remove_notifiers(self, handler, names, type):
event = self._trait_notifiers[name][type].pop(i)
except KeyError:
pass
if event.name is None:
if getattr(handler, 'name', None) is None:
self._static_trait_notifiers.remove(handler)

def on_trait_change(self, handler=None, name=None, remove=False):
Expand Down Expand Up @@ -1405,16 +1349,12 @@ def observe(self, handler, names=None, type='change', tags=None):
The type of notification to filter by. If equal to All, then all
notifications are passed to the observe handler.
"""
if isinstance(tags, six.string_types):
warn("new argument 'tags' introduced: use 'type' as keyword",
DeprecationWarning, stacklevel=2)
type, tags = tags, None
if names is None and tags is None:
names = All
names = (All,)
if isinstance(handler, ObserveHandler):
self._add_notifiers(handler, names, type)
else:
event = ObserveHandler(names, type, tags)
event = ObserveHandler(names, type=type, tags=tags)
event(handler).register(self)

def unobserve(self, handler, names=None, type='change', tags=None):
Expand Down Expand Up @@ -1521,8 +1461,7 @@ def add_traits(self, **traits):

for e in events:
if e.caches_instance_resources:
for n in e.event_of(self, traits.keys()):
e.register(self, (n,))
e.register(self)

for trait in traits.values():
trait.instance_init(self)
Expand Down

0 comments on commit 751b750

Please sign in to comment.