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.
- omlish/.omlish-manifests.json +12 -0
- omlish/README.md +199 -0
- omlish/__about__.py +21 -16
- omlish/argparse/all.py +17 -9
- omlish/argparse/cli.py +16 -3
- omlish/argparse/utils.py +21 -0
- omlish/asyncs/asyncio/rlock.py +110 -0
- omlish/asyncs/asyncio/sync.py +43 -0
- omlish/asyncs/asyncio/utils.py +2 -0
- omlish/asyncs/sync.py +25 -0
- omlish/bootstrap/_marshal.py +1 -1
- omlish/bootstrap/diag.py +12 -21
- omlish/bootstrap/main.py +2 -5
- omlish/bootstrap/sys.py +27 -28
- omlish/cexts/__init__.py +0 -0
- omlish/cexts/include/omlish/omlish.hh +1 -0
- omlish/collections/__init__.py +13 -1
- omlish/collections/attrregistry.py +210 -0
- omlish/collections/cache/impl.py +1 -0
- omlish/collections/identity.py +1 -0
- omlish/collections/mappings.py +28 -0
- omlish/collections/trie.py +5 -1
- omlish/collections/utils.py +77 -0
- omlish/concurrent/all.py +2 -1
- omlish/concurrent/futures.py +25 -0
- omlish/concurrent/threadlets.py +1 -1
- omlish/daemons/reparent.py +2 -3
- omlish/daemons/spawning.py +2 -3
- omlish/dataclasses/__init__.py +2 -0
- omlish/dataclasses/impl/api/classes/decorator.py +3 -0
- omlish/dataclasses/impl/api/classes/make.py +3 -0
- omlish/dataclasses/impl/concerns/repr.py +15 -2
- omlish/dataclasses/impl/configs.py +97 -37
- omlish/dataclasses/impl/generation/compilation.py +21 -19
- omlish/dataclasses/impl/generation/globals.py +1 -0
- omlish/dataclasses/impl/generation/ops.py +1 -0
- omlish/dataclasses/impl/generation/plans.py +2 -17
- omlish/dataclasses/impl/generation/processor.py +106 -25
- omlish/dataclasses/impl/processing/base.py +8 -0
- omlish/dataclasses/impl/processing/driving.py +19 -7
- omlish/dataclasses/specs.py +1 -0
- omlish/dataclasses/tools/modifiers.py +5 -0
- omlish/diag/_pycharm/runhack.py +1 -1
- omlish/diag/cmds/__init__.py +0 -0
- omlish/diag/{lslocks.py → cmds/lslocks.py} +6 -6
- omlish/diag/{lsof.py → cmds/lsof.py} +6 -6
- omlish/diag/{ps.py → cmds/ps.py} +6 -6
- omlish/diag/pycharm.py +16 -2
- omlish/diag/pydevd.py +58 -40
- omlish/diag/replserver/console.py +1 -1
- omlish/dispatch/__init__.py +18 -12
- omlish/dispatch/methods.py +50 -140
- omlish/dom/rendering.py +1 -1
- omlish/formats/dotenv.py +1 -1
- omlish/formats/json/stream/__init__.py +13 -0
- omlish/funcs/guard.py +225 -0
- omlish/graphs/dot/rendering.py +1 -1
- omlish/http/all.py +44 -4
- omlish/http/clients/asyncs.py +33 -27
- omlish/http/clients/base.py +17 -1
- omlish/http/clients/coro/__init__.py +0 -0
- omlish/http/clients/coro/sync.py +171 -0
- omlish/http/clients/default.py +208 -29
- omlish/http/clients/executor.py +56 -0
- omlish/http/clients/httpx.py +72 -11
- omlish/http/clients/middleware.py +181 -0
- omlish/http/clients/sync.py +33 -27
- omlish/http/clients/syncasync.py +49 -0
- omlish/http/clients/urllib.py +6 -3
- omlish/http/coro/client/connection.py +15 -6
- omlish/http/coro/io.py +2 -0
- omlish/http/flasky/__init__.py +40 -0
- omlish/http/flasky/_compat.py +2 -0
- omlish/http/flasky/api.py +82 -0
- omlish/http/flasky/app.py +203 -0
- omlish/http/flasky/cvs.py +59 -0
- omlish/http/flasky/requests.py +20 -0
- omlish/http/flasky/responses.py +23 -0
- omlish/http/flasky/routes.py +23 -0
- omlish/http/flasky/types.py +15 -0
- omlish/http/urls.py +67 -0
- omlish/inject/__init__.py +57 -29
- omlish/inject/_dataclasses.py +5148 -0
- omlish/inject/binder.py +11 -52
- omlish/inject/eagers.py +2 -0
- omlish/inject/elements.py +27 -0
- omlish/inject/helpers/__init__.py +0 -0
- omlish/inject/{utils.py → helpers/constfn.py} +3 -3
- omlish/inject/{tags.py → helpers/id.py} +2 -2
- omlish/inject/helpers/late.py +76 -0
- omlish/inject/{managed.py → helpers/managed.py} +10 -10
- omlish/inject/helpers/multis.py +143 -0
- omlish/inject/helpers/wrappers.py +54 -0
- omlish/inject/impl/elements.py +54 -21
- omlish/inject/impl/injector.py +29 -25
- omlish/inject/impl/inspect.py +10 -1
- omlish/inject/impl/maysync.py +3 -4
- omlish/inject/impl/multis.py +3 -0
- omlish/inject/impl/sync.py +3 -4
- omlish/inject/injector.py +31 -2
- omlish/inject/inspect.py +35 -0
- omlish/inject/maysync.py +2 -4
- omlish/inject/multis.py +8 -0
- omlish/inject/overrides.py +3 -3
- omlish/inject/privates.py +6 -0
- omlish/inject/providers.py +3 -2
- omlish/inject/sync.py +5 -4
- omlish/io/buffers.py +118 -0
- omlish/io/readers.py +29 -0
- omlish/iterators/transforms.py +2 -2
- omlish/lang/__init__.py +180 -97
- omlish/lang/_asyncs.cc +186 -0
- omlish/lang/asyncs.py +17 -0
- omlish/lang/casing.py +11 -0
- omlish/lang/contextmanagers.py +28 -4
- omlish/lang/functions.py +31 -22
- omlish/lang/imports/_capture.cc +11 -9
- omlish/lang/imports/capture.py +363 -170
- omlish/lang/imports/proxy.py +455 -152
- omlish/lang/lazyglobals.py +22 -9
- omlish/lang/params.py +17 -0
- omlish/lang/recursion.py +0 -1
- omlish/lang/sequences.py +124 -0
- omlish/lifecycles/README.md +30 -0
- omlish/lifecycles/__init__.py +87 -13
- omlish/lifecycles/_dataclasses.py +1388 -0
- omlish/lifecycles/base.py +178 -64
- omlish/lifecycles/contextmanagers.py +113 -4
- omlish/lifecycles/controller.py +150 -87
- omlish/lifecycles/injection.py +143 -0
- omlish/lifecycles/listeners.py +56 -0
- omlish/lifecycles/managed.py +142 -0
- omlish/lifecycles/manager.py +218 -93
- omlish/lifecycles/states.py +2 -0
- omlish/lifecycles/transitions.py +3 -0
- omlish/lifecycles/unwrap.py +57 -0
- omlish/lite/abstract.py +54 -24
- omlish/lite/asyncs.py +2 -2
- omlish/lite/attrops.py +2 -0
- omlish/lite/contextmanagers.py +4 -4
- omlish/lite/dataclasses.py +44 -0
- omlish/lite/maybes.py +8 -0
- omlish/lite/maysync.py +1 -5
- omlish/lite/pycharm.py +1 -1
- omlish/lite/typing.py +24 -0
- omlish/logs/_amalg.py +1 -1
- omlish/logs/all.py +25 -11
- omlish/logs/asyncs.py +73 -0
- omlish/logs/base.py +101 -12
- omlish/logs/contexts.py +4 -1
- omlish/logs/lists.py +125 -0
- omlish/logs/modules.py +19 -1
- omlish/logs/std/loggers.py +6 -1
- omlish/logs/std/noisy.py +11 -9
- omlish/logs/{standard.py → std/standard.py} +3 -4
- omlish/logs/utils.py +17 -2
- omlish/manifests/loading.py +2 -1
- omlish/marshal/__init__.py +33 -13
- omlish/marshal/_dataclasses.py +2774 -0
- omlish/marshal/base/configs.py +12 -0
- omlish/marshal/base/contexts.py +36 -21
- omlish/marshal/base/funcs.py +8 -11
- omlish/marshal/base/options.py +8 -0
- omlish/marshal/base/registries.py +146 -44
- omlish/marshal/base/types.py +40 -16
- omlish/marshal/composite/iterables.py +33 -20
- omlish/marshal/composite/literals.py +20 -18
- omlish/marshal/composite/mappings.py +36 -23
- omlish/marshal/composite/maybes.py +29 -19
- omlish/marshal/composite/newtypes.py +16 -16
- omlish/marshal/composite/optionals.py +14 -14
- omlish/marshal/composite/special.py +15 -15
- omlish/marshal/composite/unions/__init__.py +0 -0
- omlish/marshal/composite/unions/literals.py +93 -0
- omlish/marshal/composite/unions/primitives.py +103 -0
- omlish/marshal/factories/invalidate.py +18 -68
- omlish/marshal/factories/method.py +26 -0
- omlish/marshal/factories/moduleimport/factories.py +22 -65
- omlish/marshal/factories/multi.py +13 -25
- omlish/marshal/factories/recursive.py +42 -56
- omlish/marshal/factories/typecache.py +29 -74
- omlish/marshal/factories/typemap.py +42 -43
- omlish/marshal/objects/dataclasses.py +129 -106
- omlish/marshal/objects/marshal.py +18 -14
- omlish/marshal/objects/namedtuples.py +48 -42
- omlish/marshal/objects/unmarshal.py +19 -15
- omlish/marshal/polymorphism/marshal.py +9 -11
- omlish/marshal/polymorphism/metadata.py +16 -5
- omlish/marshal/polymorphism/standard.py +13 -1
- omlish/marshal/polymorphism/unions.py +15 -105
- omlish/marshal/polymorphism/unmarshal.py +9 -10
- omlish/marshal/singular/enums.py +14 -18
- omlish/marshal/standard.py +10 -6
- omlish/marshal/trivial/any.py +1 -1
- omlish/marshal/trivial/forbidden.py +21 -26
- omlish/metadata.py +23 -1
- omlish/os/forkhooks.py +4 -0
- omlish/os/pidfiles/pinning.py +2 -2
- omlish/reflect/__init__.py +43 -26
- omlish/reflect/ops.py +10 -1
- omlish/reflect/types.py +1 -0
- omlish/secrets/marshal.py +1 -1
- omlish/specs/jmespath/__init__.py +12 -3
- omlish/specs/jmespath/_dataclasses.py +2893 -0
- omlish/specs/jmespath/ast.py +1 -1
- omlish/specs/jsonrpc/__init__.py +13 -0
- omlish/specs/jsonrpc/_marshal.py +32 -23
- omlish/specs/jsonrpc/conns.py +10 -7
- omlish/specs/jsonschema/_marshal.py +1 -1
- omlish/specs/jsonschema/keywords/__init__.py +7 -0
- omlish/specs/jsonschema/keywords/_dataclasses.py +1644 -0
- omlish/specs/openapi/_marshal.py +31 -22
- omlish/sql/__init__.py +24 -5
- omlish/sql/{tabledefs/alchemy.py → alchemy/tabledefs.py} +2 -2
- omlish/sql/api/dbapi.py +1 -1
- omlish/sql/dbapi/__init__.py +15 -0
- omlish/sql/{dbapi.py → dbapi/drivers.py} +2 -2
- omlish/sql/queries/__init__.py +3 -0
- omlish/sql/queries/_marshal.py +2 -2
- omlish/sql/queries/rendering.py +1 -1
- omlish/sql/tabledefs/_marshal.py +1 -1
- omlish/subprocesses/base.py +4 -0
- omlish/subprocesses/editor.py +1 -1
- omlish/sync.py +155 -21
- omlish/term/alt.py +60 -0
- omlish/term/confirm.py +8 -8
- omlish/term/pager.py +235 -0
- omlish/term/terminfo.py +935 -0
- omlish/term/termstate.py +67 -0
- omlish/term/vt100/terminal.py +0 -3
- omlish/testing/pytest/plugins/asyncs/fixtures.py +4 -1
- omlish/testing/pytest/plugins/asyncs/plugin.py +2 -0
- omlish/testing/pytest/plugins/skips.py +2 -1
- omlish/testing/unittest/main.py +3 -3
- omlish/text/docwrap/__init__.py +3 -0
- omlish/text/docwrap/__main__.py +11 -0
- omlish/text/docwrap/api.py +83 -0
- omlish/text/docwrap/cli.py +91 -0
- omlish/text/docwrap/groups.py +84 -0
- omlish/text/docwrap/lists.py +167 -0
- omlish/text/docwrap/parts.py +146 -0
- omlish/text/docwrap/reflowing.py +106 -0
- omlish/text/docwrap/rendering.py +151 -0
- omlish/text/docwrap/utils.py +11 -0
- omlish/text/docwrap/wrapping.py +59 -0
- omlish/text/filecache.py +2 -2
- omlish/text/lorem.py +6 -0
- omlish/text/parts.py +2 -2
- omlish/text/textwrap.py +51 -0
- omlish/typedvalues/marshal.py +85 -59
- omlish/typedvalues/values.py +2 -1
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/METADATA +36 -32
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/RECORD +260 -199
- omlish/dataclasses/impl/generation/mangling.py +0 -18
- omlish/funcs/match.py +0 -227
- omlish/lifecycles/abstract.py +0 -86
- omlish/marshal/factories/match.py +0 -34
- omlish/marshal/factories/simple.py +0 -28
- /omlish/inject/{impl → helpers}/proxy.py +0 -0
- /omlish/inject/impl/{providers2.py → providersmap.py} +0 -0
- /omlish/sql/{abc.py → dbapi/abc.py} +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/top_level.txt +0 -0
omlish/specs/openapi/_marshal.py
CHANGED
|
@@ -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.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
10
|
+
from ..tabledefs import TableDef
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
##
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def
|
|
16
|
+
def build_td_table(
|
|
17
17
|
td: TableDef,
|
|
18
18
|
*,
|
|
19
19
|
metadata: sa.MetaData | None = None,
|
omlish/sql/api/dbapi.py
CHANGED
|
@@ -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
|
+
)
|
omlish/sql/queries/__init__.py
CHANGED
omlish/sql/queries/_marshal.py
CHANGED
|
@@ -63,7 +63,7 @@ class LowerEnumMarshaler(msh.Marshaler, msh.Unmarshaler):
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
@lang.static_init
|
|
66
|
-
def
|
|
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=
|
|
95
|
+
strip_suffix=msh.AutoStripSuffix,
|
|
96
96
|
)
|
|
97
97
|
msh.install_standard_factories(
|
|
98
98
|
msh.PolymorphismMarshalerFactory(p),
|
omlish/sql/queries/rendering.py
CHANGED
omlish/sql/tabledefs/_marshal.py
CHANGED
omlish/subprocesses/base.py
CHANGED
|
@@ -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
|
*,
|
omlish/subprocesses/editor.py
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
47
|
+
class SyncLazy(ta.Generic[T]):
|
|
44
48
|
def __init__(self) -> None:
|
|
45
49
|
super().__init__()
|
|
46
50
|
|
|
47
|
-
self._once =
|
|
48
|
-
self._v:
|
|
51
|
+
self._once = SyncOnce()
|
|
52
|
+
self._v: Maybe[T] = Maybe.empty()
|
|
49
53
|
|
|
50
|
-
def peek(self) ->
|
|
54
|
+
def peek(self) -> Maybe[T]:
|
|
51
55
|
return self._v
|
|
52
56
|
|
|
53
57
|
def set(self, v: T) -> None:
|
|
54
|
-
self._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 =
|
|
62
|
+
self._v = Maybe.just(fn())
|
|
59
63
|
self._once.do(do)
|
|
60
64
|
return self._v.must()
|
|
61
65
|
|
|
62
66
|
|
|
63
|
-
class
|
|
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 =
|
|
69
|
-
self._v:
|
|
72
|
+
self._once = SyncOnce()
|
|
73
|
+
self._v: Maybe[T] = Maybe.empty()
|
|
70
74
|
|
|
71
|
-
def peek(self) ->
|
|
75
|
+
def peek(self) -> Maybe[T]:
|
|
72
76
|
return self._v
|
|
73
77
|
|
|
74
78
|
def set(self, v: T) -> None:
|
|
75
|
-
self._v =
|
|
79
|
+
self._v = Maybe.just(v)
|
|
76
80
|
|
|
77
81
|
def get(self) -> T:
|
|
78
82
|
def do():
|
|
79
|
-
self._v =
|
|
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:
|
|
96
|
+
deque: ta.Optional[ta.Deque[T]] = None,
|
|
93
97
|
|
|
94
98
|
lock: ta.Optional['threading.RLock'] = None,
|
|
95
|
-
maxlen: int
|
|
96
|
-
init: ta.Iterable[T]
|
|
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) ->
|
|
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
|
|
133
|
+
timeout: ta.Optional[float] = None,
|
|
130
134
|
*,
|
|
131
|
-
if_empty: ta.Callable[[], 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
|
|
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
|
|
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
|
-
|
|
28
|
-
if
|
|
29
|
-
|
|
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':
|