1 | # TODO:
|
---|
2 | # - automatically .save() by default (although you can turn it off)
|
---|
3 | # - Map all Django lookup types
|
---|
4 | # - Map all Django lookup functions
|
---|
5 |
|
---|
6 | mapping = {
|
---|
7 | '>': 'gt',
|
---|
8 | '<': 'lt',
|
---|
9 | '>=': 'ge',
|
---|
10 | '<=': 'le',
|
---|
11 | '==': 'eq',
|
---|
12 | '!=': 'ne'
|
---|
13 | }
|
---|
14 |
|
---|
15 | u_mapping = {
|
---|
16 | '+': 'pos',
|
---|
17 | '-': 'neg',
|
---|
18 | '~': 'inv'
|
---|
19 | }
|
---|
20 |
|
---|
21 | class Atom:
|
---|
22 | def __init__(self, start=(), modifiers=None):
|
---|
23 | self._start = start
|
---|
24 | self._modifiers = modifiers
|
---|
25 |
|
---|
26 | def makefunc(self, key):
|
---|
27 | return lambda x: Statement(self, key, x)
|
---|
28 |
|
---|
29 | def u_makefunc(self, key):
|
---|
30 | return lambda x: Atom(self._start, key)
|
---|
31 |
|
---|
32 | for (key,val) in mapping.items():
|
---|
33 | setattr(self, '__'+val+'__', makefunc(self, key))
|
---|
34 |
|
---|
35 | for (key,val) in u_mapping.items():
|
---|
36 | setattr(self, '__'+val+'__', u_makefunc(self, key))
|
---|
37 |
|
---|
38 | def __pos__(self): return Atom(self._start, '+')
|
---|
39 |
|
---|
40 | def __getattr__(self, x):
|
---|
41 | if x.startswith('_'): return x.__dict__[x]
|
---|
42 | return Atom(self._start+(x,))
|
---|
43 |
|
---|
44 | def __repr__(self): return '.'.join(self._start)
|
---|
45 |
|
---|
46 | def _django(self): return '__'.join(self._start)
|
---|
47 |
|
---|
48 | class Statement:
|
---|
49 | def __init__(self, atom, operator, value):
|
---|
50 | self._atom = atom
|
---|
51 | self._operator = operator
|
---|
52 | self._value = value
|
---|
53 |
|
---|
54 | if isinstance(value, Atom) and value._modifiers:
|
---|
55 | self._operator += value._modifiers
|
---|
56 |
|
---|
57 | def __and__(self, x): return Group(self, 'and', x)
|
---|
58 | def __or__(self, x): return Group(self, 'or', y)
|
---|
59 |
|
---|
60 | def __repr__(self):
|
---|
61 | return repr(self._atom) + ' ' + self._operator + ' ' +repr(self._value)
|
---|
62 |
|
---|
63 | def _django(self):
|
---|
64 | mapping = {
|
---|
65 | '>': 'gt',
|
---|
66 | '<': 'lt',
|
---|
67 | '>=': 'gte',
|
---|
68 | '<=': 'lte',
|
---|
69 | '==': 'exact',
|
---|
70 | '!=': 'ne'
|
---|
71 | }
|
---|
72 |
|
---|
73 | return {self._atom._django() + '__' + mapping[self._operator]:self._value}
|
---|
74 |
|
---|
75 | class Group:
|
---|
76 | def __init__(self, stmt1, operator, stmt2):
|
---|
77 | self._stmt1 = stmt1
|
---|
78 | self._operator = operator
|
---|
79 | self._stmt2 = stmt2
|
---|
80 |
|
---|
81 | def __repr__(self):
|
---|
82 | return '('+repr(self._stmt1)+') ' + self._operator + ' ('+repr(self._stmt2)+')'
|
---|
83 |
|
---|
84 | def _django(self):
|
---|
85 | if self._operator == 'and':
|
---|
86 | return self._stmt1._django() + self._stmt2._django()
|
---|
87 | else:
|
---|
88 | raise "I don't think Django supports that operator."
|
---|
89 |
|
---|
90 | q = Atom()
|
---|
91 |
|
---|
92 | ## django-specific below this line
|
---|
93 |
|
---|
94 | class Table:
|
---|
95 | def __init__(self, table):
|
---|
96 | self.table = table
|
---|
97 |
|
---|
98 | def get(self, *args):
|
---|
99 | query = {}
|
---|
100 | for x in args:
|
---|
101 | query.update(x._django())
|
---|
102 | return Result(self.table, query)
|
---|
103 |
|
---|
104 | class Result:
|
---|
105 | def __init__(self, table, query):
|
---|
106 | self.table = table
|
---|
107 | self.query = query
|
---|
108 |
|
---|
109 | def __getitem__(self, x):
|
---|
110 | if x == 0: return self.table.get_object(**self.query)
|
---|
111 | else:
|
---|
112 | iterator = self.table.get_iterator(**self.query)
|
---|
113 | i = -1
|
---|
114 | while i != x:
|
---|
115 | iterator.next()
|
---|
116 | i += 1
|
---|
117 | return iterator.next()
|
---|
118 |
|
---|
119 | def __len__(self): return self.table.get_count(**self.query)
|
---|
120 |
|
---|
121 | def __iter__(self):
|
---|
122 | return self.table.get_iterator(**self.query)
|
---|