def _context_changed ( self, old, new ): """ Handles the underlying context being changed. """ self._context_base = None cm = ContextModified( reset = True ) dm = TraitDictEvent() if old is not None: cm.removed = [ item.name for item in old.context_items ] old.on_trait_change( self._context_is_modified, 'context_modified', remove = True ) dm.removed = dict( old ) old.on_trait_change( self._dict_is_modified, 'dict_modified', remove = True ) if new is not None: cm.added = [ item.name for item in new.context_items ] new.on_trait_change( self._context_is_modified, 'context_modified' ) dm.added = dict( new ) new.on_trait_change( self._dict_is_modified, 'dict_modified' ) self._context_is_modified( cm ) self._dict_is_modified( dm )
def _context_changed(self, old, new): """ Handles the underlying context being changed. """ self._context_base = None cm = ContextModified(reset=True) dm = TraitDictEvent() if old is not None: cm.removed = [item.name for item in old.context_items] old.on_trait_change(self._context_is_modified, 'context_modified', remove=True) dm.removed = dict(old) old.on_trait_change(self._dict_is_modified, 'dict_modified', remove=True) if new is not None: cm.added = [item.name for item in new.context_items] new.on_trait_change(self._context_is_modified, 'context_modified') dm.added = dict(new) new.on_trait_change(self._dict_is_modified, 'dict_modified') self._context_is_modified(cm) self._dict_is_modified(dm)
def _context_items_changed ( self, old, new ): """ Handles the 'items' trait being changed. """ self.post_context_modified( ContextModified( removed = self._remove_context_items( *old ), added = self._add_context_items( *new ), ) )
def _set_name ( self, name ): old = self.name if name != old: self._name = name if self.context is not None: self.post_context_modified( ContextModified( removed = [ old ], added = [ name ] ) )
def _evaluate_changed(self, evaluate): """ Handles the 'evaluate' trait being changed. """ self._block = ExpressionBlock.from_string(evaluate) self._inputs = dict.fromkeys(self._block.inputs) self._data = None if self.context is not None: self.context.post_context_modified( ContextModified(modified=[self.name]))
def _context_modified_changed_for_context(self, event): """ Handles the data associated with this item being changed. """ inputs = self._inputs if inputs is not None: for name in event.all_modified: if name in inputs: self._data = None self.context.post_context_modified( ContextModified(modified=[self.name])) break
def _set_context_group ( self, group ): if self.is_valid_array( group ): group = group.shape if (group is not None) and (group not in self._context_groups): raise TraitError, "There is no group for '%s'" % group old = self._context_group if group != old: self._context_group = group self.post_context_modified( ContextModified( reset = True ) ) self.trait_property_changed( 'context_group', old, group )
def context_group_for ( self, name = None, names = None ): """ Gets/Sets the contents of a specified context group. """ # If an array was specified as the group name, use its shape as the # name: if name is None: name = self.context_group elif self.is_valid_array( name ): name = name.shape # If this is just a query: if names is None: # Return the list of items in the specified group: return self._context_groups.get( name, empty_group )[1][:] # Only allow changing groups whose name is a string (not a shape): if not isinstance( name, basestring ): raise NumericContextError( "Can only modify a group with a string " "name, but '%s' was specified." % ( name, ) ) # Delete the old contents of the group (if any): old_group = self._context_groups.get( name, empty_group ) for cur_name in old_group[1]: self._context_items[ cur_name ].groups.remove( name ) if len( names ) == 0: # If empty list of names, delete the group (if any): self._context_groups.pop( name, None ) # If the current group was just deleted, reset it: if name == self.context_group: self.context_group = None else: # Otherwise, verify all items have the same shape: shape = None for cur_name in names: if shape is None: shape = self[ cur_name ].shape elif shape != self[ cur_name ].shape: raise NumericContextError( 'All items in a group must have ' 'the same shape.' ) # Define the group: self._context_groups[ name ] = ( shape, names[:] ) # Add the group name to the list of groups each item is in: for cur_name in names: self._context_items[ cur_name ].groups.append( name ) # If the current group was just modified, reset the context: if name == self.context_group: self.post_context_modified( ContextModified( reset = True ) )
def _propagate_context_modified(self): """ Propagate the pending event. """ self._process_context_modified_event( ContextModified(reset=self._context_reset, modified=self._context_modified.keys(), added=self._context_added.keys(), removed=self._context_removed.keys())) self._context_reset = False self._context_modified = {} self._context_added = {} self._context_removed = {}
def _sub_context_modified ( self, sub_context, name, old, event ): """ Handles a sub-context being modified. """ ci = self._context_items # Create the context modified event wewill use for all changes: cm = ContextModified() # Iterate over each name the sub-context has been bound to in our # context: for name in self._sub_contexts[ sub_context ]: # Compute the common prefix for all sub-context items under the # current name: prefix = name + '.' # Create the list of modified name within our context: modified = [ (prefix + n) for n in event.modified ] # If the sub-context was reset, add all of the items in the # sub-context's current group to the modified list (avoiding dups): if event.reset: for n in sub_context.context_names: n2 = prefix + n if n2 not in modified: modified.append( n2 ) # Add all modified items to the event: cm.modified.extend( modified ) # Add and remove all of the added and removed sub-context items # to our context and the event using the 'extended' name for our # context: cm.removed.extend( self._remove_context_items( *[ ci[ prefix + n ] for n in event.removed ] ) ) cm.added.extend( self._add_context_items( *[ SubContextItem( context = self, sub_context_name = name, sub_name = n ) for n in event.added ] ) ) # Finally, post the event: self.post_context_modified( cm )
def _defer_events_changed(self): # 'defer_events' is a Property, so we don't get an 'old' for free assert ((self._deferred_dict_modified is None) == (self._deferred_context_modified is None)) old = self._deferred_dict_modified is not None new = self.defer_events # If 'defer_events' changed, make the transition if old != new: if self.defer_events: self._deferred_dict_modified = TraitDictEvent() self._deferred_context_modified = ContextModified() else: dm = self._deferred_dict_modified cm = self._deferred_context_modified self._deferred_dict_modified = None self._deferred_context_modified = None self.post_dict_modified(dm) self.post_context_modified(cm)
def _data_updated ( self, object, name, old, new ): """ Handles the data associated with this item being changed. """ self.post_context_modified( ContextModified( modified = [ self.name ] ))
def _updated_changed_for_context_filter ( self ): if self._cur_mask is not Undefined: self._cur_mask = Undefined self.post_context_modified( ContextModified( reset = True ) )
def _context_items_items_changed ( self, event ): if not self._no_update: self.post_context_modified( ContextModified( removed = self._remove_context_items( *event.removed ), added = self._add_context_items( *event.added ), ) )
def _dict_is_modified( self, event ): """ Fires when 'context_data' fires 'dict_modified'. """ assert disjoint( event.added, event.changed, event.removed ) # How much can we optimize this while keeping it maintainable? # If the dictionary has changed, then we are dirty. (I think this is # the only place we have to do this...) self.dirty = True # These become attributes on a ContextModified event we create below. # Leave them as normal sets until the end to avoid excessive trait # validation. added = set() modified = set() removed = set() changed = set() # The following three loops duplicate code: the body of 'changed' is # simply the body of 'removed' followed by the body of 'added', # followed by some logic for group maintenance. It would be better to # abstract out the two shared chunks, but I keep waiting for a higher # level insight that will greatly simplify this logic and eliminate the # need to repeat code in the first place. for name, new in event.added.iteritems(): # Rebind renamed dynamic bindings if hashable( new ) and new in self._dynamic_bindings: self._rebind_dynamic( new, name ) # Add new data if self.is_valid_array( new ): added.update( self._add_context_items( ContextItem( name = name ) ) ) elif isinstance( new, ANumericContext ): added.update( self._add_sub_context( name, new ) ) changed.add( name ) else: changed.add( name ) for name, old in event.changed.iteritems(): new = self.context_data[ name ] # Short-circuit if possible if new is old: continue # Unbind dynamic bindings if hashable( old ) and old in self._dynamic_bindings: d = self._dynamic_bindings[ old ] self._unbind_dynamic( old, d['trait_name'], remove=False ) # Remove old data if name in self._context_items: removed.update( self._remove_context_items( self._context_items[ name ], delete = False ) ) elif isinstance( old, ANumericContext ): removed.update( self._remove_sub_context( name, old ) ) changed.add( name ) else: changed.add( name ) # Rebind dynamic bindings if hashable( new ) and new in self._dynamic_bindings: self._rebind_dynamic( new, name ) # Add new data if self.is_valid_array( new ): added.update( self._add_context_items( ContextItem( name = name ) ) ) elif isinstance( new, ANumericContext ): added.update( self._add_sub_context( name, new ) ) changed.add( name ) else: changed.add( name ) # Update an item's group if it changes shape if ( self.is_valid_array( new ) and self.is_valid_array( old ) and new.shape != old.shape ): context_groups = self._context_groups item = self._context_items[ name ] for group in item.groups: n, names = context_groups[ group ] names.remove( name ) if len( names ) == 0: del context_groups[ group ] group = new.shape item.groups = [ group ] context_groups.setdefault( group, ( group, [] ) )[1].append( name ) for name, old in event.removed.iteritems(): # Unbind dynamic bindings if hashable( old ) and old in self._dynamic_bindings: d = self._dynamic_bindings[ old ] self._unbind_dynamic( old, d['trait_name'], remove=False ) # Remove old data if name in self._context_items: removed.update( self._remove_context_items( self._context_items[ name ], delete = False ) ) elif isinstance( old, ANumericContext ): removed.update( self._remove_sub_context( name, old ) ) changed.add( name ) else: changed.add( name ) # Calculate context event modified |= added & removed added -= modified removed -= modified cm = ContextModified( added = list( added ), modified = list( modified ), removed = list( removed ), changed = list( changed ), ) # Fire events self.post_dict_modified( event ) self.post_context_modified( cm )
def _set_data(self, value): self.context.context_data[self.name] = value # ('self.context' might have just removed us) if self.context is not None: self.context.post_context_modified( ContextModified(modified=[self.name]))