mseep-txtai 9.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. mseep_txtai-9.1.1.dist-info/METADATA +262 -0
  2. mseep_txtai-9.1.1.dist-info/RECORD +251 -0
  3. mseep_txtai-9.1.1.dist-info/WHEEL +5 -0
  4. mseep_txtai-9.1.1.dist-info/licenses/LICENSE +190 -0
  5. mseep_txtai-9.1.1.dist-info/top_level.txt +1 -0
  6. txtai/__init__.py +16 -0
  7. txtai/agent/__init__.py +12 -0
  8. txtai/agent/base.py +54 -0
  9. txtai/agent/factory.py +39 -0
  10. txtai/agent/model.py +107 -0
  11. txtai/agent/placeholder.py +16 -0
  12. txtai/agent/tool/__init__.py +7 -0
  13. txtai/agent/tool/embeddings.py +69 -0
  14. txtai/agent/tool/factory.py +130 -0
  15. txtai/agent/tool/function.py +49 -0
  16. txtai/ann/__init__.py +7 -0
  17. txtai/ann/base.py +153 -0
  18. txtai/ann/dense/__init__.py +11 -0
  19. txtai/ann/dense/annoy.py +72 -0
  20. txtai/ann/dense/factory.py +76 -0
  21. txtai/ann/dense/faiss.py +233 -0
  22. txtai/ann/dense/hnsw.py +104 -0
  23. txtai/ann/dense/numpy.py +164 -0
  24. txtai/ann/dense/pgvector.py +323 -0
  25. txtai/ann/dense/sqlite.py +303 -0
  26. txtai/ann/dense/torch.py +38 -0
  27. txtai/ann/sparse/__init__.py +7 -0
  28. txtai/ann/sparse/factory.py +61 -0
  29. txtai/ann/sparse/ivfsparse.py +377 -0
  30. txtai/ann/sparse/pgsparse.py +56 -0
  31. txtai/api/__init__.py +18 -0
  32. txtai/api/application.py +134 -0
  33. txtai/api/authorization.py +53 -0
  34. txtai/api/base.py +159 -0
  35. txtai/api/cluster.py +295 -0
  36. txtai/api/extension.py +19 -0
  37. txtai/api/factory.py +40 -0
  38. txtai/api/responses/__init__.py +7 -0
  39. txtai/api/responses/factory.py +30 -0
  40. txtai/api/responses/json.py +56 -0
  41. txtai/api/responses/messagepack.py +51 -0
  42. txtai/api/route.py +41 -0
  43. txtai/api/routers/__init__.py +25 -0
  44. txtai/api/routers/agent.py +38 -0
  45. txtai/api/routers/caption.py +42 -0
  46. txtai/api/routers/embeddings.py +280 -0
  47. txtai/api/routers/entity.py +42 -0
  48. txtai/api/routers/extractor.py +28 -0
  49. txtai/api/routers/labels.py +47 -0
  50. txtai/api/routers/llm.py +61 -0
  51. txtai/api/routers/objects.py +42 -0
  52. txtai/api/routers/openai.py +191 -0
  53. txtai/api/routers/rag.py +61 -0
  54. txtai/api/routers/reranker.py +46 -0
  55. txtai/api/routers/segmentation.py +42 -0
  56. txtai/api/routers/similarity.py +48 -0
  57. txtai/api/routers/summary.py +46 -0
  58. txtai/api/routers/tabular.py +42 -0
  59. txtai/api/routers/textractor.py +42 -0
  60. txtai/api/routers/texttospeech.py +33 -0
  61. txtai/api/routers/transcription.py +42 -0
  62. txtai/api/routers/translation.py +46 -0
  63. txtai/api/routers/upload.py +36 -0
  64. txtai/api/routers/workflow.py +28 -0
  65. txtai/app/__init__.py +5 -0
  66. txtai/app/base.py +821 -0
  67. txtai/archive/__init__.py +9 -0
  68. txtai/archive/base.py +104 -0
  69. txtai/archive/compress.py +51 -0
  70. txtai/archive/factory.py +25 -0
  71. txtai/archive/tar.py +49 -0
  72. txtai/archive/zip.py +35 -0
  73. txtai/cloud/__init__.py +8 -0
  74. txtai/cloud/base.py +106 -0
  75. txtai/cloud/factory.py +70 -0
  76. txtai/cloud/hub.py +101 -0
  77. txtai/cloud/storage.py +125 -0
  78. txtai/console/__init__.py +5 -0
  79. txtai/console/__main__.py +22 -0
  80. txtai/console/base.py +264 -0
  81. txtai/data/__init__.py +10 -0
  82. txtai/data/base.py +138 -0
  83. txtai/data/labels.py +42 -0
  84. txtai/data/questions.py +135 -0
  85. txtai/data/sequences.py +48 -0
  86. txtai/data/texts.py +68 -0
  87. txtai/data/tokens.py +28 -0
  88. txtai/database/__init__.py +14 -0
  89. txtai/database/base.py +342 -0
  90. txtai/database/client.py +227 -0
  91. txtai/database/duckdb.py +150 -0
  92. txtai/database/embedded.py +76 -0
  93. txtai/database/encoder/__init__.py +8 -0
  94. txtai/database/encoder/base.py +37 -0
  95. txtai/database/encoder/factory.py +56 -0
  96. txtai/database/encoder/image.py +43 -0
  97. txtai/database/encoder/serialize.py +28 -0
  98. txtai/database/factory.py +77 -0
  99. txtai/database/rdbms.py +569 -0
  100. txtai/database/schema/__init__.py +6 -0
  101. txtai/database/schema/orm.py +99 -0
  102. txtai/database/schema/statement.py +98 -0
  103. txtai/database/sql/__init__.py +8 -0
  104. txtai/database/sql/aggregate.py +178 -0
  105. txtai/database/sql/base.py +189 -0
  106. txtai/database/sql/expression.py +404 -0
  107. txtai/database/sql/token.py +342 -0
  108. txtai/database/sqlite.py +57 -0
  109. txtai/embeddings/__init__.py +7 -0
  110. txtai/embeddings/base.py +1107 -0
  111. txtai/embeddings/index/__init__.py +14 -0
  112. txtai/embeddings/index/action.py +15 -0
  113. txtai/embeddings/index/autoid.py +92 -0
  114. txtai/embeddings/index/configuration.py +71 -0
  115. txtai/embeddings/index/documents.py +86 -0
  116. txtai/embeddings/index/functions.py +155 -0
  117. txtai/embeddings/index/indexes.py +199 -0
  118. txtai/embeddings/index/indexids.py +60 -0
  119. txtai/embeddings/index/reducer.py +104 -0
  120. txtai/embeddings/index/stream.py +67 -0
  121. txtai/embeddings/index/transform.py +205 -0
  122. txtai/embeddings/search/__init__.py +11 -0
  123. txtai/embeddings/search/base.py +344 -0
  124. txtai/embeddings/search/errors.py +9 -0
  125. txtai/embeddings/search/explain.py +120 -0
  126. txtai/embeddings/search/ids.py +61 -0
  127. txtai/embeddings/search/query.py +69 -0
  128. txtai/embeddings/search/scan.py +196 -0
  129. txtai/embeddings/search/terms.py +46 -0
  130. txtai/graph/__init__.py +10 -0
  131. txtai/graph/base.py +769 -0
  132. txtai/graph/factory.py +61 -0
  133. txtai/graph/networkx.py +275 -0
  134. txtai/graph/query.py +181 -0
  135. txtai/graph/rdbms.py +113 -0
  136. txtai/graph/topics.py +166 -0
  137. txtai/models/__init__.py +9 -0
  138. txtai/models/models.py +268 -0
  139. txtai/models/onnx.py +133 -0
  140. txtai/models/pooling/__init__.py +9 -0
  141. txtai/models/pooling/base.py +141 -0
  142. txtai/models/pooling/cls.py +28 -0
  143. txtai/models/pooling/factory.py +144 -0
  144. txtai/models/pooling/late.py +173 -0
  145. txtai/models/pooling/mean.py +33 -0
  146. txtai/models/pooling/muvera.py +164 -0
  147. txtai/models/registry.py +37 -0
  148. txtai/models/tokendetection.py +122 -0
  149. txtai/pipeline/__init__.py +17 -0
  150. txtai/pipeline/audio/__init__.py +11 -0
  151. txtai/pipeline/audio/audiomixer.py +58 -0
  152. txtai/pipeline/audio/audiostream.py +94 -0
  153. txtai/pipeline/audio/microphone.py +244 -0
  154. txtai/pipeline/audio/signal.py +186 -0
  155. txtai/pipeline/audio/texttoaudio.py +60 -0
  156. txtai/pipeline/audio/texttospeech.py +553 -0
  157. txtai/pipeline/audio/transcription.py +212 -0
  158. txtai/pipeline/base.py +23 -0
  159. txtai/pipeline/data/__init__.py +10 -0
  160. txtai/pipeline/data/filetohtml.py +206 -0
  161. txtai/pipeline/data/htmltomd.py +414 -0
  162. txtai/pipeline/data/segmentation.py +178 -0
  163. txtai/pipeline/data/tabular.py +155 -0
  164. txtai/pipeline/data/textractor.py +139 -0
  165. txtai/pipeline/data/tokenizer.py +112 -0
  166. txtai/pipeline/factory.py +77 -0
  167. txtai/pipeline/hfmodel.py +111 -0
  168. txtai/pipeline/hfpipeline.py +96 -0
  169. txtai/pipeline/image/__init__.py +7 -0
  170. txtai/pipeline/image/caption.py +55 -0
  171. txtai/pipeline/image/imagehash.py +90 -0
  172. txtai/pipeline/image/objects.py +80 -0
  173. txtai/pipeline/llm/__init__.py +11 -0
  174. txtai/pipeline/llm/factory.py +86 -0
  175. txtai/pipeline/llm/generation.py +173 -0
  176. txtai/pipeline/llm/huggingface.py +218 -0
  177. txtai/pipeline/llm/litellm.py +90 -0
  178. txtai/pipeline/llm/llama.py +152 -0
  179. txtai/pipeline/llm/llm.py +75 -0
  180. txtai/pipeline/llm/rag.py +477 -0
  181. txtai/pipeline/nop.py +14 -0
  182. txtai/pipeline/tensors.py +52 -0
  183. txtai/pipeline/text/__init__.py +13 -0
  184. txtai/pipeline/text/crossencoder.py +70 -0
  185. txtai/pipeline/text/entity.py +140 -0
  186. txtai/pipeline/text/labels.py +137 -0
  187. txtai/pipeline/text/lateencoder.py +103 -0
  188. txtai/pipeline/text/questions.py +48 -0
  189. txtai/pipeline/text/reranker.py +57 -0
  190. txtai/pipeline/text/similarity.py +83 -0
  191. txtai/pipeline/text/summary.py +98 -0
  192. txtai/pipeline/text/translation.py +298 -0
  193. txtai/pipeline/train/__init__.py +7 -0
  194. txtai/pipeline/train/hfonnx.py +196 -0
  195. txtai/pipeline/train/hftrainer.py +398 -0
  196. txtai/pipeline/train/mlonnx.py +63 -0
  197. txtai/scoring/__init__.py +12 -0
  198. txtai/scoring/base.py +188 -0
  199. txtai/scoring/bm25.py +29 -0
  200. txtai/scoring/factory.py +95 -0
  201. txtai/scoring/pgtext.py +181 -0
  202. txtai/scoring/sif.py +32 -0
  203. txtai/scoring/sparse.py +218 -0
  204. txtai/scoring/terms.py +499 -0
  205. txtai/scoring/tfidf.py +358 -0
  206. txtai/serialize/__init__.py +10 -0
  207. txtai/serialize/base.py +85 -0
  208. txtai/serialize/errors.py +9 -0
  209. txtai/serialize/factory.py +29 -0
  210. txtai/serialize/messagepack.py +42 -0
  211. txtai/serialize/pickle.py +98 -0
  212. txtai/serialize/serializer.py +46 -0
  213. txtai/util/__init__.py +7 -0
  214. txtai/util/resolver.py +32 -0
  215. txtai/util/sparsearray.py +62 -0
  216. txtai/util/template.py +16 -0
  217. txtai/vectors/__init__.py +8 -0
  218. txtai/vectors/base.py +476 -0
  219. txtai/vectors/dense/__init__.py +12 -0
  220. txtai/vectors/dense/external.py +55 -0
  221. txtai/vectors/dense/factory.py +121 -0
  222. txtai/vectors/dense/huggingface.py +44 -0
  223. txtai/vectors/dense/litellm.py +86 -0
  224. txtai/vectors/dense/llama.py +84 -0
  225. txtai/vectors/dense/m2v.py +67 -0
  226. txtai/vectors/dense/sbert.py +92 -0
  227. txtai/vectors/dense/words.py +211 -0
  228. txtai/vectors/recovery.py +57 -0
  229. txtai/vectors/sparse/__init__.py +7 -0
  230. txtai/vectors/sparse/base.py +90 -0
  231. txtai/vectors/sparse/factory.py +55 -0
  232. txtai/vectors/sparse/sbert.py +34 -0
  233. txtai/version.py +6 -0
  234. txtai/workflow/__init__.py +8 -0
  235. txtai/workflow/base.py +184 -0
  236. txtai/workflow/execute.py +99 -0
  237. txtai/workflow/factory.py +42 -0
  238. txtai/workflow/task/__init__.py +18 -0
  239. txtai/workflow/task/base.py +490 -0
  240. txtai/workflow/task/console.py +24 -0
  241. txtai/workflow/task/export.py +64 -0
  242. txtai/workflow/task/factory.py +89 -0
  243. txtai/workflow/task/file.py +28 -0
  244. txtai/workflow/task/image.py +36 -0
  245. txtai/workflow/task/retrieve.py +61 -0
  246. txtai/workflow/task/service.py +102 -0
  247. txtai/workflow/task/storage.py +110 -0
  248. txtai/workflow/task/stream.py +33 -0
  249. txtai/workflow/task/template.py +116 -0
  250. txtai/workflow/task/url.py +20 -0
  251. txtai/workflow/task/workflow.py +14 -0
