omdev 0.0.0.dev52__py3-none-any.whl → 0.0.0.dev54__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/cli/main.py CHANGED
@@ -64,9 +64,10 @@ def _main() -> None:
64
64
 
65
65
  dct: dict[str, CliCmd] = {}
66
66
  for cc in ccs:
67
- if cc.cmd_name in dct:
68
- raise NameError(cc)
69
- dct[cc.cmd_name] = cc
67
+ for cn in [cc.cmd_name] if isinstance(cc.cmd_name, str) else cc.cmd_name:
68
+ if cn in dct:
69
+ raise NameError(cc)
70
+ dct[cn] = cc
70
71
 
71
72
  #
72
73
 
@@ -76,7 +77,26 @@ def _main() -> None:
76
77
 
77
78
  args = parser.parse_args()
78
79
  if not args.cmd:
79
- parser.print_help()
80
+ mdct: dict = {}
81
+ for cc in ccs:
82
+ if isinstance(cc.cmd_name, str) and cc.cmd_name[0] == '_':
83
+ continue
84
+ if isinstance(cc, CliFunc):
85
+ mdct.setdefault('-', []).append(cc)
86
+ elif isinstance(cc, CliModule):
87
+ mdct.setdefault(cc.mod_name.partition('.')[0], []).append(cc)
88
+ else:
89
+ raise TypeError(cc)
90
+
91
+ print('Subcommands:\n')
92
+ for m, l in sorted(mdct.items(), key=lambda t: (t[0] == '-', t[0])):
93
+ print(f' {m}')
94
+ for cc in sorted(l, key=lambda c: c.primary_name):
95
+ if isinstance(cc.cmd_name, str):
96
+ print(f' {cc.cmd_name}')
97
+ else:
98
+ print(f' {cc.cmd_name[0]} ({", ".join(cc.cmd_name[1:])})')
99
+ print()
80
100
  return
81
101
 
82
102
  #
@@ -84,7 +104,7 @@ def _main() -> None:
84
104
  cc = dct[args.cmd]
85
105
 
86
106
  if isinstance(cc, CliModule):
87
- sys.argv = [cc.cmd_name, *(args.args or ())]
107
+ sys.argv = [args.cmd, *(args.args or ())]
88
108
  runpy._run_module_as_main(cc.mod_name) # type: ignore # noqa
89
109
 
90
110
  elif isinstance(cc, CliFunc):
omdev/cli/types.py CHANGED
@@ -1,10 +1,18 @@
1
+ # ruff: noqa: UP007
1
2
  import dataclasses as dc
2
3
  import typing as ta
3
4
 
4
5
 
5
6
  @dc.dataclass(frozen=True)
6
7
  class CliCmd:
7
- cmd_name: str
8
+ cmd_name: ta.Union[str, ta.Sequence[str]]
9
+
10
+ @property
11
+ def primary_name(self) -> str:
12
+ if isinstance(self.cmd_name, str):
13
+ return self.cmd_name
14
+ else:
15
+ return self.cmd_name[0]
8
16
 
9
17
 
10
18
  @dc.dataclass(frozen=True)
