Skip to content

Commit

Permalink
Fix repeated Property triggering in subclasses (#1587)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdickinson committed Oct 26, 2021
1 parent bc366e8 commit c903296
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 7 deletions.
14 changes: 14 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
Traits CHANGELOG
================

Release 6.3.2
-------------

Released: XXXX-XX-XX

Traits 6.3.2 is a bugfix release.

Fixes
~~~~~

* Fix that ``Property`` traits using ``observe`` metadata could be fired
twice in subclasses. (#1587)


Release 6.3.1
-------------

Expand Down
11 changes: 4 additions & 7 deletions traits/has_traits.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,7 @@ def update_traits_class_dict(class_name, bases, class_dict):

observer_states = getattr(value, "_observe_inputs", None)
if observer_states is not None:
stack = observers.setdefault(name, [])
stack.extend(observer_states)
observers[name] = observer_states

elif isinstance(value, property):
class_traits[name] = generic_trait
Expand Down Expand Up @@ -613,9 +612,8 @@ def update_traits_class_dict(class_name, bases, class_dict):

# Merge observer information:
for name, states in base_dict[ObserverTraits].items():
if name not in class_traits and name not in class_dict:
stack = observers.setdefault(name, [])
stack.extend(states)
if (name not in class_traits) and (name not in class_dict):
observers[name] = states

# Merge base traits:
for name, value in base_dict.get(BaseTraits).items():
Expand Down Expand Up @@ -758,8 +756,7 @@ def update_traits_class_dict(class_name, bases, class_dict):
property_name=name,
cached=trait.cached,
)
stack = observers.setdefault(name, [])
stack.append(observer_state)
observers[name] = [observer_state]

# Add processed traits back into class_dict.
class_dict[BaseTraits] = base_traits
Expand Down
24 changes: 24 additions & 0 deletions traits/tests/test_observe.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
Int,
List,
observe,
Property,
Set,
Str,
Undefined,
Expand Down Expand Up @@ -882,3 +883,26 @@ def test_anytrait_unobserve(self):

# No additional events.
self.assertEqual(len(events), 2)

def test_property_subclass_observe(self):
# Regression test for enthought/traits#1586
class Base(HasTraits):
bar = Int()

foo = Property(Int(), observe="bar")

def _get_foo(self):
return self.bar

class Derived(Base):
pass

events = []

obj = Derived(bar=3)
obj.observe(events.append, "foo")

# Changing bar should result in a single event.
self.assertEqual(len(events), 0)
obj.bar = 5
self.assertEqual(len(events), 1)

0 comments on commit c903296

Please sign in to comment.