1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
"""Define attributes on ORM-mapped classes that have 'hybrid' behavior.
'hybrid' means the attribute has distinct behaviors defined at the
class level and at the instance level.
Consider a table `interval` as below::
from sqlalchemy import MetaData, Table, Column, Integer
from sqlalchemy.orm import mapper, create_session
engine = create_engine('sqlite://')
metadata = MetaData()
interval_table = Table('interval', metadata,
Column('id', Integer, primary_key=True),
Column('start', Integer, nullable=False),
Column('end', Integer, nullable=False))
metadata.create_all(engine)
We can define higher level functions on mapped classes that produce SQL
expressions at the class level, and Python expression evaluation at the
instance level. Below, each function decorated with :func:`hybrid.method`
or :func:`hybrid.property` may receive ``self`` as an instance of the class,
or as the class itself::
# A base class for intervals
from sqlalchemy.orm import hybrid
class Interval(object):
def __init__(self, start, end):
self.start = start
self.end = end
@hybrid.property
def length(self):
return self.end - self.start
@hybrid.method
def contains(self,point):
return (self.start <= point) & (point < self.end)
@hybrid.method
def intersects(self, other):
return self.contains(other.start) | self.contains(other.end)
"""
from sqlalchemy import util
from sqlalchemy.orm import attributes, interfaces
class method(object):
def __init__(self, func, expr=None):
self.func = func
self.expr = expr or func
def __get__(self, instance, owner):
if instance is None:
return new.instancemethod(self.expr, owner, owner.__class__)
else:
return new.instancemethod(self.func, instance, owner)
def expression(self, expr):
self.expr = expr
return self
class property_(object):
def __init__(self, fget, fset=None, fdel=None, expr=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
self.expr = expr or fget
util.update_wrapper(self, fget)
def __get__(self, instance, owner):
if instance is None:
return self.expr(owner)
else:
return self.fget(instance)
def __set__(self, instance, value):
self.fset(instance, value)
def __delete__(self, instance):
self.fdel(instance)
def setter(self, fset):
self.fset = fset
return self
def deleter(self, fdel):
self.fdel = fdel
return self
def expression(self, expr):
self.expr = expr
return self
def comparator(self, comparator):
proxy_attr = attributes.\
create_proxied_attribute(self)
def expr(owner):
return proxy_attr(self.__name__, self, comparator(owner))
self.expr = expr
return self
class Comparator(interfaces.PropComparator):
def __init__(self, expression):
self.expression = expression
def __clause_element__(self):
expr = self.expression
while hasattr(expr, '__clause_element__'):
expr = expr.__clause_element__()
return expr
def adapted(self, adapter):
# interesting....
return self
|