summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-12-28 17:50:36 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2010-12-28 17:50:36 -0500
commit4f8f6b3989327398c048fa55bc2ed8f26fb022bd (patch)
treeeb197ce78f67622e3c73d3565e3d946ba6bf8d2c /lib/sqlalchemy/orm
parent7f8ca36036d9ab1f8c06ada19a2cd69349864a45 (diff)
downloadsqlalchemy-4f8f6b3989327398c048fa55bc2ed8f26fb022bd.tar.gz
- simplified the descriptor system to no longer use the hybrid extension, instead presenting
the Proxy(QueryableAttribute) object as the public facing interface. This simplifies the descriptor system and will allow straightforward integration with attribute events.
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/attributes.py26
-rw-r--r--lib/sqlalchemy/orm/descriptor_props.py40
-rw-r--r--lib/sqlalchemy/orm/util.py9
3 files changed, 34 insertions, 41 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py
index e2d2c559b..d6dc10ad4 100644
--- a/lib/sqlalchemy/orm/attributes.py
+++ b/lib/sqlalchemy/orm/attributes.py
@@ -145,16 +145,25 @@ def create_proxied_attribute(descriptor):
Returns a new QueryableAttribute type that delegates descriptor
behavior and getattr() to the given descriptor.
"""
-
+
+ # TODO: can move this to descriptor_props if the need for this
+ # function is removed from ext/hybrid.py
+
class Proxy(QueryableAttribute):
- """A combination of InsturmentedAttribute and a regular descriptor."""
+ """Presents the :class:`.QueryableAttribute` interface as a
+ proxy on top of a Python descriptor / :class:`.PropComparator`
+ combination.
+
+ """
- def __init__(self, class_, key, descriptor, comparator, adapter=None):
+ def __init__(self, class_, key, descriptor, comparator,
+ adapter=None, doc=None):
self.class_ = class_
self.key = key
self.descriptor = descriptor
self._comparator = comparator
self.adapter = adapter
+ self.__doc__ = doc
@util.memoized_property
def comparator(self):
@@ -164,11 +173,12 @@ def create_proxied_attribute(descriptor):
self._comparator = self._comparator.adapted(self.adapter)
return self._comparator
- def adapted(self, adapter):
- return self.__class__(self.class_, self.key, self.descriptor,
- self._comparator,
- adapter)
-
+ def __get__(self, instance, owner):
+ if instance is None:
+ return self
+ else:
+ return self.descriptor.__get__(instance, owner)
+
def __str__(self):
return self.key
diff --git a/lib/sqlalchemy/orm/descriptor_props.py b/lib/sqlalchemy/orm/descriptor_props.py
index 4c4bc821f..347f9bce9 100644
--- a/lib/sqlalchemy/orm/descriptor_props.py
+++ b/lib/sqlalchemy/orm/descriptor_props.py
@@ -7,8 +7,7 @@
"""Descriptor proprerties are more "auxilliary" properties
that exist as configurational elements, but don't participate
-as actively in the load/persist ORM loop. They all
-build on the "hybrid" extension to produce class descriptors.
+as actively in the load/persist ORM loop.
"""
@@ -22,13 +21,12 @@ properties = util.importlater('sqlalchemy.orm', 'properties')
class DescriptorProperty(MapperProperty):
""":class:`MapperProperty` which proxies access to a
user-defined descriptor."""
-
- def instrument_class(self, mapper):
- from sqlalchemy.ext import hybrid
+ doc = None
+
+ def instrument_class(self, mapper):
prop = self
- # hackety hack hack
class _ProxyImpl(object):
accepts_scalar_loader = False
expire_missing = True
@@ -52,39 +50,25 @@ class DescriptorProperty(MapperProperty):
delattr(obj, self.name)
def fget(obj):
return getattr(obj, self.name)
- fget.__doc__ = self.doc
- descriptor = hybrid.property_(
+ self.descriptor = property(
fget=fget,
fset=fset,
fdel=fdel,
)
- elif isinstance(self.descriptor, property):
- descriptor = hybrid.property_(
- fget=self.descriptor.fget,
- fset=self.descriptor.fset,
- fdel=self.descriptor.fdel,
- )
- else:
- descriptor = hybrid.property_(
- fget=self.descriptor.__get__,
- fset=self.descriptor.__set__,
- fdel=self.descriptor.__delete__,
- )
proxy_attr = attributes.\
- create_proxied_attribute(self.descriptor or descriptor)\
+ create_proxied_attribute(self.descriptor)\
(
self.parent.class_,
self.key,
- self.descriptor or descriptor,
- lambda: self._comparator_factory(mapper)
+ self.descriptor,
+ lambda: self._comparator_factory(mapper),
+ doc=self.doc
)
- def get_comparator(owner):
- return util.update_wrapper(proxy_attr, descriptor)
- descriptor.expr = get_comparator
- descriptor.impl = _ProxyImpl(self.key)
- mapper.class_manager.instrument_attribute(self.key, descriptor)
+
+ proxy_attr.impl = _ProxyImpl(self.key)
+ mapper.class_manager.instrument_attribute(self.key, proxy_attr)
class CompositeProperty(DescriptorProperty):
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index 52e250239..4a8b1713c 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -247,13 +247,12 @@ class AliasedClass(object):
'parentmapper':self.__mapper}
)
- def __adapt_prop(self, prop):
- existing = getattr(self.__target, prop.key)
+ def __adapt_prop(self, existing, key):
comparator = existing.comparator.adapted(self.__adapt_element)
- queryattr = attributes.QueryableAttribute(self, prop.key,
+ queryattr = attributes.QueryableAttribute(self, key,
impl=existing.impl, parententity=self, comparator=comparator)
- setattr(self, prop.key, queryattr)
+ setattr(self, key, queryattr)
return queryattr
def __getattr__(self, key):
@@ -268,7 +267,7 @@ class AliasedClass(object):
raise AttributeError(key)
if isinstance(attr, attributes.QueryableAttribute):
- return self.__adapt_prop(attr.property)
+ return self.__adapt_prop(attr, key)
elif hasattr(attr, 'func_code'):
is_method = getattr(self.__target, key, None)
if is_method and is_method.im_self is not None: