| | 16 | |
| | 17 | def clear(self): |
| | 18 | del self[:] |
| | 19 | |
| | 20 | def resolve_absolute(self, key, full_path, entity=None, root=None): |
| | 21 | if root is None: |
| | 22 | root = entity._descriptor.resolve_root |
| | 23 | if root: |
| | 24 | full_path = '%s.%s' % (root, full_path) |
| | 25 | module_path, classname = full_path.rsplit('.', 1) |
| | 26 | module = sys.modules[module_path] |
| | 27 | res = getattr(module, classname, None) |
| | 28 | if res is None: |
| | 29 | if entity is not None: |
| | 30 | raise Exception("Couldn't resolve target '%s' <%s> in '%s'!" |
| | 31 | % (key, full_path, entity.__name__)) |
| | 32 | else: |
| | 33 | raise Exception("Couldn't resolve target '%s' <%s>!" |
| | 34 | % (key, full_path)) |
| | 35 | return res |
| | 36 | |
| | 37 | def __getattr__(self, key): |
| | 38 | return self.resolve(key) |
| | 39 | |
| | 40 | # default entity collection |
| | 41 | class GlobalEntityCollection(BaseCollection): |
| | 42 | def __init__(self, entities=None): |
| | 43 | # _entities is a dict of entities keyed on their name. |
| | 44 | self._entities = {} |
| | 45 | super(GlobalEntityCollection, self).__init__(entities) |
| 59 | | del self[:] |
| | 84 | super(GlobalEntityCollection, self).clear() |
| | 85 | |
| | 86 | # backward compatible name |
| | 87 | EntityCollection = GlobalEntityCollection |
| | 88 | |
| | 89 | _leading_dots = re.compile('^([.]*).*$') |
| | 90 | |
| | 91 | class RelativeEntityCollection(BaseCollection): |
| | 92 | # the entity=None does not make any sense with a relative entity collection |
| | 93 | def resolve(self, key, entity): |
| | 94 | ''' |
| | 95 | Resolve a key to an Entity. The optional `entity` argument is the |
| | 96 | "source" entity when resolving relationship targets. |
| | 97 | ''' |
| | 98 | full_path = key |
| | 99 | |
| | 100 | if '.' not in key or key.startswith('.'): |
| | 101 | # relative target |
| | 102 | |
| | 103 | # any leading dot is stripped and with each dot removed, |
| | 104 | # the entity_module is stripped of one more chunk (starting with |
| | 105 | # the last one). |
| | 106 | num_dots = _leading_dots.match(full_path).end(1) |
| | 107 | full_path = full_path[num_dots:] |
| | 108 | chunks = entity.__module__.split('.') |
| | 109 | chunkstokeep = len(chunks) - num_dots |
| | 110 | if chunkstokeep < 0: |
| | 111 | raise Exception("Couldn't resolve relative target " |
| | 112 | "'%s' relative to '%s'" % (key, entity.__module__)) |
| | 113 | entity_module = '.'.join(chunks[:chunkstokeep]) |
| | 114 | |
| | 115 | if entity_module and entity_module is not '__main__': |
| | 116 | full_path = '%s.%s' % (entity_module, full_path) |
| | 117 | |
| | 118 | root = '' |
| | 119 | else: |
| | 120 | root = None |
| | 121 | return self.resolve_absolute(key, full_path, entity, root=root) |