omlish 0.0.0.dev246__py3-none-any.whl → 0.0.0.dev247__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.
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev246'
2
- __revision__ = '796628c78050f0ca988bfa17c2f5a5cad5ee9056'
1
+ __version__ = '0.0.0.dev247'
2
+ __revision__ = '537438b3d967f194ec6ec7277d9e06205bac12b5'
3
3
 
4
4
 
5
5
  #
@@ -40,6 +40,9 @@ class IdentityKeyDict(ta.MutableMapping[K, V]):
40
40
  for k, v in lang.yield_dict_init(*args, **kwargs):
41
41
  self[k] = v
42
42
 
43
+ def __reduce__(self):
44
+ return (type(self), (list(self.items()),))
45
+
43
46
  @property
44
47
  def debug(self) -> ta.Sequence[tuple[K, V]]:
45
48
  return list(self.items())
@@ -74,6 +77,9 @@ class IdentitySet(ta.MutableSet[T]):
74
77
  for item in init:
75
78
  self.add(item)
76
79
 
80
+ def __reduce__(self):
81
+ return (type(self), (list(self),))
82
+
77
83
  @property
78
84
  def debug(self) -> ta.Sequence[T]:
79
85
  return list(self)
@@ -53,7 +53,7 @@ def _main() -> int:
53
53
  data = json.loads(data)
54
54
 
55
55
  try:
56
- print(json_dumps(search(expression, data), ensure_ascii=False))
56
+ print(json_dumps(search(expression, data)))
57
57
  return 0
58
58
 
59
59
  except ArityError as e:
@@ -16,11 +16,11 @@ def needs_parens(self, e: Expr) -> bool:
16
16
  raise TypeError(e)