@@ -0,0 +1,404 @@
1
+ """
2
+ Expression module
3
+ """
4
+
5
+ from .token import Token
6
+
7
+
8
+ class Expression:
9
+ """
10
+ Parses expression statements and runs a set of substitution/formatting rules.
11
+ """
12
+
13
+ def __init__(self, resolver, tolist):
14
+ """
15
+ Creates a new expression parser.
16
+
17
+ Args:
18
+ resolver: function to call to resolve query column names with database column names
19
+ tolist: outputs expression lists if True, text if False
20
+ """
21
+
22
+ self.resolver = resolver
23
+ self.tolist = tolist
24
+
25
+ def __call__(self, tokens, alias=False, aliases=None, similar=None):
26
+ """
27
+ Parses and formats a list of tokens as follows:
28
+ - Replaces query column names with database column names
29
+ - Adds similar query placeholders and extracts similar function parameters
30
+ - Rewrites expression and returns
31
+
32
+ Args:
33
+ tokens: input expression
34
+ alias: if True, column aliases should be generated and added to aliases dict
35
+ aliases: dict of generated aliases, if present these tokens should NOT be resolved
36
+ similar: list of similar queries, if present new similar queries are appended to this list
37
+
38
+ Returns:
39
+ rewritten clause
40
+ """
41
+
42
+ # Processes token expressions and applies a set of transformation rules
43
+ transformed = self.process(list(tokens), alias, aliases, similar)
44
+
45
+ # Re-write alias expression and return
46
+ if alias and not self.tolist:
47
+ return self.buildalias(transformed, tokens, aliases)
48
+
49
+ # Re-write input expression and return
50
+ return self.buildlist(transformed) if self.tolist is True else self.buildtext(transformed)
51
+
52
+ def process(self, tokens, alias, aliases, similar):
53
+ """
54
+ Replaces query column names with database column names, adds similar query placeholders and
55
+ extracts similar function parameters.
56
+
57
+ Args:
58
+ tokens: input expression
59
+ alias: if True, column aliases should be generated and added to aliases dict
60
+ aliases: dict of generated aliases, if present these tokens should NOT be resolved
61
+ similar: list of similar queries, if present new similar queries are appended to this list
62
+
63
+ Returns:
64
+ transformed tokens
65
+ """
66
+
67
+ # Create clause index and token iterator. Iterator skips distinct tokens.
68
+ index, iterator = 0, ((x, token) for x, token in enumerate(tokens) if not Token.isdistinct(token))
69
+ for x, token in iterator:
70
+ # Check if separator, increment clause index
71
+ if Token.isseparator(token):
72
+ index += 1
73
+
74
+ # Check if token is a square bracket
75
+ elif Token.isbracket(token):
76
+ # Resolve bracket expression
77
+ self.bracket(iterator, tokens, x)
78
+
79
+ # Check if token is a similar function
80
+ elif Token.issimilar(tokens, x, similar):
81
+ # Resolve similar expression
82
+ self.similar(iterator, tokens, x, similar)
83
+
84
+ # Check if token is a function
85
+ elif Token.isfunction(tokens, x):
86
+ # Resolve function expression
87
+ self.function(iterator, tokens, token, aliases, similar)
88
+
89
+ # Check for alias expression
90
+ elif Token.isalias(tokens, x, alias):
91
+ # Process alias expression
92
+ self.alias(iterator, tokens, x, aliases, index)
93
+
94
+ # Check for attribute expression
95
+ elif Token.isattribute(tokens, x):
96
+ # Resolve attribute expression
97
+ self.attribute(tokens, x, aliases)
98
+
99
+ # Check for compound expression
100
+ elif Token.iscompound(tokens, x):
101
+ # Resolve compound expression
102
+ self.compound(iterator, tokens, x, aliases, similar)
103
+
104
+ # Remove replaced tokens
105
+ return [token for token in tokens if token]
106
+
107
+ def buildtext(self, tokens):
108
+ """
109
+ Builds a new expression from tokens. This method applies a set of rules to generate whitespace between tokens.
110
+
111
+ Args:
112
+ tokens: input expression
113
+
114
+ Returns:
115
+ expression text
116
+ """
117
+
118
+ # Rebuild expression
119
+ text = ""
120
+ for token in tokens:
121
+ # Write token with whitespace rules applied
122
+ text += Token.wrapspace(text, token)
123
+
124
+ # Remove any leading/trailing whitespace and return
125
+ return text.strip()
126
+
127
+ def buildlist(self, tokens):
128
+ """
129
+ Builds a new expression from tokens. This method returns a list of expression components. These components can be joined together
130
+ on commas to form a text expression.
131
+
132
+ Args:
133
+ tokens: input expression
134
+
135
+ Returns:
136
+ expression list
137
+ """
138
+
139
+ parts, current, parens, brackets = [], [], 0, 0
140
+
141
+ for token in tokens:
142
+ # Create new part
143
+ if token == "," and not parens and not brackets:
144
+ parts.append(self.buildtext(current))
145
+ current = []
146
+ else:
147
+ # Accumulate tokens
148
+ if token == "(":
149
+ parens += 1
150
+ elif token == ")":
151
+ parens -= 1
152
+ elif token == "[":
153
+ brackets += 1
154
+ elif token == "]":
155
+ brackets -= 1
156
+ elif Token.issortorder(token):
157
+ token = f" {token}"
158
+ current.append(token)
159
+
160
+ # Add last part
161
+ if current:
162
+ parts.append(self.buildtext(current))
163
+
164
+ return parts
165
+
166
+ def buildalias(self, transformed, tokens, aliases):
167
+ """
168
+ Builds new alias text expression from transformed and input tokens.
169
+
170
+ Args:
171
+ transformed: transformed tokens
172
+ tokens: original input tokens
173
+ aliases: dict of column aliases
174
+
175
+ Returns:
176
+ alias text expression
177
+ """
178
+
179
+ # Convert tokens to expressions
180
+ transformed = self.buildlist(transformed)
181
+ tokens = self.buildlist(tokens)
182
+
183
+ expression = []
184
+ for x, token in enumerate(transformed):
185
+ if x not in aliases.values():
186
+ alias = tokens[x]
187
+
188
+ # Strip leading/trailing brackets from alias name that doesn't have operators
189
+ if not any(Token.isoperator(t) for t in alias) and alias[0] in ("[", "(") and alias[-1] in ("]", ")"):
190
+ alias = alias[1:-1]
191
+
192
+ # Strip leading distinct keyword
193
+ values = alias.split()
194
+ if len(values) > 0 and Token.isdistinct(values[0]):
195
+ alias = " ".join(values[1:])
196
+
197
+ # Resolve alias
198
+ token = self.resolver(token, alias)
199
+
200
+ expression.append(token)
201
+
202
+ # Build alias text expression
203
+ return ", ".join(expression)
204
+
205
+ def bracket(self, iterator, tokens, x):
206
+ """
207
+ Consumes a [bracket] expression.
208
+
209
+ Args:
210
+ iterator: tokens iterator
211
+ tokens: input tokens
212
+ x: current position
213
+ """
214
+
215
+ # Function parameters
216
+ params = []
217
+
218
+ # Clear token from stream
219
+ token = tokens[x]
220
+ tokens[x] = None
221
+
222
+ # Bracket counter (current token is an open bracket)
223
+ brackets = 1
224
+
225
+ # Read until token is a end bracket
226
+ while token and (token != "]" or brackets > 0):
227
+ x, token = next(iterator, (None, None))
228
+
229
+ # Increase/decrease bracket counter
230
+ if token == "[":
231
+ brackets += 1
232
+ elif token == "]":
233
+ brackets -= 1
234
+
235
+ # Accumulate tokens
236
+ if token != "]" or brackets > 0:
237
+ params.append(token)
238
+
239
+ # Clear token from stream
240
+ tokens[x] = None
241
+
242
+ # Set last token to resolved bracket expression
243
+ tokens[x] = self.resolve(self.buildtext(params), None)
244
+
245
+ def similar(self, iterator, tokens, x, similar):
246
+ """
247
+ Substitutes a similar() function call with a placeholder that can later be used to add
248
+ embeddings query results as a filter.
249
+
250
+ Args:
251
+ iterator: tokens iterator
252
+ tokens: input tokens
253
+ x: current position
254
+ similar: list where similar function call parameters are stored
255
+ """
256
+
257
+ # Function parameters
258
+ params = []
259
+
260
+ # Clear token from stream
261
+ token = tokens[x]
262
+ tokens[x] = None
263
+
264
+ # Read until token is a closing paren
265
+ while token and token != ")":
266
+ x, token = next(iterator, (None, None))
267
+ if token and token not in ["(", ",", ")"]:
268
+ # Strip quotes and accumulate tokens
269
+ params.append(token.replace("'", "").replace('"', ""))
270
+
271
+ # Clear token from stream
272
+ tokens[x] = None
273
+
274
+ # Add placeholder for embedding similarity results
275
+ tokens[x] = f"{Token.SIMILAR_TOKEN}{len(similar)}"
276
+
277
+ # Save parameters
278
+ similar.append(params)
279
+
280
+ def function(self, iterator, tokens, token, aliases, similar):
281
+ """
282
+ Resolves column names within the function's parameters.
283
+
284
+ Args:
285
+ iterator: tokens iterator
286
+ tokens: input tokens
287
+ token: current token
288
+ aliases: dict of generated aliases, if present these tokens should NOT be resolved
289
+ similar: list where similar function call parameters are stored
290
+ """
291
+
292
+ # Consume function parameters
293
+ while token and token != ")":
294
+ x, token = next(iterator, (None, None))
295
+
296
+ # Check if token is a square bracket
297
+ if Token.isbracket(token):
298
+ # Resolve bracket expression
299
+ self.bracket(iterator, tokens, x)
300
+
301
+ # Check if token is a similar function
302
+ elif Token.issimilar(tokens, x, similar):
303
+ # Resolve similar expression
304
+ self.similar(iterator, tokens, x, similar)
305
+
306
+ # Check if token is a function
307
+ elif Token.isfunction(tokens, x):
308
+ # Resolve function parameters that are functions
309
+ self.function(iterator, tokens, token, aliases, similar)
310
+
311
+ # Check for attribute expression
312
+ elif Token.isattribute(tokens, x):
313
+ # Resolve attributes
314
+ self.attribute(tokens, x, aliases)
315
+
316
+ # Check for compound expression
317
+ elif Token.iscompound(tokens, x):
318
+ # Resolve compound expressions
319
+ self.compound(iterator, tokens, x, aliases, similar)
320
+
321
+ def alias(self, iterator, tokens, x, aliases, index):
322
+ """
323
+ Reads an alias clause and stores it in aliases.
324
+
325
+ Args:
326
+ iterator: tokens iterator
327
+ tokens: input tokens
328
+ x: current position
329
+ aliases: dict where aliases are stored - stores {alias: clause index}
330
+ index: clause index, used to match aliases with columns
331
+ """
332
+
333
+ token = tokens[x]
334
+
335
+ # If this is an alias token, get next token
336
+ if token in Token.ALIAS:
337
+ x, token = next(iterator, (None, None))
338
+
339
+ # Consume tokens until end of stream or a separator is found. Evaluate next token to prevent consuming here.
340
+ while x + 1 < len(tokens) and not Token.isseparator(Token.get(tokens, x + 1)):
341
+ x, token = next(iterator, (None, None))
342
+
343
+ # Add normalized alias and clause index
344
+ aliases[Token.normalize(token)] = index
345
+
346
+ def attribute(self, tokens, x, aliases):
347
+ """
348
+ Resolves an attribute column name.
349
+
350
+ Args:
351
+ tokens: input tokens
352
+ x: current token position
353
+ aliases: dict of generated aliases, if present these tokens should NOT be resolved
354
+ """
355
+
356
+ # Resolve attribute expression
357
+ tokens[x] = self.resolve(tokens[x], aliases)
358
+
359
+ def compound(self, iterator, tokens, x, aliases, similar):
360
+ """
361
+ Resolves column names in a compound expression (left side <operator(s)> right side).
362
+
363
+ Args:
364
+ iterator: tokens iterator
365
+ tokens: input tokens
366
+ x: current token position
367
+ aliases: dict of generated aliases, if present these tokens should NOT be resolved
368
+ similar: list where similar function call parameters are stored
369
+ """
370
+
371
+ # Resolve left side (left side already had function processing applied through standard loop)
372
+ if Token.iscolumn(tokens[x - 1]):
373
+ tokens[x - 1] = self.resolve(tokens[x - 1], aliases)
374
+
375
+ # Consume operator(s), handle both single and compound operators, i.e. column NOT LIKE 1
376
+ token = tokens[x]
377
+ while token and Token.isoperator(token):
378
+ x, token = next(iterator, (None, None))
379
+
380
+ # Resolve right side
381
+ if token and Token.iscolumn(token):
382
+ # Need to process functions since it hasn't went through the standard loop yet
383
+ if Token.isfunction(tokens, x):
384
+ self.function(iterator, tokens, token, aliases, similar)
385
+ else:
386
+ tokens[x] = self.resolve(token, aliases)
387
+
388
+ def resolve(self, token, aliases):
389
+ """
390
+ Resolves this token's value if it is not an alias or a bind parameter.
391
+
392
+ Args:
393
+ token: token to resolve
394
+ aliases: dict of generated aliases, if present these tokens should NOT be resolved
395
+
396
+ Returns:
397
+ resolved token value
398
+ """
399
+
400
+ # Check for alias or bind parameter
401
+ if (aliases and Token.normalize(token) in aliases) or (token.startswith(":")):
402
+ return token
403
+
404
+ return self.resolver(token)