omlish 0.0.0.dev447__py3-none-any.whl → 0.0.0.dev493__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.

Potentially problematic release.


This version of omlish might be problematic. Click here for more details.

Files changed (265) hide show
  1. omlish/.omlish-manifests.json +12 -0
  2. omlish/README.md +199 -0
  3. omlish/__about__.py +21 -16
  4. omlish/argparse/all.py +17 -9
  5. omlish/argparse/cli.py +16 -3
  6. omlish/argparse/utils.py +21 -0
  7. omlish/asyncs/asyncio/rlock.py +110 -0
  8. omlish/asyncs/asyncio/sync.py +43 -0
  9. omlish/asyncs/asyncio/utils.py +2 -0
  10. omlish/asyncs/sync.py +25 -0
  11. omlish/bootstrap/_marshal.py +1 -1
  12. omlish/bootstrap/diag.py +12 -21
  13. omlish/bootstrap/main.py +2 -5
  14. omlish/bootstrap/sys.py +27 -28
  15. omlish/cexts/__init__.py +0 -0
  16. omlish/cexts/include/omlish/omlish.hh +1 -0
  17. omlish/collections/__init__.py +13 -1
  18. omlish/collections/attrregistry.py +210 -0
  19. omlish/collections/cache/impl.py +1 -0
  20. omlish/collections/identity.py +1 -0
  21. omlish/collections/mappings.py +28 -0
  22. omlish/collections/trie.py +5 -1
  23. omlish/collections/utils.py +77 -0
  24. omlish/concurrent/all.py +2 -1
  25. omlish/concurrent/futures.py +25 -0
  26. omlish/concurrent/threadlets.py +1 -1
  27. omlish/daemons/reparent.py +2 -3
  28. omlish/daemons/spawning.py +2 -3
  29. omlish/dataclasses/__init__.py +2 -0
  30. omlish/dataclasses/impl/api/classes/decorator.py +3 -0
  31. omlish/dataclasses/impl/api/classes/make.py +3 -0
  32. omlish/dataclasses/impl/concerns/repr.py +15 -2
  33. omlish/dataclasses/impl/configs.py +97 -37
  34. omlish/dataclasses/impl/generation/compilation.py +21 -19
  35. omlish/dataclasses/impl/generation/globals.py +1 -0
  36. omlish/dataclasses/impl/generation/ops.py +1 -0
  37. omlish/dataclasses/impl/generation/plans.py +2 -17
  38. omlish/dataclasses/impl/generation/processor.py +106 -25
  39. omlish/dataclasses/impl/processing/base.py +8 -0
  40. omlish/dataclasses/impl/processing/driving.py +19 -7
  41. omlish/dataclasses/specs.py +1 -0
  42. omlish/dataclasses/tools/modifiers.py +5 -0
  43. omlish/diag/_pycharm/runhack.py +1 -1
  44. omlish/diag/cmds/__init__.py +0 -0
  45. omlish/diag/{lslocks.py → cmds/lslocks.py} +6 -6
  46. omlish/diag/{lsof.py → cmds/lsof.py} +6 -6
  47. omlish/diag/{ps.py → cmds/ps.py} +6 -6
  48. omlish/diag/pycharm.py +16 -2
  49. omlish/diag/pydevd.py +58 -40
  50. omlish/diag/replserver/console.py +1 -1
  51. omlish/dispatch/__init__.py +18 -12
  52. omlish/dispatch/methods.py +50 -140
  53. omlish/dom/rendering.py +1 -1
  54. omlish/formats/dotenv.py +1 -1
  55. omlish/formats/json/stream/__init__.py +13 -0
  56. omlish/funcs/guard.py +225 -0
  57. omlish/graphs/dot/rendering.py +1 -1
  58. omlish/http/all.py +44 -4
  59. omlish/http/clients/asyncs.py +33 -27
  60. omlish/http/clients/base.py +17 -1
  61. omlish/http/clients/coro/__init__.py +0 -0
  62. omlish/http/clients/coro/sync.py +171 -0
  63. omlish/http/clients/default.py +208 -29
  64. omlish/http/clients/executor.py +56 -0
  65. omlish/http/clients/httpx.py +72 -11
  66. omlish/http/clients/middleware.py +181 -0
  67. omlish/http/clients/sync.py +33 -27
  68. omlish/http/clients/syncasync.py +49 -0
  69. omlish/http/clients/urllib.py +6 -3
  70. omlish/http/coro/client/connection.py +15 -6
  71. omlish/http/coro/io.py +2 -0
  72. omlish/http/flasky/__init__.py +40 -0
  73. omlish/http/flasky/_compat.py +2 -0
  74. omlish/http/flasky/api.py +82 -0
  75. omlish/http/flasky/app.py +203 -0
  76. omlish/http/flasky/cvs.py +59 -0
  77. omlish/http/flasky/requests.py +20 -0
  78. omlish/http/flasky/responses.py +23 -0
  79. omlish/http/flasky/routes.py +23 -0
  80. omlish/http/flasky/types.py +15 -0
  81. omlish/http/urls.py +67 -0
  82. omlish/inject/__init__.py +57 -29
  83. omlish/inject/_dataclasses.py +5148 -0
  84. omlish/inject/binder.py +11 -52
  85. omlish/inject/eagers.py +2 -0
  86. omlish/inject/elements.py +27 -0
  87. omlish/inject/helpers/__init__.py +0 -0
  88. omlish/inject/{utils.py → helpers/constfn.py} +3 -3
  89. omlish/inject/{tags.py → helpers/id.py} +2 -2
  90. omlish/inject/helpers/late.py +76 -0
  91. omlish/inject/{managed.py → helpers/managed.py} +10 -10
  92. omlish/inject/helpers/multis.py +143 -0
  93. omlish/inject/helpers/wrappers.py +54 -0
  94. omlish/inject/impl/elements.py +54 -21
  95. omlish/inject/impl/injector.py +29 -25
  96. omlish/inject/impl/inspect.py +10 -1
  97. omlish/inject/impl/maysync.py +3 -4
  98. omlish/inject/impl/multis.py +3 -0
  99. omlish/inject/impl/sync.py +3 -4
  100. omlish/inject/injector.py +31 -2
  101. omlish/inject/inspect.py +35 -0
  102. omlish/inject/maysync.py +2 -4
  103. omlish/inject/multis.py +8 -0
  104. omlish/inject/overrides.py +3 -3
  105. omlish/inject/privates.py +6 -0
  106. omlish/inject/providers.py +3 -2
  107. omlish/inject/sync.py +5 -4
  108. omlish/io/buffers.py +118 -0
  109. omlish/io/readers.py +29 -0
  110. omlish/iterators/transforms.py +2 -2
  111. omlish/lang/__init__.py +180 -97
  112. omlish/lang/_asyncs.cc +186 -0
  113. omlish/lang/asyncs.py +17 -0
  114. omlish/lang/casing.py +11 -0
  115. omlish/lang/contextmanagers.py +28 -4
  116. omlish/lang/functions.py +31 -22
  117. omlish/lang/imports/_capture.cc +11 -9
  118. omlish/lang/imports/capture.py +363 -170
  119. omlish/lang/imports/proxy.py +455 -152
  120. omlish/lang/lazyglobals.py +22 -9
  121. omlish/lang/params.py +17 -0
  122. omlish/lang/recursion.py +0 -1
  123. omlish/lang/sequences.py +124 -0
  124. omlish/lifecycles/README.md +30 -0
  125. omlish/lifecycles/__init__.py +87 -13
  126. omlish/lifecycles/_dataclasses.py +1388 -0
  127. omlish/lifecycles/base.py +178 -64
  128. omlish/lifecycles/contextmanagers.py +113 -4
  129. omlish/lifecycles/controller.py +150 -87
  130. omlish/lifecycles/injection.py +143 -0
  131. omlish/lifecycles/listeners.py +56 -0
  132. omlish/lifecycles/managed.py +142 -0
  133. omlish/lifecycles/manager.py +218 -93
  134. omlish/lifecycles/states.py +2 -0
  135. omlish/lifecycles/transitions.py +3 -0
  136. omlish/lifecycles/unwrap.py +57 -0
  137. omlish/lite/abstract.py +54 -24
  138. omlish/lite/asyncs.py +2 -2
  139. omlish/lite/attrops.py +2 -0
  140. omlish/lite/contextmanagers.py +4 -4
  141. omlish/lite/dataclasses.py +44 -0
  142. omlish/lite/maybes.py +8 -0
  143. omlish/lite/maysync.py +1 -5
  144. omlish/lite/pycharm.py +1 -1
  145. omlish/lite/typing.py +24 -0
  146. omlish/logs/_amalg.py +1 -1
  147. omlish/logs/all.py +25 -11
  148. omlish/logs/asyncs.py +73 -0
  149. omlish/logs/base.py +101 -12
  150. omlish/logs/contexts.py +4 -1
  151. omlish/logs/lists.py +125 -0
  152. omlish/logs/modules.py +19 -1
  153. omlish/logs/std/loggers.py +6 -1
  154. omlish/logs/std/noisy.py +11 -9
  155. omlish/logs/{standard.py → std/standard.py} +3 -4
  156. omlish/logs/utils.py +17 -2
  157. omlish/manifests/loading.py +2 -1
  158. omlish/marshal/__init__.py +33 -13
  159. omlish/marshal/_dataclasses.py +2774 -0
  160. omlish/marshal/base/configs.py +12 -0
  161. omlish/marshal/base/contexts.py +36 -21
  162. omlish/marshal/base/funcs.py +8 -11
  163. omlish/marshal/base/options.py +8 -0
  164. omlish/marshal/base/registries.py +146 -44
  165. omlish/marshal/base/types.py +40 -16
  166. omlish/marshal/composite/iterables.py +33 -20
  167. omlish/marshal/composite/literals.py +20 -18
  168. omlish/marshal/composite/mappings.py +36 -23
  169. omlish/marshal/composite/maybes.py +29 -19
  170. omlish/marshal/composite/newtypes.py +16 -16
  171. omlish/marshal/composite/optionals.py +14 -14
  172. omlish/marshal/composite/special.py +15 -15
  173. omlish/marshal/composite/unions/__init__.py +0 -0
  174. omlish/marshal/composite/unions/literals.py +93 -0
  175. omlish/marshal/composite/unions/primitives.py +103 -0
  176. omlish/marshal/factories/invalidate.py +18 -68
  177. omlish/marshal/factories/method.py +26 -0
  178. omlish/marshal/factories/moduleimport/factories.py +22 -65
  179. omlish/marshal/factories/multi.py +13 -25
  180. omlish/marshal/factories/recursive.py +42 -56
  181. omlish/marshal/factories/typecache.py +29 -74
  182. omlish/marshal/factories/typemap.py +42 -43
  183. omlish/marshal/objects/dataclasses.py +129 -106
  184. omlish/marshal/objects/marshal.py +18 -14
  185. omlish/marshal/objects/namedtuples.py +48 -42
  186. omlish/marshal/objects/unmarshal.py +19 -15
  187. omlish/marshal/polymorphism/marshal.py +9 -11
  188. omlish/marshal/polymorphism/metadata.py +16 -5
  189. omlish/marshal/polymorphism/standard.py +13 -1
  190. omlish/marshal/polymorphism/unions.py +15 -105
  191. omlish/marshal/polymorphism/unmarshal.py +9 -10
  192. omlish/marshal/singular/enums.py +14 -18
  193. omlish/marshal/standard.py +10 -6
  194. omlish/marshal/trivial/any.py +1 -1
  195. omlish/marshal/trivial/forbidden.py +21 -26
  196. omlish/metadata.py +23 -1
  197. omlish/os/forkhooks.py +4 -0
  198. omlish/os/pidfiles/pinning.py +2 -2
  199. omlish/reflect/__init__.py +43 -26
  200. omlish/reflect/ops.py +10 -1
  201. omlish/reflect/types.py +1 -0
  202. omlish/secrets/marshal.py +1 -1
  203. omlish/specs/jmespath/__init__.py +12 -3
  204. omlish/specs/jmespath/_dataclasses.py +2893 -0
  205. omlish/specs/jmespath/ast.py +1 -1
  206. omlish/specs/jsonrpc/__init__.py +13 -0
  207. omlish/specs/jsonrpc/_marshal.py +32 -23
  208. omlish/specs/jsonrpc/conns.py +10 -7
  209. omlish/specs/jsonschema/_marshal.py +1 -1
  210. omlish/specs/jsonschema/keywords/__init__.py +7 -0
  211. omlish/specs/jsonschema/keywords/_dataclasses.py +1644 -0
  212. omlish/specs/openapi/_marshal.py +31 -22
  213. omlish/sql/__init__.py +24 -5
  214. omlish/sql/{tabledefs/alchemy.py → alchemy/tabledefs.py} +2 -2
  215. omlish/sql/api/dbapi.py +1 -1
  216. omlish/sql/dbapi/__init__.py +15 -0
  217. omlish/sql/{dbapi.py → dbapi/drivers.py} +2 -2
  218. omlish/sql/queries/__init__.py +3 -0
  219. omlish/sql/queries/_marshal.py +2 -2
  220. omlish/sql/queries/rendering.py +1 -1
  221. omlish/sql/tabledefs/_marshal.py +1 -1
  222. omlish/subprocesses/base.py +4 -0
  223. omlish/subprocesses/editor.py +1 -1
  224. omlish/sync.py +155 -21
  225. omlish/term/alt.py +60 -0
  226. omlish/term/confirm.py +8 -8
  227. omlish/term/pager.py +235 -0
  228. omlish/term/terminfo.py +935 -0
  229. omlish/term/termstate.py +67 -0
  230. omlish/term/vt100/terminal.py +0 -3
  231. omlish/testing/pytest/plugins/asyncs/fixtures.py +4 -1
  232. omlish/testing/pytest/plugins/asyncs/plugin.py +2 -0
  233. omlish/testing/pytest/plugins/skips.py +2 -1
  234. omlish/testing/unittest/main.py +3 -3
  235. omlish/text/docwrap/__init__.py +3 -0
  236. omlish/text/docwrap/__main__.py +11 -0
  237. omlish/text/docwrap/api.py +83 -0
  238. omlish/text/docwrap/cli.py +91 -0
  239. omlish/text/docwrap/groups.py +84 -0
  240. omlish/text/docwrap/lists.py +167 -0
  241. omlish/text/docwrap/parts.py +146 -0
  242. omlish/text/docwrap/reflowing.py +106 -0
  243. omlish/text/docwrap/rendering.py +151 -0
  244. omlish/text/docwrap/utils.py +11 -0
  245. omlish/text/docwrap/wrapping.py +59 -0
  246. omlish/text/filecache.py +2 -2
  247. omlish/text/lorem.py +6 -0
  248. omlish/text/parts.py +2 -2
  249. omlish/text/textwrap.py +51 -0
  250. omlish/typedvalues/marshal.py +85 -59
  251. omlish/typedvalues/values.py +2 -1
  252. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/METADATA +36 -32
  253. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/RECORD +260 -199
  254. omlish/dataclasses/impl/generation/mangling.py +0 -18
  255. omlish/funcs/match.py +0 -227
  256. omlish/lifecycles/abstract.py +0 -86
  257. omlish/marshal/factories/match.py +0 -34
  258. omlish/marshal/factories/simple.py +0 -28
  259. /omlish/inject/{impl → helpers}/proxy.py +0 -0
  260. /omlish/inject/impl/{providers2.py → providersmap.py} +0 -0
  261. /omlish/sql/{abc.py → dbapi/abc.py} +0 -0
  262. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/WHEEL +0 -0
  263. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/entry_points.txt +0 -0
  264. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/licenses/LICENSE +0 -0
  265. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,6 @@ from ... import dataclasses as dc
