diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-12-03 13:46:41 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-12-03 13:46:41 -0500 |
commit | 36e1aa0afdf7e42f88426da4b2e9ee631d16728c (patch) | |
tree | 233b2308824abd1faab762e5df7fbcd815049cad /lib/sqlalchemy/ext/declarative/clsregistry.py | |
parent | 21feea9c1d278036cc37add813b72d0dbd4b1754 (diff) | |
download | sqlalchemy-36e1aa0afdf7e42f88426da4b2e9ee631d16728c.tar.gz |
- The :class:`.DeferredReflection` class has been enhanced to provide
automatic reflection support for the "secondary" table referred
to by a :func:`.relationship`. "secondary", when specified
either as a string table name, or as a :class:`.Table` object with
only a name and :class:`.MetaData` object will also be included
in the reflection process when :meth:`.DeferredReflection.prepare`
is called. [ticket:2865]
- clsregistry._resolver() now uses a stateful _class_resolver()
class in order to handle the work of mapping strings to
objects. This is to provide for simpler extensibility, namely
a ._resolvers collection of ad-hoc name resolution functions;
the DeferredReflection class adds its own resolver here in order
to handle relationship(secondary) names which generate new
Table objects.
Diffstat (limited to 'lib/sqlalchemy/ext/declarative/clsregistry.py')
-rw-r--r-- | lib/sqlalchemy/ext/declarative/clsregistry.py | 89 |
1 files changed, 52 insertions, 37 deletions
diff --git a/lib/sqlalchemy/ext/declarative/clsregistry.py b/lib/sqlalchemy/ext/declarative/clsregistry.py index 8fef8f1bc..04567b32c 100644 --- a/lib/sqlalchemy/ext/declarative/clsregistry.py +++ b/lib/sqlalchemy/ext/declarative/clsregistry.py @@ -225,47 +225,62 @@ def _determine_container(key, value): return _GetColumns(value) -def _resolver(cls, prop): - def resolve_arg(arg): - import sqlalchemy - from sqlalchemy.orm import foreign, remote - - fallback = sqlalchemy.__dict__.copy() - fallback.update({'foreign': foreign, 'remote': remote}) - - def access_cls(key): - if key in cls._decl_class_registry: - return _determine_container(key, cls._decl_class_registry[key]) - elif key in cls.metadata.tables: - return cls.metadata.tables[key] - elif key in cls.metadata._schemas: - return _GetTable(key, cls.metadata) - elif '_sa_module_registry' in cls._decl_class_registry and \ - key in cls._decl_class_registry['_sa_module_registry']: - registry = cls._decl_class_registry['_sa_module_registry'] - return registry.resolve_attr(key) +class _class_resolver(object): + def __init__(self, cls, prop, fallback, arg): + self.cls = cls + self.prop = prop + self.arg = self._declarative_arg = arg + self.fallback = fallback + self._dict = util.PopulateDict(self._access_cls) + self._resolvers = () + + def _access_cls(self, key): + cls = self.cls + if key in cls._decl_class_registry: + return _determine_container(key, cls._decl_class_registry[key]) + elif key in cls.metadata.tables: + return cls.metadata.tables[key] + elif key in cls.metadata._schemas: + return _GetTable(key, cls.metadata) + elif '_sa_module_registry' in cls._decl_class_registry and \ + key in cls._decl_class_registry['_sa_module_registry']: + registry = cls._decl_class_registry['_sa_module_registry'] + return registry.resolve_attr(key) + elif self._resolvers: + for resolv in self._resolvers: + value = resolv(key) + if value is not None: + return value + + return self.fallback[key] + + def __call__(self): + try: + x = eval(self.arg, globals(), self._dict) + + if isinstance(x, _GetColumns): + return x.cls else: - return fallback[key] + return x + except NameError as n: + raise exc.InvalidRequestError( + "When initializing mapper %s, expression %r failed to " + "locate a name (%r). If this is a class name, consider " + "adding this relationship() to the %r class after " + "both dependent classes have been defined." % + (self.prop.parent, self.arg, n.args[0], self.cls) + ) - d = util.PopulateDict(access_cls) - def return_cls(): - try: - x = eval(arg, globals(), d) +def _resolver(cls, prop): + import sqlalchemy + from sqlalchemy.orm import foreign, remote - if isinstance(x, _GetColumns): - return x.cls - else: - return x - except NameError as n: - raise exc.InvalidRequestError( - "When initializing mapper %s, expression %r failed to " - "locate a name (%r). If this is a class name, consider " - "adding this relationship() to the %r class after " - "both dependent classes have been defined." % - (prop.parent, arg, n.args[0], cls) - ) - return return_cls + fallback = sqlalchemy.__dict__.copy() + fallback.update({'foreign': foreign, 'remote': remote}) + + def resolve_arg(arg): + return _class_resolver(cls, prop, fallback, arg) return resolve_arg |