Beispiel #1
0
class MagicClass(Class):
    def __init__(self, *args, **kw):
        super(MagicClass, self).__init__(*args, **kw)
        self.event_instance_init = Event()
        self.event_instance_modified = Event()
        
    # A Basic, built-in, datatype
    def create_instance(self, **kw):
        instance = super(MagicClass, self).create_instance(**kw)
        instance.event_modified.register(partial(self.instance_modified, instance), key=self)
        self.event_instance_init.send(instance)
        return instance

    def instance_modified(self, *args):
        self.event_instance_modified.send(*args)
Beispiel #2
0
class Instance(object):
    def __init__(self, cls, meta=None):
        self.cls = cls
        if meta is None:
            meta = {}
        self.meta = meta
        # This is a map from field to instance of that field
        self._fields_instances = {}
        self.event_modified = Event()
        self.event_field_instance_set = Event()
        self.event_field_instance_removed = Event()
        self.event_field_instance_linked = Event()
        
        for field in cls.fields:
            if field not in self._fields_instances:
                self.new_field(field)
                
        # TODO send this event somewhere when a new value propogates through us
        #self.event_modification_propogating = Event()

    def new_field(self, field):
        field_instance = self.create_field_instance(field)
        self.set_field_instance(field, field_instance)
        self.event_field_instance_set.send(self, field, field_instance)
        
    def create_field_instance(self, field):
        field_instance = field.cls.create_instance()
        return field_instance

    def set_field_instance(self, field, field_instance):
        if field in self._fields_instances:
            assert 0, "trying to set same field twice!"
        self._fields_instances[field] = field_instance
        #self.subfield_linked((field,), field_instance)
        field_instance.event_modified.register(partial(self.field_modified, self, field_instance), key=(self, field))

        # This should be called externally?
        self.event_field_instance_set.send(self, field, field_instance)
        
        return field_instance

    def remove_field_instance(self, field_instance):
        field = self.field_of_field_instance(field_instance)
        field_instance.event_modified.unregister((self, field))
        del self._fields_instances[field]
        # this should be called externally?
        self.event_field_instance_removed.send(self, field, field_instance)

        
##     def copy(self):
##         new = self.cls.create_instance()
##         new.meta.update(self.meta)
##         return new
    
    def __repr__(self):
        return '<%s at 0x%X, cls=%r, meta=%r>' % (self.__class__.__name__, id(self), self.cls, self.meta)

    # todo is this normal?!
    @staticmethod
    def field_modified(self, field_instance, modified_instance, modified_by):
        #print 'field modified', self, field_instance, modified_instance, modified_by
        if modified_by is self:
            return
        self.event_modified.send(field_instance, modified_by)
        
    def get_subfield_instance(self, subfield_hierarchy, stop_at_parent):
        # Returns the requested subfield's parent, the requested subfield (parent, subfield)
        if stop_at_parent:
            if len(subfield_hierarchy) == 1:
                return self
            subfield_hierarchy = subfield_hierarchy[:-1]
        subfield_instance = self
        # Deeply go into children, grandchildren, etc. until we reach the actualy instance involved
        for subfield in subfield_hierarchy:
            subfield_instance = subfield_instance._fields_instances[subfield]
        return subfield_instance

    def replace_field_instance(self, field, new_instance, modified_by):
        # This is called when a new instance is placed for afield
        if field not in self.cls.fields:
            raise ValueError("Unknown field", field, self.cls.fields)
        old_instance = self._fields_instances[field]

        if old_instance != new_instance:
            self.remove_field_instance(old_instance)
            self.set_field_instance(field, new_instance)
        
        # In this case we must send a 'modified' event because some magic function
        # might need to re-calculate because one of it's fields has changed it's instance
        self.event_modified.send(new_instance, modified_by)
        
        return new_instance

    def link_field_instance(self, field, new_instance, modified_by):
        old_instance = self._fields_instances[field]
        self.event_field_instance_linked.send(self, old_instance, new_instance)
        self.replace_field_instance(field, new_instance, modified_by)
        
    # a subfield_hierarchy is a list of: field_A, subfield_B, subsubfield_C, etc...
    def subfield_linked(self, src_subfield_hierarchy, src_subfield_instance):
        #print 'src len', self, len(src_subfield_hierarchy)
        # Replaces the instances of all subfields using the given one
        linked_subfields_hierarchies = self.cls.links.set_of(src_subfield_hierarchy)
        #print 'number of links', len(linked_subfields_hierarchies)
        for subfield_hierarchy in linked_subfields_hierarchies:
            subfield_parent_instance = self.get_subfield_instance(subfield_hierarchy, True)
            
            subfield_parent_instance.link_field_instance(subfield_hierarchy[-1], src_subfield_instance, self)

    def subfield_unlinked(self, subfield_hierarchy):
        # in this case we can go straight to the depest level, and insert a new instance
        # TODO copy the instance instead of just creating new
        subfield_parent_instance = self.get_subfield_instance(subfield_hierarchy, True)
        
        old_subfield_instance = subfield_parent_instance._fields_instances[subfield_hierarchy[-1]]
        new_subfield_instance = subfield_parent_instance.create_field_instance(subfield_hierarchy[-1])
        # old_subfield_instance.copy() #subfield_hierarchy[-1].cls.create_instance()

        subfield_parent_instance.replace_field_instance(subfield_hierarchy[-1], new_subfield_instance, self)
        


    # UTility functions
    def subfield_hierarchy_by_instance(self, subfield_instance, return_empty_list_if_none=False):
        for field, field_instance in self._fields_instances.iteritems():
            res = [field]
            if subfield_instance is field_instance:
                return res
            f_res = field_instance.subfield_hierarchy_by_instance(subfield_instance, return_empty_list_if_none=True)
            if f_res:
                res.extend(f_res)
                return res
        if return_empty_list_if_none:
            return []
        # This can happen if someone stupid requested the hierarchy to an instance that is not our subfield!
        raise ValueError("No such subfield instance", subfield_instance)

    def field_of_field_instance(self, field_instance):
        for field, fi in self._fields_instances.iteritems():
            if fi == field_instance:
                return field
        raise ValueError("No such field instance")
        
    def field_instances(self):
        return list(self._fields_instances.values())
    
    def field_instances_by_name(self):
        # Utility func
        res = {}
        for field, field_instance in self._fields_instances.iteritems():
            res[field.meta['name']] = field_instance
        return res
    def fields_by_name(self):
        # Utility func
        res = {}
        for field, field_instance in self._fields_instances.iteritems():
            res[field.meta['name']] = field
        return res
    def self_modified(self, modified_by):
        # todo if instances are immutable, this shouldn't exist!
        self.event_modified.send(self, modified_by)