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
|
@@ -10,6 +10,8 @@ import typing as ta
|
|
|
10
10
|
from .... import check
|
|
11
11
|
from .... import lang
|
|
12
12
|
from ...specs import ClassSpec
|
|
13
|
+
from ..configs import DEFAULT_NAMED_PACKAGE_CONFIG
|
|
14
|
+
from ..configs import NamedPackageConfig
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
T = ta.TypeVar('T')
|
|
@@ -33,6 +35,7 @@ class ProcessingContext:
|
|
|
33
35
|
cs: ClassSpec,
|
|
34
36
|
item_factories: ta.Mapping[type, ProcessingContextItemFactory],
|
|
35
37
|
*,
|
|
38
|
+
pkg_cfg: NamedPackageConfig = DEFAULT_NAMED_PACKAGE_CONFIG,
|
|
36
39
|
options: ta.Sequence[ProcessingOption] | None = None,
|
|
37
40
|
) -> None:
|
|
38
41
|
super().__init__()
|
|
@@ -40,6 +43,7 @@ class ProcessingContext:
|
|
|
40
43
|
self._cls = cls
|
|
41
44
|
self._cs = cs
|
|
42
45
|
self._item_factories = item_factories
|
|
46
|
+
self._pkg_cfg = pkg_cfg
|
|
43
47
|
|
|
44
48
|
options_dct: dict = {}
|
|
45
49
|
for o in options or ():
|
|
@@ -57,6 +61,10 @@ class ProcessingContext:
|
|
|
57
61
|
def cs(self) -> ClassSpec:
|
|
58
62
|
return self._cs
|
|
59
63
|
|
|
64
|
+
@property
|
|
65
|
+
def pkg_cfg(self) -> NamedPackageConfig:
|
|
66
|
+
return self._pkg_cfg
|
|
67
|
+
|
|
60
68
|
def __getitem__(self, ty: type[T]) -> T:
|
|
61
69
|
try:
|
|
62
70
|
return self._items[ty]
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import contextlib
|
|
2
2
|
import contextvars
|
|
3
|
+
import sys
|
|
3
4
|
import typing as ta
|
|
4
5
|
|
|
5
6
|
from .... import lang
|
|
6
7
|
from ...specs import ClassSpec
|
|
7
8
|
from .. import concerns as _concerns # noqa # imported for registration
|
|
8
|
-
from ..configs import
|
|
9
|
+
from ..configs import DEFAULT_NAMED_PACKAGE_CONFIG
|
|
9
10
|
from ..configs import PACKAGE_CONFIG_CACHE
|
|
10
11
|
from ..generation import processor as gp
|
|
11
12
|
from .base import ProcessingContext
|
|
@@ -36,26 +37,36 @@ def processing_options_context(*opts: ProcessingOption) -> ta.Iterator[None]:
|
|
|
36
37
|
##
|
|
37
38
|
|
|
38
39
|
|
|
40
|
+
def _is_pkg_init_mod(mod_name: str) -> bool:
|
|
41
|
+
if (mod_obj := sys.modules.get(mod_name)) is None:
|
|
42
|
+
return False
|
|
43
|
+
if (mod_spec := getattr(mod_obj, '__spec__', None)) is None:
|
|
44
|
+
return False
|
|
45
|
+
return bool(mod_spec.submodule_search_locations)
|
|
46
|
+
|
|
47
|
+
|
|
39
48
|
def drive_cls_processing(
|
|
40
49
|
cls: type,
|
|
41
50
|
cs: ClassSpec,
|
|
42
51
|
*,
|
|
43
52
|
plan_only: bool = False,
|
|
44
|
-
|
|
53
|
+
warn: bool = False,
|
|
54
|
+
debug: bool = False,
|
|
45
55
|
) -> type:
|
|
46
56
|
options: list[ProcessingOption] = list(_OPTIONS_CONTEXT_VAR.get())
|
|
47
57
|
if plan_only:
|
|
48
58
|
options.append(gp.PlanOnly(True))
|
|
49
|
-
if
|
|
50
|
-
options.append(gp.
|
|
59
|
+
if warn or debug:
|
|
60
|
+
options.append(gp.Verbosity(warn=warn, debug=debug))
|
|
51
61
|
|
|
52
62
|
#
|
|
53
63
|
|
|
54
|
-
pkg_config = DEFAULT_PACKAGE_CONFIG
|
|
55
64
|
cls_mod = cls.__module__
|
|
56
|
-
if
|
|
65
|
+
if _is_pkg_init_mod(cls_mod):
|
|
66
|
+
cls_pkg = cls_mod
|
|
67
|
+
else:
|
|
57
68
|
cls_pkg = cls_mod.rpartition('.')[0]
|
|
58
|
-
|
|
69
|
+
pkg_cfg = lang.coalesce(PACKAGE_CONFIG_CACHE.get(cls_pkg), DEFAULT_NAMED_PACKAGE_CONFIG)
|
|
59
70
|
|
|
60
71
|
#
|
|
61
72
|
|
|
@@ -63,6 +74,7 @@ def drive_cls_processing(
|
|
|
63
74
|
cls,
|
|
64
75
|
cs,
|
|
65
76
|
all_processing_context_item_factories(),
|
|
77
|
+
pkg_cfg=pkg_cfg,
|
|
66
78
|
options=options,
|
|
67
79
|
)
|
|
68
80
|
|
omlish/dataclasses/specs.py
CHANGED
|
@@ -3,6 +3,7 @@ import typing as ta
|
|
|
3
3
|
|
|
4
4
|
from ... import check
|
|
5
5
|
from ... import lang
|
|
6
|
+
from ...lite.dataclasses import is_immediate_dataclass
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
if ta.TYPE_CHECKING:
|
|
@@ -40,6 +41,8 @@ def update_fields(
|
|
|
40
41
|
def inner(cls):
|
|
41
42
|
if issubclass(cls, meta.DataMeta):
|
|
42
43
|
raise TypeError('update_fields() cannot be used on DataMeta subclasses')
|
|
44
|
+
if is_immediate_dataclass(cls):
|
|
45
|
+
raise TypeError('update_fields() cannot be used on already processed dataclasses')
|
|
43
46
|
|
|
44
47
|
if fields is None:
|
|
45
48
|
for a, v in list(cls.__dict__.items()):
|
|
@@ -51,6 +54,8 @@ def update_fields(
|
|
|
51
54
|
try:
|
|
52
55
|
v = cls.__dict__[a]
|
|
53
56
|
except KeyError:
|
|
57
|
+
if hasattr(cls, a):
|
|
58
|
+
raise TypeError('update_fields() cannot be used on parent dataclass fields') from None
|
|
54
59
|
v = dc.field()
|
|
55
60
|
else:
|
|
56
61
|
if not isinstance(v, dc.Field):
|
omlish/diag/_pycharm/runhack.py
CHANGED
|
@@ -95,7 +95,7 @@ _BOOL_ENV_VAR_VALUES = {
|
|
|
95
95
|
def _get_opt_env_bool(n, d): # type: (str | None, bool) -> bool
|
|
96
96
|
if n is None or n not in os.environ:
|
|
97
97
|
return d
|
|
98
|
-
return _BOOL_ENV_VAR_VALUES[os.environ[n]]
|
|
98
|
+
return _BOOL_ENV_VAR_VALUES[os.environ[n].lower()]
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
def _get_env_path_list(k): # type: (str) -> list[str]
|
|
File without changes
|
|
@@ -7,12 +7,12 @@ import dataclasses as dc
|
|
|
7
7
|
import json
|
|
8
8
|
import typing as ta
|
|
9
9
|
|
|
10
|
-
from
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
10
|
+
from ...lite.check import check
|
|
11
|
+
from ...lite.marshal import OBJ_MARSHALER_FIELD_KEY
|
|
12
|
+
from ...lite.marshal import unmarshal_obj
|
|
13
|
+
from ...subprocesses.run import SubprocessRun
|
|
14
|
+
from ...subprocesses.run import SubprocessRunnable
|
|
15
|
+
from ...subprocesses.run import SubprocessRunOutput
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
##
|
|
@@ -7,12 +7,12 @@ import dataclasses as dc
|
|
|
7
7
|
import enum
|
|
8
8
|
import typing as ta
|
|
9
9
|
|
|
10
|
-
from
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
10
|
+
from ...lite.check import check
|
|
11
|
+
from ...lite.dataclasses import dataclass_repr_omit_falsey
|
|
12
|
+
from ...lite.marshal import OBJ_MARSHALER_OMIT_IF_NONE
|
|
13
|
+
from ...subprocesses.run import SubprocessRun
|
|
14
|
+
from ...subprocesses.run import SubprocessRunnable
|
|
15
|
+
from ...subprocesses.run import SubprocessRunOutput
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
##
|
omlish/diag/{ps.py → cmds/ps.py}
RENAMED
|
@@ -4,12 +4,12 @@ import dataclasses as dc
|
|
|
4
4
|
import os
|
|
5
5
|
import typing as ta
|
|
6
6
|
|
|
7
|
-
from
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from
|
|
11
|
-
from
|
|
12
|
-
from
|
|
7
|
+
from ...lite.check import check
|
|
8
|
+
from ...lite.timeouts import Timeout
|
|
9
|
+
from ...subprocesses.run import SubprocessRun
|
|
10
|
+
from ...subprocesses.run import SubprocessRunnable
|
|
11
|
+
from ...subprocesses.run import SubprocessRunOutput
|
|
12
|
+
from ...subprocesses.sync import subprocesses
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
##
|
omlish/diag/pycharm.py
CHANGED
|
@@ -191,9 +191,23 @@ def pycharm_remote_debugger_attach(prd: PycharmRemoteDebugger) -> None:
|
|
|
191
191
|
else:
|
|
192
192
|
pydevd_pycharm = _import_pydevd_pycharm(version=version)
|
|
193
193
|
|
|
194
|
+
import inspect
|
|
195
|
+
st_sig = inspect.signature(pydevd_pycharm.settrace)
|
|
196
|
+
|
|
197
|
+
kw: dict = {}
|
|
198
|
+
if 'stdoutToServer' in st_sig.parameters:
|
|
199
|
+
kw.update(
|
|
200
|
+
stdoutToServer=True,
|
|
201
|
+
stderrToServer=True,
|
|
202
|
+
)
|
|
203
|
+
else:
|
|
204
|
+
kw.update(
|
|
205
|
+
stdout_to_server=True,
|
|
206
|
+
stderr_to_server=True,
|
|
207
|
+
)
|
|
208
|
+
|
|
194
209
|
pydevd_pycharm.settrace(
|
|
195
210
|
host,
|
|
196
211
|
port=prd.port,
|
|
197
|
-
|
|
198
|
-
stderrToServer=True,
|
|
212
|
+
**kw,
|
|
199
213
|
)
|
omlish/diag/pydevd.py
CHANGED
|
@@ -6,7 +6,7 @@ an already-debugging PyCharm instance to debug PySpark jobs.
|
|
|
6
6
|
TODO:
|
|
7
7
|
- https://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html#
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
====
|
|
10
10
|
|
|
11
11
|
https://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html#remote-debug-config ->
|
|
12
12
|
|
|
@@ -25,13 +25,34 @@ buf = textwrap.dedent(f'''
|
|
|
25
25
|
stderrToServer=True,
|
|
26
26
|
)
|
|
27
27
|
''') + '\n' * 2 + buf
|
|
28
|
+
|
|
29
|
+
====
|
|
30
|
+
|
|
31
|
+
TODO: monkeypatch:
|
|
32
|
+
|
|
33
|
+
/Applications/PyCharm.app/Contents/plugins/python-ce/helpers/pydev/_pydev_bundle/pydev_monkey.py ::
|
|
34
|
+
|
|
35
|
+
def starts_with_python_shebang(path):
|
|
36
|
+
try:
|
|
37
|
+
with open(path) as f:
|
|
38
|
+
for line in f:
|
|
39
|
+
line = line.strip()
|
|
40
|
+
if line:
|
|
41
|
+
for name in PYTHON_NAMES:
|
|
42
|
+
if line.startswith('#!/usr/bin/env %s' % name):
|
|
43
|
+
return True
|
|
44
|
+
return False
|
|
45
|
+
except (UnicodeDecodeError, IsADirectoryError): # <-- Add catch for `IsADirectoryError`
|
|
46
|
+
return False
|
|
47
|
+
except:
|
|
48
|
+
traceback.print_exc()
|
|
49
|
+
return False
|
|
28
50
|
"""
|
|
29
51
|
import json
|
|
30
52
|
import os
|
|
31
53
|
import sys
|
|
32
54
|
import tempfile
|
|
33
55
|
import textwrap
|
|
34
|
-
import threading
|
|
35
56
|
import types
|
|
36
57
|
import typing as ta
|
|
37
58
|
|
|
@@ -119,7 +140,19 @@ def _pydevd() -> types.ModuleType | None:
|
|
|
119
140
|
|
|
120
141
|
|
|
121
142
|
def is_present() -> bool:
|
|
122
|
-
|
|
143
|
+
# FIXME: try to use `lang.can_import('pydevd'), but raises with:
|
|
144
|
+
# INTERNALERROR> File "/Users/spinlock/src/wrmsr/omlish/omlish/lang/imports/resolving.py", line 16, in can_import
|
|
145
|
+
# INTERNALERROR> spec = importlib.util.find_spec(name, package)
|
|
146
|
+
# INTERNALERROR> File "<frozen importlib.util>", line 111, in find_spec
|
|
147
|
+
# INTERNALERROR> ValueError: pydevd.__spec__ is None
|
|
148
|
+
# Really want to avoid actually importing pydevd due to side-effects, slowness, and even a pkg_resources deprecation
|
|
149
|
+
# warning...
|
|
150
|
+
try:
|
|
151
|
+
__import__('pydevd')
|
|
152
|
+
except ImportError:
|
|
153
|
+
return False
|
|
154
|
+
else:
|
|
155
|
+
return True
|
|
123
156
|
|
|
124
157
|
|
|
125
158
|
def get_setup() -> dict | None:
|
|
@@ -243,23 +276,23 @@ def maybe_reexec(
|
|
|
243
276
|
bootstrap_path = os.path.join(tmpdir, 'bootstrap.py')
|
|
244
277
|
with open(bootstrap_path, 'w') as f:
|
|
245
278
|
f.write(textwrap.dedent(f"""
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
279
|
+
import sys
|
|
280
|
+
old_paths = set(sys.path)
|
|
281
|
+
for new_path in {sys.path!r}:
|
|
282
|
+
if new_path not in old_paths:
|
|
283
|
+
sys.path.insert(0, new_path)
|
|
284
|
+
|
|
285
|
+
_stderr_write = sys.stderr.write
|
|
286
|
+
def stderr_write(*args, **kwargs):
|
|
287
|
+
code = sys._getframe(1).f_code
|
|
288
|
+
if code is not None and code.co_filename and code.co_filename.endswith('/pydev_log.py'):
|
|
289
|
+
return
|
|
290
|
+
_stderr_write(*args, **kwargs)
|
|
291
|
+
sys.stderr.write = stderr_write
|
|
292
|
+
|
|
293
|
+
sys.argv = {args[1:]!r}
|
|
294
|
+
import runpy
|
|
295
|
+
runpy.run_path({args[1]!r}, run_name='__main__')
|
|
263
296
|
"""))
|
|
264
297
|
args = [args[0], bootstrap_path]
|
|
265
298
|
|
|
@@ -272,29 +305,14 @@ def debug_unhandled_exception(exc_info: ta.Any = None) -> None:
|
|
|
272
305
|
|
|
273
306
|
try:
|
|
274
307
|
import pydevd
|
|
275
|
-
from pydevd import pydevd_tracing
|
|
276
308
|
|
|
277
309
|
except ImportError:
|
|
278
310
|
return
|
|
279
311
|
|
|
280
|
-
|
|
281
|
-
frames = []
|
|
282
|
-
while traceback:
|
|
283
|
-
frames.append(traceback.tb_frame)
|
|
284
|
-
traceback = traceback.tb_next
|
|
285
|
-
|
|
286
|
-
thread = threading.current_thread()
|
|
287
|
-
frames_by_id = {id(frame): frame for frame in frames}
|
|
288
|
-
frame = frames[-1]
|
|
289
|
-
exception = (exctype, value, traceback)
|
|
290
|
-
|
|
291
|
-
if hasattr(thread, 'additional_info'):
|
|
292
|
-
thread.additional_info.pydev_message = 'server exception'
|
|
293
|
-
try:
|
|
294
|
-
debugger = pydevd.debugger # noqa
|
|
295
|
-
except AttributeError:
|
|
296
|
-
debugger = pydevd.get_global_debugger() # noqa
|
|
312
|
+
et, e, tb = exc_info
|
|
297
313
|
|
|
298
|
-
|
|
314
|
+
while tb.tb_next is not None:
|
|
315
|
+
tb = tb.tb_next
|
|
316
|
+
original_frame = tb.tb_frame
|
|
299
317
|
|
|
300
|
-
|
|
318
|
+
pydevd.settrace(stop_at_frame=original_frame, suspend=True)
|
omlish/dispatch/__init__.py
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
from .. import lang as _lang
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
with _lang.auto_proxy_init(globals()):
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
from .dispatch import ( # noqa
|
|
8
|
+
Dispatcher,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from .functions import ( # noqa
|
|
12
|
+
function,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from .methods import ( # noqa
|
|
16
|
+
install_method,
|
|
17
|
+
method,
|
|
18
|
+
)
|