From: Mike Bayer Date: Wed, 12 Jan 2011 20:35:20 +0000 (-0500) Subject: - rename hybrid.property_, hybrid.method to hybrid_property, hybrid_method. more... X-Git-Tag: rel_0_7b1~81 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9ebe3b723ecc17bb171343f05534f4fd7c9a9fc;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - rename hybrid.property_, hybrid.method to hybrid_property, hybrid_method. more typing on the import but this is just clearer. - adapt dictlike-polymorphic.py to use hybrid. --- diff --git a/examples/vertical/dictlike-polymorphic.py b/examples/vertical/dictlike-polymorphic.py index 1acb6aee5c..d66b1872f3 100644 --- a/examples/vertical/dictlike-polymorphic.py +++ b/examples/vertical/dictlike-polymorphic.py @@ -21,14 +21,16 @@ For any given properties row, the value of the 'type' column will point to the This example approach uses exactly the same dict mapping approach as the 'dictlike' example. It only differs in the mapping for vertical rows. Here, -we'll use a Python @property to build a smart '.value' attribute that wraps up +we'll use a @hybrid_property to build a smart '.value' attribute that wraps up reading and writing those various '_value' columns and keeps the '.type' up to date. +Class decorators are used, so Python 2.6 or greater is required. """ from sqlalchemy.orm.interfaces import PropComparator from sqlalchemy.orm import comparable_property +from sqlalchemy.ext.hybrid import hybrid_property # Using the VerticalPropertyDictMixin from the base example from dictlike import VerticalPropertyDictMixin @@ -72,39 +74,19 @@ class PolymorphicVerticalProperty(object): type(None): (None, None), } - class Comparator(PropComparator): - """A comparator for .value, builds a polymorphic comparison via CASE. - - Optional. If desired, install it as a comparator in the mapping:: - - mapper(..., properties={ - 'value': comparable_property(PolymorphicVerticalProperty.Comparator, - PolymorphicVerticalProperty.value) - }) - """ - - def _case(self): - cls = self.prop.parent.class_ - whens = [(text("'%s'" % p[0]), getattr(cls, p[1])) - for p in cls.type_map.values() - if p[1] is not None] - return case(whens, cls.type, null()) - def __eq__(self, other): - return cast(self._case(), String) == cast(other, String) - def __ne__(self, other): - return cast(self._case(), String) != cast(other, String) - def __init__(self, key, value=None): self.key = key self.value = value - def _get_value(self): + @hybrid_property + def value(self): for discriminator, field in self.type_map.values(): if self.type == discriminator: return getattr(self, field) return None - def _set_value(self, value): + @value.setter + def value(self, value): py_type = type(value) if py_type not in self.type_map: raise TypeError(py_type) @@ -118,11 +100,27 @@ class PolymorphicVerticalProperty(object): if field is not None: setattr(self, field, field_value) - def _del_value(self): + @value.deleter + def value(self): self._set_value(None) - value = property(_get_value, _set_value, _del_value, doc= - """The logical value of this property.""") + @value.comparator + class value(PropComparator): + """A comparator for .value, builds a polymorphic comparison via CASE. + + """ + def __init__(self, cls): + self.cls = cls + + def _case(self): + whens = [(text("'%s'" % p[0]), getattr(self.cls, p[1])) + for p in self.cls.type_map.values() + if p[1] is not None] + return case(whens, self.cls.type, null()) + def __eq__(self, other): + return cast(self._case(), String) == cast(other, String) + def __ne__(self, other): + return cast(self._case(), String) != cast(other, String) def __repr__(self): return '<%s %r=%r>' % (self.__class__.__name__, self.key, self.value) @@ -131,7 +129,7 @@ class PolymorphicVerticalProperty(object): if __name__ == '__main__': from sqlalchemy import (MetaData, Table, Column, Integer, Unicode, ForeignKey, UnicodeText, and_, not_, or_, String, Boolean, cast, text, - null, case) + null, case, create_engine) from sqlalchemy.orm import mapper, relationship, Session from sqlalchemy.orm.collections import attribute_mapped_collection @@ -185,11 +183,9 @@ if __name__ == '__main__': collection_class=attribute_mapped_collection('key')), }) - mapper(AnimalFact, chars, properties={ - 'value': comparable_property(AnimalFact.Comparator, AnimalFact.value) - }) + mapper(AnimalFact, chars) - metadata.bind = 'sqlite:///' + metadata.bind = create_engine('sqlite://', echo=True) metadata.create_all() session = Session() @@ -208,9 +204,7 @@ if __name__ == '__main__': print "changing cuteness value and type:" critter[u'cuteness'] = u'very cute' - metadata.bind.echo = True session.commit() - metadata.bind.echo = False marten = Animal(u'marten') marten[u'cuteness'] = 5 diff --git a/lib/sqlalchemy/ext/hybrid.py b/lib/sqlalchemy/ext/hybrid.py index f3989a84d4..9fb8a27d82 100644 --- a/lib/sqlalchemy/ext/hybrid.py +++ b/lib/sqlalchemy/ext/hybrid.py @@ -31,22 +31,22 @@ or as the class itself:: # A base class for intervals - from sqlalchemy.orm import hybrid + from sqlalchemy.orm.hybrid import hybrid_property, hybrid_method class Interval(object): def __init__(self, start, end): self.start = start self.end = end - @hybrid.property + @hybrid_property def length(self): return self.end - self.start - @hybrid.method + @hybrid_method def contains(self,point): return (self.start <= point) & (point < self.end) - @hybrid.method + @hybrid_method def intersects(self, other): return self.contains(other.start) | self.contains(other.end) @@ -56,7 +56,7 @@ or as the class itself:: from sqlalchemy import util from sqlalchemy.orm import attributes, interfaces -class method(object): +class hybrid_method(object): def __init__(self, func, expr=None): self.func = func self.expr = expr or func @@ -71,7 +71,7 @@ class method(object): self.expr = expr return self -class property_(object): +class hybrid_property(object): def __init__(self, fget, fset=None, fdel=None, expr=None): self.fget = fget self.fset = fset @@ -107,7 +107,7 @@ class property_(object): proxy_attr = attributes.\ create_proxied_attribute(self) def expr(owner): - return proxy_attr(self.__name__, self, comparator(owner)) + return proxy_attr(owner, self.__name__, self, comparator(owner)) self.expr = expr return self