omdev 0.0.0.dev395__py3-none-any.whl → 0.0.0.dev397__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
@@ -59,6 +59,18 @@
59
59
  }
60
60
  }
61
61
  },
62
+ {
63
+ "module": ".dataclasses.__main__",
64
+ "attr": "_CLI_MODULE",
65
+ "file": "omdev/dataclasses/__main__.py",
66
+ "line": 4,
67
+ "value": {
68
+ "$.cli.types.CliModule": {
69
+ "cmd_name": "dataclasses",
70
+ "mod_name": "omdev.dataclasses.__main__"
71
+ }
72
+ }
73
+ },
62
74
  {
63
75
  "module": ".imgur",
64
76
  "attr": "_FOO_CLI_MODULE",
@@ -503,7 +515,7 @@
503
515
  "module": ".tools.prof",
504
516
  "attr": "_CLI_MODULE",
505
517
  "file": "omdev/tools/prof.py",
506
- "line": 57,
518
+ "line": 128,
507
519
  "value": {
508
520
  "$.cli.types.CliModule": {
509
521
  "cmd_name": "prof",
@@ -2,7 +2,6 @@ import datetime
2
2
 
3
3
  from omlish import __about__ as about
4
4
  from omlish import cached
5
- from omlish import check
6
5
  from omlish import dataclasses as dc
7
6
 
8
7
  from ...git.revisions import get_git_revision
@@ -14,11 +13,11 @@ from .specs import Spec
14
13
 
15
14
 
16
15
  @cached.function
17
- def _lib_revision() -> str:
16
+ def _lib_revision() -> str | None:
18
17
  if (rev := about.__revision__) is not None:
19
18
  return rev # type: ignore
20
19
 
21
- return check.not_none(get_git_revision())
20
+ return get_git_revision()
22
21
 
23
22
 
24
23
  ##
@@ -28,13 +27,15 @@ def _lib_revision() -> str:
28
27
  class Manifest:
29
28
  spec: Spec
30
29
 
31
- start_at: datetime.datetime = dc.field(kw_only=True)
32
- end_at: datetime.datetime = dc.field(kw_only=True)
30
+ _: dc.KW_ONLY
33
31
 
34
- lib_version: str = dc.field(default_factory=lambda: about.__version__, kw_only=True)
35
- lib_revision: str = dc.field(default_factory=_lib_revision, kw_only=True)
32
+ start_at: datetime.datetime = dc.field()
33
+ end_at: datetime.datetime = dc.field()
36
34
 
37
- serialization_version: int = dc.field(default=SERIALIZATION_VERSION, kw_only=True)
35
+ lib_version: str = dc.field(default_factory=lambda: about.__version__)
36
+ lib_revision: str | None = dc.field(default_factory=_lib_revision)
37
+
38
+ serialization_version: int = dc.field(default=SERIALIZATION_VERSION)
38
39
 
39
40
  @dc.validate
40
41
  def _validate_serialization_versions(self) -> bool:
File without changes
@@ -0,0 +1,11 @@
1
+ from ..cli import CliModule
2
+
3
+
4
+ # @omlish-manifest
5
+ _CLI_MODULE = CliModule('dataclasses', __name__)
6
+
7
+
8
+ if __name__ == '__main__':
9
+ from .cli import _main # noqa
10
+
11
+ _main()
@@ -0,0 +1,28 @@
1
+ from omlish.argparse import all as ap
2
+ from omlish.logs.standard import configure_standard_logging
3
+
4
+ from .codegen import DataclassCodeGen
5
+
6
+
7
+ ##
8
+
9
+
10
+ class Cli(ap.Cli):
11
+ @ap.cmd(
12
+ ap.arg('roots', metavar='root', nargs='+'),
13
+ )
14
+ def codegen(self) -> None:
15
+ DataclassCodeGen().run(self.args.roots)
16
+
17
+
18
+ ##
19
+
20
+
21
+ def _main() -> None:
22
+ configure_standard_logging()
23
+
24
+ Cli().cli_run_and_exit()
25
+
26
+
27
+ if __name__ == '__main__':
28
+ _main()
@@ -0,0 +1,95 @@
1
+ """
2
+ TODO:
3
+ - subdir conf files override parents, codegen those separately, don't duplicate
4
+ - refactor dc gen to just Execute and Codegen
5
+ - need to bubble up imports, preamble, deduped
6
+ - still need plan repr / cmp
7
+ - !! manifests for dataclass config?
8
+ - more sparse / diffuse intent, not package-level
9
+ """
10
+ import logging
11
+ import os.path
12
+ import typing as ta
13
+
14
+ from omlish import check
15
+ from omlish import collections as col
16
+ from omlish import lang
17
+ from omlish.dataclasses.impl.configs import PACKAGE_CONFIG_FILE_NAME
18
+ from omlish.dataclasses.impl.configs import PackageConfig
19
+ from omlish.dataclasses.impl.generation.compilation import OpCompiler
20
+ from omlish.dataclasses.impl.generation.processor import Codegen as CodegenProcessingOption
21
+ from omlish.dataclasses.impl.generation.processor import GeneratorProcessor
22
+ from omlish.dataclasses.impl.processing.base import ProcessingContext
23
+ from omlish.dataclasses.impl.processing.driving import processing_options_context
24
+
25
+
26
+ log = logging.getLogger(__name__)
27
+
28
+
29
+ ##
30
+
31
+
32
+ class DataclassCodeGen:
33
+ def __init__(self) -> None:
34
+ super().__init__()
35
+
36
+ def run_package_config(
37
+ self,
38
+ pkg_root: str,
39
+ config: PackageConfig,
40
+ ) -> None:
41
+ if not config.codegen:
42
+ return
43
+
44
+ log.info('Running codegen on package: %s', pkg_root)
45
+
46
+ sub_pkgs = sorted(lang.yield_importable(
47
+ pkg_root,
48
+ recursive=True,
49
+ include_special=True,
50
+ ))
51
+
52
+ for sub_pkg in sub_pkgs:
53
+ def callback(
54
+ ctx: ProcessingContext,
55
+ prepared: GeneratorProcessor.Prepared,
56
+ comp: OpCompiler.CompileResult,
57
+ ) -> None:
58
+ print(ctx.cls)
59
+ print(prepared.plans)
60
+ print(comp.src)
61
+
62
+ with processing_options_context(CodegenProcessingOption(callback)):
63
+ print(f'{sub_pkg=}')
64
+ try:
65
+ __import__(sub_pkg)
66
+ except ImportError as e:
67
+ print(repr(e))
68
+
69
+ def build_config_trie(
70
+ self,
71
+ root_dirs: ta.Iterable[str],
72
+ ) -> col.Trie[str, PackageConfig]:
73
+ check.not_isinstance(root_dirs, str)
74
+
75
+ trie: col.Trie[str, PackageConfig] = col.Trie()
76
+ for root_dir in root_dirs:
77
+ for dp, _, fns in os.walk(root_dir):
78
+ if PACKAGE_CONFIG_FILE_NAME in fns:
79
+ with open(os.path.join(dp, PACKAGE_CONFIG_FILE_NAME)) as f:
80
+ config = PackageConfig.loads(f.read())
81
+ pkg_parts = dp.split(os.sep)
82
+ trie[pkg_parts] = config
83
+
84
+ return trie
85
+
86
+ def run(
87
+ self,
88
+ root_dirs: ta.Iterable[str],
89
+ ) -> None:
90
+ check.not_isinstance(root_dirs, str)
91
+
92
+ config_trie = self.build_config_trie(root_dirs)
93
+
94
+ for pkg_parts, pkg_config in config_trie.iter_items(sort_children=True):
95
+ self.run_package_config('.'.join(pkg_parts), pkg_config)
omdev/tools/prof.py CHANGED
@@ -3,6 +3,7 @@ TODO:
3
3
  - a general purpose profile tool lol - or is this for / in bootstrap?
4
4
  """
5
5
  import os.path
6
+ import shutil
6
7
  import subprocess
7
8
  import sys
8
9
  import tempfile
@@ -15,43 +16,113 @@ from ..cli import CliModule
15
16
  ##
16
17
 
17
18
 
19
+ def pstats_to_pdf(
20
+ pstats_file: str,
21
+ pdf_file: str,
22
+ ) -> None:
23
+ dot = subprocess.check_output([
24
+ sys.executable,
25
+ '-m', 'gprof2dot',
26
+ '-f', 'pstats',
27
+ pstats_file,
28
+ ])
29
+
30
+ pdf = subprocess.check_output(
31
+ ['dot', '-Tpdf'],
32
+ input=dot,
33
+ )
34
+
35
+ with open(pdf_file, 'wb') as f:
36
+ f.write(pdf)
37
+
38
+
18
39
  class Cli(ap.Cli):
19
40
  @ap.cmd(
20
- ap.arg('file'),
21
- ap.arg('out-file', nargs='?'),
41
+ ap.arg('pstats-file'),
42
+ ap.arg('pdf-file', nargs='?'),
22
43
  ap.arg('-w', '--write', action='store_true'),
23
44
  ap.arg('-o', '--open', action='store_true'),
24
45
  ap.arg('-O', '--overwrite', action='store_true'),
25
46
  )
26
47
  def pstats_pdf(self) -> None:
27
- out_file = self.args.out_file
28
- if out_file is None and self.args.write:
29
- out_file = self.args.file + '.pdf'
48
+ pdf_file = self.args.pdf_file
49
+ if pdf_file is None and self.args.write:
50
+ pdf_file = self.args.pstats_file + '.pdf'
30
51
 
31
- if out_file is not None:
32
- if os.path.exists(out_file) and not self.args.overwrite:
33
- raise OSError(f'File exists: {out_file}')
52
+ if pdf_file is not None:
53
+ if os.path.exists(pdf_file) and not self.args.overwrite:
54
+ raise OSError(f'File exists: {pdf_file}')
34
55
  else:
35
- out_file = tempfile.mktemp(suffix=os.path.basename(self.args.file) + '.pdf') # noqa
56
+ pdf_file = tempfile.mktemp(suffix=os.path.basename(self.args.pstats_file) + '.pdf') # noqa
57
+
58
+ pstats_to_pdf(
59
+ self.args.pstats_file,
60
+ self.args.pdf_file,
61
+ )
62
+
63
+ print(pdf_file)
64
+
65
+ if self.args.open:
66
+ subprocess.check_call(['open', pdf_file])
67
+
68
+ @ap.cmd(
69
+ ap.arg('src'),
70
+ ap.arg('out-file', nargs='?'),
71
+ ap.arg('-p', '--pdf', action='store_true'),
72
+ ap.arg('-o', '--open', action='store_true'),
73
+ ap.arg('-O', '--overwrite', action='store_true'),
74
+ )
75
+ def pstats_exec(self) -> None:
76
+ if self.args.out_file is not None:
77
+ if os.path.exists(self.args.out_file) and not self.args.overwrite:
78
+ raise OSError(f'File exists: {self.args.out_file}')
79
+
80
+ tmp_dir = tempfile.mkdtemp()
81
+
82
+ src_file = os.path.join(tmp_dir, 'pstats_exec.py')
83
+ with open(src_file, 'w') as f:
84
+ f.write(self.args.src)
85
+
86
+ pstats_file = os.path.join(tmp_dir, 'prof.pstats')
36
87
 
37
- dot = subprocess.check_output([
88
+ # TODO: --python - and handle env vars, unset venv and pythonpath stuff - helper for this, scrub env
89
+ # - share with execstat, -x
90
+ subprocess.check_call([
38
91
  sys.executable,
39
- '-m', 'gprof2dot',
40
- '-f', 'pstats',
41
- self.args.file,
92
+ '-m', 'cProfile',
93
+ '-o', pstats_file,
94
+ os.path.abspath(src_file),
42
95
  ])
43
96
 
44
- pdf = subprocess.check_output(
45
- ['dot', '-Tpdf'],
46
- input=dot,
47
- )
97
+ if self.args.pdf:
98
+ out_file = os.path.join(tmp_dir, 'pstats.pdf')
99
+
100
+ pstats_to_pdf(
101
+ pstats_file,
102
+ out_file,
103
+ )
104
+
105
+ else:
106
+ out_file = pstats_file
107
+
108
+ if self.args.out_file is not None:
109
+ shutil.move(out_file, self.args.out_file)
110
+ out_file = self.args.out_file
48
111
 
49
- with open(out_file, 'wb') as f:
50
- f.write(pdf)
51
112
  print(out_file)
52
113
 
53
114
  if self.args.open:
54
- subprocess.check_call(['open', out_file])
115
+ if self.args.pdf:
116
+ subprocess.check_call(['open', out_file])
117
+
118
+ else:
119
+ # Alt: python -i <setup.py> where setup.py is 'import pstats; stats = pstats.Stats(<out_file>)'
120
+ os.execl(
121
+ sys.executable,
122
+ sys.executable,
123
+ '-m', 'pstats',
124
+ out_file,
125
+ )
55
126
 
56
127
 
57
128
  # @omlish-manifest
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omdev
3
- Version: 0.0.0.dev395
3
+ Version: 0.0.0.dev397
4
4
  Summary: omdev
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: omlish==0.0.0.dev395
17
+ Requires-Dist: omlish==0.0.0.dev397
18
18
  Provides-Extra: all
19
19
  Requires-Dist: black~=25.1; extra == "all"
20
20
  Requires-Dist: pycparser~=2.22; extra == "all"
@@ -1,4 +1,4 @@
1
- omdev/.manifests.json,sha256=IuYiaGqGlhwqLm9NpW2koVLjr5dmDxt-BztIpn3E9YQ,12170
1
+ omdev/.manifests.json,sha256=vqg148YzWHn61WpGqC2PuTiOIR2HcH5O55XZZGTcnVw,12452
2
2
  omdev/__about__.py,sha256=fQNmzSa1MntcPSrzg_Vpo6JRU2RbXik2NqRz0oQCApE,1202
3
3
  omdev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  omdev/cmake.py,sha256=9rfSvFHPmKDj9ngvfDB2vK8O-xO_ZwUm7hMKLWA-yOw,4578
@@ -30,7 +30,7 @@ omdev/cache/data/actions.py,sha256=Mv7eXeZuohCjQLpmLyvqvGjjBacXIvTYzIRMVpEh-zM,1
30
30
  omdev/cache/data/cache.py,sha256=oveyGl6gfTmQ4fKVO-NbB5Zx4rmEcti3BdZIvv5C6CU,7632
31
31
  omdev/cache/data/consts.py,sha256=d6W_aeMqgah6PmPYi9RA8Be54oQ4BcNCy8kDQ7FlB_Q,26
32
32
  omdev/cache/data/defaults.py,sha256=NL_mT7kaSLm2Mk9VO5wdSu-DIcHTR1KgcihJqdSd4TY,312
33
- omdev/cache/data/manifests.py,sha256=3bgVaduql65Jy3a7CXlBLQN4NzFGIUD2fMSmWCE2Rg8,1023
33
+ omdev/cache/data/manifests.py,sha256=NweXxbkuLMBG1DiUFliOSYeXBrLPMIY4GA_gOZzHwho,949
34
34
  omdev/cache/data/specs.py,sha256=P50VSvMf2Jp3VHjhHy4i1-PwYwEGD4MMXEpxIg0CQis,2468
35
35
  omdev/capi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  omdev/capi/darwin/__init__.py,sha256=iAlc3ReV3LJOv5X9zGME1FKeZ2yf0auUuj1I3sGSo4E,86
@@ -125,6 +125,10 @@ omdev/cmdlog/__main__.py,sha256=m31h6AcI9rjRNVeBGoLcR-5pWp-yS8LXCorf4iBhX9w,162
125
125
  omdev/cmdlog/_cmdlog.py,sha256=9VSuUKXBMBHAH3OfBCeqp16YPddPT9Man2zDHgzzCtI,1507
126
126
  omdev/cmdlog/cli.py,sha256=9AJC3xeQA-2pdmTnsjo__9WRAML1jpEJUJMn6qQQpJA,1427
127
127
  omdev/cmdlog/cmdlog.py,sha256=MJqfCG7sVWjSK_i1shD7cgWpFZXZkPvGhGEh-yd6iwM,1982
128
+ omdev/dataclasses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
129
+ omdev/dataclasses/__main__.py,sha256=N-a0Lf_s7D0VajuZCCY_dt8R4rSpeck9inbCsoIvciQ,175
130
+ omdev/dataclasses/cli.py,sha256=j5GfpJQSkA_jmV94XTVb3amCFYjgrasMs-bp_zJEkqE,445
131
+ omdev/dataclasses/codegen.py,sha256=T9SYsTjmNrM1HMUFVMO46-Szd3DH0Em0B-I_UTan6qg,3029
128
132
  omdev/dataserver/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
129
133
  omdev/dataserver/handlers.py,sha256=YTuRfZehP9panTwq8dPReHZwXF1_fFIueh-_ZoztA98,5446
130
134
  omdev/dataserver/http.py,sha256=SMS6w-GVevG58FypqmPytcEqW8aUWpd2_F6JlBDIuBc,1730
@@ -284,7 +288,7 @@ omdev/tools/linehisto.py,sha256=0ZNm34EuiZBE9Q2YC6KNLNNydNT8QPSOwvYzXiU9S2Q,8881
284
288
  omdev/tools/mkenv.py,sha256=G2tu5bmiyKFyZuqtUoM7Z-6AI6CI86F2LwoIozoWOvo,2300
285
289
  omdev/tools/notebook.py,sha256=MGi2JEwyIPR1n7gakaaYZL1HHbSVmDKGQROqH56ppgU,3499
286
290
  omdev/tools/pip.py,sha256=HF5ILsNcU1IGn9bRthwjp4XicafZWR7zdp6rOhqSMiw,3464
287
- omdev/tools/prof.py,sha256=yPU0gkw4yWVsbAr3L95sO2FC8MM1DpzZiVVMcQlFt4c,1472
291
+ omdev/tools/prof.py,sha256=AWcuToo3VACxyFRdUEmdqtGcfidPlvJCwkD-q_b6uIs,3485
288
292
  omdev/tools/qr.py,sha256=1p4tMJmImDa4YTQQNPwQPkM8FnhGRYj6J79BJR-MNHo,1742
289
293
  omdev/tools/shadow.py,sha256=4E2ilxa16liIvQxvgU37ITkOMrP6ufShRQfeW7wwtRc,1697
290
294
  omdev/tools/shell.py,sha256=5hF_8DCtB3XrzJSfmQDsr7X3Fi9KRV4M70q9qp0KREA,2341
@@ -317,9 +321,9 @@ omdev/tools/jsonview/resources/jsonview.js,sha256=faDvXDOXKvEvjOuIlz4D3F2ReQXb_b
317
321
  omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
318
322
  omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
319
323
  omdev/tools/pawk/pawk.py,sha256=ao5mdrpiSU4AZ8mBozoEaV3UVlmVTnRG9wD9XP70MZE,11429
320
- omdev-0.0.0.dev395.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
321
- omdev-0.0.0.dev395.dist-info/METADATA,sha256=y91uxnWMPgach_tKBqEg8wNntllDmyEseaH-IzoFY_o,5094
322
- omdev-0.0.0.dev395.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
323
- omdev-0.0.0.dev395.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
324
- omdev-0.0.0.dev395.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
325
- omdev-0.0.0.dev395.dist-info/RECORD,,
324
+ omdev-0.0.0.dev397.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
325
+ omdev-0.0.0.dev397.dist-info/METADATA,sha256=bAgNwHp9Gc2_P6AUojLiMF61tGyHIvXlOmx8C065zhI,5094
326
+ omdev-0.0.0.dev397.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
327
+ omdev-0.0.0.dev397.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
328
+ omdev-0.0.0.dev397.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
329
+ omdev-0.0.0.dev397.dist-info/RECORD,,