@@ -118,11 +118,15 @@ def __init__(self):
118
118
"""Initialize a Computable."""
119
119
super ().__init__ ()
120
120
121
+ # fixme have 2 signal: change and is_dirty?
122
+ self .signal_types : set = {
123
+ "change" ,
124
+ }
125
+
121
126
def __get__ (self , instance , owner ): # noqa: D105
122
127
computed = getattr (instance , self .private_name )
123
128
old_value = computed ._value
124
129
125
- # fixme, we are not detecting if one computable is dependent on another
126
130
if CURRENT_COMPUTED is not None :
127
131
CURRENT_COMPUTED ._add_parent (instance , self .public_name , old_value )
128
132
@@ -139,11 +143,14 @@ def __get__(self, instance, owner): # noqa: D105
139
143
else :
140
144
return old_value
141
145
142
- def __set__ (self , instance : HasObservables , value ): # noqa D103
143
- # no on change event?
146
+ def __set__ (self , instance : HasObservables , value : Computed ): # noqa D103
147
+ if not isinstance (value , Computed ):
148
+ raise ValueError ("value has to be a Computable instance" )
149
+
144
150
setattr (instance , self .private_name , value )
145
151
value .name = self .public_name
146
152
value .owner = instance
153
+ getattr (instance , self .public_name ) # force evaluation of the computed to build the dependency graph
147
154
148
155
149
156
class Computed :
@@ -191,7 +198,7 @@ def _remove_parents(self):
191
198
"""Remove all parent Observables."""
192
199
# we can unsubscribe from everything on each parent
193
200
for parent in self .parents :
194
- parent .unobserve (All (), All ())
201
+ parent .unobserve (All (), All (), self . _set_dirty )
195
202
196
203
def __call__ (self ):
197
204
global CURRENT_COMPUTED # noqa: PLW0603
@@ -208,25 +215,26 @@ def __call__(self):
208
215
# we might be dirty but values might have changed
209
216
# back and forth in our parents so let's check to make sure we
210
217
# really need to recalculate
211
- for parent in self .parents .keyrefs ():
212
- # does parent still exist?
213
- if parent := parent ():
214
- # if yes, compare old and new values for all
215
- # tracked observables on this parent
216
- for name , old_value in self .parents [parent ].items ():
217
- new_value = getattr (parent , name )
218
- if new_value != old_value :
219
- changed = True
220
- break # we need to recalculate
218
+ if not changed :
219
+ for parent in self .parents .keyrefs ():
220
+ # does parent still exist?
221
+ if parent := parent ():
222
+ # if yes, compare old and new values for all
223
+ # tracked observables on this parent
224
+ for name , old_value in self .parents [parent ].items ():
225
+ new_value = getattr (parent , name )
226
+ if new_value != old_value :
227
+ changed = True
228
+ break # we need to recalculate
229
+ else :
230
+ # trick for breaking cleanly out of nested for loops
231
+ # see https://stackoverflow.com/questions/653509/breaking-out-of-nested-loops
232
+ continue
233
+ break
221
234
else :
222
- # trick for breaking cleanly out of nested for loops
223
- # see https://stackoverflow.com/questions/653509/breaking-out-of-nested-loops
224
- continue
225
- break
226
- else :
227
- # one of our parents no longer exists
228
- changed = True
229
- break
235
+ # one of our parents no longer exists
236
+ changed = True
237
+ break
230
238
231
239
if changed :
232
240
# the dependencies of the computable function might have changed
0 commit comments