omlish 0.0.0.dev133__py3-none-any.whl → 0.0.0.dev177__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/.manifests.json +265 -7
- omlish/__about__.py +5 -3
- omlish/antlr/_runtime/__init__.py +0 -22
- omlish/antlr/_runtime/_all.py +24 -0
- omlish/antlr/_runtime/atn/ParserATNSimulator.py +1 -1
- omlish/antlr/_runtime/dfa/DFASerializer.py +1 -1
- omlish/antlr/_runtime/error/DiagnosticErrorListener.py +2 -1
- omlish/antlr/_runtime/xpath/XPath.py +7 -1
- omlish/antlr/_runtime/xpath/XPathLexer.py +1 -1
- omlish/antlr/delimit.py +106 -0
- omlish/antlr/dot.py +31 -0
- omlish/antlr/errors.py +11 -0
- omlish/antlr/input.py +96 -0
- omlish/antlr/parsing.py +19 -0
- omlish/antlr/runtime.py +102 -0
- omlish/antlr/utils.py +38 -0
- omlish/argparse/all.py +45 -0
- omlish/{argparse.py → argparse/cli.py} +112 -107
- omlish/asyncs/__init__.py +0 -35
- omlish/asyncs/all.py +35 -0
- omlish/asyncs/asyncio/all.py +7 -0
- omlish/asyncs/asyncio/channels.py +40 -0
- omlish/asyncs/asyncio/streams.py +45 -0
- omlish/asyncs/asyncio/subprocesses.py +238 -0
- omlish/asyncs/asyncio/timeouts.py +16 -0
- omlish/asyncs/bluelet/LICENSE +6 -0
- omlish/asyncs/bluelet/all.py +67 -0
- omlish/asyncs/bluelet/api.py +23 -0
- omlish/asyncs/bluelet/core.py +178 -0
- omlish/asyncs/bluelet/events.py +78 -0
- omlish/asyncs/bluelet/files.py +80 -0
- omlish/asyncs/bluelet/runner.py +416 -0
- omlish/asyncs/bluelet/sockets.py +214 -0
- omlish/bootstrap/sys.py +3 -3
- omlish/cached.py +2 -2
- omlish/check.py +49 -460
- omlish/codecs/__init__.py +72 -0
- omlish/codecs/base.py +106 -0
- omlish/codecs/bytes.py +119 -0
- omlish/codecs/chain.py +23 -0
- omlish/codecs/funcs.py +39 -0
- omlish/codecs/registry.py +139 -0
- omlish/codecs/standard.py +4 -0
- omlish/codecs/text.py +217 -0
- omlish/collections/cache/impl.py +50 -57
- omlish/collections/coerce.py +1 -0
- omlish/collections/mappings.py +1 -1
- omlish/configs/flattening.py +1 -1
- omlish/defs.py +1 -1
- omlish/diag/_pycharm/runhack.py +8 -2
- omlish/diag/procfs.py +8 -8
- omlish/docker/__init__.py +0 -36
- omlish/docker/all.py +31 -0
- omlish/docker/consts.py +4 -0
- omlish/{lite/docker.py → docker/detect.py} +18 -0
- omlish/docker/{helpers.py → timebomb.py} +0 -21
- omlish/formats/cbor.py +31 -0
- omlish/formats/cloudpickle.py +31 -0
- omlish/formats/codecs.py +93 -0
- omlish/formats/json/codecs.py +29 -0
- omlish/formats/json/delimted.py +4 -0
- omlish/formats/json/stream/errors.py +2 -0
- omlish/formats/json/stream/lex.py +12 -6
- omlish/formats/json/stream/parse.py +38 -22
- omlish/formats/json5.py +31 -0
- omlish/formats/pickle.py +31 -0
- omlish/formats/repr.py +25 -0
- omlish/formats/toml.py +17 -0
- omlish/formats/yaml.py +25 -0
- omlish/funcs/__init__.py +0 -0
- omlish/{genmachine.py → funcs/genmachine.py} +5 -4
- omlish/{matchfns.py → funcs/match.py} +1 -1
- omlish/funcs/pairs.py +215 -0
- omlish/http/__init__.py +0 -48
- omlish/http/all.py +48 -0
- omlish/http/coro/__init__.py +0 -0
- omlish/{lite/fdio/corohttp.py → http/coro/fdio.py} +21 -19
- omlish/{lite/http/coroserver.py → http/coro/server.py} +20 -21
- omlish/{lite/http → http}/handlers.py +3 -2
- omlish/{lite/http → http}/parsing.py +1 -0
- omlish/http/sessions.py +1 -1
- omlish/{lite/http → http}/versions.py +1 -0
- omlish/inject/managed.py +2 -2
- omlish/io/__init__.py +0 -3
- omlish/{lite/io.py → io/buffers.py} +8 -9
- omlish/io/compress/__init__.py +9 -0
- omlish/io/compress/abc.py +104 -0
- omlish/io/compress/adapters.py +148 -0
- omlish/io/compress/base.py +24 -0
- omlish/io/compress/brotli.py +47 -0
- omlish/io/compress/bz2.py +61 -0
- omlish/io/compress/codecs.py +78 -0
- omlish/io/compress/gzip.py +350 -0
- omlish/io/compress/lz4.py +91 -0
- omlish/io/compress/lzma.py +81 -0
- omlish/io/compress/snappy.py +34 -0
- omlish/io/compress/zlib.py +74 -0
- omlish/io/compress/zstd.py +44 -0
- omlish/io/fdio/__init__.py +1 -0
- omlish/{lite → io}/fdio/handlers.py +5 -5
- omlish/{lite → io}/fdio/kqueue.py +8 -8
- omlish/{lite → io}/fdio/manager.py +7 -7
- omlish/{lite → io}/fdio/pollers.py +13 -13
- omlish/io/generators/__init__.py +56 -0
- omlish/io/generators/consts.py +1 -0
- omlish/io/generators/direct.py +13 -0
- omlish/io/generators/readers.py +189 -0
- omlish/io/generators/stepped.py +191 -0
- omlish/io/pyio.py +5 -2
- omlish/iterators/__init__.py +24 -0
- omlish/iterators/iterators.py +132 -0
- omlish/iterators/recipes.py +18 -0
- omlish/iterators/tools.py +96 -0
- omlish/iterators/unique.py +67 -0
- omlish/lang/__init__.py +13 -1
- omlish/lang/functions.py +11 -2
- omlish/lang/generators.py +243 -0
- omlish/lang/iterables.py +46 -49
- omlish/lang/maybes.py +4 -4
- omlish/lite/cached.py +39 -6
- omlish/lite/check.py +438 -75
- omlish/lite/contextmanagers.py +17 -4
- omlish/lite/dataclasses.py +42 -0
- omlish/lite/inject.py +28 -45
- omlish/lite/logs.py +0 -270
- omlish/lite/marshal.py +309 -144
- omlish/lite/pycharm.py +47 -0
- omlish/lite/reflect.py +33 -0
- omlish/lite/resources.py +8 -0
- omlish/lite/runtime.py +4 -4
- omlish/lite/shlex.py +12 -0
- omlish/lite/socketserver.py +2 -2
- omlish/lite/strings.py +31 -0
- omlish/logs/__init__.py +0 -32
- omlish/logs/{_abc.py → abc.py} +0 -1
- omlish/logs/all.py +37 -0
- omlish/logs/{formatters.py → color.py} +1 -2
- omlish/logs/configs.py +7 -38
- omlish/logs/filters.py +10 -0
- omlish/logs/handlers.py +4 -1
- omlish/logs/json.py +56 -0
- omlish/logs/proxy.py +99 -0
- omlish/logs/standard.py +128 -0
- omlish/logs/utils.py +2 -2
- omlish/manifests/__init__.py +2 -0
- omlish/manifests/load.py +209 -0
- omlish/manifests/types.py +17 -0
- omlish/marshal/base.py +1 -1
- omlish/marshal/factories.py +1 -1
- omlish/marshal/forbidden.py +1 -1
- omlish/marshal/iterables.py +1 -1
- omlish/marshal/literals.py +50 -0
- omlish/marshal/mappings.py +1 -1
- omlish/marshal/maybes.py +1 -1
- omlish/marshal/standard.py +5 -1
- omlish/marshal/unions.py +1 -1
- omlish/os/__init__.py +0 -0
- omlish/os/atomics.py +205 -0
- omlish/os/deathsig.py +23 -0
- omlish/{os.py → os/files.py} +0 -9
- omlish/{lite → os}/journald.py +2 -1
- omlish/os/linux.py +484 -0
- omlish/os/paths.py +36 -0
- omlish/{lite → os}/pidfile.py +1 -0
- omlish/os/sizes.py +9 -0
- omlish/reflect/__init__.py +3 -0
- omlish/reflect/subst.py +2 -1
- omlish/reflect/types.py +126 -44
- omlish/secrets/pwhash.py +1 -1
- omlish/secrets/subprocesses.py +3 -1
- omlish/specs/jsonrpc/marshal.py +1 -1
- omlish/specs/openapi/marshal.py +1 -1
- omlish/sql/alchemy/asyncs.py +1 -1
- omlish/sql/queries/__init__.py +9 -1
- omlish/sql/queries/building.py +3 -0
- omlish/sql/queries/exprs.py +10 -27
- omlish/sql/queries/idents.py +48 -10
- omlish/sql/queries/names.py +80 -13
- omlish/sql/queries/params.py +64 -0
- omlish/sql/queries/rendering.py +1 -1
- omlish/subprocesses.py +340 -0
- omlish/term.py +29 -14
- omlish/testing/pytest/marks.py +2 -2
- omlish/testing/pytest/plugins/asyncs.py +6 -1
- omlish/testing/pytest/plugins/logging.py +1 -1
- omlish/testing/pytest/plugins/switches.py +1 -1
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/METADATA +7 -5
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/RECORD +200 -117
- omlish/fnpairs.py +0 -496
- omlish/formats/json/cli/__main__.py +0 -11
- omlish/formats/json/cli/cli.py +0 -298
- omlish/formats/json/cli/formats.py +0 -71
- omlish/formats/json/cli/io.py +0 -74
- omlish/formats/json/cli/parsing.py +0 -82
- omlish/formats/json/cli/processing.py +0 -48
- omlish/formats/json/cli/rendering.py +0 -92
- omlish/iterators.py +0 -300
- omlish/lite/subprocesses.py +0 -130
- /omlish/{formats/json/cli → argparse}/__init__.py +0 -0
- /omlish/{lite/fdio → asyncs/asyncio}/__init__.py +0 -0
- /omlish/asyncs/{asyncio.py → asyncio/asyncio.py} +0 -0
- /omlish/{lite/http → asyncs/bluelet}/__init__.py +0 -0
- /omlish/collections/{_abc.py → abc.py} +0 -0
- /omlish/{fnpipes.py → funcs/pipes.py} +0 -0
- /omlish/io/{_abc.py → abc.py} +0 -0
- /omlish/sql/{_abc.py → abc.py} +0 -0
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/top_level.txt +0 -0
omlish/reflect/types.py
CHANGED
@@ -7,6 +7,7 @@ TODO:
|
|
7
7
|
- cache this shit, esp generic_mro shit
|
8
8
|
- cache __hash__ in Generic/Union
|
9
9
|
"""
|
10
|
+
import abc
|
10
11
|
import dataclasses as dc
|
11
12
|
import types
|
12
13
|
import typing as ta
|
@@ -17,11 +18,12 @@ _NoneType = types.NoneType # type: ignore
|
|
17
18
|
_NONE_TYPE_FROZENSET: frozenset['Type'] = frozenset([_NoneType])
|
18
19
|
|
19
20
|
|
20
|
-
|
21
|
+
_AnnotatedAlias = ta._AnnotatedAlias # type: ignore # noqa
|
21
22
|
_CallableGenericAlias = ta._CallableGenericAlias # type: ignore # noqa
|
23
|
+
_GenericAlias = ta._GenericAlias # type: ignore # noqa
|
24
|
+
_LiteralGenericAlias = ta._LiteralGenericAlias # type: ignore # noqa
|
22
25
|
_SpecialGenericAlias = ta._SpecialGenericAlias # type: ignore # noqa
|
23
26
|
_UnionGenericAlias = ta._UnionGenericAlias # type: ignore # noqa
|
24
|
-
_AnnotatedAlias = ta._AnnotatedAlias # type: ignore # noqa
|
25
27
|
|
26
28
|
|
27
29
|
##
|
@@ -116,19 +118,29 @@ def get_newtype_supertype(obj: ta.Any) -> ta.Any:
|
|
116
118
|
##
|
117
119
|
|
118
120
|
|
119
|
-
|
121
|
+
class TypeInfo(abc.ABC): # noqa
|
122
|
+
pass
|
123
|
+
|
124
|
+
|
125
|
+
Type: ta.TypeAlias = ta.Union[ # noqa
|
120
126
|
type,
|
121
127
|
ta.TypeVar,
|
122
|
-
|
123
|
-
'Generic',
|
124
|
-
'NewType',
|
125
|
-
'Annotated',
|
126
|
-
'Any',
|
128
|
+
TypeInfo,
|
127
129
|
]
|
128
130
|
|
129
131
|
|
132
|
+
TYPES: tuple[type, ...] = (
|
133
|
+
type,
|
134
|
+
ta.TypeVar,
|
135
|
+
TypeInfo,
|
136
|
+
)
|
137
|
+
|
138
|
+
|
139
|
+
##
|
140
|
+
|
141
|
+
|
130
142
|
@dc.dataclass(frozen=True)
|
131
|
-
class Union:
|
143
|
+
class Union(TypeInfo):
|
132
144
|
args: frozenset[Type]
|
133
145
|
|
134
146
|
@property
|
@@ -144,8 +156,11 @@ class Union:
|
|
144
156
|
return Union(rem)
|
145
157
|
|
146
158
|
|
159
|
+
#
|
160
|
+
|
161
|
+
|
147
162
|
@dc.dataclass(frozen=True)
|
148
|
-
class Generic:
|
163
|
+
class Generic(TypeInfo):
|
149
164
|
cls: type
|
150
165
|
args: tuple[Type, ...] # map[int, V] = (int, V) | map[T, T] = (T, T)
|
151
166
|
|
@@ -167,39 +182,51 @@ class Generic:
|
|
167
182
|
)
|
168
183
|
|
169
184
|
|
185
|
+
#
|
186
|
+
|
187
|
+
|
170
188
|
@dc.dataclass(frozen=True)
|
171
|
-
class NewType:
|
189
|
+
class NewType(TypeInfo):
|
172
190
|
obj: ta.Any
|
173
191
|
ty: Type
|
174
192
|
|
175
193
|
|
194
|
+
#
|
195
|
+
|
196
|
+
|
176
197
|
@dc.dataclass(frozen=True)
|
177
|
-
class Annotated:
|
198
|
+
class Annotated(TypeInfo):
|
178
199
|
ty: Type
|
179
200
|
md: ta.Sequence[ta.Any]
|
180
201
|
|
181
202
|
obj: ta.Any = dc.field(compare=False, repr=False)
|
182
203
|
|
183
204
|
|
184
|
-
|
205
|
+
#
|
206
|
+
|
207
|
+
|
208
|
+
@dc.dataclass(frozen=True)
|
209
|
+
class Literal(TypeInfo):
|
210
|
+
args: tuple[ta.Any, ...]
|
211
|
+
|
212
|
+
obj: ta.Any = dc.field(compare=False, repr=False)
|
213
|
+
|
214
|
+
|
215
|
+
#
|
216
|
+
|
217
|
+
|
218
|
+
class Any(TypeInfo):
|
185
219
|
pass
|
186
220
|
|
187
221
|
|
188
222
|
ANY = Any()
|
189
223
|
|
190
224
|
|
191
|
-
|
192
|
-
type,
|
193
|
-
ta.TypeVar,
|
194
|
-
Union,
|
195
|
-
Generic,
|
196
|
-
NewType,
|
197
|
-
Annotated,
|
198
|
-
Any,
|
199
|
-
)
|
225
|
+
##
|
200
226
|
|
201
227
|
|
202
|
-
|
228
|
+
class ReflectTypeError(TypeError):
|
229
|
+
pass
|
203
230
|
|
204
231
|
|
205
232
|
class Reflector:
|
@@ -212,57 +239,80 @@ class Reflector:
|
|
212
239
|
|
213
240
|
self._override = override
|
214
241
|
|
242
|
+
#
|
243
|
+
|
215
244
|
def is_type(self, obj: ta.Any) -> bool:
|
216
|
-
|
245
|
+
try:
|
246
|
+
self._type(obj, check_only=True)
|
247
|
+
except ReflectTypeError:
|
248
|
+
return False
|
249
|
+
else:
|
217
250
|
return True
|
218
251
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
isinstance(obj, ta.NewType) or # noqa
|
225
|
-
|
226
|
-
(
|
227
|
-
is_simple_generic_alias_type(oty) or
|
228
|
-
oty is _CallableGenericAlias
|
229
|
-
) or
|
252
|
+
def type(self, obj: ta.Any) -> Type:
|
253
|
+
if (ty := self._type(obj, check_only=False)) is None:
|
254
|
+
raise RuntimeError(obj)
|
255
|
+
return ty
|
230
256
|
|
231
|
-
|
257
|
+
#
|
232
258
|
|
233
|
-
|
234
|
-
|
259
|
+
def _type(self, obj: ta.Any, *, check_only: bool) -> Type | None:
|
260
|
+
##
|
261
|
+
# Overrides beat everything
|
235
262
|
|
236
|
-
def type(self, obj: ta.Any) -> Type:
|
237
263
|
if self._override is not None:
|
238
264
|
if (ovr := self._override(obj)) is not None:
|
239
265
|
return ovr
|
240
266
|
|
267
|
+
##
|
268
|
+
# Any
|
269
|
+
|
241
270
|
if obj is ta.Any:
|
242
271
|
return ANY
|
243
272
|
|
244
|
-
|
273
|
+
##
|
274
|
+
# Already a Type?
|
275
|
+
|
276
|
+
if isinstance(obj, (ta.TypeVar, TypeInfo)): # noqa
|
245
277
|
return obj
|
246
278
|
|
247
279
|
oty = type(obj)
|
248
280
|
|
281
|
+
##
|
282
|
+
# Union
|
283
|
+
|
249
284
|
if oty is _UnionGenericAlias or oty is types.UnionType:
|
285
|
+
if check_only:
|
286
|
+
return None
|
287
|
+
|
250
288
|
return Union(frozenset(self.type(a) for a in ta.get_args(obj)))
|
251
289
|
|
290
|
+
##
|
291
|
+
# NewType
|
292
|
+
|
252
293
|
if isinstance(obj, ta.NewType): # noqa
|
294
|
+
if check_only:
|
295
|
+
return None
|
296
|
+
|
253
297
|
return NewType(obj, get_newtype_supertype(obj))
|
254
298
|
|
299
|
+
##
|
300
|
+
# Simple Generic
|
301
|
+
|
255
302
|
if (
|
256
303
|
is_simple_generic_alias_type(oty) or
|
257
304
|
oty is _CallableGenericAlias
|
258
305
|
):
|
306
|
+
if check_only:
|
307
|
+
return None
|
308
|
+
|
259
309
|
origin = ta.get_origin(obj)
|
260
310
|
args = ta.get_args(obj)
|
261
311
|
|
262
312
|
if oty is _CallableGenericAlias:
|
263
313
|
p, r = args
|
264
314
|
if p is Ellipsis or isinstance(p, ta.ParamSpec):
|
265
|
-
raise
|
315
|
+
raise ReflectTypeError(f'Callable argument not yet supported for {obj=}')
|
266
316
|
args = (*p, r)
|
267
317
|
params = _KNOWN_SPECIAL_TYPE_VARS[:len(args)]
|
268
318
|
|
@@ -276,7 +326,7 @@ class Reflector:
|
|
276
326
|
params = get_params(origin)
|
277
327
|
|
278
328
|
if len(args) != len(params):
|
279
|
-
raise
|
329
|
+
raise ReflectTypeError(f'Mismatched {args=} and {params=} for {obj=}')
|
280
330
|
|
281
331
|
return Generic(
|
282
332
|
origin,
|
@@ -285,7 +335,13 @@ class Reflector:
|
|
285
335
|
obj,
|
286
336
|
)
|
287
337
|
|
338
|
+
##
|
339
|
+
# Full Generic
|
340
|
+
|
288
341
|
if isinstance(obj, type):
|
342
|
+
if check_only:
|
343
|
+
return None
|
344
|
+
|
289
345
|
if issubclass(obj, ta.Generic): # type: ignore
|
290
346
|
params = get_params(obj)
|
291
347
|
if params:
|
@@ -295,12 +351,20 @@ class Reflector:
|
|
295
351
|
params,
|
296
352
|
obj,
|
297
353
|
)
|
354
|
+
|
298
355
|
return obj
|
299
356
|
|
357
|
+
##
|
358
|
+
# Special Generic
|
359
|
+
|
300
360
|
if isinstance(obj, _SpecialGenericAlias):
|
301
361
|
if (ks := _KNOWN_SPECIALS_BY_ALIAS.get(obj)) is not None:
|
362
|
+
if check_only:
|
363
|
+
return None
|
364
|
+
|
302
365
|
if (np := ks.nparams) < 0:
|
303
|
-
raise
|
366
|
+
raise ReflectTypeError(obj)
|
367
|
+
|
304
368
|
params = _KNOWN_SPECIAL_TYPE_VARS[:np]
|
305
369
|
return Generic(
|
306
370
|
ks.origin,
|
@@ -309,11 +373,29 @@ class Reflector:
|
|
309
373
|
obj,
|
310
374
|
)
|
311
375
|
|
376
|
+
##
|
377
|
+
# Annotated
|
378
|
+
|
312
379
|
if isinstance(obj, _AnnotatedAlias):
|
380
|
+
if check_only:
|
381
|
+
return None
|
382
|
+
|
313
383
|
o = ta.get_args(obj)[0]
|
314
384
|
return Annotated(self.type(o), md=obj.__metadata__, obj=obj)
|
315
385
|
|
316
|
-
|
386
|
+
##
|
387
|
+
# Literal
|
388
|
+
|
389
|
+
if isinstance(obj, _LiteralGenericAlias):
|
390
|
+
if check_only:
|
391
|
+
return None
|
392
|
+
|
393
|
+
return Literal(ta.get_args(obj), obj=obj)
|
394
|
+
|
395
|
+
##
|
396
|
+
# Failure
|
397
|
+
|
398
|
+
raise ReflectTypeError(obj)
|
317
399
|
|
318
400
|
|
319
401
|
DEFAULT_REFLECTOR = Reflector()
|
omlish/secrets/pwhash.py
CHANGED
omlish/secrets/subprocesses.py
CHANGED
@@ -32,7 +32,9 @@ def pipe_fd_subprocess_file_input(buf: bytes) -> ta.Iterator[SubprocessFileInput
|
|
32
32
|
try:
|
33
33
|
if hasattr(fcntl, 'F_SETPIPE_SZ'):
|
34
34
|
fcntl.fcntl(wfd, fcntl.F_SETPIPE_SZ, max(len(buf), 0x1000))
|
35
|
-
os.write(wfd, buf)
|
35
|
+
n = os.write(wfd, buf)
|
36
|
+
if n != len(buf):
|
37
|
+
raise OSError(f'Failed to write data to pipe: {n=} {len(buf)=}')
|
36
38
|
os.close(wfd)
|
37
39
|
closed_wfd = True
|
38
40
|
yield SubprocessFileInput(f'/dev/fd/{rfd}', [rfd])
|
omlish/specs/jsonrpc/marshal.py
CHANGED
omlish/specs/openapi/marshal.py
CHANGED
omlish/sql/alchemy/asyncs.py
CHANGED
omlish/sql/queries/__init__.py
CHANGED
@@ -22,13 +22,13 @@ from .exprs import ( # noqa
|
|
22
22
|
ExprBuilder,
|
23
23
|
Literal,
|
24
24
|
NameExpr,
|
25
|
-
Param,
|
26
25
|
)
|
27
26
|
|
28
27
|
from .idents import ( # noqa
|
29
28
|
CanIdent,
|
30
29
|
Ident,
|
31
30
|
IdentBuilder,
|
31
|
+
IdentLike,
|
32
32
|
)
|
33
33
|
|
34
34
|
from .multi import ( # noqa
|
@@ -41,12 +41,20 @@ from .names import ( # noqa
|
|
41
41
|
CanName,
|
42
42
|
Name,
|
43
43
|
NameBuilder,
|
44
|
+
NameLike,
|
44
45
|
)
|
45
46
|
|
46
47
|
from .ops import ( # noqa
|
47
48
|
OpKind,
|
48
49
|
)
|
49
50
|
|
51
|
+
from .params import ( # noqa
|
52
|
+
CanParam,
|
53
|
+
Param,
|
54
|
+
ParamBuilder,
|
55
|
+
as_param,
|
56
|
+
)
|
57
|
+
|
50
58
|
from .relations import ( # noqa
|
51
59
|
CanRelation,
|
52
60
|
CanTable,
|
omlish/sql/queries/building.py
CHANGED
@@ -5,6 +5,7 @@ from .idents import IdentBuilder
|
|
5
5
|
from .inserts import InsertBuilder
|
6
6
|
from .multi import MultiBuilder
|
7
7
|
from .names import NameBuilder
|
8
|
+
from .params import ParamBuilder
|
8
9
|
from .relations import RelationBuilder
|
9
10
|
from .selects import SelectBuilder
|
10
11
|
from .stmts import StmtBuilder
|
@@ -23,6 +24,8 @@ class StdBuilder(
|
|
23
24
|
|
24
25
|
RelationBuilder,
|
25
26
|
|
27
|
+
ParamBuilder,
|
28
|
+
|
26
29
|
NameBuilder,
|
27
30
|
IdentBuilder,
|
28
31
|
|
omlish/sql/queries/exprs.py
CHANGED
@@ -8,10 +8,11 @@ import typing as ta
|
|
8
8
|
from ... import lang
|
9
9
|
from .base import Node
|
10
10
|
from .base import Value
|
11
|
-
from .idents import
|
11
|
+
from .idents import IdentLike
|
12
12
|
from .names import CanName
|
13
13
|
from .names import Name
|
14
14
|
from .names import NameBuilder
|
15
|
+
from .names import NameLike
|
15
16
|
|
16
17
|
|
17
18
|
##
|
@@ -21,30 +22,21 @@ class Expr(Node, lang.Abstract):
|
|
21
22
|
pass
|
22
23
|
|
23
24
|
|
25
|
+
#
|
26
|
+
|
27
|
+
|
24
28
|
class Literal(Expr, lang.Final):
|
25
29
|
v: Value
|
26
30
|
|
27
31
|
|
28
|
-
|
29
|
-
n: Name
|
32
|
+
#
|
30
33
|
|
31
34
|
|
32
|
-
class
|
33
|
-
n:
|
35
|
+
class NameExpr(Expr, lang.Final):
|
36
|
+
n: Name
|
34
37
|
|
35
|
-
def __repr__(self) -> str:
|
36
|
-
if self.n is not None:
|
37
|
-
return f'{self.__class__.__name__}({self.n!r})'
|
38
|
-
else:
|
39
|
-
return f'{self.__class__.__name__}(@{hex(id(self))[2:]})'
|
40
38
|
|
41
|
-
|
42
|
-
if not isinstance(other, Param):
|
43
|
-
return False
|
44
|
-
if self.n is None and other.n is None:
|
45
|
-
return self is other
|
46
|
-
else:
|
47
|
-
return self.n == other.n
|
39
|
+
##
|
48
40
|
|
49
41
|
|
50
42
|
CanLiteral: ta.TypeAlias = Literal | Value
|
@@ -69,7 +61,7 @@ class ExprBuilder(NameBuilder):
|
|
69
61
|
def expr(self, o: CanExpr) -> Expr:
|
70
62
|
if isinstance(o, Expr):
|
71
63
|
return o
|
72
|
-
elif isinstance(o, (
|
64
|
+
elif isinstance(o, (NameLike, IdentLike)):
|
73
65
|
return NameExpr(self.name(o))
|
74
66
|
else:
|
75
67
|
return self.literal(o)
|
@@ -77,12 +69,3 @@ class ExprBuilder(NameBuilder):
|
|
77
69
|
@ta.final
|
78
70
|
def e(self, o: CanExpr) -> Expr:
|
79
71
|
return self.expr(o)
|
80
|
-
|
81
|
-
#
|
82
|
-
|
83
|
-
def param(self, n: str | None = None) -> Param:
|
84
|
-
return Param(n)
|
85
|
-
|
86
|
-
@ta.final
|
87
|
-
def p(self, n: str | None = None) -> Param:
|
88
|
-
return self.param(n)
|
omlish/sql/queries/idents.py
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import abc
|
2
|
+
import functools
|
1
3
|
import typing as ta
|
2
4
|
|
3
5
|
from ... import lang
|
@@ -8,22 +10,58 @@ from .base import Node
|
|
8
10
|
##
|
9
11
|
|
10
12
|
|
11
|
-
class
|
13
|
+
class IdentLike(abc.ABC): # noqa
|
14
|
+
pass
|
15
|
+
|
16
|
+
|
17
|
+
##
|
18
|
+
|
19
|
+
|
20
|
+
class Ident(Node, IdentLike, lang.Final):
|
12
21
|
s: str
|
13
22
|
|
14
23
|
|
15
|
-
|
24
|
+
##
|
25
|
+
|
26
|
+
|
27
|
+
@functools.singledispatch
|
28
|
+
def as_ident(o: ta.Any) -> Ident:
|
29
|
+
raise TypeError(o)
|
30
|
+
|
31
|
+
|
32
|
+
@as_ident.register
|
33
|
+
def _(i: Ident) -> Ident:
|
34
|
+
return i
|
35
|
+
|
36
|
+
|
37
|
+
@as_ident.register
|
38
|
+
def _(s: str) -> Ident:
|
39
|
+
return Ident(s)
|
40
|
+
|
41
|
+
|
42
|
+
##
|
43
|
+
|
44
|
+
|
45
|
+
CanIdent: ta.TypeAlias = IdentLike | Ident | str
|
46
|
+
|
47
|
+
|
48
|
+
class IdentAccessor(lang.Final):
|
49
|
+
def __getattr__(self, s: str) -> Ident:
|
50
|
+
return Ident(s)
|
51
|
+
|
52
|
+
def __call__(self, o: CanIdent) -> Ident:
|
53
|
+
return as_ident(o)
|
54
|
+
|
55
|
+
|
56
|
+
##
|
16
57
|
|
17
58
|
|
18
59
|
class IdentBuilder(Builder):
|
60
|
+
@ta.final
|
19
61
|
def ident(self, o: CanIdent) -> Ident:
|
20
|
-
|
21
|
-
return o
|
22
|
-
elif isinstance(o, str):
|
23
|
-
return Ident(o)
|
24
|
-
else:
|
25
|
-
raise TypeError(o)
|
62
|
+
return as_ident(o)
|
26
63
|
|
27
64
|
@ta.final
|
28
|
-
|
29
|
-
|
65
|
+
@property
|
66
|
+
def i(self) -> IdentAccessor:
|
67
|
+
return IdentAccessor()
|
omlish/sql/queries/names.py
CHANGED
@@ -1,34 +1,101 @@
|
|
1
|
+
import abc
|
2
|
+
import functools
|
1
3
|
import typing as ta
|
2
4
|
|
5
|
+
from ... import check
|
3
6
|
from ... import dataclasses as dc
|
4
7
|
from ... import lang
|
5
8
|
from .base import Node
|
6
9
|
from .idents import CanIdent
|
7
10
|
from .idents import Ident
|
8
11
|
from .idents import IdentBuilder
|
12
|
+
from .idents import as_ident
|
9
13
|
|
10
14
|
|
11
15
|
##
|
12
16
|
|
13
17
|
|
14
|
-
class
|
15
|
-
|
18
|
+
class NameLike(abc.ABC): # noqa
|
19
|
+
pass
|
16
20
|
|
17
21
|
|
18
|
-
|
22
|
+
##
|
23
|
+
|
24
|
+
|
25
|
+
def _coerce_name_parts(o: ta.Iterable[Ident]) -> ta.Sequence[Ident]:
|
26
|
+
check.not_isinstance(o, str)
|
27
|
+
return check.not_empty(tuple(check.isinstance(e, Ident) for e in o))
|
28
|
+
|
29
|
+
|
30
|
+
class Name(Node, NameLike, lang.Final):
|
31
|
+
ps: ta.Sequence[Ident] = dc.xfield(coerce=_coerce_name_parts)
|
32
|
+
|
33
|
+
|
34
|
+
##
|
35
|
+
|
36
|
+
|
37
|
+
@functools.singledispatch
|
38
|
+
def as_name(o: ta.Any) -> Name:
|
39
|
+
if isinstance(o, ta.Sequence):
|
40
|
+
return Name([as_ident(p) for p in o])
|
41
|
+
else:
|
42
|
+
raise TypeError(o)
|
43
|
+
|
44
|
+
|
45
|
+
@as_name.register
|
46
|
+
def _(n: Name) -> Name:
|
47
|
+
return n
|
48
|
+
|
49
|
+
|
50
|
+
@as_name.register
|
51
|
+
def _(o: Ident | str) -> Name:
|
52
|
+
return Name([as_ident(o)])
|
53
|
+
|
54
|
+
|
55
|
+
##
|
56
|
+
|
57
|
+
|
58
|
+
CanName: ta.TypeAlias = ta.Union[
|
59
|
+
NameLike,
|
60
|
+
Name,
|
61
|
+
CanIdent,
|
62
|
+
ta.Sequence[CanIdent],
|
63
|
+
'NameAccessor',
|
64
|
+
]
|
65
|
+
|
66
|
+
|
67
|
+
class NameAccessor(NameLike, lang.Final):
|
68
|
+
def __init__(self, ps: tuple[str, ...] = ()) -> None:
|
69
|
+
super().__init__()
|
70
|
+
self.__query_name_parts__ = ps
|
71
|
+
|
72
|
+
def __repr__(self) -> str:
|
73
|
+
return f'{self.__class__.__name__}({self.__query_name_parts__!r})'
|
74
|
+
|
75
|
+
def __getattr__(self, s: str) -> 'NameAccessor':
|
76
|
+
return NameAccessor((*self.__query_name_parts__, s))
|
77
|
+
|
78
|
+
def __call__(self, o: CanName) -> Name:
|
79
|
+
n = as_name(o)
|
80
|
+
if (ps := self.__query_name_parts__):
|
81
|
+
n = Name(tuple(*tuple(Ident(p) for p in ps), *n.ps)) # type: ignore[arg-type]
|
82
|
+
return n
|
83
|
+
|
84
|
+
|
85
|
+
@as_name.register
|
86
|
+
def _(a: NameAccessor) -> Name:
|
87
|
+
return Name(tuple(Ident(p) for p in a.__query_name_parts__))
|
88
|
+
|
89
|
+
|
90
|
+
##
|
19
91
|
|
20
92
|
|
21
93
|
class NameBuilder(IdentBuilder):
|
94
|
+
@ta.final
|
22
95
|
def name(self, o: CanName) -> Name:
|
23
|
-
|
24
|
-
return o
|
25
|
-
elif isinstance(o, (Ident, str)):
|
26
|
-
return Name([self.ident(o)])
|
27
|
-
elif isinstance(o, ta.Sequence):
|
28
|
-
return Name([self.ident(p) for p in o])
|
29
|
-
else:
|
30
|
-
raise TypeError(o)
|
96
|
+
return as_name(o)
|
31
97
|
|
32
98
|
@ta.final
|
33
|
-
|
34
|
-
|
99
|
+
@property
|
100
|
+
def n(self) -> NameAccessor:
|
101
|
+
return NameAccessor()
|