omdev 0.0.0.dev372__py3-none-any.whl → 0.0.0.dev373__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.
- omdev/.manifests.json +15 -15
- omdev/intellij/__init__.py +11 -0
- omdev/intellij/cli.py +86 -0
- omdev/intellij/ides.py +85 -0
- omdev/intellij/open.py +113 -0
- omdev/scripts/ci.py +63 -3
- omdev/scripts/pyproject.py +63 -3
- {omdev-0.0.0.dev372.dist-info → omdev-0.0.0.dev373.dist-info}/METADATA +2 -2
- {omdev-0.0.0.dev372.dist-info → omdev-0.0.0.dev373.dist-info}/RECORD +13 -10
- omdev/tools/intellij.py +0 -253
- {omdev-0.0.0.dev372.dist-info → omdev-0.0.0.dev373.dist-info}/WHEEL +0 -0
- {omdev-0.0.0.dev372.dist-info → omdev-0.0.0.dev373.dist-info}/entry_points.txt +0 -0
- {omdev-0.0.0.dev372.dist-info → omdev-0.0.0.dev373.dist-info}/licenses/LICENSE +0 -0
- {omdev-0.0.0.dev372.dist-info → omdev-0.0.0.dev373.dist-info}/top_level.txt +0 -0
omdev/.manifests.json
CHANGED
@@ -71,6 +71,21 @@
|
|
71
71
|
}
|
72
72
|
}
|
73
73
|
},
|
74
|
+
{
|
75
|
+
"module": ".intellij.cli",
|
76
|
+
"attr": "_CLI_MODULE",
|
77
|
+
"file": "omdev/intellij/cli.py",
|
78
|
+
"line": 81,
|
79
|
+
"value": {
|
80
|
+
"$.cli.types.CliModule": {
|
81
|
+
"cmd_name": [
|
82
|
+
"intellij",
|
83
|
+
"ij"
|
84
|
+
],
|
85
|
+
"mod_name": "omdev.intellij.cli"
|
86
|
+
}
|
87
|
+
}
|
88
|
+
},
|
74
89
|
{
|
75
90
|
"module": ".interp.__main__",
|
76
91
|
"attr": "_CLI_MODULE",
|
@@ -378,21 +393,6 @@
|
|
378
393
|
}
|
379
394
|
}
|
380
395
|
},
|
381
|
-
{
|
382
|
-
"module": ".tools.intellij",
|
383
|
-
"attr": "_CLI_MODULE",
|
384
|
-
"file": "omdev/tools/intellij.py",
|
385
|
-
"line": 248,
|
386
|
-
"value": {
|
387
|
-
"$.cli.types.CliModule": {
|
388
|
-
"cmd_name": [
|
389
|
-
"intellij",
|
390
|
-
"ij"
|
391
|
-
],
|
392
|
-
"mod_name": "omdev.tools.intellij"
|
393
|
-
}
|
394
|
-
}
|
395
|
-
},
|
396
396
|
{
|
397
397
|
"module": ".tools.json.__main__",
|
398
398
|
"attr": "_CLI_MODULE",
|
omdev/intellij/cli.py
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- PyCharm.app/Contents/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_constants.py -> USE_LOW_IMPACT_MONITORING
|
4
|
+
- DISPLAY=":1" - ls /tmp/.X11-unix/X1 ?
|
5
|
+
- https://unix.stackexchange.com/questions/17255/is-there-a-command-to-list-all-open-displays-on-a-machine
|
6
|
+
- w -oush
|
7
|
+
"""
|
8
|
+
import inspect
|
9
|
+
import os.path
|
10
|
+
import subprocess
|
11
|
+
import tempfile
|
12
|
+
|
13
|
+
from omlish.argparse import all as ap
|
14
|
+
|
15
|
+
from ..cli import CliModule
|
16
|
+
from .ides import Ide
|
17
|
+
from .ides import get_ide_version
|
18
|
+
from .ides import infer_directory_ide
|
19
|
+
from .open import open_ide
|
20
|
+
|
21
|
+
|
22
|
+
##
|
23
|
+
|
24
|
+
|
25
|
+
class IntellijCli(ap.Cli):
|
26
|
+
@ap.cmd(
|
27
|
+
ap.arg('python-exe'),
|
28
|
+
ap.arg('args', nargs=ap.REMAINDER),
|
29
|
+
)
|
30
|
+
def pycharm_runhack(self) -> int:
|
31
|
+
if not os.path.isfile(exe := self.args.python_exe):
|
32
|
+
raise FileNotFoundError(exe)
|
33
|
+
|
34
|
+
from omlish.diag._pycharm import runhack # noqa
|
35
|
+
src = inspect.getsource(runhack)
|
36
|
+
|
37
|
+
src_file = tempfile.mktemp(__package__ + '-runhack') # noqa
|
38
|
+
with open(src_file, 'w') as f:
|
39
|
+
f.write(src)
|
40
|
+
|
41
|
+
proc = subprocess.run([exe, src_file, *self.args.args], check=False)
|
42
|
+
return proc.returncode
|
43
|
+
|
44
|
+
#
|
45
|
+
|
46
|
+
def _get_ide(
|
47
|
+
self,
|
48
|
+
*,
|
49
|
+
cwd: str | None = None,
|
50
|
+
) -> Ide: # noqa
|
51
|
+
if (ai := self.args.ide) is not None:
|
52
|
+
return Ide[ai.upper()] # noqa
|
53
|
+
|
54
|
+
if (ii := infer_directory_ide(cwd)) is not None:
|
55
|
+
return ii
|
56
|
+
|
57
|
+
return Ide.PYCHARM
|
58
|
+
|
59
|
+
@ap.cmd(
|
60
|
+
ap.arg('-e', '--ide'),
|
61
|
+
)
|
62
|
+
def version(self) -> None:
|
63
|
+
i = self._get_ide()
|
64
|
+
v = get_ide_version(i)
|
65
|
+
print(v)
|
66
|
+
|
67
|
+
@ap.cmd(
|
68
|
+
ap.arg('dir', nargs='?'),
|
69
|
+
ap.arg('-e', '--ide'),
|
70
|
+
)
|
71
|
+
def open(self) -> None:
|
72
|
+
dir = os.path.abspath(self.args.dir or '.') # noqa
|
73
|
+
ide = self._get_ide(cwd=dir)
|
74
|
+
open_ide(dir, ide=ide)
|
75
|
+
|
76
|
+
|
77
|
+
def _main() -> None:
|
78
|
+
IntellijCli()(exit=True)
|
79
|
+
|
80
|
+
|
81
|
+
# @omlish-manifest
|
82
|
+
_CLI_MODULE = CliModule(['intellij', 'ij'], __name__)
|
83
|
+
|
84
|
+
|
85
|
+
if __name__ == '__main__':
|
86
|
+
_main()
|
omdev/intellij/ides.py
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- read .idea/ for inference?
|
4
|
+
"""
|
5
|
+
import enum
|
6
|
+
import os.path
|
7
|
+
import typing as ta
|
8
|
+
|
9
|
+
from omlish.diag.pycharm import get_pycharm_version
|
10
|
+
|
11
|
+
|
12
|
+
##
|
13
|
+
|
14
|
+
|
15
|
+
class Ide(enum.Enum):
|
16
|
+
PYCHARM = enum.auto()
|
17
|
+
IDEA = enum.auto()
|
18
|
+
CLION = enum.auto()
|
19
|
+
WEBSTORM = enum.auto()
|
20
|
+
GOLAND = enum.auto()
|
21
|
+
|
22
|
+
|
23
|
+
##
|
24
|
+
|
25
|
+
|
26
|
+
_INFER_FILE_NAME_SETS_BY_IDE: ta.Mapping[Ide, ta.AbstractSet[str]] = {
|
27
|
+
Ide.PYCHARM: frozenset([
|
28
|
+
'setup.py',
|
29
|
+
'setup.cfg',
|
30
|
+
'pyproject.toml',
|
31
|
+
'requirements.txt',
|
32
|
+
'Pipfile',
|
33
|
+
'poetry.lock',
|
34
|
+
'.python-version',
|
35
|
+
'wsgi.py',
|
36
|
+
'asgi.py',
|
37
|
+
'manage.py',
|
38
|
+
]),
|
39
|
+
Ide.IDEA: frozenset([
|
40
|
+
'pom.xml',
|
41
|
+
'mvnw',
|
42
|
+
'build.gradle',
|
43
|
+
'build.gradle.kts',
|
44
|
+
'gradlew',
|
45
|
+
'module-info.java',
|
46
|
+
'.java-version',
|
47
|
+
]),
|
48
|
+
Ide.CLION: frozenset([
|
49
|
+
'CMakeLists.txt',
|
50
|
+
'configure.ac',
|
51
|
+
'configure.in',
|
52
|
+
'config.h.in',
|
53
|
+
'vcpkg.json',
|
54
|
+
]),
|
55
|
+
Ide.WEBSTORM: frozenset([
|
56
|
+
'package.json',
|
57
|
+
'package-lock.json',
|
58
|
+
]),
|
59
|
+
Ide.GOLAND: frozenset([
|
60
|
+
'go.mod',
|
61
|
+
'go.sum',
|
62
|
+
]),
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
def infer_directory_ide(cwd: str | None) -> Ide | None:
|
67
|
+
if cwd is None:
|
68
|
+
cwd = os.getcwd()
|
69
|
+
|
70
|
+
for i, fs in _INFER_FILE_NAME_SETS_BY_IDE.items():
|
71
|
+
for f in fs:
|
72
|
+
if os.path.exists(os.path.join(cwd, f)):
|
73
|
+
return i
|
74
|
+
|
75
|
+
return None
|
76
|
+
|
77
|
+
|
78
|
+
##
|
79
|
+
|
80
|
+
|
81
|
+
def get_ide_version(ide: Ide) -> str:
|
82
|
+
if ide is Ide.PYCHARM:
|
83
|
+
return get_pycharm_version()
|
84
|
+
else:
|
85
|
+
raise ValueError(ide)
|
omdev/intellij/open.py
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
import dataclasses as dc
|
2
|
+
import os.path
|
3
|
+
import shlex
|
4
|
+
import subprocess
|
5
|
+
import sys
|
6
|
+
import tempfile
|
7
|
+
import typing as ta
|
8
|
+
|
9
|
+
from .ides import Ide
|
10
|
+
from .ides import infer_directory_ide
|
11
|
+
|
12
|
+
|
13
|
+
##
|
14
|
+
|
15
|
+
|
16
|
+
_DARWIN_OPEN_SCRIPT_APP_BY_IDE: ta.Mapping[Ide, str] = {
|
17
|
+
Ide.PYCHARM: 'PyCharm',
|
18
|
+
Ide.CLION: 'CLion',
|
19
|
+
Ide.IDEA: 'IntelliJ IDEA',
|
20
|
+
Ide.WEBSTORM: 'WebStorm',
|
21
|
+
Ide.GOLAND: 'GoLand',
|
22
|
+
}
|
23
|
+
|
24
|
+
_DARWIN_OPEN_SCRIPT = """
|
25
|
+
tell application "{app}"
|
26
|
+
activate
|
27
|
+
open "{dir}"
|
28
|
+
end tell
|
29
|
+
return
|
30
|
+
"""
|
31
|
+
|
32
|
+
|
33
|
+
#
|
34
|
+
|
35
|
+
|
36
|
+
_LINUX_WM_CLASS_BY_IDE: ta.Mapping[Ide, str] = {
|
37
|
+
Ide.PYCHARM: 'jetbrains-pycharm.jetbrains-pycharm',
|
38
|
+
Ide.CLION: 'jetbrains-clion.jetbrains-clion',
|
39
|
+
Ide.IDEA: 'jetbrains-idea.jetbrains-idea',
|
40
|
+
Ide.WEBSTORM: 'jetbrains-webstorm.jetbrains-webstorm',
|
41
|
+
Ide.GOLAND: 'jetbrains-goland.jetbrains-goland',
|
42
|
+
}
|
43
|
+
|
44
|
+
|
45
|
+
# sudo apt install xdotool wmctrl
|
46
|
+
# TODO: nohup pycharm.sh "$PROJECT_PATH" > /dev/null 2>&1 & ?
|
47
|
+
_LINUX_OPEN_SCRIPT = """
|
48
|
+
xdotool key --delay 1000 alt+f alt+o
|
49
|
+
xdotool type --delay 1000 {dir}
|
50
|
+
xdotool key Return
|
51
|
+
"""
|
52
|
+
|
53
|
+
|
54
|
+
@dc.dataclass(frozen=True)
|
55
|
+
class _WmctrlLine:
|
56
|
+
window_id: str
|
57
|
+
desktop_id: str
|
58
|
+
pid: str
|
59
|
+
wm_class: str
|
60
|
+
user: str
|
61
|
+
title: str
|
62
|
+
|
63
|
+
|
64
|
+
# TODO: https://stackoverflow.com/a/79016360
|
65
|
+
def _parse_wmctrl_lxp_line(l: str) -> _WmctrlLine:
|
66
|
+
return _WmctrlLine(*l.strip().split(maxsplit=5))
|
67
|
+
|
68
|
+
|
69
|
+
#
|
70
|
+
|
71
|
+
|
72
|
+
def open_ide(
|
73
|
+
dir: str, # noqa
|
74
|
+
*,
|
75
|
+
ide: Ide | None = None,
|
76
|
+
default_ide: Ide = Ide.PYCHARM,
|
77
|
+
) -> None:
|
78
|
+
if ide is None:
|
79
|
+
if (ide := infer_directory_ide(dir)) is None:
|
80
|
+
ide = default_ide
|
81
|
+
|
82
|
+
if (plat := sys.platform) == 'darwin':
|
83
|
+
if '"' in dir:
|
84
|
+
raise ValueError(dir)
|
85
|
+
|
86
|
+
scpt_src = _DARWIN_OPEN_SCRIPT.format(
|
87
|
+
app=_DARWIN_OPEN_SCRIPT_APP_BY_IDE[ide],
|
88
|
+
dir=dir,
|
89
|
+
)
|
90
|
+
|
91
|
+
scpt_file = tempfile.mktemp(__package__ + '-intellij-open') # noqa
|
92
|
+
with open(scpt_file, 'w') as f:
|
93
|
+
f.write(scpt_src)
|
94
|
+
|
95
|
+
subprocess.check_call(['osascript', scpt_file])
|
96
|
+
|
97
|
+
elif plat == 'linux':
|
98
|
+
env = os.environ
|
99
|
+
env.setdefault('DISPLAY', ':1')
|
100
|
+
|
101
|
+
wmc_out = subprocess.check_output(['wmctrl', '-lxp'], env=env).decode()
|
102
|
+
wls = [_parse_wmctrl_lxp_line(l) for l in wmc_out.splitlines()]
|
103
|
+
tgt_wmc = _LINUX_WM_CLASS_BY_IDE[ide]
|
104
|
+
tgt_wl = next(wl for wl in wls if wl.wm_class == tgt_wmc)
|
105
|
+
subprocess.check_call(['wmctrl', '-ia', tgt_wl.window_id], env=env)
|
106
|
+
|
107
|
+
scpt = _LINUX_OPEN_SCRIPT.format(dir=shlex.quote(os.path.expanduser(dir)))
|
108
|
+
print(scpt)
|
109
|
+
# subprocess.check_call(scpt, shell=True, env=env) # noqa
|
110
|
+
raise NotImplementedError
|
111
|
+
|
112
|
+
else:
|
113
|
+
raise OSError(plat)
|
omdev/scripts/ci.py
CHANGED
@@ -4753,7 +4753,6 @@ inj = InjectionApi()
|
|
4753
4753
|
"""
|
4754
4754
|
TODO:
|
4755
4755
|
- pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
|
4756
|
-
- literals
|
4757
4756
|
- Options.sequence_cls = list, mapping_cls = dict, ... - def with_mutable_containers() -> Options
|
4758
4757
|
"""
|
4759
4758
|
|
@@ -4867,6 +4866,28 @@ class OptionalObjMarshaler(ObjMarshaler):
|
|
4867
4866
|
return self.item.unmarshal(o, ctx)
|
4868
4867
|
|
4869
4868
|
|
4869
|
+
@dc.dataclass(frozen=True)
|
4870
|
+
class PrimitiveUnionObjMarshaler(ObjMarshaler):
|
4871
|
+
pt: ta.Tuple[type, ...]
|
4872
|
+
x: ta.Optional[ObjMarshaler] = None
|
4873
|
+
|
4874
|
+
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
4875
|
+
if isinstance(o, self.pt):
|
4876
|
+
return o
|
4877
|
+
elif self.x is not None:
|
4878
|
+
return self.x.marshal(o, ctx)
|
4879
|
+
else:
|
4880
|
+
raise TypeError(o)
|
4881
|
+
|
4882
|
+
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
4883
|
+
if isinstance(o, self.pt):
|
4884
|
+
return o
|
4885
|
+
elif self.x is not None:
|
4886
|
+
return self.x.unmarshal(o, ctx)
|
4887
|
+
else:
|
4888
|
+
raise TypeError(o)
|
4889
|
+
|
4890
|
+
|
4870
4891
|
@dc.dataclass(frozen=True)
|
4871
4892
|
class LiteralObjMarshaler(ObjMarshaler):
|
4872
4893
|
item: ObjMarshaler
|
@@ -5065,6 +5086,13 @@ _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES: ta.Dict[ta.Any, type] = {
|
|
5065
5086
|
collections.abc.MutableSequence: list,
|
5066
5087
|
}
|
5067
5088
|
|
5089
|
+
_OBJ_MARSHALER_PRIMITIVE_TYPES: ta.Set[type] = {
|
5090
|
+
int,
|
5091
|
+
float,
|
5092
|
+
bool,
|
5093
|
+
str,
|
5094
|
+
}
|
5095
|
+
|
5068
5096
|
|
5069
5097
|
##
|
5070
5098
|
|
@@ -5213,8 +5241,16 @@ class ObjMarshalerManager:
|
|
5213
5241
|
|
5214
5242
|
if is_literal_type(ty):
|
5215
5243
|
lvs = frozenset(get_literal_type_args(ty))
|
5244
|
+
if None in lvs:
|
5245
|
+
is_opt = True
|
5246
|
+
lvs -= frozenset([None])
|
5247
|
+
else:
|
5248
|
+
is_opt = False
|
5216
5249
|
lty = check.single(set(map(type, lvs)))
|
5217
|
-
|
5250
|
+
lm: ObjMarshaler = LiteralObjMarshaler(rec(lty), lvs)
|
5251
|
+
if is_opt:
|
5252
|
+
lm = OptionalObjMarshaler(lm)
|
5253
|
+
return lm
|
5218
5254
|
|
5219
5255
|
if is_generic_alias(ty):
|
5220
5256
|
try:
|
@@ -5234,7 +5270,31 @@ class ObjMarshalerManager:
|
|
5234
5270
|
return IterableObjMarshaler(st, rec(e))
|
5235
5271
|
|
5236
5272
|
if is_union_alias(ty):
|
5237
|
-
|
5273
|
+
uts = frozenset(ta.get_args(ty))
|
5274
|
+
if None in uts or type(None) in uts:
|
5275
|
+
is_opt = True
|
5276
|
+
uts = frozenset(ut for ut in uts if ut not in (None, type(None)))
|
5277
|
+
else:
|
5278
|
+
is_opt = False
|
5279
|
+
|
5280
|
+
um: ObjMarshaler
|
5281
|
+
if not uts:
|
5282
|
+
raise TypeError(ty)
|
5283
|
+
elif len(uts) == 1:
|
5284
|
+
um = rec(check.single(uts))
|
5285
|
+
else:
|
5286
|
+
pt = tuple({ut for ut in uts if ut in _OBJ_MARSHALER_PRIMITIVE_TYPES})
|
5287
|
+
np_uts = {ut for ut in uts if ut not in _OBJ_MARSHALER_PRIMITIVE_TYPES}
|
5288
|
+
if not np_uts:
|
5289
|
+
um = PrimitiveUnionObjMarshaler(pt)
|
5290
|
+
elif len(np_uts) == 1:
|
5291
|
+
um = PrimitiveUnionObjMarshaler(pt, x=rec(check.single(np_uts)))
|
5292
|
+
else:
|
5293
|
+
raise TypeError(ty)
|
5294
|
+
|
5295
|
+
if is_opt:
|
5296
|
+
um = OptionalObjMarshaler(um)
|
5297
|
+
return um
|
5238
5298
|
|
5239
5299
|
raise TypeError(ty)
|
5240
5300
|
|
omdev/scripts/pyproject.py
CHANGED
@@ -5508,7 +5508,6 @@ inj = InjectionApi()
|
|
5508
5508
|
"""
|
5509
5509
|
TODO:
|
5510
5510
|
- pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
|
5511
|
-
- literals
|
5512
5511
|
- Options.sequence_cls = list, mapping_cls = dict, ... - def with_mutable_containers() -> Options
|
5513
5512
|
"""
|
5514
5513
|
|
@@ -5622,6 +5621,28 @@ class OptionalObjMarshaler(ObjMarshaler):
|
|
5622
5621
|
return self.item.unmarshal(o, ctx)
|
5623
5622
|
|
5624
5623
|
|
5624
|
+
@dc.dataclass(frozen=True)
|
5625
|
+
class PrimitiveUnionObjMarshaler(ObjMarshaler):
|
5626
|
+
pt: ta.Tuple[type, ...]
|
5627
|
+
x: ta.Optional[ObjMarshaler] = None
|
5628
|
+
|
5629
|
+
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
5630
|
+
if isinstance(o, self.pt):
|
5631
|
+
return o
|
5632
|
+
elif self.x is not None:
|
5633
|
+
return self.x.marshal(o, ctx)
|
5634
|
+
else:
|
5635
|
+
raise TypeError(o)
|
5636
|
+
|
5637
|
+
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
5638
|
+
if isinstance(o, self.pt):
|
5639
|
+
return o
|
5640
|
+
elif self.x is not None:
|
5641
|
+
return self.x.unmarshal(o, ctx)
|
5642
|
+
else:
|
5643
|
+
raise TypeError(o)
|
5644
|
+
|
5645
|
+
|
5625
5646
|
@dc.dataclass(frozen=True)
|
5626
5647
|
class LiteralObjMarshaler(ObjMarshaler):
|
5627
5648
|
item: ObjMarshaler
|
@@ -5820,6 +5841,13 @@ _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES: ta.Dict[ta.Any, type] = {
|
|
5820
5841
|
collections.abc.MutableSequence: list,
|
5821
5842
|
}
|
5822
5843
|
|
5844
|
+
_OBJ_MARSHALER_PRIMITIVE_TYPES: ta.Set[type] = {
|
5845
|
+
int,
|
5846
|
+
float,
|
5847
|
+
bool,
|
5848
|
+
str,
|
5849
|
+
}
|
5850
|
+
|
5823
5851
|
|
5824
5852
|
##
|
5825
5853
|
|
@@ -5968,8 +5996,16 @@ class ObjMarshalerManager:
|
|
5968
5996
|
|
5969
5997
|
if is_literal_type(ty):
|
5970
5998
|
lvs = frozenset(get_literal_type_args(ty))
|
5999
|
+
if None in lvs:
|
6000
|
+
is_opt = True
|
6001
|
+
lvs -= frozenset([None])
|
6002
|
+
else:
|
6003
|
+
is_opt = False
|
5971
6004
|
lty = check.single(set(map(type, lvs)))
|
5972
|
-
|
6005
|
+
lm: ObjMarshaler = LiteralObjMarshaler(rec(lty), lvs)
|
6006
|
+
if is_opt:
|
6007
|
+
lm = OptionalObjMarshaler(lm)
|
6008
|
+
return lm
|
5973
6009
|
|
5974
6010
|
if is_generic_alias(ty):
|
5975
6011
|
try:
|
@@ -5989,7 +6025,31 @@ class ObjMarshalerManager:
|
|
5989
6025
|
return IterableObjMarshaler(st, rec(e))
|
5990
6026
|
|
5991
6027
|
if is_union_alias(ty):
|
5992
|
-
|
6028
|
+
uts = frozenset(ta.get_args(ty))
|
6029
|
+
if None in uts or type(None) in uts:
|
6030
|
+
is_opt = True
|
6031
|
+
uts = frozenset(ut for ut in uts if ut not in (None, type(None)))
|
6032
|
+
else:
|
6033
|
+
is_opt = False
|
6034
|
+
|
6035
|
+
um: ObjMarshaler
|
6036
|
+
if not uts:
|
6037
|
+
raise TypeError(ty)
|
6038
|
+
elif len(uts) == 1:
|
6039
|
+
um = rec(check.single(uts))
|
6040
|
+
else:
|
6041
|
+
pt = tuple({ut for ut in uts if ut in _OBJ_MARSHALER_PRIMITIVE_TYPES})
|
6042
|
+
np_uts = {ut for ut in uts if ut not in _OBJ_MARSHALER_PRIMITIVE_TYPES}
|
6043
|
+
if not np_uts:
|
6044
|
+
um = PrimitiveUnionObjMarshaler(pt)
|
6045
|
+
elif len(np_uts) == 1:
|
6046
|
+
um = PrimitiveUnionObjMarshaler(pt, x=rec(check.single(np_uts)))
|
6047
|
+
else:
|
6048
|
+
raise TypeError(ty)
|
6049
|
+
|
6050
|
+
if is_opt:
|
6051
|
+
um = OptionalObjMarshaler(um)
|
6052
|
+
return um
|
5993
6053
|
|
5994
6054
|
raise TypeError(ty)
|
5995
6055
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: omdev
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev373
|
4
4
|
Summary: omdev
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Operating System :: POSIX
|
13
13
|
Requires-Python: >=3.13
|
14
14
|
License-File: LICENSE
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
15
|
+
Requires-Dist: omlish==0.0.0.dev373
|
16
16
|
Provides-Extra: all
|
17
17
|
Requires-Dist: black~=25.1; extra == "all"
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
omdev/.manifests.json,sha256=
|
1
|
+
omdev/.manifests.json,sha256=cprM065HGO3vKL_ru2fzUGi-J3goZ_jMLkm_B3qGM94,11863
|
2
2
|
omdev/__about__.py,sha256=_c693iMsl07FKXJ_2zrWiE8t84SSbDxlCrash1rJR7M,1202
|
3
3
|
omdev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
omdev/cmake.py,sha256=9rfSvFHPmKDj9ngvfDB2vK8O-xO_ZwUm7hMKLWA-yOw,4578
|
@@ -132,6 +132,10 @@ omdev/home/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
132
132
|
omdev/home/paths.py,sha256=tnRuEzA1nRc9NJKGSxyZMOLlZBk5Da0AQhNeSmBozYA,1331
|
133
133
|
omdev/home/secrets.py,sha256=XarB-uhwjRc3dpT5ZF-9yoRPDr7kpyr4Hgs0I4kKL4I,1992
|
134
134
|
omdev/home/shadow.py,sha256=6mGDJV70IExa-nzd7mOUW4R3OZIXO0fBwmOUU9T9f4M,295
|
135
|
+
omdev/intellij/__init__.py,sha256=OkihYdld_LTk_gTcyzOWc9Nze_drjsIYMYpbA5DG6m4,132
|
136
|
+
omdev/intellij/cli.py,sha256=Sds9Xj_OHgbm76j70frhwrZEzlVi-1Rd93g0ypIe6t4,2038
|
137
|
+
omdev/intellij/ides.py,sha256=ll-NKTKeS6ZgcWB3xYXr3gxGFgNOc0ZPulTimHkvU9Y,1573
|
138
|
+
omdev/intellij/open.py,sha256=3HlbJsGkwZ28UBi1P7dVJMRDMLbJyOGQs9QMQqgYVus,2679
|
135
139
|
omdev/interp/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
136
140
|
omdev/interp/__main__.py,sha256=GMCqeGYltgt5dlJzHxY9gqisa8cRkrPfmZYuZnjg4WI,162
|
137
141
|
omdev/interp/cli.py,sha256=xYZHts_tYuWPenTTLQIQ-I1JWHao6XolsH0R73AufDY,2380
|
@@ -253,9 +257,9 @@ omdev/pyproject/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
253
257
|
omdev/pyproject/resources/docker-dev.sh,sha256=DHkz5D18jok_oDolfg2mqrvGRWFoCe9GQo04dR1czcc,838
|
254
258
|
omdev/pyproject/resources/python.sh,sha256=rFaN4SiJ9hdLDXXsDTwugI6zsw6EPkgYMmtacZeTbvw,749
|
255
259
|
omdev/scripts/__init__.py,sha256=MKCvUAEQwsIvwLixwtPlpBqmkMXLCnjjXyAXvVpDwVk,91
|
256
|
-
omdev/scripts/ci.py,sha256=
|
260
|
+
omdev/scripts/ci.py,sha256=R-zzmbR38A68_5Qvfo8RRnyeBhBej6FwB4a7LZMNvqw,362103
|
257
261
|
omdev/scripts/interp.py,sha256=T8EdNxuncwqCXfIBfCLoUcsYNqEhOrOE8V1hC9vTzqI,158095
|
258
|
-
omdev/scripts/pyproject.py,sha256=
|
262
|
+
omdev/scripts/pyproject.py,sha256=Hwy7pK9-_qk3Uayer5kqDWeS8T5OSo0kZZzPqPXUA8U,269593
|
259
263
|
omdev/scripts/slowcat.py,sha256=lssv4yrgJHiWfOiHkUut2p8E8Tq32zB-ujXESQxFFHY,2728
|
260
264
|
omdev/scripts/tmpexec.py,sha256=WTYcf56Tj2qjYV14AWmV8SfT0u6Y8eIU6cKgQRvEK3c,1442
|
261
265
|
omdev/tokens/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -267,7 +271,6 @@ omdev/tools/cloc.py,sha256=BiIf2PnnoRH6ByH4mnua69Vv-ZDPHsSAPUds7giRolI,6013
|
|
267
271
|
omdev/tools/diff.py,sha256=S6ddB7pBeMtzKh2hiHfzQ93pj6mclKt1UZQMKy4Bt5M,520
|
268
272
|
omdev/tools/doc.py,sha256=PCtqDjFA55Ed4QVUpMiw05NwyXivCeox-ZE_JDN0BD0,2575
|
269
273
|
omdev/tools/docker.py,sha256=4TdpKiWMr9eCffAPHo6sAWGURGTYMY5AK_F5lmnwlJA,7363
|
270
|
-
omdev/tools/intellij.py,sha256=yy6Uw2hcYyEWLZESAupKvd3U6omirYMbjnbw7UllhV4,5834
|
271
274
|
omdev/tools/linehisto.py,sha256=0ZNm34EuiZBE9Q2YC6KNLNNydNT8QPSOwvYzXiU9S2Q,8881
|
272
275
|
omdev/tools/mkenv.py,sha256=G2tu5bmiyKFyZuqtUoM7Z-6AI6CI86F2LwoIozoWOvo,2300
|
273
276
|
omdev/tools/notebook.py,sha256=MGi2JEwyIPR1n7gakaaYZL1HHbSVmDKGQROqH56ppgU,3499
|
@@ -304,9 +307,9 @@ omdev/tools/jsonview/resources/jsonview.js,sha256=faDvXDOXKvEvjOuIlz4D3F2ReQXb_b
|
|
304
307
|
omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
305
308
|
omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
|
306
309
|
omdev/tools/pawk/pawk.py,sha256=ao5mdrpiSU4AZ8mBozoEaV3UVlmVTnRG9wD9XP70MZE,11429
|
307
|
-
omdev-0.0.0.
|
308
|
-
omdev-0.0.0.
|
309
|
-
omdev-0.0.0.
|
310
|
-
omdev-0.0.0.
|
311
|
-
omdev-0.0.0.
|
312
|
-
omdev-0.0.0.
|
310
|
+
omdev-0.0.0.dev373.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
311
|
+
omdev-0.0.0.dev373.dist-info/METADATA,sha256=zGQo4AZ9GWEy7Aymxc7RH7vOJP5XlUtay1iKjAJF4q8,1674
|
312
|
+
omdev-0.0.0.dev373.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
313
|
+
omdev-0.0.0.dev373.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
|
314
|
+
omdev-0.0.0.dev373.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
|
315
|
+
omdev-0.0.0.dev373.dist-info/RECORD,,
|
omdev/tools/intellij.py
DELETED
@@ -1,253 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
TODO:
|
3
|
-
- read .idea/ for inference?
|
4
|
-
- PyCharm.app/Contents/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_constants.py -> USE_LOW_IMPACT_MONITORING
|
5
|
-
- DISPLAY=":1" - ls /tmp/.X11-unix/X1 ?
|
6
|
-
- https://unix.stackexchange.com/questions/17255/is-there-a-command-to-list-all-open-displays-on-a-machine
|
7
|
-
- w -oush
|
8
|
-
"""
|
9
|
-
import dataclasses as dc
|
10
|
-
import enum
|
11
|
-
import inspect
|
12
|
-
import os.path
|
13
|
-
import shlex
|
14
|
-
import subprocess
|
15
|
-
import sys
|
16
|
-
import tempfile
|
17
|
-
import typing as ta
|
18
|
-
|
19
|
-
from omlish.argparse import all as ap
|
20
|
-
from omlish.diag.pycharm import get_pycharm_version
|
21
|
-
|
22
|
-
from ..cli import CliModule
|
23
|
-
|
24
|
-
|
25
|
-
##
|
26
|
-
|
27
|
-
|
28
|
-
class Ide(enum.Enum):
|
29
|
-
PYCHARM = enum.auto()
|
30
|
-
IDEA = enum.auto()
|
31
|
-
CLION = enum.auto()
|
32
|
-
WEBSTORM = enum.auto()
|
33
|
-
GOLAND = enum.auto()
|
34
|
-
|
35
|
-
|
36
|
-
##
|
37
|
-
|
38
|
-
|
39
|
-
_INFER_FILE_NAME_SETS_BY_IDE: ta.Mapping[Ide, ta.AbstractSet[str]] = {
|
40
|
-
Ide.PYCHARM: frozenset([
|
41
|
-
'setup.py',
|
42
|
-
'setup.cfg',
|
43
|
-
'pyproject.toml',
|
44
|
-
'requirements.txt',
|
45
|
-
'Pipfile',
|
46
|
-
'poetry.lock',
|
47
|
-
'.python-version',
|
48
|
-
'wsgi.py',
|
49
|
-
'asgi.py',
|
50
|
-
'manage.py',
|
51
|
-
]),
|
52
|
-
Ide.IDEA: frozenset([
|
53
|
-
'pom.xml',
|
54
|
-
'mvnw',
|
55
|
-
'build.gradle',
|
56
|
-
'build.gradle.kts',
|
57
|
-
'gradlew',
|
58
|
-
'module-info.java',
|
59
|
-
'.java-version',
|
60
|
-
]),
|
61
|
-
Ide.CLION: frozenset([
|
62
|
-
'CMakeLists.txt',
|
63
|
-
'configure.ac',
|
64
|
-
'configure.in',
|
65
|
-
'config.h.in',
|
66
|
-
'vcpkg.json',
|
67
|
-
]),
|
68
|
-
Ide.WEBSTORM: frozenset([
|
69
|
-
'package.json',
|
70
|
-
'package-lock.json',
|
71
|
-
]),
|
72
|
-
Ide.GOLAND: frozenset([
|
73
|
-
'go.mod',
|
74
|
-
'go.sum',
|
75
|
-
]),
|
76
|
-
}
|
77
|
-
|
78
|
-
|
79
|
-
def _infer_directory_ide(cwd: str | None) -> Ide | None:
|
80
|
-
if cwd is None:
|
81
|
-
cwd = os.getcwd()
|
82
|
-
|
83
|
-
for i, fs in _INFER_FILE_NAME_SETS_BY_IDE.items():
|
84
|
-
for f in fs:
|
85
|
-
if os.path.exists(os.path.join(cwd, f)):
|
86
|
-
return i
|
87
|
-
|
88
|
-
return None
|
89
|
-
|
90
|
-
|
91
|
-
##
|
92
|
-
|
93
|
-
|
94
|
-
def _get_ide_version(ide: Ide) -> str:
|
95
|
-
if ide is Ide.PYCHARM:
|
96
|
-
return get_pycharm_version()
|
97
|
-
else:
|
98
|
-
raise ValueError(ide)
|
99
|
-
|
100
|
-
|
101
|
-
##
|
102
|
-
|
103
|
-
|
104
|
-
_DARWIN_OPEN_SCRIPT_APP_BY_IDE: ta.Mapping[Ide, str] = {
|
105
|
-
Ide.PYCHARM: 'PyCharm',
|
106
|
-
Ide.CLION: 'CLion',
|
107
|
-
Ide.IDEA: 'IntelliJ IDEA',
|
108
|
-
Ide.WEBSTORM: 'WebStorm',
|
109
|
-
Ide.GOLAND: 'GoLand',
|
110
|
-
}
|
111
|
-
|
112
|
-
_DARWIN_OPEN_SCRIPT = """
|
113
|
-
tell application "{app}"
|
114
|
-
activate
|
115
|
-
open "{dir}"
|
116
|
-
end tell
|
117
|
-
return
|
118
|
-
"""
|
119
|
-
|
120
|
-
|
121
|
-
##
|
122
|
-
|
123
|
-
|
124
|
-
_LINUX_WM_CLASS_BY_IDE: ta.Mapping[Ide, str] = {
|
125
|
-
Ide.PYCHARM: 'jetbrains-pycharm.jetbrains-pycharm',
|
126
|
-
Ide.CLION: 'jetbrains-clion.jetbrains-clion',
|
127
|
-
Ide.IDEA: 'jetbrains-idea.jetbrains-idea',
|
128
|
-
Ide.WEBSTORM: 'jetbrains-webstorm.jetbrains-webstorm',
|
129
|
-
Ide.GOLAND: 'jetbrains-goland.jetbrains-goland',
|
130
|
-
}
|
131
|
-
|
132
|
-
|
133
|
-
# sudo apt install xdotool wmctrl
|
134
|
-
# TODO: nohup pycharm.sh "$PROJECT_PATH" > /dev/null 2>&1 & ?
|
135
|
-
_LINUX_OPEN_SCRIPT = """
|
136
|
-
xdotool key --delay 1000 alt+f alt+o
|
137
|
-
xdotool type --delay 1000 {dir}
|
138
|
-
xdotool key Return
|
139
|
-
"""
|
140
|
-
|
141
|
-
|
142
|
-
@dc.dataclass(frozen=True)
|
143
|
-
class WmctrlLine:
|
144
|
-
window_id: str
|
145
|
-
desktop_id: str
|
146
|
-
pid: str
|
147
|
-
wm_class: str
|
148
|
-
user: str
|
149
|
-
title: str
|
150
|
-
|
151
|
-
|
152
|
-
# TODO: https://stackoverflow.com/a/79016360
|
153
|
-
def parse_wmctrl_lxp_line(l: str) -> WmctrlLine:
|
154
|
-
return WmctrlLine(*l.strip().split(maxsplit=5))
|
155
|
-
|
156
|
-
|
157
|
-
##
|
158
|
-
|
159
|
-
|
160
|
-
class IntellijCli(ap.Cli):
|
161
|
-
@ap.cmd(
|
162
|
-
ap.arg('python-exe'),
|
163
|
-
ap.arg('args', nargs=ap.REMAINDER),
|
164
|
-
)
|
165
|
-
def pycharm_runhack(self) -> int:
|
166
|
-
if not os.path.isfile(exe := self.args.python_exe):
|
167
|
-
raise FileNotFoundError(exe)
|
168
|
-
|
169
|
-
from omlish.diag._pycharm import runhack # noqa
|
170
|
-
src = inspect.getsource(runhack)
|
171
|
-
|
172
|
-
src_file = tempfile.mktemp(__package__ + '-runhack') # noqa
|
173
|
-
with open(src_file, 'w') as f:
|
174
|
-
f.write(src)
|
175
|
-
|
176
|
-
proc = subprocess.run([exe, src_file, *self.args.args], check=False)
|
177
|
-
return proc.returncode
|
178
|
-
|
179
|
-
#
|
180
|
-
|
181
|
-
def _get_ide(
|
182
|
-
self,
|
183
|
-
*,
|
184
|
-
cwd: str | None = None,
|
185
|
-
) -> Ide: # noqa
|
186
|
-
if (ai := self.args.ide) is not None:
|
187
|
-
return Ide[ai.upper()] # noqa
|
188
|
-
|
189
|
-
if (ii := _infer_directory_ide(cwd)) is not None:
|
190
|
-
return ii
|
191
|
-
|
192
|
-
return Ide.PYCHARM
|
193
|
-
|
194
|
-
@ap.cmd(
|
195
|
-
ap.arg('-e', '--ide'),
|
196
|
-
)
|
197
|
-
def version(self) -> None:
|
198
|
-
i = self._get_ide()
|
199
|
-
v = _get_ide_version(i)
|
200
|
-
print(v)
|
201
|
-
|
202
|
-
@ap.cmd(
|
203
|
-
ap.arg('dir', nargs='?'),
|
204
|
-
ap.arg('-e', '--ide'),
|
205
|
-
)
|
206
|
-
def open(self) -> None:
|
207
|
-
dir = os.path.abspath(self.args.dir or '.') # noqa
|
208
|
-
ide = self._get_ide(cwd=dir)
|
209
|
-
|
210
|
-
if (plat := sys.platform) == 'darwin':
|
211
|
-
if '"' in dir:
|
212
|
-
raise ValueError(dir)
|
213
|
-
|
214
|
-
scpt_src = _DARWIN_OPEN_SCRIPT.format(
|
215
|
-
app=_DARWIN_OPEN_SCRIPT_APP_BY_IDE[ide],
|
216
|
-
dir=dir,
|
217
|
-
)
|
218
|
-
|
219
|
-
scpt_file = tempfile.mktemp(__package__ + '-intellij-open') # noqa
|
220
|
-
with open(scpt_file, 'w') as f:
|
221
|
-
f.write(scpt_src)
|
222
|
-
|
223
|
-
subprocess.check_call(['osascript', scpt_file])
|
224
|
-
|
225
|
-
elif plat == 'linux':
|
226
|
-
env = os.environ
|
227
|
-
env.setdefault('DISPLAY', ':1')
|
228
|
-
|
229
|
-
wmc_out = subprocess.check_output(['wmctrl', '-lxp'], env=env).decode()
|
230
|
-
wls = [parse_wmctrl_lxp_line(l) for l in wmc_out.splitlines()]
|
231
|
-
tgt_wmc = _LINUX_WM_CLASS_BY_IDE[ide]
|
232
|
-
tgt_wl = next(wl for wl in wls if wl.wm_class == tgt_wmc)
|
233
|
-
subprocess.check_call(['wmctrl', '-ia', tgt_wl.window_id], env=env)
|
234
|
-
|
235
|
-
scpt = _LINUX_OPEN_SCRIPT.format(dir=shlex.quote(os.path.expanduser(dir)))
|
236
|
-
print(scpt)
|
237
|
-
# subprocess.check_call(scpt, shell=True, env=env) # noqa
|
238
|
-
raise NotImplementedError
|
239
|
-
|
240
|
-
else:
|
241
|
-
raise OSError(plat)
|
242
|
-
|
243
|
-
|
244
|
-
def _main() -> None:
|
245
|
-
IntellijCli()(exit=True)
|
246
|
-
|
247
|
-
|
248
|
-
# @omlish-manifest
|
249
|
-
_CLI_MODULE = CliModule(['intellij', 'ij'], __name__)
|
250
|
-
|
251
|
-
|
252
|
-
if __name__ == '__main__':
|
253
|
-
_main()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|