omdev 0.0.0.dev99__py3-none-any.whl → 0.0.0.dev100__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 omdev might be problematic. Click here for more details.

omdev/.manifests.json CHANGED
@@ -71,18 +71,6 @@
71
71
  }
72
72
  }
73
73
  },
74
- {
75
- "module": ".findmagic",
76
- "attr": "_CLI_MODULE",
77
- "file": "omdev/findmagic.py",
78
- "line": 65,
79
- "value": {
80
- "$.cli.types.CliModule": {
81
- "cmd_name": "py/findmagic",
82
- "mod_name": "omdev.findmagic"
83
- }
84
- }
85
- },
86
74
  {
87
75
  "module": ".imgur",
88
76
  "attr": "_FOO_CLI_MODULE",
@@ -107,6 +95,18 @@
107
95
  }
108
96
  }
109
97
  },
98
+ {
99
+ "module": ".magic.find",
100
+ "attr": "_CLI_MODULE",
101
+ "file": "omdev/magic/find.py",
102
+ "line": 230,
103
+ "value": {
104
+ "$.cli.types.CliModule": {
105
+ "cmd_name": "py/findmagic",
106
+ "mod_name": "omdev.magic.find"
107
+ }
108
+ }
109
+ },
110
110
  {
111
111
  "module": ".precheck.__main__",
112
112
  "attr": "_CLI_MODULE",
omdev/amalg/amalg.py CHANGED
@@ -41,7 +41,7 @@ from omlish import lang
41
41
  from omlish import logs
42
42
  from omlish.lite.runtime import REQUIRED_PYTHON_VERSION
43
43
 
44
- from .. import findmagic
44
+ from .. import magic
45
45
  from .. import tokens as tks
46
46
 
47
47
 
@@ -94,11 +94,14 @@ def strip_main_lines(cls: ta.Sequence[Tokens]) -> list[Tokens]:
94
94
 
95
95
 
96
96
  STRIPPED_HEADER_MAGICS = [
97
- '# @omlish-lite',
98
- '# @omlish-script',
97
+ '@omlish-lite',
98
+ '@omlish-script',
99
99
  ]
100
100
 
101
- STRIPPED_HEADER_PATS = [findmagic.compile_magic_pat(m) for m in STRIPPED_HEADER_MAGICS]
101
+ STRIPPED_HEADER_PAT = magic.compile_magic_style_pat(
102
+ magic.PY_MAGIC_STYLE,
103
+ keys=STRIPPED_HEADER_MAGICS,
104
+ )
102
105
 
103
106
 
104
107
  def strip_header_lines(hls: ta.Sequence[Tokens]) -> list[Tokens]:
@@ -107,7 +110,7 @@ def strip_header_lines(hls: ta.Sequence[Tokens]) -> list[Tokens]:
107
110
  out = []
108
111
  for l in hls:
109
112
  ls = tks.join_toks(l)
110
- if not any(p.fullmatch(ls) for p in STRIPPED_HEADER_PATS):
113
+ if not STRIPPED_HEADER_PAT.fullmatch(ls):
111
114
  out.append(l)
112
115
  return out
113
116
 
omdev/cexts/cmake.py CHANGED
@@ -37,7 +37,7 @@ from omlish import lang
37
37
  from omlish import logs
38
38
 
39
39
  from .. import cmake
40
- from .. import findmagic
40
+ from .. import magic
41
41
  from ..cli import CliModule
42
42
  from .magic import CextMagic
43
43
 
@@ -137,10 +137,10 @@ class CmakeProjectGen:
137
137
  out.append(e)
138
138
  elif os.path.isdir(e):
139
139
  out.extend(
140
- findmagic.find_magic(
140
+ magic.find_magic_files(
141
+ CextMagic.STYLE,
141
142
  [e],
142
- [CextMagic.MAGIC_COMMENT],
143
- CextMagic.FILE_EXTENSIONS,
143
+ keys=[CextMagic.KEY],
144
144
  ),
145
145
  )
146
146
  else:
omdev/cexts/magic.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # @omlish-lite
2
+ from ..magic.styles import C_MAGIC_STYLE
2
3
 
3
- class CextMagic:
4
- MAGIC = '@omlish-cext'
5
- MAGIC_COMMENT = f'// {MAGIC}'
6
4
 
7
- FILE_EXTENSIONS = ('c', 'cc', 'cpp')
5
+ class CextMagic:
6
+ KEY = '@omlish-cext'
7
+ STYLE = C_MAGIC_STYLE
omdev/cexts/scan.py CHANGED
@@ -15,7 +15,7 @@ def scan_one(
15
15
  input_path: str,
16
16
  **kwargs: ta.Any,
17
17
  ) -> None:
18
- if not any(input_path.endswith('.' + fx) for fx in CextMagic.FILE_EXTENSIONS):
18
+ if not any(input_path.endswith('.' + fx) for fx in CextMagic.STYLE.exts):
19
19
  return
20
20
 
21
21
  with open(input_path, 'rb') as f:
@@ -26,9 +26,9 @@ def scan_one(
26
26
  except UnicodeDecodeError:
27
27
  return
28
28
 
29
- sls = [l for l in src.splitlines() if l.startswith(CextMagic.MAGIC_COMMENT)]
29
+ sls = [l for l in src.splitlines() if l.startswith('// ' + CextMagic.KEY)] # FIXME
30
30
  for sl in sls:
31
- sas = sl[len(CextMagic.MAGIC_COMMENT):].split() # noqa
31
+ sas = sl[len(CextMagic.KEY) + 3:].split() # noqa
32
32
 
33
33
  log.info('Found ext: %s', input_path)
34
34
 
@@ -0,0 +1,28 @@
1
+ # @omlish-lite
2
+
3
+ from .find import ( # noqa
4
+ chop_magic_block,
5
+ chop_magic_lines,
6
+ compile_magic_style_pat,
7
+ find_magic,
8
+ find_magic_files,
9
+ find_magic_py_modules,
10
+ )
11
+
12
+ from .magic import ( # noqa
13
+ Magic,
14
+ )
15
+
16
+ from .prepare import ( # noqa
17
+ MagicPrepareError,
18
+ json_magic_preparer,
19
+ py_compile_magic_preparer,
20
+ py_eval_magic_preparer,
21
+ )
22
+
23
+ from .styles import ( # noqa
24
+ C_MAGIC_STYLE,
25
+ MAGIC_KEY_PREFIX,
26
+ MagicStyle,
27
+ PY_MAGIC_STYLE,
28
+ )
omdev/magic/find.py ADDED
@@ -0,0 +1,268 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import functools
3
+ import os.path
4
+ import re
5
+ import typing as ta
6
+
7
+ from .magic import Magic
8
+ from .prepare import MagicPrepareError
9
+ from .prepare import py_compile_magic_preparer
10
+ from .styles import C_MAGIC_STYLE
11
+ from .styles import PY_MAGIC_STYLE
12
+ from .styles import MagicStyle
13
+
14
+
15
+ ##
16
+
17
+
18
+ def compile_magic_style_pat(
19
+ style: MagicStyle,
20
+ *,
21
+ keys: ta.Optional[ta.Iterable[str]] = None,
22
+ ) -> re.Pattern:
23
+ ps: ta.List[str] = []
24
+ if style.line_prefix is not None:
25
+ ps.append(style.line_prefix)
26
+ if style.block_prefix_suffix is not None:
27
+ ps.append(style.block_prefix_suffix[0])
28
+ if not ps:
29
+ raise Exception('No prefixes')
30
+
31
+ ms: ta.List[str] = []
32
+ if keys is not None:
33
+ if isinstance(keys, str):
34
+ raise TypeError(keys)
35
+ for k in keys:
36
+ if not k.startswith(style.key_prefix):
37
+ raise Exception(f'Key does not start with prefix: {k!r} {style.key_prefix!r}')
38
+ ms.extend([re.escape(p + k) for p in ps])
39
+ else:
40
+ ms = [re.escape(p + style.key_prefix) + r'\S*' for p in ps]
41
+ if not ms:
42
+ raise Exception('No matchers')
43
+
44
+ b = '|'.join(f'({m})' for m in ms)
45
+ s = '^(' + b + r')($|(\s.*))'
46
+ return re.compile(s)
47
+
48
+
49
+ ##
50
+
51
+
52
+ def chop_magic_lines(
53
+ magic_key: str,
54
+ prefix: str,
55
+ lines: ta.Iterable[str],
56
+ ) -> ta.Optional[ta.List[str]]:
57
+ out: ta.List[str] = []
58
+ for i, line in enumerate(lines):
59
+ if not i:
60
+ if not line.startswith(prefix + magic_key):
61
+ return None
62
+ out.append(line[len(prefix) + len(magic_key) + 1:])
63
+ else:
64
+ if not line.startswith(prefix):
65
+ return None
66
+ out.append(line[len(prefix):])
67
+ return out
68
+
69
+
70
+ def chop_magic_block(
71
+ magic_key: str,
72
+ prefix: str,
73
+ suffix: str,
74
+ lines: ta.Iterable[str],
75
+ ) -> ta.Optional[ta.List[str]]:
76
+ out: ta.List[str] = []
77
+ for i, line in enumerate(lines):
78
+ if not i:
79
+ if not line.startswith(prefix + magic_key):
80
+ return None
81
+ s = line[len(prefix) + len(magic_key) + 1:]
82
+ if s.rstrip().endswith(suffix):
83
+ out.append(s.rstrip()[:-len(suffix)])
84
+ break
85
+ out.append(s)
86
+ elif line.rstrip().endswith(suffix):
87
+ out.append(line.rstrip()[:-len(suffix)])
88
+ break
89
+ else:
90
+ out.append(line)
91
+ return out
92
+
93
+
94
+ ##
95
+
96
+
97
+ def find_magic(
98
+ style: MagicStyle,
99
+ lines: ta.Sequence[str],
100
+ *,
101
+ file: ta.Optional[str] = None,
102
+ preparer: ta.Callable[[str], ta.Any] = py_compile_magic_preparer,
103
+ ) -> ta.List[Magic]:
104
+ out: ta.List[Magic] = []
105
+
106
+ start = 0
107
+ while start < len(lines):
108
+ start_line = lines[start]
109
+
110
+ chopper: ta.Callable[[ta.Iterable[str]], ta.Optional[ta.List[str]]]
111
+ if (
112
+ style.line_prefix is not None and
113
+ start_line.startswith(style.line_prefix + style.key_prefix)
114
+ ):
115
+ key = start_line[len(style.line_prefix):].split()[0]
116
+ chopper = functools.partial(
117
+ chop_magic_lines,
118
+ key,
119
+ style.line_prefix,
120
+ )
121
+
122
+ elif (
123
+ style.block_prefix_suffix is not None and
124
+ start_line.startswith(style.block_prefix_suffix[0] + style.key_prefix)
125
+ ):
126
+ key = start_line[len(style.block_prefix_suffix[0]):].split()[0]
127
+ chopper = functools.partial(
128
+ chop_magic_block,
129
+ key,
130
+ *style.block_prefix_suffix,
131
+ )
132
+
133
+ else:
134
+ start += 1
135
+ continue
136
+
137
+ end = start
138
+ magic: ta.Optional[Magic] = None
139
+ while end < len(lines):
140
+ block_lines = chopper(lines[start:end + 1])
141
+ if block_lines is None:
142
+ raise Exception(f'Failed to find magic block terminator : {file=} {start=} {end=}')
143
+
144
+ block_src = ''.join(block_lines)
145
+ if not block_src:
146
+ prepared = None
147
+ else:
148
+ try:
149
+ prepared = preparer(block_src)
150
+ except MagicPrepareError:
151
+ end += 1
152
+ continue
153
+
154
+ magic = Magic(
155
+ key=key,
156
+ file=file,
157
+ start_line=start + 1,
158
+ end_line=end + 1,
159
+ body=block_src,
160
+ prepared=prepared,
161
+ )
162
+ break
163
+
164
+ if magic is None:
165
+ raise Exception(f'Failed to find magic block terminator : {file=} {start=} {end=}')
166
+
167
+ out.append(magic)
168
+ start = end + 1
169
+
170
+ return out
171
+
172
+
173
+ ##
174
+
175
+
176
+ def find_magic_files(
177
+ style: MagicStyle,
178
+ roots: ta.Sequence[str],
179
+ *,
180
+ keys: ta.Optional[ta.Iterable[str]] = None,
181
+ ) -> ta.Iterator[str]:
182
+ if isinstance(roots, str):
183
+ raise TypeError(roots)
184
+
185
+ pat = compile_magic_style_pat(
186
+ style,
187
+ keys=keys,
188
+ )
189
+
190
+ for root in roots:
191
+ for dp, dns, fns in os.walk(root): # noqa
192
+ for fn in fns:
193
+ if not any(fn.endswith(f'.{x}') for x in style.exts):
194
+ continue
195
+
196
+ fp = os.path.join(dp, fn)
197
+ try:
198
+ with open(fp) as f:
199
+ src = f.read()
200
+ except UnicodeDecodeError:
201
+ continue
202
+
203
+ if not any(pat.fullmatch(l) for l in src.splitlines()):
204
+ continue
205
+
206
+ yield fp
207
+
208
+
209
+ def find_magic_py_modules(
210
+ roots: ta.Sequence[str],
211
+ *,
212
+ style: MagicStyle = PY_MAGIC_STYLE,
213
+ **kwargs: ta.Any,
214
+ ) -> ta.Iterator[str]:
215
+ for fp in find_magic_files(style, roots, **kwargs):
216
+ dp = os.path.dirname(fp)
217
+ fn = os.path.basename(fp)
218
+
219
+ if fn == '__init__.py':
220
+ yield dp.replace(os.sep, '.')
221
+ elif fn.endswith('.py'):
222
+ yield fp[:-3].replace(os.sep, '.')
223
+ else:
224
+ yield fp
225
+
226
+
227
+ ##
228
+
229
+
230
+ # @omlish-manifest
231
+ _CLI_MODULE = {'$omdev.cli.types.CliModule': {
232
+ 'cmd_name': 'py/findmagic',
233
+ 'mod_name': __name__,
234
+ }}
235
+
236
+
237
+ if __name__ == '__main__':
238
+ def _main(argv=None) -> None:
239
+ import argparse
240
+
241
+ arg_parser = argparse.ArgumentParser()
242
+ arg_parser.add_argument('--style', '-s', default='py')
243
+ arg_parser.add_argument('--key', '-k', dest='keys', action='append')
244
+ arg_parser.add_argument('--modules', action='store_true')
245
+ arg_parser.add_argument('roots', nargs='*')
246
+ args = arg_parser.parse_args(argv)
247
+
248
+ style = {
249
+ 'py': PY_MAGIC_STYLE,
250
+ 'c': C_MAGIC_STYLE,
251
+ }[args.style]
252
+
253
+ kw: dict = dict(
254
+ roots=args.roots,
255
+ style=style,
256
+ keys=args.keys,
257
+ )
258
+
259
+ fn: ta.Callable
260
+ if args.modules:
261
+ fn = find_magic_py_modules
262
+ else:
263
+ fn = find_magic_files
264
+
265
+ for out in fn(**kw):
266
+ print(out)
267
+
268
+ _main()
omdev/magic/magic.py ADDED
@@ -0,0 +1,17 @@
1
+ # ruff: noqa: UP007
2
+ import dataclasses as dc
3
+ import typing as ta
4
+
5
+
6
+ @dc.dataclass(frozen=True)
7
+ class Magic:
8
+ key: str
9
+
10
+ file: ta.Optional[str]
11
+
12
+ start_line: int
13
+ end_line: int
14
+
15
+ body: str
16
+
17
+ prepared: ta.Any
omdev/magic/prepare.py ADDED
@@ -0,0 +1,27 @@
1
+ import json
2
+ import typing as ta
3
+
4
+
5
+ class MagicPrepareError(Exception):
6
+ pass
7
+
8
+
9
+ def py_compile_magic_preparer(src: str) -> ta.Any:
10
+ try:
11
+ prepared = compile(f'({src})', '<magic>', 'eval')
12
+ except SyntaxError:
13
+ raise MagicPrepareError # noqa
14
+ return prepared
15
+
16
+
17
+ def py_eval_magic_preparer(src: str) -> ta.Any:
18
+ code = py_compile_magic_preparer(src)
19
+ return eval(code) # noqa
20
+
21
+
22
+ def json_magic_preparer(src: str) -> ta.Any:
23
+ try:
24
+ prepared = json.loads(src)
25
+ except json.JSONDecodeError:
26
+ raise MagicPrepareError # noqa
27
+ return prepared
omdev/magic/styles.py ADDED
@@ -0,0 +1,33 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
3
+ import typing as ta
4
+
5
+
6
+ MAGIC_KEY_PREFIX = '@omlish-'
7
+
8
+
9
+ @dc.dataclass(frozen=True)
10
+ class MagicStyle:
11
+ name: str
12
+
13
+ exts: ta.FrozenSet[str] = frozenset()
14
+
15
+ key_prefix: str = MAGIC_KEY_PREFIX
16
+
17
+ line_prefix: ta.Optional[str] = None
18
+ block_prefix_suffix: ta.Optional[ta.Tuple[str, str]] = None
19
+
20
+
21
+ PY_MAGIC_STYLE = MagicStyle(
22
+ name='py',
23
+ exts=frozenset(['py']),
24
+ line_prefix='# ',
25
+ )
26
+
27
+
28
+ C_MAGIC_STYLE = MagicStyle(
29
+ name='c',
30
+ exts=frozenset(['c', 'cc', 'cpp']),
31
+ line_prefix='// ',
32
+ block_prefix_suffix=('/* ', '*/'),
33
+ )
omdev/manifests/build.py CHANGED
@@ -32,7 +32,7 @@ from omlish.lite.json import json_dumps_pretty
32
32
  from omlish.lite.logs import configure_standard_logging
33
33
  from omlish.lite.logs import log
34
34
 
35
- from .. import findmagic
35
+ from .. import magic
36
36
  from .load import ManifestLoader
37
37
  from .types import Manifest
38
38
  from .types import ManifestOrigin
@@ -44,7 +44,7 @@ T = ta.TypeVar('T')
44
44
  ##
45
45
 
46
46
 
47
- MANIFEST_MAGIC = '# @omlish-manifest'
47
+ MANIFEST_MAGIC_KEY = '@omlish-manifest'
48
48
 
49
49
  _MANIFEST_GLOBAL_PAT = re.compile(r'^(?P<name>[A-Za-z_][A-Za-z0-9_]*)\s*=.*')
50
50
 
@@ -148,7 +148,7 @@ class ManifestBuilder:
148
148
  origins: ta.List[ManifestOrigin] = []
149
149
  lines = src.splitlines(keepends=True)
150
150
  for i, l in enumerate(lines):
151
- if l.startswith(MANIFEST_MAGIC):
151
+ if l.startswith('# ' + MANIFEST_MAGIC_KEY):
152
152
  if (m := _MANIFEST_GLOBAL_PAT.match(nl := lines[i + 1])) is None:
153
153
  raise Exception(nl)
154
154
 
@@ -235,10 +235,10 @@ class ManifestBuilder:
235
235
  if not os.path.isdir(pkg_dir) or not os.path.isfile(os.path.join(pkg_dir, '__init__.py')):
236
236
  raise Exception(pkg_dir)
237
237
 
238
- files = sorted(findmagic.find_magic(
238
+ files = sorted(magic.find_magic_files(
239
+ magic.PY_MAGIC_STYLE,
239
240
  [pkg_dir],
240
- [MANIFEST_MAGIC],
241
- ['py'],
241
+ keys=[MANIFEST_MAGIC_KEY],
242
242
  ))
243
243
  manifests: ta.List[Manifest] = list(itertools.chain.from_iterable(await asyncio.gather(*[
244
244
  self._spawn(
omdev/precheck/lite.py CHANGED
@@ -8,10 +8,10 @@ import subprocess
8
8
  import textwrap
9
9
  import typing as ta
10
10
 
11
- from omdev import findmagic
12
11
  from omlish import cached
13
12
  from omlish.lite.subprocesses import subprocess_maybe_shell_wrap_exec
14
13
 
14
+ from .. import magic
15
15
  from .base import Precheck
16
16
  from .base import PrecheckContext
17
17
 
@@ -121,10 +121,10 @@ class LitePython8Precheck(Precheck['LitePython8Precheck.Config']):
121
121
  return vs
122
122
 
123
123
  async def run(self) -> ta.AsyncGenerator[Precheck.Violation, None]:
124
- for fp in findmagic.find_magic(
124
+ for fp in magic.find_magic_files(
125
+ magic.PY_MAGIC_STYLE,
125
126
  self._context.src_roots,
126
- ['# @omlish-lite'],
127
- ['py'],
127
+ keys=['@omlish-lite'],
128
128
  ):
129
129
  with open(fp) as f: # noqa # FIXME
130
130
  src = f.read()
omdev/precheck/scripts.py CHANGED
@@ -3,9 +3,8 @@ import os
3
3
  import stat
4
4
  import typing as ta
5
5
 
6
- from omdev import findimports
7
- from omdev import findmagic
8
-
6
+ from .. import findimports
7
+ from .. import magic
9
8
  from .base import Precheck
10
9
  from .base import PrecheckContext
11
10
 
@@ -22,10 +21,10 @@ class ScriptDepsPrecheck(Precheck['ScriptDepsPrecheck.Config']):
22
21
  super().__init__(context, config)
23
22
 
24
23
  async def run(self) -> ta.AsyncGenerator[Precheck.Violation, None]:
25
- for fp in findmagic.find_magic(
24
+ for fp in magic.find_magic_files(
25
+ magic.PY_MAGIC_STYLE,
26
26
  self._context.src_roots,
27
- ['# @omlish-script'],
28
- ['py'],
27
+ keys=['@omlish-script'],
29
28
  ):
30
29
  if not (stat.S_IXUSR & os.stat(fp).st_mode):
31
30
  yield Precheck.Violation(self, f'script {fp} is not executable')
omdev/pyproject/pkg.py CHANGED
@@ -40,7 +40,7 @@ from omlish.lite.logs import log
40
40
  from omlish.lite.subprocesses import subprocess_check_call
41
41
 
42
42
  from ..cexts.magic import CextMagic
43
- from ..findmagic import find_magic
43
+ from ..magic.find import find_magic_files
44
44
  from ..revisions import GitRevisionAdder
45
45
  from ..toml.writer import TomlWriter
46
46
 
@@ -403,10 +403,10 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
403
403
 
404
404
  @cached_nullary
405
405
  def find_cext_srcs(self) -> ta.Sequence[str]:
406
- return sorted(find_magic(
406
+ return sorted(find_magic_files(
407
+ CextMagic.STYLE,
407
408
  [self._dir_name],
408
- [CextMagic.MAGIC_COMMENT],
409
- CextMagic.FILE_EXTENSIONS,
409
+ keys=[CextMagic.KEY],
410
410
  ))
411
411
 
412
412
  #
@@ -99,84 +99,6 @@ UnparsedVersionVar = ta.TypeVar('UnparsedVersionVar', bound=UnparsedVersion)
99
99
  CallableVersionOperator = ta.Callable[['Version', str], bool]
100
100
 
101
101
 
102
- ########################################
103
- # ../../cexts/magic.py
104
-
105
-
106
- class CextMagic:
107
- MAGIC = '@omlish-cext'
108
- MAGIC_COMMENT = f'// {MAGIC}'
109
-
110
- FILE_EXTENSIONS = ('c', 'cc', 'cpp')
111
-
112
-
113
- ########################################
114
- # ../../findmagic.py
115
-
116
-
117
- def compile_magic_pat(m: str) -> re.Pattern:
118
- return re.compile('^' + re.escape(m) + r'($|(\s.*))')
119
-
120
-
121
- def find_magic(
122
- roots: ta.Sequence[str],
123
- magics: ta.Sequence[str],
124
- exts: ta.Sequence[str],
125
- *,
126
- py: bool = False,
127
- ) -> ta.Iterator[str]:
128
- if isinstance(roots, str):
129
- raise TypeError(roots)
130
- if isinstance(magics, str):
131
- raise TypeError(magics)
132
- if isinstance(exts, str):
133
- raise TypeError(exts)
134
-
135
- if not magics:
136
- raise Exception('Must specify magics')
137
- if not exts:
138
- raise Exception('Must specify extensions')
139
-
140
- pats = [compile_magic_pat(m) for m in magics]
141
-
142
- for root in roots:
143
- for dp, dns, fns in os.walk(root): # noqa
144
- for fn in fns:
145
- if not any(fn.endswith(f'.{x}') for x in exts):
146
- continue
147
-
148
- fp = os.path.join(dp, fn)
149
- try:
150
- with open(fp) as f:
151
- src = f.read()
152
- except UnicodeDecodeError:
153
- continue
154
-
155
- if not any(
156
- any(pat.fullmatch(l) for pat in pats)
157
- for l in src.splitlines()
158
- ):
159
- continue
160
-
161
- if py:
162
- if fn == '__init__.py':
163
- out = dp.replace(os.sep, '.')
164
- elif fn.endswith('.py'):
165
- out = fp[:-3].replace(os.sep, '.')
166
- else:
167
- out = fp
168
- else:
169
- out = fp
170
- yield out
171
-
172
-
173
- # # @omlish-manifest
174
- # _CLI_MODULE = {'$omdev.cli.types.CliModule': {
175
- # 'cmd_name': 'py/findmagic',
176
- # 'mod_name': __name__,
177
- # }}
178
-
179
-
180
102
  ########################################
181
103
  # ../../git.py
182
104
 
@@ -280,6 +202,87 @@ def get_git_revision(
280
202
  return dirty_rev + ('-untracked' if has_untracked else '')
281
203
 
282
204
 
205
+ ########################################
206
+ # ../../magic/magic.py
207
+
208
+
209
+ @dc.dataclass(frozen=True)
210
+ class Magic:
211
+ key: str
212
+
213
+ file: ta.Optional[str]
214
+
215
+ start_line: int
216
+ end_line: int
217
+
218
+ body: str
219
+
220
+ prepared: ta.Any
221
+
222
+
223
+ ########################################
224
+ # ../../magic/prepare.py
225
+
226
+
227
+ class MagicPrepareError(Exception):
228
+ pass
229
+
230
+
231
+ def py_compile_magic_preparer(src: str) -> ta.Any:
232
+ try:
233
+ prepared = compile(f'({src})', '<magic>', 'eval')
234
+ except SyntaxError:
235
+ raise MagicPrepareError # noqa
236
+ return prepared
237
+
238
+
239
+ def py_eval_magic_preparer(src: str) -> ta.Any:
240
+ code = py_compile_magic_preparer(src)
241
+ return eval(code) # noqa
242
+
243
+
244
+ def json_magic_preparer(src: str) -> ta.Any:
245
+ try:
246
+ prepared = json.loads(src)
247
+ except json.JSONDecodeError:
248
+ raise MagicPrepareError # noqa
249
+ return prepared
250
+
251
+
252
+ ########################################
253
+ # ../../magic/styles.py
254
+
255
+
256
+ MAGIC_KEY_PREFIX = '@omlish-'
257
+
258
+
259
+ @dc.dataclass(frozen=True)
260
+ class MagicStyle:
261
+ name: str
262
+
263
+ exts: ta.FrozenSet[str] = frozenset()
264
+
265
+ key_prefix: str = MAGIC_KEY_PREFIX
266
+
267
+ line_prefix: ta.Optional[str] = None
268
+ block_prefix_suffix: ta.Optional[ta.Tuple[str, str]] = None
269
+
270
+
271
+ PY_MAGIC_STYLE = MagicStyle(
272
+ name='py',
273
+ exts=frozenset(['py']),
274
+ line_prefix='# ',
275
+ )
276
+
277
+
278
+ C_MAGIC_STYLE = MagicStyle(
279
+ name='c',
280
+ exts=frozenset(['c', 'cc', 'cpp']),
281
+ line_prefix='// ',
282
+ block_prefix_suffix=('/* ', '*/'),
283
+ )
284
+
285
+
283
286
  ########################################
284
287
  # ../../packaging/versions.py
285
288
  # Copyright (c) Donald Stufft and individual contributors.
@@ -2077,6 +2080,241 @@ def format_num_bytes(num_bytes: int) -> str:
2077
2080
  return f'{num_bytes / 1024 ** (len(FORMAT_NUM_BYTES_SUFFIXES) - 1):.2f}{FORMAT_NUM_BYTES_SUFFIXES[-1]}'
2078
2081
 
2079
2082
 
2083
+ ########################################
2084
+ # ../../cexts/magic.py
2085
+
2086
+
2087
+ class CextMagic:
2088
+ KEY = '@omlish-cext'
2089
+ STYLE = C_MAGIC_STYLE
2090
+
2091
+
2092
+ ########################################
2093
+ # ../../magic/find.py
2094
+
2095
+
2096
+ ##
2097
+
2098
+
2099
+ def compile_magic_style_pat(
2100
+ style: MagicStyle,
2101
+ *,
2102
+ keys: ta.Optional[ta.Iterable[str]] = None,
2103
+ ) -> re.Pattern:
2104
+ ps: ta.List[str] = []
2105
+ if style.line_prefix is not None:
2106
+ ps.append(style.line_prefix)
2107
+ if style.block_prefix_suffix is not None:
2108
+ ps.append(style.block_prefix_suffix[0])
2109
+ if not ps:
2110
+ raise Exception('No prefixes')
2111
+
2112
+ ms: ta.List[str] = []
2113
+ if keys is not None:
2114
+ if isinstance(keys, str):
2115
+ raise TypeError(keys)
2116
+ for k in keys:
2117
+ if not k.startswith(style.key_prefix):
2118
+ raise Exception(f'Key does not start with prefix: {k!r} {style.key_prefix!r}')
2119
+ ms.extend([re.escape(p + k) for p in ps])
2120
+ else:
2121
+ ms = [re.escape(p + style.key_prefix) + r'\S*' for p in ps]
2122
+ if not ms:
2123
+ raise Exception('No matchers')
2124
+
2125
+ b = '|'.join(f'({m})' for m in ms)
2126
+ s = '^(' + b + r')($|(\s.*))'
2127
+ return re.compile(s)
2128
+
2129
+
2130
+ ##
2131
+
2132
+
2133
+ def chop_magic_lines(
2134
+ magic_key: str,
2135
+ prefix: str,
2136
+ lines: ta.Iterable[str],
2137
+ ) -> ta.Optional[ta.List[str]]:
2138
+ out: ta.List[str] = []
2139
+ for i, line in enumerate(lines):
2140
+ if not i:
2141
+ if not line.startswith(prefix + magic_key):
2142
+ return None
2143
+ out.append(line[len(prefix) + len(magic_key) + 1:])
2144
+ else:
2145
+ if not line.startswith(prefix):
2146
+ return None
2147
+ out.append(line[len(prefix):])
2148
+ return out
2149
+
2150
+
2151
+ def chop_magic_block(
2152
+ magic_key: str,
2153
+ prefix: str,
2154
+ suffix: str,
2155
+ lines: ta.Iterable[str],
2156
+ ) -> ta.Optional[ta.List[str]]:
2157
+ out: ta.List[str] = []
2158
+ for i, line in enumerate(lines):
2159
+ if not i:
2160
+ if not line.startswith(prefix + magic_key):
2161
+ return None
2162
+ s = line[len(prefix) + len(magic_key) + 1:]
2163
+ if s.rstrip().endswith(suffix):
2164
+ out.append(s.rstrip()[:-len(suffix)])
2165
+ break
2166
+ out.append(s)
2167
+ elif line.rstrip().endswith(suffix):
2168
+ out.append(line.rstrip()[:-len(suffix)])
2169
+ break
2170
+ else:
2171
+ out.append(line)
2172
+ return out
2173
+
2174
+
2175
+ ##
2176
+
2177
+
2178
+ def find_magic(
2179
+ style: MagicStyle,
2180
+ lines: ta.Sequence[str],
2181
+ *,
2182
+ file: ta.Optional[str] = None,
2183
+ preparer: ta.Callable[[str], ta.Any] = py_compile_magic_preparer,
2184
+ ) -> ta.List[Magic]:
2185
+ out: ta.List[Magic] = []
2186
+
2187
+ start = 0
2188
+ while start < len(lines):
2189
+ start_line = lines[start]
2190
+
2191
+ chopper: ta.Callable[[ta.Iterable[str]], ta.Optional[ta.List[str]]]
2192
+ if (
2193
+ style.line_prefix is not None and
2194
+ start_line.startswith(style.line_prefix + style.key_prefix)
2195
+ ):
2196
+ key = start_line[len(style.line_prefix):].split()[0]
2197
+ chopper = functools.partial(
2198
+ chop_magic_lines,
2199
+ key,
2200
+ style.line_prefix,
2201
+ )
2202
+
2203
+ elif (
2204
+ style.block_prefix_suffix is not None and
2205
+ start_line.startswith(style.block_prefix_suffix[0] + style.key_prefix)
2206
+ ):
2207
+ key = start_line[len(style.block_prefix_suffix[0]):].split()[0]
2208
+ chopper = functools.partial(
2209
+ chop_magic_block,
2210
+ key,
2211
+ *style.block_prefix_suffix,
2212
+ )
2213
+
2214
+ else:
2215
+ start += 1
2216
+ continue
2217
+
2218
+ end = start
2219
+ magic: ta.Optional[Magic] = None
2220
+ while end < len(lines):
2221
+ block_lines = chopper(lines[start:end + 1])
2222
+ if block_lines is None:
2223
+ raise Exception(f'Failed to find magic block terminator : {file=} {start=} {end=}')
2224
+
2225
+ block_src = ''.join(block_lines)
2226
+ if not block_src:
2227
+ prepared = None
2228
+ else:
2229
+ try:
2230
+ prepared = preparer(block_src)
2231
+ except MagicPrepareError:
2232
+ end += 1
2233
+ continue
2234
+
2235
+ magic = Magic(
2236
+ key=key,
2237
+ file=file,
2238
+ start_line=start + 1,
2239
+ end_line=end + 1,
2240
+ body=block_src,
2241
+ prepared=prepared,
2242
+ )
2243
+ break
2244
+
2245
+ if magic is None:
2246
+ raise Exception(f'Failed to find magic block terminator : {file=} {start=} {end=}')
2247
+
2248
+ out.append(magic)
2249
+ start = end + 1
2250
+
2251
+ return out
2252
+
2253
+
2254
+ ##
2255
+
2256
+
2257
+ def find_magic_files(
2258
+ style: MagicStyle,
2259
+ roots: ta.Sequence[str],
2260
+ *,
2261
+ keys: ta.Optional[ta.Iterable[str]] = None,
2262
+ ) -> ta.Iterator[str]:
2263
+ if isinstance(roots, str):
2264
+ raise TypeError(roots)
2265
+
2266
+ pat = compile_magic_style_pat(
2267
+ style,
2268
+ keys=keys,
2269
+ )
2270
+
2271
+ for root in roots:
2272
+ for dp, dns, fns in os.walk(root): # noqa
2273
+ for fn in fns:
2274
+ if not any(fn.endswith(f'.{x}') for x in style.exts):
2275
+ continue
2276
+
2277
+ fp = os.path.join(dp, fn)
2278
+ try:
2279
+ with open(fp) as f:
2280
+ src = f.read()
2281
+ except UnicodeDecodeError:
2282
+ continue
2283
+
2284
+ if not any(pat.fullmatch(l) for l in src.splitlines()):
2285
+ continue
2286
+
2287
+ yield fp
2288
+
2289
+
2290
+ def find_magic_py_modules(
2291
+ roots: ta.Sequence[str],
2292
+ *,
2293
+ style: MagicStyle = PY_MAGIC_STYLE,
2294
+ **kwargs: ta.Any,
2295
+ ) -> ta.Iterator[str]:
2296
+ for fp in find_magic_files(style, roots, **kwargs):
2297
+ dp = os.path.dirname(fp)
2298
+ fn = os.path.basename(fp)
2299
+
2300
+ if fn == '__init__.py':
2301
+ yield dp.replace(os.sep, '.')
2302
+ elif fn.endswith('.py'):
2303
+ yield fp[:-3].replace(os.sep, '.')
2304
+ else:
2305
+ yield fp
2306
+
2307
+
2308
+ ##
2309
+
2310
+
2311
+ # # @omlish-manifest
2312
+ # _CLI_MODULE = {'$omdev.cli.types.CliModule': {
2313
+ # 'cmd_name': 'py/findmagic',
2314
+ # 'mod_name': __name__,
2315
+ # }}
2316
+
2317
+
2080
2318
  ########################################
2081
2319
  # ../../packaging/specifiers.py
2082
2320
  # Copyright (c) Donald Stufft and individual contributors.
@@ -4162,10 +4400,10 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
4162
4400
 
4163
4401
  @cached_nullary
4164
4402
  def find_cext_srcs(self) -> ta.Sequence[str]:
4165
- return sorted(find_magic(
4403
+ return sorted(find_magic_files(
4404
+ CextMagic.STYLE,
4166
4405
  [self._dir_name],
4167
- [CextMagic.MAGIC_COMMENT],
4168
- CextMagic.FILE_EXTENSIONS,
4406
+ keys=[CextMagic.KEY],
4169
4407
  ))
4170
4408
 
4171
4409
  #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omdev
3
- Version: 0.0.0.dev99
3
+ Version: 0.0.0.dev100
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.dev99
15
+ Requires-Dist: omlish ==0.0.0.dev100
16
16
  Provides-Extra: all
17
17
  Requires-Dist: black ~=24.10 ; extra == 'all'
18
18
  Requires-Dist: pycparser ~=2.22 ; extra == 'all'
@@ -1,11 +1,10 @@
1
- omdev/.manifests.json,sha256=UalOm-SBfhxFAFX9AQDI1x3Q_IVBf4kCHoZrc4ZG8M0,6709
1
+ omdev/.manifests.json,sha256=nBS0fk7qpXG5VCITHxGUgJgh8Ghd3LyckoYCcfwb8Qc,6713
2
2
  omdev/__about__.py,sha256=ON7EnhbxbwLsMj60wkd9OEYPloXZ7jmnMMzeLg44LXY,1225
3
3
  omdev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  omdev/bracepy.py,sha256=I8EdqtDvxzAi3I8TuMEW-RBfwXfqKbwp06CfOdj3L1o,2743
5
5
  omdev/classdot.py,sha256=YOvgy6x295I_8NKBbBlRVd3AN7Osirm_Lqt4Wj0j9rY,1631
6
6
  omdev/cmake.py,sha256=Diy2ry65806dQP125DAstD3w46z_wszMH7PwC2-6iik,4578
7
7
  omdev/findimports.py,sha256=2t8QP852saEEJFeXySEzhi_nxRSxghlkXz2jVdvy08M,2392
8
- omdev/findmagic.py,sha256=XoKPGjSM0qn1PCiiBPwfTHkpqJYQJmLW8v_4QFJ16Mk,2486
9
8
  omdev/git.py,sha256=riM2KqSpQPC3N89uipd7Vm3kVgv4EYYDBU9tV1Z8juM,2208
10
9
  omdev/imgur.py,sha256=il12R3t19tALolteYCZywvcdQUEOcgvPyUYgWtKiqt4,2993
11
10
  omdev/revisions.py,sha256=U657hf4zeEN32y3g4CzqCAodx_HlfkHj2cIIKALNFDo,5009
@@ -14,7 +13,7 @@ omdev/tokens.py,sha256=GusxQ1Cd_eiScuR8XTTtc9QFhOgYviYGBZmFnn3Hj7s,756
14
13
  omdev/wheelfile.py,sha256=yfupGcGkbFlmzGzKU64k_vmOKpaKnUlDWxeGn2KdekU,10005
15
14
  omdev/amalg/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
15
  omdev/amalg/__main__.py,sha256=h94M-VqZ3AFBU2a8zOsjeKK7RF6uINhTHl6OiGbVMgw,163
17
- omdev/amalg/amalg.py,sha256=v_4Y9b6eUWUArhIRnTkboe8ZNMr_mHJTWi8GajdDvUs,15139
16
+ omdev/amalg/amalg.py,sha256=b5lo2EZno62_5HbQV-TSMcsLe5ztm4vz3QrJ1-h_ppo,15140
18
17
  omdev/antlr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
18
  omdev/antlr/consts.py,sha256=8pR6r0m0P3hAiyiAoJZ-nptd2GYbZ98mxwPL9cpaRuw,279
20
19
  omdev/antlr/gen.py,sha256=QnPyVWUrJYqHoOc3XsXA8fJdoiwAj6pyUwdG-DVrIeA,2953
@@ -38,10 +37,10 @@ omdev/cache/data/specs.py,sha256=0a9NPJ76Wz69s94KlNbr1Xma3UQ0z2oCAQN7s6uXe4w,249
38
37
  omdev/cexts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
38
  omdev/cexts/_boilerplate.cc,sha256=sbpXEgdFrkdzZXgaNWFFNN27fL9TZu6VrwvMY4-nnFM,1726
40
39
  omdev/cexts/build.py,sha256=F3z1-CjDlEM-Gzi5IunKUBO52qdH_pMsFylobTdGJnI,2654
41
- omdev/cexts/cmake.py,sha256=H-fafsK5TCHAoxOcxvZm83CXFAJl3Gf-nm9GjXfa8SU,9833
40
+ omdev/cexts/cmake.py,sha256=m7Md-mZP252EMa05TZVHRjy8vzhS9tw0nhO1GVQtkQU,9816
42
41
  omdev/cexts/importhook.py,sha256=ko0KRxah_ZHhLVcCigYIIDvNHCfHpJ8qhmmuHKbCOt4,3546
43
- omdev/cexts/magic.py,sha256=FxMfciRvbrcyH-kfQgcAgZL7ekyp5BdkyQ5IC9YjFzo,136
44
- omdev/cexts/scan.py,sha256=_U5DX9ksHP1845PdGxWh4Rf1a6x_sG1MH3uL_hwBnKY,1669
42
+ omdev/cexts/magic.py,sha256=MPmdhGANFVRaA3351BSTBrXm214dWXro1RMRHaJ2_O0,126
43
+ omdev/cexts/scan.py,sha256=fTDy4DKgGQHdyf2Pp80Z_Ra5o984jFF9LeKfJm39IyM,1665
45
44
  omdev/cexts/_distutils/LICENSE,sha256=22p14FIRp3F4Cb7Mj_GK33PKr25issFGHC2JN6dg9vc,1023
46
45
  omdev/cexts/_distutils/__init__.py,sha256=c1zImtnPh3uY8BUTV4RLKtGKqTPx3c_pBbhA6tPtNsE,297
47
46
  omdev/cexts/_distutils/build_ext.py,sha256=STHl9Rq2KeWJ3dQ8j8LwIQ-vFc4-3XsYWQ8Qc5_VByU,13833
@@ -79,8 +78,13 @@ omdev/interp/resolvers.py,sha256=tpzlmqGp1C4QKdA6TfcPmtmaygu7mb6WK2RPSbyNQ6s,302
79
78
  omdev/interp/standalone.py,sha256=XcltiL7ypcfV89C82_3knQ3Kx7aW4wnnxf2056ZXC3A,7731
80
79
  omdev/interp/system.py,sha256=bI-JhX4GVJqW7wMxnIa-DGJWnCLmFcIsnl9pc1RGY2g,3513
81
80
  omdev/interp/types.py,sha256=EMN3StEMkFoQAMUIZd7JYL4uUWqzFGY-2hTL8EBznYM,2437
81
+ omdev/magic/__init__.py,sha256=CBzRB71RLyylkrj8dph6JUEddA8KSMJvDgriHqFfJGU,478
82
+ omdev/magic/find.py,sha256=tTmpWXAleaXG3_kNOsRF7s8D0CpYMXbdz6-HbCNBW90,7070
83
+ omdev/magic/magic.py,sha256=h1nxoW6CV1MRCiHjDt3sO4kmG0qTtTRbkDNiPLGo2BE,224
84
+ omdev/magic/prepare.py,sha256=V5jYT2AeFmazzPwk9sNismSouLwFXEoik6FwKcWCNUY,589
85
+ omdev/magic/styles.py,sha256=YZrLend-O5-7TKrIu4Ukxk1q0I2yaQtxwa6tn7TRbJM,599
82
86
  omdev/manifests/__init__.py,sha256=P2B0dpT8D7l5lJwRGPA92IcQj6oeXfd90X5-q9BJrKg,51
83
- omdev/manifests/build.py,sha256=omRyKmj4NhZ6PrhmoJIKYCTYaU1OB7bZEtfso29hIEo,10831
87
+ omdev/manifests/build.py,sha256=E7BelbrJEJes-BEbAUZCVLVs79sYuC0fbthgXAoxaOk,10865
84
88
  omdev/manifests/load.py,sha256=LtEsluDdd8CkNGj0QGBxee3twBn095Fru0xz2mtr7uk,4788
85
89
  omdev/manifests/types.py,sha256=Jv6PAdVLPb9Hh4y6vDhPlWuMNBBViin1bC_u83jfsH4,234
86
90
  omdev/mypy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -94,10 +98,10 @@ omdev/precheck/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
98
  omdev/precheck/__main__.py,sha256=UEuS4z5-heIrwTtB-ONe1KeXJdqj8tYXMqWMpuO10so,165
95
99
  omdev/precheck/base.py,sha256=a_lGoFM-QhL8u8XDUYFhb-feEyfPbP4j8lcmNO51sHY,732
96
100
  omdev/precheck/git.py,sha256=APC5Ln7x0zDrQiGPRWPsBcVJK3vWhbU-brqR5M63JQA,849
97
- omdev/precheck/lite.py,sha256=d8D-BY-Z0rqQigQ_aR9QXxdB3EBCHJc7WgBJngGiEiE,3871
101
+ omdev/precheck/lite.py,sha256=z99pgTO4SAmLEqSj6qaKd4hcs0WpwixYkQZn75lZRX8,3883
98
102
  omdev/precheck/main.py,sha256=2YizDZSDhMeQaZKVH83s99pBmtOUL9B-8dXwIcw6fQQ,2674
99
103
  omdev/precheck/manifests.py,sha256=YfXqt6u0hlFXY0QkBMec6V_6Y9T4eCVAmrJDkQkB13U,774
100
- omdev/precheck/scripts.py,sha256=qq6MXkxgrYngPg5pWnXH4uRSuRkP3mFqbeml1UmvGBc,1265
104
+ omdev/precheck/scripts.py,sha256=Xw9kkQzlDd_2V9av9qlaNpNZG9jZdy3TTo7x60MeR2I,1273
101
105
  omdev/ptk/__init__.py,sha256=StAwXQ96e8Xkkg7ciR9oBBhcSgqHT76vhoZML82BuY0,447
102
106
  omdev/ptk/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
103
107
  omdev/ptk/apps/ncdu.py,sha256=ov6AEjne2NyVE45XiAtteq5SmbxXHQkUsybuu5KSwRQ,4479
@@ -106,7 +110,7 @@ omdev/pyproject/__main__.py,sha256=gn3Rl1aYPYdiTtEqa9ifi0t-e4ZwPY0vhJ4UXvYdJDY,1
106
110
  omdev/pyproject/cexts.py,sha256=x13piOOnNrYbA17qZLDVuR0p1sqhgEwpk4FtImX-klM,4281
107
111
  omdev/pyproject/cli.py,sha256=kw0Jyzywwt6QOc6QHDevWW9p85aXT7jvVFFb8Sb_EAU,11365
108
112
  omdev/pyproject/configs.py,sha256=K9H5cGwVLgHi8wKwtYvlXHZ9ThtmnI4jo8JAb-t1-70,2859
109
- omdev/pyproject/pkg.py,sha256=rNKzJOIgPDrtT2i14Pebldoboz45w00sKb5l_kYFaRI,14562
113
+ omdev/pyproject/pkg.py,sha256=WB9k3zEpHSAR24H09kikgAnLMWUz-bk9f0aB-2L_ITw,14560
110
114
  omdev/pyproject/reqs.py,sha256=8feZ71YnGzwKbLK4zO28CDQeNcZIIuq6cnkBhs6M-7E,2406
111
115
  omdev/scripts/__init__.py,sha256=MKCvUAEQwsIvwLixwtPlpBqmkMXLCnjjXyAXvVpDwVk,91
112
116
  omdev/scripts/bumpversion.py,sha256=Kn7fo73Hs8uJh3Hi3EIyLOlzLPWAC6dwuD_lZ3cIzuY,1064
@@ -114,7 +118,7 @@ omdev/scripts/execrss.py,sha256=hJTWBig_-XqKIj1DphYTfeVDtdQTM1XUl-Hvzs2x9iY,451
114
118
  omdev/scripts/exectime.py,sha256=dBdn3KV2jR6tCrzGvb9dTl2uGe2vNpLxmHMtExmnaiM,410
115
119
  omdev/scripts/importtrace.py,sha256=Jbo3Yk2RAbE8_tJ97iTcVNpoxCJxrRb2tl1W_CV3NG0,14067
116
120
  omdev/scripts/interp.py,sha256=ls04OE3g_TpiK5_inRfOzUvBGUtBgSt5vnkqC3eZhTM,72076
117
- omdev/scripts/pyproject.py,sha256=g5f0AyRii_DSY-D6mMDUVqKNPNxWXAQJoWrYi1F2KGM,158772
121
+ omdev/scripts/pyproject.py,sha256=0etqlpe2wL2lRLKgRo6X5llzpvM-I7AHbu1oWqdV-6M,164318
118
122
  omdev/scripts/slowcat.py,sha256=lssv4yrgJHiWfOiHkUut2p8E8Tq32zB-ujXESQxFFHY,2728
119
123
  omdev/toml/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
120
124
  omdev/toml/parser.py,sha256=84bn09uhYHwQGyfww6Rw6y1RxPAE_HDltODOSakcqDM,29186
@@ -132,9 +136,9 @@ omdev/tools/sqlrepl.py,sha256=tmFZh80-xsGM62dyQ7_UGLebChrj7IHbIPYBWDJMgVk,5741
132
136
  omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
133
137
  omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
134
138
  omdev/tools/pawk/pawk.py,sha256=Eckymn22GfychCQcQi96BFqRo_LmiJ-EPhC8TTUJdB4,11446
135
- omdev-0.0.0.dev99.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
136
- omdev-0.0.0.dev99.dist-info/METADATA,sha256=TQ0PYL0VRRuYy3tYL-UAzTDAGQITWSQlfWSwsQISdAA,1702
137
- omdev-0.0.0.dev99.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
138
- omdev-0.0.0.dev99.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
139
- omdev-0.0.0.dev99.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
140
- omdev-0.0.0.dev99.dist-info/RECORD,,
139
+ omdev-0.0.0.dev100.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
140
+ omdev-0.0.0.dev100.dist-info/METADATA,sha256=jBN-gpjo8p3RwVShev6g75Sg2bNhC4oAAfL5Nj-Pqm0,1704
141
+ omdev-0.0.0.dev100.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
142
+ omdev-0.0.0.dev100.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
143
+ omdev-0.0.0.dev100.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
144
+ omdev-0.0.0.dev100.dist-info/RECORD,,
omdev/findmagic.py DELETED
@@ -1,91 +0,0 @@
1
- #!/usr/bin/env python3
2
- # @omlish-lite
3
- # @omlish-script
4
- import os.path
5
- import re
6
- import typing as ta
7
-
8
-
9
- def compile_magic_pat(m: str) -> re.Pattern:
10
- return re.compile('^' + re.escape(m) + r'($|(\s.*))')
11
-
12
-
13
- def find_magic(
14
- roots: ta.Sequence[str],
15
- magics: ta.Sequence[str],
16
- exts: ta.Sequence[str],
17
- *,
18
- py: bool = False,
19
- ) -> ta.Iterator[str]:
20
- if isinstance(roots, str):
21
- raise TypeError(roots)
22
- if isinstance(magics, str):
23
- raise TypeError(magics)
24
- if isinstance(exts, str):
25
- raise TypeError(exts)
26
-
27
- if not magics:
28
- raise Exception('Must specify magics')
29
- if not exts:
30
- raise Exception('Must specify extensions')
31
-
32
- pats = [compile_magic_pat(m) for m in magics]
33
-
34
- for root in roots:
35
- for dp, dns, fns in os.walk(root): # noqa
36
- for fn in fns:
37
- if not any(fn.endswith(f'.{x}') for x in exts):
38
- continue
39
-
40
- fp = os.path.join(dp, fn)
41
- try:
42
- with open(fp) as f:
43
- src = f.read()
44
- except UnicodeDecodeError:
45
- continue
46
-
47
- if not any(
48
- any(pat.fullmatch(l) for pat in pats)
49
- for l in src.splitlines()
50
- ):
51
- continue
52
-
53
- if py:
54
- if fn == '__init__.py':
55
- out = dp.replace(os.sep, '.')
56
- elif fn.endswith('.py'):
57
- out = fp[:-3].replace(os.sep, '.')
58
- else:
59
- out = fp
60
- else:
61
- out = fp
62
- yield out
63
-
64
-
65
- # @omlish-manifest
66
- _CLI_MODULE = {'$omdev.cli.types.CliModule': {
67
- 'cmd_name': 'py/findmagic',
68
- 'mod_name': __name__,
69
- }}
70
-
71
-
72
- if __name__ == '__main__':
73
- def _main(argv=None) -> None:
74
- import argparse
75
-
76
- arg_parser = argparse.ArgumentParser()
77
- arg_parser.add_argument('--ext', '-x', dest='exts', action='append')
78
- arg_parser.add_argument('--magic', '-m', dest='magics', action='append')
79
- arg_parser.add_argument('--py', action='store_true')
80
- arg_parser.add_argument('roots', nargs='*')
81
- args = arg_parser.parse_args(argv)
82
-
83
- for out in find_magic(
84
- roots=args.roots,
85
- magics=args.magics,
86
- exts=args.exts,
87
- py=args.py,
88
- ):
89
- print(out)
90
-
91
- _main()