17
17
  """
18
18
  import dataclasses as dc
19
- import io
20
19
  import typing as ta
21
20
 
22
21
  from ... import dispatch
23
22
  from ... import lang
23
+ from ...text import parts as tp
24
24
  from ..params import ParamStyle
25
25
  from ..params import make_params_preparer
26
26
  from .base import Node
@@ -46,6 +46,12 @@ from .unary import UnaryOp
46
46
  from .unary import UnaryOps
47
47
 
48
48
 
49
+ @dc.dataclass(frozen=True)
50
+ class RenderedQueryParts(lang.Final):
51
+ p: tp.Part
52
+ args: lang.Args
53
+
54
+
49
55
  @dc.dataclass(frozen=True)
50
56
  class RenderedQuery(lang.Final):
51
57
  s: str
@@ -55,12 +61,11 @@ class RenderedQuery(lang.Final):
55
61
  class Renderer(lang.Abstract):
56
62
  def __init__(
57
63
  self,
58
- out: ta.TextIO,
59
64
  *,
60
65
  param_style: ParamStyle | None = None,
61
66
  ) -> None:
62
67
  super().__init__()
63
- self._out = out
68
+
64
69
  self._param_style = param_style if param_style is not None else self.default_param_style
65
70
 
66
71
  self._params_preparer = make_params_preparer(self._param_style)
@@ -71,18 +76,41 @@ class Renderer(lang.Abstract):
71
76
  return self._params_preparer.prepare()
72
77
 
73
78
  @dispatch.method
74
- def render(self, o: ta.Any) -> None:
79
+ def render(self, o: ta.Any) -> tp.Part:
75
80
  raise TypeError(o)
76
81
 
77
82
  @classmethod
78
- def render_str(cls, o: ta.Any, *args: ta.Any, **kwargs: ta.Any) -> RenderedQuery:
79
- out = io.StringIO()
80
- pp = cls(out, *args, **kwargs)
81
- pp.render(o)
82
- return RenderedQuery(out.getvalue(), pp.args())
83
+ def render_query_parts(cls, o: ta.Any, *args: ta.Any, **kwargs: ta.Any) -> RenderedQueryParts:
84
+ r = cls(*args, **kwargs)
85
+ return RenderedQueryParts(
86
+ r.render(o),
87
+ r.args(),
88
+ )
89
+
90
+ @classmethod
91
+ def render_query(cls, o: ta.Any, *args: ta.Any, **kwargs: ta.Any) -> RenderedQuery:
92
+ rqp = cls.render_query_parts(o, *args, **kwargs)
93
+ return RenderedQuery(
94
+ tp.render(rqp.p),
95
+ rqp.args,
96
+ )
83
97
 
84
98
 
85
99
  class StdRenderer(Renderer):
100
+ # parens
101
+
102
+ NEEDS_PAREN_TYPES: ta.AbstractSet[type[Node]] = {
103
+ Binary,
104
+ # IsNull,
105
+ # SelectExpr,
106
+ }
107
+
108
+ def needs_paren(self, node: Node) -> bool:
109
+ return type(node) in self.NEEDS_PAREN_TYPES
110
+
111
+ def paren(self, node: Node) -> tp.Part:
112
+ return tp.Wrap(self.render(node)) if self.needs_paren(node) else self.render(node)
113
+
86
114
  # binary
87
115
 
88
116
  BINARY_OP_TO_STR: ta.ClassVar[ta.Mapping[BinaryOp, str]] = {
@@ -103,55 +131,50 @@ class StdRenderer(Renderer):
103
131
  }
104
132
 
105
133
  @Renderer.render.register
106
- def render_binary(self, o: Binary) -> None:
107
- self._out.write('(')
108
- self.render(o.l)
109
- self._out.write(f' {self.BINARY_OP_TO_STR[o.op]} ')
110
- self.render(o.r)
111
- self._out.write(')')
134
+ def render_binary(self, o: Binary) -> tp.Part:
135
+ return [
136
+ self.paren(o.l),
137
+ self.BINARY_OP_TO_STR[o.op],
138
+ self.paren(o.r),
139
+ ]
112
140
 
113
141
  # exprs
114
142
 
115
143
  @Renderer.render.register
116
- def render_literal(self, o: Literal) -> None:
117
- self._out.write(repr(o.v))
144
+ def render_literal(self, o: Literal) -> tp.Part:
145
+ return repr(o.v)
118
146
 
119
147
  @Renderer.render.register
120
- def render_name_expr(self, o: NameExpr) -> None:
121
- self.render(o.n)
148
+ def render_name_expr(self, o: NameExpr) -> tp.Part:
149
+ return self.render(o.n)
122
150
 
123
151
  @Renderer.render.register
124
- def render_param(self, o: Param) -> None:
125
- self._out.write(self._params_preparer.add(o.n if o.n is not None else id(o)))
152
+ def render_param(self, o: Param) -> tp.Part:
153
+ return self._params_preparer.add(o.n if o.n is not None else id(o))
126
154
 
127
155
  # idents
128
156
 
129
157
  @Renderer.render.register
130
- def render_ident(self, o: Ident) -> None:
131
- self._out.write(f'"{o.s}"')
158
+ def render_ident(self, o: Ident) -> tp.Part:
159
+ return f'"{o.s}"'
132
160
 
133
161
  # inserts
134
162
 
135
163
  @Renderer.render.register
136
- def render_values(self, o: Values) -> None:
137
- self._out.write('values (')
138
- for i, v in enumerate(o.vs):
139
- if i:
140
- self._out.write(', ')
141
- self.render(v)
142
- self._out.write(')')
164
+ def render_values(self, o: Values) -> tp.Part:
165
+ return [
166
+ 'values',
167
+ tp.Wrap(tp.List([self.render(v) for v in o.vs])),
168
+ ]
143
169
 
144
170
  @Renderer.render.register
145
- def render_insert(self, o: Insert) -> None:
146
- self._out.write('insert into ')
147
- self.render(o.into)
148
- self._out.write(' (')
149
- for i, c in enumerate(o.columns):
150
- if i:
151
- self._out.write(', ')
152
- self.render(c)
153
- self._out.write(') ')
154
- self.render(o.data)
171
+ def render_insert(self, o: Insert) -> tp.Part:
172
+ return [
173
+ 'insert into',
174
+ self.render(o.into),
175
+ tp.Wrap(tp.List([self.render(c) for c in o.columns])),
176
+ self.render(o.data),
177
+ ]
155
178
 
156
179
  # multis
157
180
 
@@ -161,32 +184,31 @@ class StdRenderer(Renderer):
161
184
  }
162
185
 
163
186
  @Renderer.render.register
164
- def render_multi(self, o: Multi) -> None:
165
- d = f' {self.MULTI_KIND_TO_STR[o.k]} '
166
- self._out.write('(')
167
- for i, e in enumerate(o.es):
168
- if i:
169
- self._out.write(d)
170
- self.render(e)
171
- self._out.write(')')
187
+ def render_multi(self, o: Multi) -> tp.Part:
188
+ return tp.Wrap(tp.List(
189
+ [self.render(e) for e in o.es],
190
+ delimiter=' ' + self.MULTI_KIND_TO_STR[o.k], # FIXME: Part
191
+ ))
172
192
 
173
193
  # names
174
194
 
175
195
  @Renderer.render.register
176
- def render_name(self, o: Name) -> None:
196
+ def render_name(self, o: Name) -> tp.Part:
197
+ out: list[tp.Part] = []
177
198
  for n, i in enumerate(o.ps):
178
199
  if n:
179
- self._out.write('.')
180
- self.render(i)
200
+ out.append('.')
201
+ out.append(self.render(i))
202
+ return tp.Concat(out)
181
203
 
182
204
  # relations
183
205
 
184
206
  @Renderer.render.register
185
- def render_table(self, o: Table) -> None:
186
- self.render(o.n)
187
- if o.a is not None:
188
- self._out.write(' as ')
189
- self.render(o.a)
207
+ def render_table(self, o: Table) -> tp.Part:
208
+ return [
209
+ self.render(o.n),
210
+ *(['as', self.render(o.a)] if o.a is not None else []),
211
+ ]
190
212
 
191
213
  JOIN_KIND_TO_STR: ta.ClassVar[ta.Mapping[JoinKind, str]] = {
192
214
  JoinKind.DEFAULT: 'join',
@@ -202,38 +224,31 @@ class StdRenderer(Renderer):
202
224
  }
203
225
 
204
226
  @Renderer.render.register
205
- def render_join(self, o: Join) -> None:
206
- self.render(o.l)
207
- self._out.write(' ')
208
- self._out.write(self.JOIN_KIND_TO_STR[o.k])
209
- self._out.write(' ')
210
- self.render(o.r)
211
- if o.c is not None:
212
- self._out.write(' on ')
213
- self.render(o.c)
227
+ def render_join(self, o: Join) -> tp.Part:
228
+ return [
229
+ self.render(o.l),
230
+ self.JOIN_KIND_TO_STR[o.k],
231
+ self.render(o.r),
232
+ *(['on', self.render(o.c)] if o.c is not None else []),
233
+ ]
214
234
 
215
235
  # selects
216
236
 
217
237
  @Renderer.render.register
218
- def render_select_item(self, o: SelectItem) -> None:
219
- self.render(o.v)
220
- if o.a is not None:
221
- self._out.write(' as ')
222
- self.render(o.a)
238
+ def render_select_item(self, o: SelectItem) -> tp.Part:
239
+ return [
240
+ self.render(o.v),
241
+ *(['as', self.render(o.a)] if o.a is not None else []),
242
+ ]
223
243
 
224
244
  @Renderer.render.register
225
- def render_select(self, o: Select) -> None:
226
- self._out.write('select ')
227
- for i, it in enumerate(o.items):
228
- if i:
229
- self._out.write(', ')
230
- self.render(it)
231
- if o.from_ is not None:
232
- self._out.write(' from ')
233
- self.render(o.from_)
234
- if o.where:
235
- self._out.write(' where ')
236
- self.render(o.where)
245
+ def render_select(self, o: Select) -> tp.Part:
246
+ return [
247
+ 'select',
248
+ tp.List([self.render(i) for i in o.items]),
249
+ *(['from', self.render(o.from_)] if o.from_ is not None else []),
250
+ *(['where', self.render(o.where)] if o.where is not None else []),
251
+ ]
237
252
 
238
253
  # unary
239
254
 
@@ -247,12 +262,18 @@ class StdRenderer(Renderer):
247
262
  }
248
263
 
249
264
  @Renderer.render.register
250
- def render_unary(self, o: Unary) -> None:
265
+ def render_unary(self, o: Unary) -> tp.Part:
251
266
  pfx, sfx = self.UNARY_OP_TO_STR[o.op]
252
- self._out.write(pfx)
253
- self.render(o.v)
254
- self._out.write(sfx)
267
+ return tp.Concat([
268
+ pfx,
269
+ self.render(o.v),
270
+ sfx,
271
+ ])
272
+
273
+
274
+ def render_parts(n: Node, **kwargs: ta.Any) -> RenderedQueryParts:
275
+ return StdRenderer.render_query_parts(n, **kwargs)
255
276
 
256
277
 
257
278
  def render(n: Node, **kwargs: ta.Any) -> RenderedQuery:
258
- return StdRenderer.render_str(n, **kwargs)
279
+ return StdRenderer.render_query(n, **kwargs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: omlish
3
- Version: 0.0.0.dev246
3
+ Version: 0.0.0.dev247
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=vQTAIvR8OblSq-uP2GUfnbei0RnmAnM5j0T1-OToh9E,8253
2
- omlish/__about__.py,sha256=FBmEuLfID7wGs4KGaP2kpxM0kLF3oWiG6kw4s45Nwk8,3380
2
+ omlish/__about__.py,sha256=bQqOi2ALumtKm7vdnP1J3xHEquOOa8I2437ZblRqbuU,3380
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
5
5
  omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
@@ -142,7 +142,7 @@ omlish/collections/coerce.py,sha256=g68ROb_-5HgH-vI8612mU2S0FZ8-wp2ZHK5_Zy_kVC0,
142
142
  omlish/collections/exceptions.py,sha256=shcS-NCnEUudF8qC_SmO2TQyjivKlS4TDjaz_faqQ0c,44
143
143
  omlish/collections/frozen.py,sha256=jQppK1pyQ3e_aAvw8OEKfnr7b0OB4RI5Qr1g9xXTZaQ,4137
144
144
  omlish/collections/hasheq.py,sha256=SQdVICLZWKkYu4vUXrfmWBXO3i-jx01iM9IInDWkKfU,3664
145
- omlish/collections/identity.py,sha256=BTXn3r3ZprHluIl1DIXC9BYCmjak0BWhN7L6SxXo9ws,2687
145
+ omlish/collections/identity.py,sha256=1kdiByfzKHGQZgUg1vkwILt8oPPQgerGh0_HbLDdqKw,2835
146
146
  omlish/collections/mappings.py,sha256=fCHQatlAstiZkWZiyIlOw637Yep7ce79EPPbJcWHHUA,2784
147
147
  omlish/collections/ordered.py,sha256=tUAl99XHbSbzn7Hdh99jUBl27NcC2J7ZTI67slTMe5M,2333
148
148
  omlish/collections/ranked.py,sha256=rg6DL36oOUiG5JQEAkGnT8b6f9mSndQlIovtt8GQj_w,2229
@@ -602,7 +602,7 @@ omlish/specs/jmespath/LICENSE,sha256=IH-ZZlZkS8XMkf_ubNVD1aYHQ2l_wd0tmHtXrCcYpRU
602
602
  omlish/specs/jmespath/__init__.py,sha256=9tsrquw1kXe1KAhTP3WeL0GlGBiTguQVxsC-lUYTWP4,2087
603
603
  omlish/specs/jmespath/__main__.py,sha256=wIXm6bs08etNG_GZlN2rBkADPb0rKfL2HSkm8spnpxw,200
604
604
  omlish/specs/jmespath/ast.py,sha256=XhcUGodHIdsY3-hVZEfpeW6LBehRjLbxVFXkMfZhRdk,5386
605
- omlish/specs/jmespath/cli.py,sha256=3KZwgbPXjJF_yd8H40f0vCNTNkcYLGbV7OQjp1etOdg,2182
605
+ omlish/specs/jmespath/cli.py,sha256=6lCzF3wtFvcPGFjZuq9erypFTpX2Xzu4XtKSbV1meG4,2162
606
606
  omlish/specs/jmespath/exceptions.py,sha256=Co1HiUBPFNwFgZY3FV_ayuZoSgZIAmDcImImxauYNxc,4435
607
607
  omlish/specs/jmespath/functions.py,sha256=lE_MlW5rDQirDCE9HtcAG-17kuHhH36RaPaQfk97xDY,22595
608
608
  omlish/specs/jmespath/lexer.py,sha256=hlPGCXPzGhd9ySj-z2cGTbyC9z3e0Io78IMYJZSEwNk,12647
@@ -670,8 +670,7 @@ omlish/sql/queries/names.py,sha256=4sDvgRobMEt_6mDeuYVbCqHzLCOwpXUdEyyB4-QjxKo,1
670
670
  omlish/sql/queries/ops.py,sha256=B7IDfjr2DW5LJhWoNaY1WW90BJhe5ZtmxIELhWXbW-0,129
671
671
  omlish/sql/queries/params.py,sha256=iR8tnetkZFWY378iUbPe08d86g-Wf1J3YqfZr_KhIwQ,1175
672
672
  omlish/sql/queries/relations.py,sha256=7YrEC9IjoVpRGLAFKRSRsHHnTmx-g7hBNXsOgP2HOuI,2998
673
- omlish/sql/queries/rendering.py,sha256=8naCMwxVEFAJaMP5m2bf6kCyhvwFZhXiWYEma51fQ4k,6813
674
- omlish/sql/queries/rendering2.py,sha256=S7BD7i2tMEWdxOtvw-udWfk5nei-vV3hUghR7qEIL-I,6469
673
+ omlish/sql/queries/rendering.py,sha256=3oSwzx713J81V0JM4FnVgNpeHjaenoWrds41M9j__Dg,7328
675
674
  omlish/sql/queries/selects.py,sha256=RFySZ9sb-nE29QrLLbQ7JYZW_V_ifaFTcl-RQTgQncY,1369
676
675
  omlish/sql/queries/std.py,sha256=J2ZDfDyLzRm8q5-TLAN6I_qjhs-7RpfW23yuCYYLf5k,643
677
676
  omlish/sql/queries/stmts.py,sha256=pBqwD7dRlqMu6uh6vR3xaWOEgbZCcFWbOQ9ryYd17T4,441
@@ -734,9 +733,9 @@ omlish/text/mangle.py,sha256=kfzFLfvepH-chl1P89_mdc5vC4FSqyPA2aVtgzuB8IY,1133
734
733
  omlish/text/minja.py,sha256=jZC-fp3Xuhx48ppqsf2Sf1pHbC0t8XBB7UpUUoOk2Qw,5751
735
734
  omlish/text/parts.py,sha256=JkNZpyR2tv2CNcTaWJJhpQ9E4F0yPR8P_YfDbZfMtwQ,6182
736
735
  omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
737
- omlish-0.0.0.dev246.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
738
- omlish-0.0.0.dev246.dist-info/METADATA,sha256=da_rz6vvTRxwUkKvXh0ZlBAklAosQv_ZvmsnuiTE_E8,4176
739
- omlish-0.0.0.dev246.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
740
- omlish-0.0.0.dev246.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
741
- omlish-0.0.0.dev246.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
742
- omlish-0.0.0.dev246.dist-info/RECORD,,
736
+ omlish-0.0.0.dev247.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
737
+ omlish-0.0.0.dev247.dist-info/METADATA,sha256=82nI3LSDtkEUH8RynMRyrECBuyL-TP_WYtoC8UNk_OU,4176
738
+ omlish-0.0.0.dev247.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
739
+ omlish-0.0.0.dev247.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
740
+ omlish-0.0.0.dev247.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
741
+ omlish-0.0.0.dev247.dist-info/RECORD,,
@@ -1,248 +0,0 @@
1
- """
2
- TODO:
3
- - minimal parens
4
- - text.parts
5
- - QuoteStyle
6
- - ParamStyle
7
-
8
- ==
9
-
10
- def needs_parens(self, e: Expr) -> bool:
11
- if isinstance(e, (Literal, Ident, Name)):
12
- return True
13
- elif isinstance(e, Expr):
14
- return False
15
- else:
16
- raise TypeError(e)
17
- """
18
- import dataclasses as dc
19
- import typing as ta
20
-
21
- from ... import dispatch
22
- from ... import lang
23
- from ...text import parts as tp
24
- from ..params import ParamStyle
25
- from ..params import make_params_preparer
26
- from .base import Node
27
- from .binary import Binary
28
- from .binary import BinaryOp
29
- from .binary import BinaryOps
30
- from .exprs import Literal
31
- from .exprs import NameExpr
32
- from .idents import Ident
33
- from .inserts import Insert
34
- from .inserts import Values
35
- from .multi import Multi
36
- from .multi import MultiKind
37
- from .names import Name
38
- from .params import Param
39
- from .relations import Join
40
- from .relations import JoinKind
41
- from .relations import Table
42
- from .selects import Select
43
- from .selects import SelectItem
44
- from .unary import Unary
45
- from .unary import UnaryOp
46
- from .unary import UnaryOps
47
-
48
-
49
- @dc.dataclass(frozen=True)
50
- class RenderedQuery(lang.Final):
51
- t: tp.Part
52
- args: lang.Args
53
-
54
-
55
- class Renderer(lang.Abstract):
56
- def __init__(
57
- self,
58
- *,
59
- param_style: ParamStyle | None = None,
60
- ) -> None:
61
- super().__init__()
62
-
63
- self._param_style = param_style if param_style is not None else self.default_param_style
64
-
65
- self._params_preparer = make_params_preparer(self._param_style)
66
-
67
- default_param_style: ta.ClassVar[ParamStyle] = ParamStyle.PYFORMAT
68
-
69
- def args(self) -> lang.Args:
70
- return self._params_preparer.prepare()
71
-
72
- @dispatch.method
73
- def render(self, o: ta.Any) -> tp.Part:
74
- raise TypeError(o)
75
-
76
-
77
- class StdRenderer(Renderer):
78
- # parens
79
-
80
- NEEDS_PAREN_TYPES: ta.AbstractSet[type[Node]] = {
81
- Binary,
82
- # IsNull,
83
- # SelectExpr,
84
- }
85
-
86
- def needs_paren(self, node: Node) -> bool:
87
- return type(node) in self.NEEDS_PAREN_TYPES
88
-
89
- def paren(self, node: Node) -> tp.Part:
90
- return tp.Wrap(self.render(node)) if self.needs_paren(node) else self.render(node)
91
-
92
- # binary
93
-
94
- BINARY_OP_TO_STR: ta.ClassVar[ta.Mapping[BinaryOp, str]] = {
95
- BinaryOps.EQ: '=',
96
- BinaryOps.NE: '!=',
97
- BinaryOps.LT: '<',
98
- BinaryOps.LE: '<=',
99
- BinaryOps.GT: '>',
100
- BinaryOps.GE: '>=',
101
-
102
- BinaryOps.ADD: '+',
103
- BinaryOps.SUB: '-',
104
- BinaryOps.MUL: '*',
105
- BinaryOps.DIV: '/',
106
- BinaryOps.MOD: '%',
107
-
108
- BinaryOps.CONCAT: '||',
109
- }
110
-
111
- @Renderer.render.register
112
- def render_binary(self, o: Binary) -> tp.Part:
113
- return [
114
- self.paren(o.l),
115
- self.BINARY_OP_TO_STR[o.op],
116
- self.paren(o.r),
117
- ]
118
-
119
- # exprs
120
-
121
- @Renderer.render.register
122
- def render_literal(self, o: Literal) -> tp.Part:
123
- return repr(o.v)
124
-
125
- @Renderer.render.register
126
- def render_name_expr(self, o: NameExpr) -> tp.Part:
127
- return self.render(o.n)
128
-
129
- @Renderer.render.register
130
- def render_param(self, o: Param) -> tp.Part:
131
- return self._params_preparer.add(o.n if o.n is not None else id(o))
132
-
133
- # idents
134
-
135
- @Renderer.render.register
136
- def render_ident(self, o: Ident) -> tp.Part:
137
- return f'"{o.s}"'
138
-
139
- # inserts
140
-
141
- @Renderer.render.register
142
- def render_values(self, o: Values) -> tp.Part:
143
- return [
144
- 'values',
145
- tp.Wrap(tp.List([self.render(v) for v in o.vs])),
146
- ]
147
-
148
- @Renderer.render.register
149
- def render_insert(self, o: Insert) -> tp.Part:
150
- return [
151
- 'insert into',
152
- self.render(o.into),
153
- tp.Wrap(tp.List([self.render(c) for c in o.columns])),
154
- ]
155
-
156
- # multis
157
-
158
- MULTI_KIND_TO_STR: ta.ClassVar[ta.Mapping[MultiKind, str]] = {
159
- MultiKind.AND: 'and',
160
- MultiKind.OR: 'or',
161
- }
162
-
163
- @Renderer.render.register
164
- def render_multi(self, o: Multi) -> tp.Part:
165
- return tp.Wrap(tp.List(
166
- [self.render(e) for e in o.es],
167
- delimiter=' ' + self.MULTI_KIND_TO_STR[o.k], # FIXME: Part
168
- ))
169
-
170
- # names
171
-
172
- @Renderer.render.register
173
- def render_name(self, o: Name) -> tp.Part:
174
- out: list[tp.Part] = []
175
- for n, i in enumerate(o.ps):
176
- if n:
177
- out.append('.')
178
- out.append(self.render(i))
179
- return tp.Concat(out)
180
-
181
- # relations
182
-
183
- @Renderer.render.register
184
- def render_table(self, o: Table) -> tp.Part:
185
- return [
186
- self.render(o.n),
187
- *(['as', self.render(o.a)] if o.a is not None else []),
188
- ]
189
-
190
- JOIN_KIND_TO_STR: ta.ClassVar[ta.Mapping[JoinKind, str]] = {
191
- JoinKind.DEFAULT: 'join',
192
- JoinKind.INNER: 'inner join',
193
- JoinKind.LEFT: 'left join',
194
- JoinKind.LEFT_OUTER: 'left outer join',
195
- JoinKind.RIGHT: 'right join',
196
- JoinKind.RIGHT_OUTER: 'right outer join',
197
- JoinKind.FULL: 'full join',
198
- JoinKind.FULL_OUTER: 'full outer join',
199
- JoinKind.CROSS: 'cross join',
200
- JoinKind.NATURAL: 'natural join',
201
- }
202
-
203
- @Renderer.render.register
204
- def render_join(self, o: Join) -> tp.Part:
205
- return [
206
- self.render(o.l),
207
- self.JOIN_KIND_TO_STR[o.k],
208
- self.render(o.r),
209
- *(['on', self.render(o.c)] if o.c is not None else []),
210
- ]
211
-
212
- # selects
213
-
214
- @Renderer.render.register
215
- def render_select_item(self, o: SelectItem) -> tp.Part:
216
- return [
217
- self.render(o.v),
218
- *(['as', self.render(o.a)] if o.a is not None else []),
219
- ]
220
-
221
- @Renderer.render.register
222
- def render_select(self, o: Select) -> tp.Part:
223
- return [
224
- 'select',
225
- tp.List([self.render(i) for i in o.items]),
226
- *(['from', self.render(o.from_)] if o.from_ is not None else []),
227
- *(['where', self.render(o.where)] if o.where is not None else []),
228
- ]
229
-
230
- # unary
231
-
232
- UNARY_OP_TO_STR: ta.ClassVar[ta.Mapping[UnaryOp, tuple[str, str]]] = {
233
- UnaryOps.NOT: ('not ', ''),
234
- UnaryOps.IS_NULL: ('', ' is null'),
235
- UnaryOps.IS_NOT_NULL: ('', ' is not null'),
236
-
237
- UnaryOps.POS: ('+', ''),
238
- UnaryOps.NEG: ('-', ''),
239
- }
240
-
241
- @Renderer.render.register
242
- def render_unary(self, o: Unary) -> tp.Part:
243
- pfx, sfx = self.UNARY_OP_TO_STR[o.op]
244
- return tp.Concat([
245
- pfx,
246
- self.render(o.v),
247
- sfx,
248
- ])