Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2@file
3@brief One class which visits a syntax tree.
4"""
6from .translation_class import TranslateClass
9class Translate2Python(TranslateClass):
11 """
12 Translates a code into :epkg:`Python`.
13 """
15 def __init__(self, code_func):
16 """
17 constructor
19 @param code_func code (str) or function(func)
20 """
21 TranslateClass.__init__(self, code_func)
23 def Signature(self, name, rows):
24 """
25 Builds the signature of a function based
26 on its name and its children.
28 @param name name
29 @param rows list of arguments
30 @return list of strings (code)
31 """
32 code_rows = ["def {0}({1}):".format(name, ", ".join(rows))]
33 return code_rows
35 def Select(self, name, table, rows):
36 """
37 Interprets a select statement.
39 @param name name of the table which receives the results
40 @param table name of the table it applies to
41 @param rows rows to consider
42 @return list of strings (code)
43 """
44 code_rows = []
45 code_rows.append("{0} = [ ]".format(name))
46 code_rows.append("for row in {0}:".format(table))
48 done = {}
49 code_exp = []
50 code_exp.append(" newr = {")
51 for r in rows:
52 if r["type"] == "Attribute":
53 tbl, att = r["str"].split(".")
54 if tbl != table:
55 self.RaiseCodeException(
56 "an attribute comes from an unexpected table {0}!={1}".format(
57 table,
58 tbl))
59 if att not in done:
60 code_rows.append(" _{0}=row['{0}']".format(att))
61 done[att] = att
62 code_exp.append(" '{0}':_{0},".format(att))
63 elif r["type"] == "keyword":
64 # it has to be an expression
65 att0 = r["str"]
66 exp, fields, functions = self.ResolveExpression(r, "_")
68 if len(functions) > 0:
69 # we do nothing here, we assume the function is known
70 # when it will be called
71 pass
73 for att_ in fields:
74 spl = att_.split(".")
75 if len(spl) != 2:
76 self.RaiseCodeException(
77 "unexpected field name: " +
78 att_)
79 if spl[0] != table:
80 self.RaiseCodeException(
81 "unexpected table name: " +
82 att_)
83 att = spl[1]
84 if att not in done:
85 code_rows.append(" _{0}=row['{0}']".format(att))
86 done[att] = att
87 exp = exp.replace(att_, att)
88 code_exp.append(" '{0}':{1},".format(att0, exp))
89 else:
90 self.RaiseCodeException("type expected {0}".format(r["type"]))
91 r["processed"] = True
93 code_rows.extend(code_exp)
94 code_rows.append(" }")
95 code_rows.append(" {0}.append(newr)".format(name))
96 return [" " + _ for _ in code_rows]
98 def Where(self, name, table, rows):
99 """
100 Interprets a where statement.
102 @param name name of the table which receives the results
103 @param table name of the table it applies to
104 @param rows rows to consider
105 @return list of strings (code)
106 """
107 code_rows = []
108 code_rows.append("{0} = [ ]".format(name))
109 code_rows.append("for row in {0}:".format(table))
111 done = {}
112 first = True
113 for r in rows:
114 if not first:
115 self.RaiseCodeException(
116 "SyntaxError, only one clause where is allowed")
117 # att0 = r["str"]
118 exp, fields, functions = self.ResolveExpression(r, "_")
119 for att_ in fields:
120 spl = att_.split(".")
121 if len(spl) != 2:
122 self.RaiseCodeException("unexpected field name: " + att_)
123 if spl[0] != table:
124 self.RaiseCodeException("unexpected table name: " + att_)
125 att = spl[1]
126 if att not in done:
127 code_rows.append(" _{0}=row['{0}']".format(att))
128 done[att] = att
129 exp = exp.replace(att_, att)
130 code_rows.append(" _exp={0}".format(exp))
131 code_rows.append(" if _exp: {0}.append(row)".format(name))
132 r["processed"] = True
133 first = False
135 return [" " + _ for _ in code_rows]
137 def setReturn(self, nodes):
138 """
139 Indicates all nodes containing information about returned results.
141 @param nodes list of nodes
142 @return list of string
143 """
144 for node in nodes:
145 node["processed"] = True
146 names = [node["str"] for node in nodes]
147 return [" return " + ",".join(names)]
149 def GroupBy(self, name, table, rows):
150 """
151 Interprets a select statement.
153 @param name name of the table which receives the results
154 @param table name of the table it applies to
155 @param rows rows to consider
156 @return list of strings (code)
157 """
158 code_rows = []
159 code_rows.append("__groupby__ = {}")
161 keys = []
162 done = {}
163 code_exp = []
164 loop_exp = []
165 agg_function = []
166 code_exp.append(" newr = {")
167 for r in rows:
168 if r["type"] == "Attribute":
169 tbl, att = r["str"].split(".")
170 if tbl != table:
171 self.RaiseCodeException(
172 "an attribute comes from an unexpected table {0}!={1}".format(
173 table,
174 tbl))
175 if att not in done:
176 loop_exp.append(" _{0}=row['{0}']".format(att))
177 done[att] = att
178 code_exp.append(" '{0}':_{0},".format(att))
179 keys.append(att)
180 elif r["type"] == "keyword":
181 ####################
182 # it has to be an expression
183 ####################
184 att0 = r["str"]
185 exp, fields, functions = self.ResolveExpression(r, "_")
187 if len(functions) > 0:
188 # we do nothing here, we assume the function is known
189 # when it will be called
190 pass
192 for att_ in fields:
193 spl = att_.split(".")
194 if len(spl) != 1:
195 self.RaiseCodeException(
196 "unexpected field name: " +
197 att_)
198 funcname = att_
200 chil = fields[att_]["children"]
201 if len(chil) != 1:
202 self.RaiseCodeException(
203 "two many children: " + str(len(chil)))
204 chil = chil[0]
205 spl = chil["str"].split(".")
206 if len(spl) != 2:
207 self.RaiseCodeException(
208 "unexpected field name: " +
209 chil["str"])
210 table, att = spl
211 chil["processed"] = True
213 if att not in done:
214 loop_exp.append(" _{0}=row['{0}']".format(att))
215 code_exp.append(" '{0}':_{0},".format(att))
216 done[att] = att
217 #exp = exp.replace(att_,att)
218 agg_function.append((att0, funcname, table, att))
219 else:
220 self.RaiseCodeException("type expected {0}".format(r["type"]))
221 r["processed"] = True
223 code_rows.append(
224 "keys = [ {0} ]".format(
225 ",".join(
226 '"{0}"'.format(k) for k in keys)))
227 code_rows.append("for row in {0}:".format(table))
228 code_rows.extend(loop_exp)
229 code_rows.extend(code_exp)
230 code_rows.append(" }")
231 allk = ",".join('_' + _ for _ in keys)
232 code_rows.append(" _k_ = tuple( [ {0}, ] )".format(allk))
233 code_rows.append(
234 " if _k_ not in __groupby__: __groupby__[_k_] = []")
235 code_rows.append(" __groupby__[_k_].append( newr )")
236 code_rows.append("")
237 code_rows.append("{0} = [ ]".format(name))
239 code_rows.append("for gr,rows in __groupby__.items():")
240 code_rows.append(" r = {")
241 for i, key in enumerate(keys):
242 code_rows.append(" '{0}':gr[{1}],".format(key, i))
243 code_rows.append(" }")
244 for newatt, funcname, tablel, att in agg_function:
245 c = "[ d['{0}'] for d in rows ]".format(att)
246 code_rows.append(
247 " r['{0}'] = {1} ( {2} )".format(newatt, funcname, c))
248 code_rows.append(" iter.append( r )")
250 return [" " + _ for _ in code_rows]