5
5
  from ... import lang
6
6
  from ... import marshal as msh
7
7
  from ... import reflect as rfl
8
- from ...funcs import match as mfs
9
8
  from .. import jsonschema as jsch
10
9
  from .openapi import Reference
11
10
  from .openapi import Schema
@@ -36,10 +35,14 @@ class _ReferenceUnionMarshaler(msh.Marshaler):
36
35
  return self.m.marshal(ctx, o)
37
36
 
38
37
 
39
- class _ReferenceUnionMarshalerFactory(msh.MarshalerFactoryMatchClass):
40
- @mfs.simple(lambda _, ctx, rty: _reference_union_arg(rty) is not None)
41
- def _build(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
42
- return _ReferenceUnionMarshaler(ctx.make(check.not_none(_reference_union_arg(rty))), ctx.make(Reference))
38
+ class _ReferenceUnionMarshalerFactory(msh.MarshalerFactory):
39
+ def make_marshaler(self, ctx: msh.MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Marshaler] | None:
40
+ if (rua := _reference_union_arg(rty)) is None:
41
+ return None
42
+ return lambda: _ReferenceUnionMarshaler(
43
+ ctx.make_marshaler(check.not_none(rua)),
44
+ ctx.make_marshaler(Reference),
45
+ )
43
46
 
44
47
 
45
48
  #
@@ -59,10 +62,14 @@ class _ReferenceUnionUnmarshaler(msh.Unmarshaler):
59
62
  return self.u.unmarshal(ctx, v) # noqa
60
63
 
61
64
 
62
- class _ReferenceUnionUnmarshalerFactory(msh.UnmarshalerFactoryMatchClass):
63
- @mfs.simple(lambda _, ctx, rty: _reference_union_arg(rty) is not None)
64
- def _build(self, ctx: msh.UnmarshalContext, rty: rfl.Type) -> msh.Unmarshaler:
65
- return _ReferenceUnionUnmarshaler(ctx.make(check.not_none(_reference_union_arg(rty))), ctx.make(Reference))
65
+ class _ReferenceUnionUnmarshalerFactory(msh.UnmarshalerFactory):
66
+ def make_unmarshaler(self, ctx: msh.UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Unmarshaler] | None: # noqa
67
+ if (rua := _reference_union_arg(rty)) is None:
68
+ return None
69
+ return lambda: _ReferenceUnionUnmarshaler(
70
+ ctx.make_unmarshaler(check.not_none(rua)),
71
+ ctx.make_unmarshaler(Reference),
72
+ )
66
73
 
67
74
 
68
75
  ##
@@ -86,16 +93,17 @@ class _SchemaMarshaler(msh.Marshaler):
86
93
  return dct
87
94
 
88
95
 
89
- class _SchemaMarshalerFactory(msh.MarshalerFactoryMatchClass):
90
- @mfs.simple(lambda _, ctx, rty: rty is Schema)
91
- def _build(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
92
- return _SchemaMarshaler(
96
+ class _SchemaMarshalerFactory(msh.MarshalerFactory):
97
+ def make_marshaler(self, ctx: msh.MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Marshaler] | None:
98
+ if rty is not Schema:
99
+ return None
100
+ return lambda: _SchemaMarshaler(
93
101
  {
94
- f: (msh.translate_name(f, msh.Naming.LOW_CAMEL), ctx.make(rfl.type_(a)))
102
+ f: (msh.translate_name(f, msh.Naming.LOW_CAMEL), ctx.make_marshaler(rfl.type_(a)))
95
103
  for f, a in dc.reflect(Schema).field_annotations.items()
96
104
  if f != 'keywords'
97
105
  },
98
- ctx.make(jsch.Keywords),
106
+ ctx.make_marshaler(jsch.Keywords),
99
107
  )
100
108
 
101
109
 
@@ -121,16 +129,17 @@ class _SchemaUnmarshaler(msh.Unmarshaler):
121
129
  return Schema(**kw)
122
130
 
123
131
 
124
- class _SchemaUnmarshalerFactory(msh.UnmarshalerFactoryMatchClass):
125
- @mfs.simple(lambda _, ctx, rty: rty is Schema)
126
- def _build(self, ctx: msh.UnmarshalContext, rty: rfl.Type) -> msh.Unmarshaler:
127
- return _SchemaUnmarshaler(
132
+ class _SchemaUnmarshalerFactory(msh.UnmarshalerFactory):
133
+ def make_unmarshaler(self, ctx: msh.UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Unmarshaler] | None: # noqa
134
+ if rty is not Schema:
135
+ return None
136
+ return lambda: _SchemaUnmarshaler(
128
137
  {
129
- msh.translate_name(f, msh.Naming.LOW_CAMEL): (f, ctx.make(rfl.type_(a)))
138
+ msh.translate_name(f, msh.Naming.LOW_CAMEL): (f, ctx.make_unmarshaler(rfl.type_(a)))
130
139
  for f, a in dc.reflect(Schema).field_annotations.items()
131
140
  if f != 'keywords'
132
141
  },
133
- ctx.make(jsch.Keywords),
142
+ ctx.make_unmarshaler(jsch.Keywords),
134
143
  )
135
144
 
136
145
 
@@ -138,7 +147,7 @@ class _SchemaUnmarshalerFactory(msh.UnmarshalerFactoryMatchClass):
138
147
 
139
148
 
140
149
  @lang.static_init
141
- def _install_standard_marshalling() -> None:
150
+ def _install_standard_marshaling() -> None:
142
151
  msh.install_standard_factories(
143
152
  _ReferenceUnionMarshalerFactory(),
144
153
  _ReferenceUnionUnmarshalerFactory(),
omlish/sql/__init__.py CHANGED
@@ -7,18 +7,37 @@ with _lang.auto_proxy_init(globals()):
7
7
 
8
8
  from . import api # noqa
9
9
 
10
+ from . import dbapi # noqa
11
+
12
+ from . import queries # noqa
13
+
14
+ #
15
+
10
16
  from .dbs import ( # noqa
11
- DbLoc,
12
- DbSpec,
13
17
  DbType,
14
18
  DbTypes,
15
- HostDbLoc,
19
+
20
+ DbLoc,
16
21
  UrlDbLoc,
22
+ HostDbLoc,
23
+
24
+ DbSpec,
25
+ )
26
+
27
+ from .params import ( # noqa
28
+ ParamKey,
29
+ ParamsPreparer,
30
+ LinearParamsPreparer,
31
+ NumericParamsPreparer,
32
+ NamedParamsPreparer,
33
+
34
+ ParamStyle,
35
+ make_params_preparer,
36
+
37
+ substitute_params,
17
38
  )
18
39
 
19
40
  from .qualifiedname import ( # noqa
20
41
  QualifiedName,
21
42
  qn,
22
43
  )
23
-
24
- from . import queries # noqa
@@ -7,13 +7,13 @@ import typing as ta
7
7
  import sqlalchemy as sa
8
8
  import sqlalchemy.sql.schema
9
9
 
10
- from .tabledefs import TableDef
10
+ from ..tabledefs import TableDef
11
11
 
12
12
 
13
13
  ##
14
14
 
15
15
 
16
- def build_sa_table(
16
+ def build_td_table(
17
17
  td: TableDef,
18
18
  *,
19
19
  metadata: sa.MetaData | None = None,
omlish/sql/api/dbapi.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import typing as ta
2
2
 
3
3
  from ... import check
4
- from .. import abc as dbapi_abc
4
+ from ..dbapi import abc as dbapi_abc
5
5
  from .base import Adapter
6
6
  from .base import Conn
7
7
  from .base import Db
@@ -0,0 +1,15 @@
1
+ from .abc import ( # noqa
2
+ DbapiTypeCode,
3
+ DbapiColumnDescription,
4
+ DbapiColumnDescription_,
5
+ DbapiConnection,
6
+ DbapiCursor,
7
+ DbapiThreadSafety,
8
+ DbapiModule,
9
+ )
10
+
11
+ from .drivers import ( # noqa
12
+ DbapiDialect,
13
+ DbapiDriver,
14
+ DbapiDrivers,
15
+ )
@@ -41,8 +41,8 @@ ROWID type
41
41
  import dataclasses as dc
42
42
  import enum
43
43
 
44
- from .. import lang
45
- from .params import ParamStyle
44
+ from ... import lang
45
+ from ..params import ParamStyle
46
46
 
47
47
 
48
48
  ##
@@ -65,9 +65,12 @@ from .relations import ( # noqa
65
65
  )
66
66
 
67
67
  from .rendering import ( # noqa
68
+ RenderedQuery,
69
+ RenderedQueryParts,
68
70
  Renderer,
69
71
  StdRenderer,
70
72
  render,
73
+ render_parts,
71
74
  )
72
75
 
73
76
  from .selects import ( # noqa
@@ -63,7 +63,7 @@ class LowerEnumMarshaler(msh.Marshaler, msh.Unmarshaler):
63
63
 
64
64
 
65
65
  @lang.static_init
66
- def _install_standard_marshalling() -> None:
66
+ def _install_standard_marshaling() -> None:
67
67
  for ty, ns in [
68
68
  (BinaryOp, BinaryOps),
69
69
  (UnaryOp, UnaryOps),
@@ -92,7 +92,7 @@ def _install_standard_marshalling() -> None:
92
92
  p = msh.polymorphism_from_subclasses(
93
93
  cls,
94
94
  naming=msh.Naming.SNAKE,
95
- strip_suffix='auto',
95
+ strip_suffix=msh.AutoStripSuffix,
96
96
  )
97
97
  msh.install_standard_factories(
98
98
  msh.PolymorphismMarshalerFactory(p),
@@ -81,7 +81,7 @@ class Renderer(lang.Abstract):
81
81
  def args(self) -> lang.Args:
82
82
  return self._params_preparer.prepare()
83
83
 
84
- @dispatch.method
84
+ @dispatch.method(instance_cache=True)
85
85
  def render(self, o: ta.Any) -> tp.Part:
86
86
  raise TypeError(o)
87
87
 
@@ -16,6 +16,6 @@ def _install_poly(cls: type) -> None:
16
16
 
17
17
 
18
18
  @lang.static_init
19
- def _install_standard_marshalling() -> None:
19
+ def _install_standard_marshaling() -> None:
20
20
  _install_poly(Dtype)
21
21
  _install_poly(Element)
@@ -58,6 +58,10 @@ class VerboseCalledProcessError(subprocess.CalledProcessError):
58
58
  class BaseSubprocesses(Abstract):
59
59
  DEFAULT_LOGGER: ta.ClassVar[ta.Optional[LoggerLike]] = None
60
60
 
61
+ PIPE: ta.ClassVar[int] = subprocess.PIPE
62
+ STDOUT: ta.ClassVar[int] = subprocess.STDOUT
63
+ DEVNULL: ta.ClassVar[int] = subprocess.DEVNULL
64
+
61
65
  def __init__(
62
66
  self,
63
67
  *,
@@ -32,7 +32,7 @@ def get_user_text_editor(default: ta.Optional[str] = None) -> str:
32
32
  ##
33
33
 
34
34
 
35
- class EditTextWithUserEditor(SubprocessRunnable, ExitStacked):
35
+ class EditTextWithUserEditor(SubprocessRunnable[ta.Optional[str]], ExitStacked):
36
36
  def __init__(self, initial_text: str = '') -> None:
37
37
  super().__init__()
38
38
 
omlish/sync.py CHANGED
@@ -1,3 +1,5 @@
1
+ # ruff: noqa: UP006 UP043 UP045
2
+ # @omlish-lite
1
3
  """
2
4
  TODO:
3
5
  - sync (lol) w/ asyncs.anyio
@@ -5,19 +7,21 @@ TODO:
5
7
  - Once poison=False, PoisonedError
6
8
  """
7
9
  import collections
10
+ import contextlib
8
11
  import threading
9
12
  import typing as ta
10
13
 
11
- from . import lang
14
+ from .lite.maybes import Maybe
12
15
 
13
16
 
14
17
  T = ta.TypeVar('T')
18
+ U = ta.TypeVar('U')
15
19
 
16
20
 
17
21
  ##
18
22
 
19
23
 
20
- class Once:
24
+ class SyncOnce:
21
25
  def __init__(self) -> None:
22
26
  super().__init__()
23
27
 
@@ -40,43 +44,43 @@ class Once:
40
44
  ##
41
45
 
42
46
 
43
- class Lazy(ta.Generic[T]):
47
+ class SyncLazy(ta.Generic[T]):
44
48
  def __init__(self) -> None:
45
49
  super().__init__()
46
50
 
47
- self._once = Once()
48
- self._v: lang.Maybe[T] = lang.empty()
51
+ self._once = SyncOnce()
52
+ self._v: Maybe[T] = Maybe.empty()
49
53
 
50
- def peek(self) -> lang.Maybe[T]:
54
+ def peek(self) -> Maybe[T]:
51
55
  return self._v
52
56
 
53
57
  def set(self, v: T) -> None:
54
- self._v = lang.just(v)
58
+ self._v = Maybe.just(v)
55
59
 
56
60
  def get(self, fn: ta.Callable[[], T]) -> T:
57
61
  def do():
58
- self._v = lang.just(fn())
62
+ self._v = Maybe.just(fn())
59
63
  self._once.do(do)
60
64
  return self._v.must()
61
65
 
62
66
 
63
- class LazyFn(ta.Generic[T]):
67
+ class SyncLazyFn(ta.Generic[T]):
64
68
  def __init__(self, fn: ta.Callable[[], T]) -> None:
65
69
  super().__init__()
66
70
 
67
71
  self._fn = fn
68
- self._once = Once()
69
- self._v: lang.Maybe[T] = lang.empty()
72
+ self._once = SyncOnce()
73
+ self._v: Maybe[T] = Maybe.empty()
70
74
 
71
- def peek(self) -> lang.Maybe[T]:
75
+ def peek(self) -> Maybe[T]:
72
76
  return self._v
73
77
 
74
78
  def set(self, v: T) -> None:
75
- self._v = lang.just(v)
79
+ self._v = Maybe.just(v)
76
80
 
77
81
  def get(self) -> T:
78
82
  def do():
79
- self._v = lang.just(self._fn())
83
+ self._v = Maybe.just(self._fn())
80
84
  self._once.do(do)
81
85
  return self._v.must()
82
86
 
@@ -89,11 +93,11 @@ class ConditionDeque(ta.Generic[T]):
89
93
  self,
90
94
  *,
91
95
  cond: ta.Optional['threading.Condition'] = None,
92
- deque: collections.deque[T] | None = None,
96
+ deque: ta.Optional[ta.Deque[T]] = None,
93
97
 
94
98
  lock: ta.Optional['threading.RLock'] = None,
95
- maxlen: int | None = None,
96
- init: ta.Iterable[T] | None = None,
99
+ maxlen: ta.Optional[int] = None,
100
+ init: ta.Optional[ta.Iterable[T]] = None,
97
101
  ) -> None:
98
102
  super().__init__()
99
103
 
@@ -112,7 +116,7 @@ class ConditionDeque(ta.Generic[T]):
112
116
  return self._cond
113
117
 
114
118
  @property
115
- def deque(self) -> collections.deque[T]:
119
+ def deque(self) -> ta.Deque[T]:
116
120
  return self._deque
117
121
 
118
122
  def push(
@@ -126,9 +130,9 @@ class ConditionDeque(ta.Generic[T]):
126
130
 
127
131
  def pop(
128
132
  self,
129
- timeout: float | None = None,
133
+ timeout: ta.Optional[float] = None,
130
134
  *,
131
- if_empty: ta.Callable[[], None] | None = None,
135
+ if_empty: ta.Optional[ta.Callable[[], None]] = None,
132
136
  ) -> T:
133
137
  with self.cond:
134
138
  if not self.deque and if_empty is not None:
@@ -141,6 +145,45 @@ class ConditionDeque(ta.Generic[T]):
141
145
  ##
142
146
 
143
147
 
148
+ class SyncBufferRelay(ta.Generic[T]):
149
+ def __init__(
150
+ self,
151
+ *,
152
+ wake_fn: ta.Callable[[], None],
153
+ ) -> None:
154
+ super().__init__()
155
+
156
+ self._wake_fn = wake_fn
157
+
158
+ self._lock = threading.Lock()
159
+ self._buffer: SyncBufferRelay._Buffer = SyncBufferRelay._Buffer()
160
+
161
+ class _Buffer:
162
+ def __init__(self) -> None:
163
+ self.lst: list = []
164
+ self.age = 0
165
+
166
+ def __repr__(self) -> str:
167
+ return f'{self.__class__.__qualname__}({self.lst!r}, age={self.age!r})'
168
+
169
+ def push(self, *vs: T) -> None:
170
+ with self._lock:
171
+ buf = self._buffer
172
+ needs_wake = not buf.age
173
+ buf.lst.extend(vs)
174
+ buf.age += 1
175
+ if needs_wake:
176
+ self._wake_fn()
177
+
178
+ def swap(self) -> ta.Sequence[T]:
179
+ with self._lock:
180
+ buf, self._buffer = self._buffer, SyncBufferRelay._Buffer()
181
+ return buf.lst
182
+
183
+
184
+ ##
185
+
186
+
144
187
  class CountDownLatch:
145
188
  def __init__(self, count: int) -> None:
146
189
  super().__init__()
@@ -156,10 +199,101 @@ class CountDownLatch:
156
199
 
157
200
  def wait(
158
201
  self,
159
- timeout: float | None = None,
202
+ timeout: ta.Optional[float] = None,
160
203
  ) -> bool:
161
204
  with self._cond:
162
205
  return self._cond.wait_for(
163
206
  lambda: self._count < 1,
164
207
  timeout,
165
208
  )
209
+
210
+
211
+ ##
212
+
213
+
214
+ class ObjectPool(ta.Generic[T]):
215
+ def __init__(self, new: ta.Optional[ta.Callable[[], T]] = None) -> None:
216
+ super().__init__()
217
+
218
+ self._new = new
219
+
220
+ self._lock = threading.Lock()
221
+ self._pool: ta.List[T] = []
222
+ self._closed: bool = False
223
+
224
+ #
225
+
226
+ class ClosedError(Exception):
227
+ pass
228
+
229
+ def _check_not_closed(self) -> None:
230
+ if self._closed:
231
+ raise ObjectPool.ClosedError
232
+
233
+ def close(self) -> None:
234
+ with self._lock:
235
+ self._closed = True
236
+
237
+ #
238
+
239
+ class EmptyError(Exception):
240
+ pass
241
+
242
+ def get(self, new: ta.Optional[ta.Callable[[], T]] = None) -> T:
243
+ with self._lock:
244
+ self._check_not_closed()
245
+ if self._pool:
246
+ return self._pool.pop()
247
+
248
+ if new is None:
249
+ new = self._new
250
+ if new is not None:
251
+ return new()
252
+
253
+ raise ObjectPool.EmptyError
254
+
255
+ def put(self, obj: T) -> None:
256
+ with self._lock:
257
+ self._check_not_closed()
258
+ self._pool.append(obj)
259
+
260
+ def acquire(self, new: ta.Optional[ta.Callable[[], T]] = None) -> ta.ContextManager[T]:
261
+ @contextlib.contextmanager
262
+ def inner():
263
+ o = self.get(new)
264
+ try:
265
+ yield o
266
+ finally:
267
+ self.put(o)
268
+
269
+ return inner()
270
+
271
+ def drain(self) -> ta.List[T]:
272
+ with self._lock:
273
+ out = self._pool
274
+ self._pool = []
275
+
276
+ return out
277
+
278
+ #
279
+
280
+ def manage(
281
+ self,
282
+ drain: ta.Optional[ta.Callable[[T], None]] = None,
283
+ ) -> ta.ContextManager['ObjectPool[T]']:
284
+ @contextlib.contextmanager
285
+ def inner():
286
+ with self._lock:
287
+ self._check_not_closed()
288
+
289
+ try:
290
+ yield self
291
+
292
+ finally:
293
+ self.close()
294
+
295
+ if drain is not None:
296
+ for o in self.drain():
297
+ drain(o)
298
+
299
+ return inner()
omlish/term/alt.py ADDED
@@ -0,0 +1,60 @@
1
+ import io
2
+
3
+
4
+ ##
5
+
6
+
7
+ _ESC = '\x1b'
8
+
9
+
10
+ def _csi(seq: str) -> str:
11
+ return f'{_ESC}[{seq}'
12
+
13
+
14
+ _ENTER_ALT = _csi('?1049h')
15
+ _LEAVE_ALT = _csi('?1049l')
16
+ _HIDE_CURSOR = _csi('?25l')
17
+ _SHOW_CURSOR = _csi('?25h')
18
+ _CLEAR_LINE = _csi('2K')
19
+
20
+ _SYNC_OUTPUT_ON = _csi('?2026h')
21
+ _SYNC_OUTPUT_OFF = _csi('?2026l')
22
+
23
+
24
+ def _move(row: int, col: int) -> str:
25
+ return _csi(f'{row};{col}H') # CUP
26
+
27
+
28
+ _MOVE_BOTTOM_LEFT = _move(999, 1) # clamped
29
+
30
+
31
+ ##
32
+
33
+
34
+ def render_write_from_alt(
35
+ s: str,
36
+ *,
37
+ no_sync_output: bool = False,
38
+ move_and_clear: bool = False,
39
+ ) -> str:
40
+ out = io.StringIO()
41
+
42
+ if not no_sync_output:
43
+ out.write(_SYNC_OUTPUT_ON)
44
+
45
+ out.write(_HIDE_CURSOR)
46
+ out.write(_LEAVE_ALT)
47
+
48
+ if move_and_clear:
49
+ out.write(_MOVE_BOTTOM_LEFT)
50
+ out.write(_CLEAR_LINE)
51
+
52
+ out.write(s)
53
+
54
+ out.write(_ENTER_ALT)
55
+ out.write(_SHOW_CURSOR)
56
+
57
+ if not no_sync_output:
58
+ out.write(_SYNC_OUTPUT_OFF)
59
+
60
+ return out.getvalue()
omlish/term/confirm.py CHANGED
@@ -15,7 +15,7 @@ def confirm_action(
15
15
  stdin = sys.stdin
16
16
  if not stdin.isatty():
17
17
  raise OSError(f'stdin {stdin!r} is not a tty')
18
- # FIXME: we want to make sure we only run on a tty, but we als want input()'s readline goodies..
18
+ # FIXME: we want to make sure we only run on a tty, but we also want input()'s readline goodies..
19
19
  if stdin is not sys.stdin:
20
20
  raise RuntimeError('Unsupported stdin')
21
21
 
@@ -24,15 +24,15 @@ def confirm_action(
24
24
  if not stdout.isatty():
25
25
  raise OSError(f'stdout {stdout!r} is not a tty')
26
26
 
27
- while True:
28
- if message and not message[-1].isspace():
29
- if '\n' in message:
30
- prefix = message + '\n\n'
31
- else:
32
- prefix = message + ' '
27
+ if message:
28
+ if '\n' in message:
29
+ prefix = message + '\n\n'
33
30
  else:
34
- prefix = ''
31
+ prefix = message + ' '
32
+ else:
33
+ prefix = ''
35
34
 
35
+ while True:
36
36
  c = input(f'{prefix}(y/n): ').lower().strip()
37
37
 
38
38
  if c == 'y':