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 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",
@@ -0,0 +1,11 @@
1
+ from .ides import ( # noqa
2
+ Ide,
3
+
4
+ infer_directory_ide,
5
+
6
+ get_ide_version,
7
+ )
8
+
9
+ from .open import ( # noqa
10
+ open_ide,
11
+ )
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
- return LiteralObjMarshaler(rec(lty), lvs)
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
- return OptionalObjMarshaler(rec(get_optional_alias_arg(ty)))
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
 
@@ -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
- return LiteralObjMarshaler(rec(lty), lvs)
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
- return OptionalObjMarshaler(rec(get_optional_alias_arg(ty)))
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.dev372
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.dev372
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=_LJ5KSvdCmh-6Pp6pXzha4pbPOwD3F_QQNH2JpewWHk,11870
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=tzVEK-JKZ4WNDGAziUbXpw_HEuYGQiMhsxUmM-usvu0,360136
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=qBBXmbdKMYzqxnb0zEWYhCOg9Cy0pWno3wjulICFj_o,267626
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.dev372.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
308
- omdev-0.0.0.dev372.dist-info/METADATA,sha256=MQ778T7dZ0Qmc0WSp9cqsPqVYnSPZE5GE97jij-hyEo,1674
309
- omdev-0.0.0.dev372.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
310
- omdev-0.0.0.dev372.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
311
- omdev-0.0.0.dev372.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
312
- omdev-0.0.0.dev372.dist-info/RECORD,,
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()