Changeset 511 for elixir/trunk/elixir

Show
Ignore:
Timestamp:
11/09/09 13:02:22 (3 years ago)
Author:
ged
Message:

- Entities can now be declared "abstract" so that they do not create a table,

etc... This allows, among others, an entity to inherit from multiple abstract
classes (patch from Stéphane Klein, closes #89).

Location:
elixir/trunk/elixir
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • elixir/trunk/elixir/entity.py

    r510 r511  
    1919 
    2020import elixir 
    21 from elixir.statements import process_mutators 
     21from elixir.statements import process_mutators, MUTATORS 
    2222from elixir import options 
    2323from elixir.properties import Property 
     
    6565        for base in entity.__bases__: 
    6666            if isinstance(base, EntityMeta): 
    67                 if is_entity(base): 
     67                if ( 
     68                    is_entity(base) and 
     69                    (not is_abstract_entity(base)) 
     70                ): 
    6871                    if self.parent: 
    6972                        raise Exception( 
     
    693696    return base_props 
    694697 
     698def is_abstract_entity(dict_or_cls): 
     699    if isinstance(dict_or_cls, dict): 
     700        mutators = dict_or_cls.get(MUTATORS, []) 
     701    else: 
     702        mutators = getattr(dict_or_cls, MUTATORS, []) 
     703         
     704    for m in mutators: 
     705        if 'abstract' in m[2]: 
     706            return m[2]['abstract'] 
     707 
     708    return False 
    695709 
    696710def instrument_class(cls): 
     
    706720 
    707721    # Determine whether this entity is a *direct* subclass of its base entity 
    708     entity_base = None 
     722    entity_bases = [] 
    709723    for base in cls.__bases__: 
    710724        if isinstance(base, EntityMeta): 
    711             if not is_entity(base): 
    712                 entity_base = base 
    713  
    714     if entity_base: 
     725            if not is_entity(base) or is_abstract_entity(base): 
     726                entity_bases.append(base) 
     727  
     728    base_props = [] 
     729    if entity_bases: 
    715730        # If so, copy the base entity properties ('Property' instances). 
    716731        # We use inspect.getmembers (instead of __dict__) so that we also 
    717732        # get the properties from the parents of the base_class if any. 
    718         base_props = getmembers(entity_base, 
    719                                 lambda a: isinstance(a, Property)) 
    720         base_props = [(name, deepcopy(attr)) for name, attr in base_props] 
    721     else: 
    722         base_props = [] 
     733        for base in entity_bases: 
     734            base_props += [(name, deepcopy(attr)) for name, attr in  
     735                           getmembers(base, lambda a: isinstance(a, Property))] 
    723736 
    724737    # Process attributes (using the assignment syntax), looking for 
     
    750763        # be registered in an entity collection, nor to have a table name and 
    751764        # so on. 
     765 
     766        if is_abstract_entity(dict_): 
     767            return 
     768 
    752769        if not is_entity(cls): 
    753770            if isinstance(cls, EntityMeta): 
  • elixir/trunk/elixir/options.py

    r505 r511  
    3535|                     | #mapping-class-inheritance-hierarchies for an         | 
    3636|                     | explanation of the different kinds of inheritances.   | 
     37+---------------------+-------------------------------------------------------+ 
     38| ``abstract``        | Set 'abstract'=True to declare abstract entity.       | 
     39|                     | Abstract base classes are useful when you want to put | 
     40|                     | some common information into a number of other        | 
     41|                     | entities. Abstract entity will not be used to create  | 
     42|                     | any database table. Instead, when it is used as a base| 
     43|                     | class for other entity, its fields will be added to   | 
     44|                     | those of the child class.                             | 
    3745+---------------------+-------------------------------------------------------+ 
    3846| ``polymorphic``     | Whether the inheritance should be polymorphic or not. | 
     
    165173using_options_defaults (nor specifically on a particular Entity) will use the 
    166174global defaults, so you don't have to provide a default value for all options, 
    167 but only those you want to change. 
    168  
     175but only those you want to change. Please also note that this statement does 
     176not work on normal entities, and the normal using_options statement does not 
     177work on base classes (because normal options do not and should not propagate to 
     178the children classes). 
    169179''' 
    170180 
     
    205215# 
    206216options_defaults = dict( 
     217    abstract=False, 
    207218    inheritance='single', 
    208219    polymorphic=True,