omdev 0.0.0.dev305__py3-none-any.whl → 0.0.0.dev307__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
@@ -47,6 +47,18 @@
47
47
  }
48
48
  }
49
49
  },
50
+ {
51
+ "module": ".cmdlog.__main__",
52
+ "attr": "_CLI_MODULE",
53
+ "file": "omdev/cmdlog/__main__.py",
54
+ "line": 4,
55
+ "value": {
56
+ "$.cli.types.CliModule": {
57
+ "cmd_name": "cmdlog",
58
+ "mod_name": "omdev.cmdlog.__main__"
59
+ }
60
+ }
61
+ },
50
62
  {
51
63
  "module": ".imgur",
52
64
  "attr": "_FOO_CLI_MODULE",
@@ -0,0 +1,7 @@
1
+ from ._cmdlog import ( # noqa
2
+ CmdLogEntry,
3
+ )
4
+
5
+ from .cmdlog import ( # noqa
6
+ CmdLog,
7
+ )
@@ -0,0 +1,11 @@
1
+ from ..cli import CliModule
2
+
3
+
4
+ # @omlish-manifest
5
+ _CLI_MODULE = CliModule('cmdlog', __name__)
6
+
7
+
8
+ if __name__ == '__main__':
9
+ from .cli import _main
10
+
11
+ _main()
@@ -0,0 +1,73 @@
1
+ # NOTE: not '@omlish-lite' due to root level __init__ imports, but effectively lite.
2
+ import dataclasses as dc
3
+ import fcntl
4
+ import json
5
+ import os.path
6
+ import shutil
7
+ import sys
8
+ import time
9
+ import typing as ta
10
+
11
+
12
+ ##
13
+
14
+
15
+ @dc.dataclass(frozen=True)
16
+ class CmdLogEntry:
17
+ cmd: str
18
+ pid: int
19
+ ppid: int
20
+ time: float
21
+ cwd: str
22
+
23
+ argv: ta.Sequence[str]
24
+ env: ta.Mapping[str, str]
25
+
26
+
27
+ ##
28
+
29
+
30
+ LOG_FILE_ENV_VAR: str = '_CMD_LOG_FILE'
31
+
32
+
33
+ def _main() -> None:
34
+ cmd = os.path.basename(sys.argv[0])
35
+
36
+ entry = CmdLogEntry(
37
+ cmd=cmd,
38
+ pid=os.getpid(),
39
+ ppid=os.getppid(),
40
+ time=time.time(),
41
+ cwd=os.getcwd(),
42
+
43
+ argv=sys.argv,
44
+ env=dict(os.environ),
45
+ )
46
+
47
+ entry_json = json.dumps(dc.asdict(entry), separators=(',', ':'), indent=None)
48
+
49
+ log_file = os.environ[LOG_FILE_ENV_VAR]
50
+ fd = os.open(log_file, os.O_WRONLY | os.O_CREAT | os.O_APPEND)
51
+ fcntl.flock(fd, fcntl.LOCK_EX)
52
+ os.write(fd, entry_json.encode() + b'\n')
53
+ os.close(fd)
54
+
55
+ u_ap = None # type: str | None
56
+ self_ap = os.path.abspath(os.path.realpath(__file__))
57
+ for p in os.environ.get('PATH', '').split(os.pathsep):
58
+ if (p_cmd := shutil.which(cmd, path=p)) is None:
59
+ continue
60
+ p_ap = os.path.abspath(os.path.realpath(p_cmd))
61
+ if p_ap == self_ap:
62
+ continue
63
+ u_ap = p_ap
64
+ break
65
+
66
+ if u_ap is None:
67
+ raise FileNotFoundError(cmd)
68
+
69
+ os.execl(u_ap, cmd, *sys.argv[1:])
70
+
71
+
72
+ if __name__ == '__main__':
73
+ _main()
omdev/cmdlog/cli.py ADDED
@@ -0,0 +1,67 @@
1
+ import argparse
2
+ import os.path
3
+ import subprocess
4
+ import sys
5
+ import typing as ta
6
+
7
+ from omlish.formats import json
8
+
9
+ from .cmdlog import CmdLog
10
+
11
+
12
+ ##
13
+
14
+
15
+ DEFAULT_PROXIED_CMDS: ta.Collection[str] = [
16
+ 'ar',
17
+ 'as',
18
+ 'clang',
19
+ 'clang++',
20
+ 'g++',
21
+ 'gcc',
22
+ 'ld',
23
+ 'lld',
24
+ 'make',
25
+ ]
26
+
27
+
28
+ def _main() -> None:
29
+ parser = argparse.ArgumentParser()
30
+ parser.add_argument('cmd', nargs=argparse.REMAINDER)
31
+ parser.add_argument('-l', '--log-file')
32
+ parser.add_argument('-P', '--print', action='store_true')
33
+ parser.add_argument('-p', '--proxy', action='append')
34
+ args = parser.parse_args()
35
+
36
+ if not args.cmd:
37
+ parser.error('Must specify cmd')
38
+ raise RuntimeError # noqa
39
+
40
+ exec_cmd, *exec_argv = args.cmd
41
+
42
+ #
43
+
44
+ cl = CmdLog(
45
+ args.proxy if args.proxy is not None else DEFAULT_PROXIED_CMDS,
46
+ log_file=os.path.abspath(args.log_file) if args.log_file is not None else None,
47
+ )
48
+ cl.exe()
49
+ cl.proxy_cmds()
50
+
51
+ rc = subprocess.call(
52
+ [exec_cmd, *exec_argv],
53
+ env=cl.child_env(),
54
+ )
55
+
56
+ if args.log_file is None or args.print:
57
+ if os.path.exists(cl.log_file()):
58
+ with open(cl.log_file()) as f:
59
+ log_lines = f.readlines()
60
+ entry_dcts = [json.loads(sl) for l in log_lines if (sl := l.strip())]
61
+ print(json.dumps_compact(entry_dcts))
62
+
63
+ sys.exit(rc)
64
+
65
+
66
+ if __name__ == '__main__':
67
+ _main()
omdev/cmdlog/cmdlog.py ADDED
@@ -0,0 +1,86 @@
1
+ import inspect
2
+ import os.path
3
+ import sys
4
+ import tempfile
5
+ import typing as ta
6
+
7
+ from omlish import cached
8
+ from omlish import check
9
+
10
+ from . import _cmdlog
11
+
12
+
13
+ ##
14
+
15
+
16
+ class CmdLog:
17
+ def __init__(
18
+ self,
19
+ proxied_cmds: ta.Iterable[str],
20
+ *,
21
+ tmp_dir: str | None = None,
22
+ log_file: str | None = None,
23
+ exe_name: str | None = None,
24
+ ) -> None:
25
+ super().__init__()
26
+
27
+ self._proxied_cmds = {
28
+ check.non_empty_str(c)
29
+ for c in check.not_isinstance(proxied_cmds, str)
30
+ }
31
+
32
+ self._given_tmp_dir = tmp_dir
33
+ self._given_log_file = log_file
34
+ self._exe_name = check.non_empty_str(exe_name) if exe_name is not None else self.DEFAULT_EXE_NAME
35
+
36
+ #
37
+
38
+ @cached.function
39
+ def tmp_dir(self) -> str:
40
+ if (gtd := self._given_tmp_dir) is not None:
41
+ return gtd
42
+ return tempfile.mkdtemp()
43
+
44
+ #
45
+
46
+ DEFAULT_LOG_FILE_NAME: ta.ClassVar[str] = '_cmdlog.jsonl'
47
+
48
+ @cached.function
49
+ def log_file(self) -> str:
50
+ if (glf := self._given_log_file) is not None:
51
+ return glf
52
+ return os.path.join(self.tmp_dir(), self.DEFAULT_LOG_FILE_NAME)
53
+
54
+ #
55
+
56
+ DEFAULT_EXE_NAME: ta.ClassVar[str] = '_cmdlog.py'
57
+
58
+ @cached.function
59
+ def exe(self) -> str:
60
+ src = '\n'.join([
61
+ f'#!{os.path.abspath(sys.executable)}',
62
+ inspect.getsource(_cmdlog),
63
+ ])
64
+
65
+ exe = os.path.join(self.tmp_dir(), self._exe_name)
66
+
67
+ with open(exe, 'w') as f:
68
+ f.write(src)
69
+
70
+ os.chmod(exe, 0o550) # noqa
71
+
72
+ return exe
73
+
74
+ #
75
+
76
+ def proxy_cmds(self) -> None:
77
+ for p_c in self._proxied_cmds:
78
+ os.symlink(self._exe_name, os.path.join(self.tmp_dir(), p_c))
79
+
80
+ #
81
+
82
+ def child_env(self) -> ta.Mapping[str, str]:
83
+ return {
84
+ _cmdlog.LOG_FILE_ENV_VAR: self.log_file(),
85
+ 'PATH': os.pathsep.join([self.tmp_dir(), os.environ['PATH']]),
86
+ }
@@ -4,10 +4,10 @@ import typing as ta
4
4
 
5
5
  from omlish import check
6
6
  from omlish import lang
7
- from omlish.formats.json.stream.build import JsonObjectBuilder
8
- from omlish.formats.json.stream.lex import JsonStreamLexer
9
- from omlish.formats.json.stream.parse import JsonStreamParser
10
- from omlish.formats.json.stream.parse import JsonStreamParserEvent
7
+ from omlish.formats.json.stream.building import JsonObjectBuilder
8
+ from omlish.formats.json.stream.lexing import JsonStreamLexer
9
+ from omlish.formats.json.stream.parsing import JsonStreamParser
10
+ from omlish.formats.json.stream.parsing import JsonStreamParserEvent
11
11
  from omlish.io.buffers import DelimitingBuffer
12
12
 
13
13
  from .formats import Format
@@ -3,9 +3,9 @@ import json
3
3
  import typing as ta
4
4
 
5
5
  from omlish import lang
6
- from omlish.formats.json.render import JsonRenderer
7
- from omlish.formats.json.stream.parse import JsonStreamParserEvent
8
- from omlish.formats.json.stream.render import StreamJsonRenderer
6
+ from omlish.formats.json.rendering import JsonRenderer
7
+ from omlish.formats.json.stream.parsing import JsonStreamParserEvent
8
+ from omlish.formats.json.stream.rendering import StreamJsonRenderer
9
9
  from omlish.term import codes as tc
10
10
 
11
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omdev
3
- Version: 0.0.0.dev305
3
+ Version: 0.0.0.dev307
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.12
14
14
  License-File: LICENSE
15
- Requires-Dist: omlish==0.0.0.dev305
15
+ Requires-Dist: omlish==0.0.0.dev307
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=ouzCsEt6dHvLXr-DyZ-gLxbnizOFe0BE6u6xKH3RKEI,10721
1
+ omdev/.manifests.json,sha256=M4fAkk-dlyvEzkya4HhuU9Hb9QpVYgp1AgJB6eXgmuI,10982
2
2
  omdev/__about__.py,sha256=16xa_1BdZanTpZbkjAOQ11_x5kJcb1m1tKdvb06J7VI,1202
3
3
  omdev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  omdev/cmake.py,sha256=9rfSvFHPmKDj9ngvfDB2vK8O-xO_ZwUm7hMKLWA-yOw,4578
@@ -114,6 +114,11 @@ omdev/clipboard/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
114
  omdev/clipboard/clipboard.py,sha256=9HFpcijpn0XDTI89ZRm2WA1G7O4HsTdVXZHqMULu3N0,1630
115
115
  omdev/clipboard/darwin_cf.py,sha256=1gFkxEN6w9HTcA0eiWw14oL7xjC1wSmY_hUrRr5OU4Y,7687
116
116
  omdev/clipboard/linux_x11.py,sha256=oa-mxMRNaZJOdBAZ8Nki-CAGIb63X8OFUTXKjmiwfSo,6718
117
+ omdev/cmdlog/__init__.py,sha256=026o1leEXU5bsNZPpEOeLf_Ml1wQXzbiFDmlcKHX-Nw,95
118
+ omdev/cmdlog/__main__.py,sha256=m31h6AcI9rjRNVeBGoLcR-5pWp-yS8LXCorf4iBhX9w,162
119
+ omdev/cmdlog/_cmdlog.py,sha256=9VSuUKXBMBHAH3OfBCeqp16YPddPT9Man2zDHgzzCtI,1507
120
+ omdev/cmdlog/cli.py,sha256=9AJC3xeQA-2pdmTnsjo__9WRAML1jpEJUJMn6qQQpJA,1427
121
+ omdev/cmdlog/cmdlog.py,sha256=MJqfCG7sVWjSK_i1shD7cgWpFZXZkPvGhGEh-yd6iwM,1982
117
122
  omdev/dataserver/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
118
123
  omdev/dataserver/handlers.py,sha256=rCptrmV2RnutmGE5MAgjLDYW1QncqsSHhyRBL4H5bsg,5440
119
124
  omdev/dataserver/http.py,sha256=SozI4233RP40m2EX45HtBvdIj-CBFlhHH7ekIbMir-Q,1724
@@ -271,15 +276,15 @@ omdev/tools/json/__main__.py,sha256=wqpkN_NsQyNwKW4qjVj8ADJ4_C98KhrFBtE-Z1UamfU,
271
276
  omdev/tools/json/cli.py,sha256=WQ8VQ9EkGD6IeIuUci8hLPwfx6y2B8ZzFlTTizwwKXU,9598
272
277
  omdev/tools/json/formats.py,sha256=RgtPdcs294o9n9czjafHppg1iSzD-olsIc3v8ApM9Os,1908
273
278
  omdev/tools/json/io.py,sha256=sfj2hJS9Hy3aUR8a_lLzOrYcmL9fSKyvOHiofdUASsI,1427
274
- omdev/tools/json/parsing.py,sha256=BNCOcPs6eDvB6wePnjl9H0C-ngHxLRgzLM1EPetWnrQ,2093
279
+ omdev/tools/json/parsing.py,sha256=csoTuG2C2AJB7PgG4TKt2XqdiBAQXtpXRWBxoMkk14g,2103
275
280
  omdev/tools/json/processing.py,sha256=iFm5VqaxJ97WHaun2ed7NEjMxhFeJqf28bLNfoDJft0,1209
276
- omdev/tools/json/rendering.py,sha256=tMcjOW5edfozcMSTxxvF7WVTsbYLoe9bCKFh50qyaGw,2236
281
+ omdev/tools/json/rendering.py,sha256=3HhdlKSetS6iK1tjF2aILzsl8Mb3D8wW92vYwGpRdVA,2244
277
282
  omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
278
283
  omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
279
284
  omdev/tools/pawk/pawk.py,sha256=zsEkfQX0jF5bn712uqPAyBSdJt2dno1LH2oeSMNfXQI,11424
280
- omdev-0.0.0.dev305.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
281
- omdev-0.0.0.dev305.dist-info/METADATA,sha256=Dp_xG1ayIA3fP9VGM69G_Xa_oVLFp24uVQFOSMaNQew,1674
282
- omdev-0.0.0.dev305.dist-info/WHEEL,sha256=wXxTzcEDnjrTwFYjLPcsW_7_XihufBwmpiBeiXNBGEA,91
283
- omdev-0.0.0.dev305.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
284
- omdev-0.0.0.dev305.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
285
- omdev-0.0.0.dev305.dist-info/RECORD,,
285
+ omdev-0.0.0.dev307.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
286
+ omdev-0.0.0.dev307.dist-info/METADATA,sha256=0jPC9ndeHfkBuwMuBVx4376pei_zDitc66yb3610pj0,1674
287
+ omdev-0.0.0.dev307.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
288
+ omdev-0.0.0.dev307.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
289
+ omdev-0.0.0.dev307.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
290
+ omdev-0.0.0.dev307.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.1.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5