Changeset 363
- Timestamp:
- 07/14/08 21:51:36 (5 years ago)
- Location:
- elixir/trunk
- Files:
-
- 6 modified
-
CHANGES (modified) (2 diffs)
-
elixir/__init__.py (modified) (4 diffs)
-
elixir/entity.py (modified) (1 diff)
-
tests/test_associable.py (modified) (1 diff)
-
tests/test_collections.py (modified) (1 diff)
-
tests/test_packages.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
elixir/trunk/CHANGES
r362 r363 9 9 polymorphic or not). Concrete polymorphic inheritance requires SQLalchemy 10 10 0.4.5 or later. 11 - Moved the entity to string mapping and resolving code to the (newly created) 12 EntityCollection class (which stores lists of entities). This allows one to 13 provide a custom mapping method if needed. The default class also overrides 14 the __getattr__ method, providing and handy way to get at your entities. 15 See source:elixir/trunk/tests/test_collections.py#L58 11 16 - Added new "identity" option which can be used to set a custom polymorphic 12 17 identity for an entity. It also accepts a callable so that you can generate … … 30 35 31 36 Changes: 37 - Default "target entity resolving code" changed slightly. It now uses a global 38 collection keyed on the entity name. This means that entities can refer to 39 other entities in a different module simply with the target entity name 40 instead of its full path. The full path is only required when there is an 41 ambiguity (ie when there are two classes with the same name in two different 42 modules). Closes #9. 32 43 - Added support for SQLAlchemy 0.5, and dropped support for version 0.3 and 33 44 earlier. -
elixir/trunk/elixir/__init__.py
r357 r363 71 71 class EntityCollection(list): 72 72 def __init__(self): 73 # _entities is a dict of entities for each frame where there are 74 # entities defined. 73 # _entities is a dict of entities keyed on their name. 75 74 self._entities = {} 76 # self._entity_map = {}77 75 list.__init__(self) 78 76 79 def map_entity(self, entity): 80 self.append(entity) 77 def append(self, entity): 78 ''' 79 Add an entity to the collection. 80 ''' 81 super(EntityCollection, self).append(entity) 81 82 82 83 key = entity.__name__ 83 84 # if key in self._entity_map: 85 # warnings.warn('An entity named `%s` is already registered!' % key) 86 87 # 3 is because map_entity is called by: 88 # EntityDescriptor::setup_options (which is called by) 89 # EntityMeta::__init__ 90 # which is called when the entity is defined 91 caller_frame = sys._getframe(3) 92 cid = entity._caller = id(caller_frame) 93 caller_entities = self._entities.setdefault(cid, {}) 94 caller_entities[key] = entity 95 96 # Append all entities which are currently visible by the entity. This 97 # will find more entities only if some of them where imported from 98 # another module. 99 for ent in [e for e in caller_frame.f_locals.values() 100 if isinstance(e, EntityMeta)]: 101 caller_entities[ent.__name__] = ent 102 103 # self._entity_map[key] = entity 84 mapped_entity = self._entities.get(key) 85 if mapped_entity: 86 if isinstance(mapped_entity, list): 87 mapped_entity.append(entity) 88 else: 89 self._entities[key] = [mapped_entity, entity] 90 else: 91 self._entities[key] = entity 104 92 105 93 def resolve(self, key, entity=None): … … 110 98 path = rsplit(key, '.', 1) 111 99 classname = path.pop() 112 #XXX: use eval()?113 114 100 if path: 115 101 # Do we have a fully qualified entity name? … … 117 103 return getattr(module, classname, None) 118 104 else: 119 # If not, try the list of entities of the "caller" of the 120 # source class. Most of the time, this will be the module 121 # the class is defined in. But it could also be a method 122 # (inner classes). 123 caller_entities = self._entities[entity._caller] 124 return caller_entities[classname] 105 # Otherwise we look in the entities of this collection 106 res = self._entities[key] 107 if isinstance(res, list): 108 raise Exception("%s resolves to several entities, you should " 109 "use the full path (including the full module " 110 "name) to that entity.") 111 else: 112 return res 125 113 126 114 def clear(self): … … 129 117 130 118 def __getattr__(self, key): 131 print "GLOBALS", globals().keys()132 print "LOCALS", locals().keys()133 119 return self.resolve(key) 134 # return self._entity_map.get(key)135 120 136 121 entities = EntityCollection() -
elixir/trunk/elixir/entity.py
r360 r363 98 98 elixir.metadatas.add(self.metadata) 99 99 if self.collection is not None: 100 self.collection. map_entity(self.entity)100 self.collection.append(self.entity) 101 101 102 102 entity = self.entity -
elixir/trunk/tests/test_associable.py
r349 r363 4 4 5 5 from sqlalchemy import create_engine, and_ 6 from elixir import * 6 7 from elixir import * 7 8 from elixir.ext.associable import associable 8 9 9 10 10 def setup( self):11 def setup(): 11 12 # metadata.bind = create_engine('sqlite:///', echo=True) 12 13 metadata.bind = 'sqlite:///' -
elixir/trunk/tests/test_collections.py
r347 r363 1 1 """ 2 test collections2 Test collections 3 3 """ 4 4 -
elixir/trunk/tests/test_packages.py
r349 r363 1 1 """ 2 simple test case 2 Test spreading entities accross several modules 3 3 """ 4 4 5 from elixir import *6 5 import sys 7 6 8 def setup(self): 7 from elixir import * 8 9 def setup(): 9 10 metadata.bind = 'sqlite:///' 10 11 … … 13 14 cleanup_all(True) 14 15 15 def test_ packages(self):16 def test_full_entity_path(self): 16 17 # This is an ugly workaround because when nosetest is run globally (ie 17 18 # either on the tests directory or in the "trunk" directory, it imports … … 21 22 # and reimporting their modules does nothing because they were already 22 23 # imported. 24 23 25 sys.modules.pop('tests.a', None) 24 26 sys.modules.pop('tests.b', None)