omdev/manifests/build.py CHANGED
@@ -12,10 +12,9 @@ See (entry_points):
12
12
  """
13
13
  # ruff: noqa: UP006 UP007
14
14
  import argparse
15
+ import asyncio
15
16
  import collections
16
- import concurrent.futures as cf
17
17
  import dataclasses as dc
18
- import functools
19
18
  import inspect
20
19
  import itertools
21
20
  import json
@@ -39,6 +38,9 @@ from .types import Manifest
39
38
  from .types import ManifestOrigin
40
39
 
41
40
 
41
+ T = ta.TypeVar('T')
42
+
43
+
42
44
  ##
43
45
 
44
46
 
@@ -98,138 +100,160 @@ def _payload_src() -> str:
98
100
  return inspect.getsource(_dump_module_manifests)
99
101
 
100
102
 
101
- def build_module_manifests(
102
- file: str,
103
- base: str,
104
- *,
105
- shell_wrap: bool = True,
106
- warn_threshold_s: ta.Optional[float] = 1.,
107
- ) -> ta.Sequence[Manifest]:
108
- log.info('Extracting manifests from file %s', file)
109
-
110
- if not file.endswith('.py'):
111
- raise Exception(file)
112
-
113
- mod_name = file.rpartition('.')[0].replace(os.sep, '.')
114
- mod_base = mod_name.split('.')[0]
115
- if mod_base != (first_dir := file.split(os.path.sep)[0]):
116
- raise Exception(f'Unexpected module base: {mod_base=} != {first_dir=}')
117
-
118
- with open(os.path.join(base, file)) as f:
119
- src = f.read()
120
-
121
- origins: ta.List[ManifestOrigin] = []
122
- lines = src.splitlines(keepends=True)
123
- for i, l in enumerate(lines):
124
- if l.startswith(MANIFEST_MAGIC):
125
- if (m := _MANIFEST_GLOBAL_PAT.match(nl := lines[i + 1])) is None:
126
- raise Exception(nl)
127
-
128
- origins.append(ManifestOrigin(
129
- module='.'.join(['', *mod_name.split('.')[1:]]),
130
- attr=m.groupdict()['name'],
131
-
132
- file=file,
133
- line=i + 1,
134
- ))
103
+ class ManifestBuilder:
104
+ def __init__(
105
+ self,
106
+ base: str,
107
+ concurrency: int = 8,
108
+ *,
109
+ write: bool = False,
110
+ ) -> None:
111
+ super().__init__()
112
+
113
+ self._base = base
114
+ self._sem = asyncio.Semaphore(concurrency)
115
+ self._write = write
116
+
117
+ async def _spawn(self, fn: ta.Callable[..., ta.Awaitable[T]], *args: ta.Any, **kwargs: ta.Any) -> T:
118
+ await self._sem.acquire()
119
+ try:
120
+ try:
121
+ return await fn(*args, **kwargs)
122
+ except Exception: # noqa
123
+ log.exception('Exception in task: %s, %r, %r', fn, args, kwargs)
124
+ raise
125
+ finally:
126
+ self._sem.release()
127
+
128
+ async def build_module_manifests(
129
+ self,
130
+ file: str,
131
+ *,
132
+ shell_wrap: bool = True,
133
+ warn_threshold_s: ta.Optional[float] = 1.,
134
+ ) -> ta.Sequence[Manifest]:
135
+ log.info('Extracting manifests from file %s', file)
136
+
137
+ if not file.endswith('.py'):
138
+ raise Exception(file)
139
+
140
+ mod_name = file.rpartition('.')[0].replace(os.sep, '.')
141
+ mod_base = mod_name.split('.')[0]
142
+ if mod_base != (first_dir := file.split(os.path.sep)[0]):
143
+ raise Exception(f'Unexpected module base: {mod_base=} != {first_dir=}')
144
+
145
+ with open(os.path.join(self._base, file)) as f: # noqa
146
+ src = f.read()
147
+
148
+ origins: ta.List[ManifestOrigin] = []
149
+ lines = src.splitlines(keepends=True)
150
+ for i, l in enumerate(lines):
151
+ if l.startswith(MANIFEST_MAGIC):
152
+ if (m := _MANIFEST_GLOBAL_PAT.match(nl := lines[i + 1])) is None:
153
+ raise Exception(nl)
154
+
155
+ origins.append(ManifestOrigin(
156
+ module='.'.join(['', *mod_name.split('.')[1:]]),
157
+ attr=m.groupdict()['name'],
158
+
159
+ file=file,
160
+ line=i + 1,
161
+ ))
135
162
 
136
- if not origins:
137
- raise Exception('no manifests found')
163
+ if not origins:
164
+ raise Exception('no manifests found')
138
165
 
139
- if (dups := [k for k, v in collections.Counter(o.attr for o in origins).items() if v > 1]):
140
- raise Exception(f'Duplicate attrs: {dups}')
166
+ if (dups := [k for k, v in collections.Counter(o.attr for o in origins).items() if v > 1]):
167
+ raise Exception(f'Duplicate attrs: {dups}')
141
168
 
142
- attrs = [o.attr for o in origins]
169
+ attrs = [o.attr for o in origins]
143
170
 
144
- subproc_src = '\n\n'.join([
145
- _payload_src(),
146
- f'_dump_module_manifests({mod_name!r}, {", ".join(repr(a) for a in attrs)})\n',
147
- ])
171
+ subproc_src = '\n\n'.join([
172
+ _payload_src(),
173
+ f'_dump_module_manifests({mod_name!r}, {", ".join(repr(a) for a in attrs)})\n',
174
+ ])
148
175
 
149
- args = [
150
- sys.executable,
151
- '-c',
152
- subproc_src,
153
- ]
176
+ args = [
177
+ sys.executable,
178
+ '-c',
179
+ subproc_src,
180
+ ]
154
181
 
155
- if shell_wrap:
156
- args = ['sh', '-c', ' '.join(map(shlex.quote, args))]
182
+ if shell_wrap:
183
+ args = ['sh', '-c', ' '.join(map(shlex.quote, args))]
157
184
 
158
- start_time = time.time()
185
+ start_time = time.time()
159
186
 
160
- subproc_out = subprocess.check_output(args)
187
+ proc = await asyncio.create_subprocess_exec(*args, stdout=subprocess.PIPE)
188
+ subproc_out, _ = await proc.communicate()
189
+ if proc.returncode:
190
+ raise Exception('Subprocess failed')
161
191
 
162
- end_time = time.time()
192
+ end_time = time.time()
163
193
 
164
- if warn_threshold_s is not None and (elapsed_time := (end_time - start_time)) >= warn_threshold_s:
165
- log.warning('Manifest extraction took a long time: %s, %.2f s', file, elapsed_time)
194
+ if warn_threshold_s is not None and (elapsed_time := (end_time - start_time)) >= warn_threshold_s:
195
+ log.warning('Manifest extraction took a long time: %s, %.2f s', file, elapsed_time)
166
196
 
167
- sp_lines = subproc_out.decode().strip().splitlines()
168
- if len(sp_lines) != 1:
169
- raise Exception('Unexpected subprocess output')
197
+ sp_lines = subproc_out.decode().strip().splitlines()
198
+ if len(sp_lines) != 1:
199
+ raise Exception('Unexpected subprocess output')
170
200
 
171
- dct = json.loads(sp_lines[0])
172
- if set(dct) != set(attrs):
173
- raise Exception('Unexpected subprocess output keys')
201
+ dct = json.loads(sp_lines[0])
202
+ if set(dct) != set(attrs):
203
+ raise Exception('Unexpected subprocess output keys')
174
204
 
175
- out: ta.List[Manifest] = []
205
+ out: ta.List[Manifest] = []
176
206
 
177
- for o in origins:
178
- value = dct[o.attr]
207
+ for o in origins:
208
+ value = dct[o.attr]
179
209
 
180
- if not (
181
- isinstance(value, ta.Mapping) and
182
- len(value) == 1 and
183
- all(isinstance(k, str) and k.startswith('$') and len(k) > 1 for k in value)
184
- ):
185
- raise TypeError(f'Manifests must be mappings of strings starting with $: {value!r}')
210
+ if not (
211
+ isinstance(value, ta.Mapping) and
212
+ len(value) == 1 and
213
+ all(isinstance(k, str) and k.startswith('$') and len(k) > 1 for k in value)
214
+ ):
215
+ raise TypeError(f'Manifests must be mappings of strings starting with $: {value!r}')
186
216
 
187
- [(key, value_dct)] = value.items()
188
- kb, _, kr = key[1:].partition('.') # noqa
189
- if kb == mod_base: # noqa
190
- key = f'$.{kr}'
191
- value = {key: value_dct}
217
+ [(key, value_dct)] = value.items()
218
+ kb, _, kr = key[1:].partition('.') # noqa
219
+ if kb == mod_base: # noqa
220
+ key = f'$.{kr}'
221
+ value = {key: value_dct}
192
222
 
193
- out.append(Manifest(
194
- **dc.asdict(o),
195
- value=value,
196
- ))
223
+ out.append(Manifest(
224
+ **dc.asdict(o),
225
+ value=value,
226
+ ))
197
227
 
198
- return out
228
+ return out
199
229
 
230
+ async def build_package_manifests(
231
+ self,
232
+ name: str,
233
+ ) -> ta.List[Manifest]:
234
+ pkg_dir = os.path.join(self._base, name)
235
+ if not os.path.isdir(pkg_dir) or not os.path.isfile(os.path.join(pkg_dir, '__init__.py')):
236
+ raise Exception(pkg_dir)
200
237
 
201
- def build_package_manifests(
202
- ex: cf.Executor,
203
- name: str,
204
- base: str,
205
- *,
206
- write: bool = False,
207
- ) -> ta.List[Manifest]:
208
- pkg_dir = os.path.join(base, name)
209
- if not os.path.isdir(pkg_dir) or not os.path.isfile(os.path.join(pkg_dir, '__init__.py')):
210
- raise Exception(pkg_dir)
211
-
212
- files = sorted(findmagic.find_magic(
213
- [pkg_dir],
214
- [MANIFEST_MAGIC],
215
- ['py'],
216
- ))
217
- futs = [
218
- ex.submit(functools.partial(
219
- build_module_manifests,
220
- os.path.relpath(file, base),
221
- base,
238
+ files = sorted(findmagic.find_magic(
239
+ [pkg_dir],
240
+ [MANIFEST_MAGIC],
241
+ ['py'],
222
242
  ))
223
- for file in files
224
- ]
225
- manifests: ta.List[Manifest] = list(itertools.chain.from_iterable(fut.result() for fut in futs))
243
+ manifests: ta.List[Manifest] = list(itertools.chain.from_iterable(await asyncio.gather(*[
244
+ self._spawn(
245
+ self.build_module_manifests,
246
+ os.path.relpath(file, self._base),
247
+ )
248
+ for file in files
249
+ ])))
226
250
 
227
- if write:
228
- with open(os.path.join(pkg_dir, '.manifests.json'), 'w') as f:
229
- f.write(json_dumps_pretty([dc.asdict(m) for m in manifests]))
230
- f.write('\n')
251
+ if self._write:
252
+ with open(os.path.join(pkg_dir, '.manifests.json'), 'w') as f: # noqa
253
+ f.write(json_dumps_pretty([dc.asdict(m) for m in manifests]))
254
+ f.write('\n')
231
255
 
232
- return manifests
256
+ return manifests
233
257
 
234
258
 
235
259
  ##
@@ -277,22 +301,23 @@ if __name__ == '__main__':
277
301
  def _gen_cmd(args) -> None:
278
302
  base = _get_base(args)
279
303
 
280
- num_threads = args.jobs or max(mp.cpu_count() // 2, 1)
281
- with cf.ThreadPoolExecutor(num_threads) as ex:
282
- futs = [
283
- ex.submit(functools.partial(
284
- build_package_manifests,
285
- ex,
286
- pkg,
287
- base,
288
- write=args.write or False,
289
- ))
304
+ jobs = args.jobs or int(max(mp.cpu_count() // 1.5, 1))
305
+ builder = ManifestBuilder(
306
+ base,
307
+ jobs,
308
+ write=args.write or False,
309
+ )
310
+
311
+ async def do():
312
+ return await asyncio.gather(*[
313
+ builder.build_package_manifests(pkg)
290
314
  for pkg in args.package
291
- ]
292
- mss = [fut.result() for fut in futs]
293
- if not args.quiet:
294
- for ms in mss:
295
- print(json_dumps_pretty([dc.asdict(m) for m in ms]))
315
+ ])
316
+
317
+ mss = asyncio.run(do())
318
+ if not args.quiet:
319
+ for ms in mss:
320
+ print(json_dumps_pretty([dc.asdict(m) for m in ms]))
296
321
 
297
322
  def _check_cmd(args) -> None:
298
323
  base = _get_base(args)
omdev/pyproject/cli.py CHANGED
@@ -348,7 +348,7 @@ def _pkg_cmd(args) -> None:
348
348
  ]
349
349
  pgs = list(itertools.chain.from_iterable([pg, *pg.children()] for pg in pgs))
350
350
 
351
- num_threads = args.jobs or max(mp.cpu_count() // 2, 1)
351
+ num_threads = args.jobs or int(max(mp.cpu_count() // 1.5, 1))
352
352
  futs: ta.List[cf.Future]
353
353
  with cf.ThreadPoolExecutor(num_threads) as ex:
354
354
  futs = [ex.submit(pg.gen) for pg in pgs]
@@ -5287,7 +5287,7 @@ def _pkg_cmd(args) -> None:
5287
5287
  ]
5288
5288
  pgs = list(itertools.chain.from_iterable([pg, *pg.children()] for pg in pgs))
5289
5289
 
5290
- num_threads = args.jobs or max(mp.cpu_count() // 2, 1)
5290
+ num_threads = args.jobs or int(max(mp.cpu_count() // 1.5, 1))
5291
5291
  futs: ta.List[cf.Future]
5292
5292
  with cf.ThreadPoolExecutor(num_threads) as ex:
5293
5293
  futs = [ex.submit(pg.gen) for pg in pgs]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omdev
3
- Version: 0.0.0.dev52
3
+ Version: 0.0.0.dev54
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.dev52
15
+ Requires-Dist: omlish ==0.0.0.dev54
16
16
  Provides-Extra: all
17
17
  Requires-Dist: pycparser ~=2.22 ; extra == 'all'
18
18
  Requires-Dist: cffi ~=1.17 ; extra == 'all'
@@ -57,9 +57,9 @@ omdev/cli/__init__.py,sha256=V_l6VP1SZMlJbO-8CJwSuO9TThOy2S_oaPepNYgIrbE,37
57
57
  omdev/cli/__main__.py,sha256=5IeIERm-371fSI5ZvPv8eldAJBwgKwpR0R49pTsILNM,76
58
58
  omdev/cli/clicli.py,sha256=rQ9-F9XI3BevnfIVALHVKrrHNQPdYhkQ-IKESTNB5RA,2447
59
59
  omdev/cli/install.py,sha256=C-W171YlIHt4Cfok-nWSMbHwWhqF_PFqq2HixFttYx8,4460
60
- omdev/cli/main.py,sha256=wVhrzwEfUFKjlfSeJK5CM23yId4v3-36IuY4VbrOSQA,1873
60
+ omdev/cli/main.py,sha256=uyrpniI2nz84EV5-mFbcKJXf0sROJXSomEsangsRI_w,2751
61
61
  omdev/cli/managers.py,sha256=zqhMgNnv2VbXoTP6SgZeSuWfAVo1Ge-HJnQ1ftL-Mq8,2590
62
- omdev/cli/types.py,sha256=7_Owg0P8C8oOObSuOp6aEYSjkEukVFxTT00SRy1bLHM,250
62
+ omdev/cli/types.py,sha256=bqKw9SbtBtAip2vF9v4khh0CqKG6LBr6n9VzWBz7AJE,474
63
63
  omdev/interp/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
64
64
  omdev/interp/__main__.py,sha256=GMCqeGYltgt5dlJzHxY9gqisa8cRkrPfmZYuZnjg4WI,162
65
65
  omdev/interp/cli.py,sha256=sh7PZQoLletUViw1Y9OXNr9ekyNZ6YyxYuOQ_n9hyqU,2072
@@ -71,7 +71,7 @@ omdev/interp/standalone.py,sha256=XcltiL7ypcfV89C82_3knQ3Kx7aW4wnnxf2056ZXC3A,77
71
71
  omdev/interp/system.py,sha256=bI-JhX4GVJqW7wMxnIa-DGJWnCLmFcIsnl9pc1RGY2g,3513
72
72
  omdev/interp/types.py,sha256=EMN3StEMkFoQAMUIZd7JYL4uUWqzFGY-2hTL8EBznYM,2437
73
73
  omdev/manifests/__init__.py,sha256=P2B0dpT8D7l5lJwRGPA92IcQj6oeXfd90X5-q9BJrKg,51
74
- omdev/manifests/build.py,sha256=UxmuJhnWG16nwyFU9bTsv_FRzQ3lw1nZvAFI_XI3wuY,9727
74
+ omdev/manifests/build.py,sha256=65Bw8gc8avQdXveKqO6hG25LQjdkXknY3cypojmw7Js,10823
75
75
  omdev/manifests/load.py,sha256=LtEsluDdd8CkNGj0QGBxee3twBn095Fru0xz2mtr7uk,4788
76
76
  omdev/manifests/types.py,sha256=Jv6PAdVLPb9Hh4y6vDhPlWuMNBBViin1bC_u83jfsH4,234
77
77
  omdev/mypy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -91,7 +91,7 @@ omdev/precheck/scripts.py,sha256=qq6MXkxgrYngPg5pWnXH4uRSuRkP3mFqbeml1UmvGBc,126
91
91
  omdev/pyproject/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
92
92
  omdev/pyproject/__main__.py,sha256=gn3Rl1aYPYdiTtEqa9ifi0t-e4ZwPY0vhJ4UXvYdJDY,165
93
93
  omdev/pyproject/cexts.py,sha256=x13piOOnNrYbA17qZLDVuR0p1sqhgEwpk4FtImX-klM,4281
94
- omdev/pyproject/cli.py,sha256=QnlptoCJQ0yvJ1C2mXEYfOMS6agRQMn2nGS9KgWoJ5U,11358
94
+ omdev/pyproject/cli.py,sha256=kw0Jyzywwt6QOc6QHDevWW9p85aXT7jvVFFb8Sb_EAU,11365
95
95
  omdev/pyproject/configs.py,sha256=K9H5cGwVLgHi8wKwtYvlXHZ9ThtmnI4jo8JAb-t1-70,2859
96
96
  omdev/pyproject/pkg.py,sha256=rNKzJOIgPDrtT2i14Pebldoboz45w00sKb5l_kYFaRI,14562
97
97
  omdev/pyproject/reqs.py,sha256=8feZ71YnGzwKbLK4zO28CDQeNcZIIuq6cnkBhs6M-7E,2406
@@ -101,7 +101,7 @@ omdev/scripts/execrss.py,sha256=d6purJqU99OkMcNxCS1kG2CMfSsw7wjnvBQW7SjyJ70,448
101
101
  omdev/scripts/exectime.py,sha256=LRVIJsnvGYUqH-zfCdFnrQCZv1KLXJPtWBWplXMDwhI,407
102
102
  omdev/scripts/importtrace.py,sha256=4ozdphT4VuP8L0kE0HmGMyWaWHnXg1KEukbET4pFgJU,14064
103
103
  omdev/scripts/interp.py,sha256=7xeihsrt3DI_s1fZqNweivBUUwuGkS5C5cWw4QY6q30,70999
104
- omdev/scripts/pyproject.py,sha256=ETGBPUdMeifuDdG7lcf8HUBVRwLPdx3VE_GfvhulTrY,157486
104
+ omdev/scripts/pyproject.py,sha256=fuCXOk44Ui5cangCFGi44ckPezawW2N9aJ8bdOAxL50,157493
105
105
  omdev/toml/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
106
106
  omdev/toml/parser.py,sha256=84bn09uhYHwQGyfww6Rw6y1RxPAE_HDltODOSakcqDM,29186
107
107
  omdev/toml/writer.py,sha256=lk3on3YXVbWuLJa-xsOzOhs1bBAT1vXqw4mBbluZl_w,3040
@@ -114,9 +114,9 @@ omdev/tools/piptools.py,sha256=-jR5q3w4sHqntxCLExFCBNIARB788FUsAbJ62PK2sBU,2774
114
114
  omdev/tools/proftools.py,sha256=xKSm_yPoCnfsvS3iT9MblDqFMuZmGfI3_koGj8amMyU,145
115
115
  omdev/tools/rst.py,sha256=6dWk8QZHoGiLSuBw3TKsXZjjFK6wWBEtPi9krdCLKKg,977
116
116
  omdev/tools/sqlrepl.py,sha256=tmFZh80-xsGM62dyQ7_UGLebChrj7IHbIPYBWDJMgVk,5741
117
- omdev-0.0.0.dev52.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
118
- omdev-0.0.0.dev52.dist-info/METADATA,sha256=i-4H3TQh4h9ahk0VXKuSobql_G4gPEjzk_PVRfqjF3A,1252
119
- omdev-0.0.0.dev52.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
120
- omdev-0.0.0.dev52.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
121
- omdev-0.0.0.dev52.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
122
- omdev-0.0.0.dev52.dist-info/RECORD,,
117
+ omdev-0.0.0.dev54.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
118
+ omdev-0.0.0.dev54.dist-info/METADATA,sha256=C1LUlE7rmomgvnwcZ8ChfuCsoULQWW-wuRrFMpZe-vQ,1252
119
+ omdev-0.0.0.dev54.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
120
+ omdev-0.0.0.dev54.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
121
+ omdev-0.0.0.dev54.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
122
+ omdev-0.0.0.dev54.dist-info/RECORD,,