omdev 0.0.0.dev101__py3-none-any.whl → 0.0.0.dev112__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
@@ -123,7 +123,7 @@
123
123
  "module": ".ptk.apps.ncdu",
124
124
  "attr": "_CLI_MODULE",
125
125
  "file": "omdev/ptk/apps/ncdu.py",
126
- "line": 157,
126
+ "line": 159,
127
127
  "value": {
128
128
  "$.cli.types.CliModule": {
129
129
  "cmd_name": "ptk/ncdu",
@@ -131,6 +131,18 @@
131
131
  }
132
132
  }
133
133
  },
134
+ {
135
+ "module": ".pycharm.__main__",
136
+ "attr": "_CLI_MODULE",
137
+ "file": "omdev/pycharm/__main__.py",
138
+ "line": 4,
139
+ "value": {
140
+ "$.cli.types.CliModule": {
141
+ "cmd_name": "pycharm",
142
+ "mod_name": "omdev.pycharm.__main__"
143
+ }
144
+ }
145
+ },
134
146
  {
135
147
  "module": ".pyproject.__main__",
136
148
  "attr": "_CLI_MODULE",
@@ -191,6 +203,18 @@
191
203
  }
192
204
  }
193
205
  },
206
+ {
207
+ "module": ".scripts.tmpexec",
208
+ "attr": "_CLI_MODULE",
209
+ "file": "omdev/scripts/tmpexec.py",
210
+ "line": 50,
211
+ "value": {
212
+ "$.cli.types.CliModule": {
213
+ "cmd_name": "tmpexec",
214
+ "mod_name": "omdev.scripts.tmpexec"
215
+ }
216
+ }
217
+ },
194
218
  {
195
219
  "module": ".tools.doc",
196
220
  "attr": "_CLI_MODULE",
@@ -219,7 +243,7 @@
219
243
  "module": ".tools.git",
220
244
  "attr": "_CLI_MODULE",
221
245
  "file": "omdev/tools/git.py",
222
- "line": 124,
246
+ "line": 128,
223
247
  "value": {
224
248
  "$.cli.types.CliModule": {
225
249
  "cmd_name": "git",
@@ -282,7 +306,7 @@
282
306
  "module": ".tools.pip",
283
307
  "attr": "_CLI_MODULE",
284
308
  "file": "omdev/tools/pip.py",
285
- "line": 88,
309
+ "line": 164,
286
310
  "value": {
287
311
  "$.cli.types.CliModule": {
288
312
  "cmd_name": "pip",
@@ -302,6 +326,18 @@
302
326
  }
303
327
  }
304
328
  },
329
+ {
330
+ "module": ".tools.qr",
331
+ "attr": "_CLI_MODULE",
332
+ "file": "omdev/tools/qr.py",
333
+ "line": 74,
334
+ "value": {
335
+ "$.cli.types.CliModule": {
336
+ "cmd_name": "qr",
337
+ "mod_name": "omdev.tools.qr"
338
+ }
339
+ }
340
+ },
305
341
  {
306
342
  "module": ".tools.sqlrepl",
307
343
  "attr": "_CLI_MODULE",
omdev/__about__.py CHANGED
@@ -41,6 +41,10 @@ class Project(ProjectBase):
41
41
  'prompt-toolkit ~= 3.0',
42
42
  ],
43
43
 
44
+ 'qr': [
45
+ 'segno ~= 1.6',
46
+ ],
47
+
44
48
  'tokens': [
45
49
  'tokenize-rt ~= 6.1',
46
50
  ],
omdev/cli/clicli.py CHANGED
@@ -51,7 +51,7 @@ class CliCli(ap.Cli):
51
51
  )
52
52
  def reinstall(self) -> None:
53
53
  mod_name = globals()['__spec__'].name
54
- tool_name = '.'.join([mod_name.partition('.')[0], 'tools', 'piptools'])
54
+ tool_name = '.'.join([mod_name.partition('.')[0], 'tools', 'pip'])
55
55
 
56
56
  out = subprocess.check_output([
57
57
  sys.executable,
omdev/clipboard/darwin.py CHANGED
@@ -1,4 +1,31 @@
1
1
  # ruff: noqa: N802 N816
2
+ """
3
+ imageProperties = dict(
4
+ ColorModel = "RGB"
5
+ DPIHeight = 144
6
+ DPIWidth = 144
7
+ Depth = 8
8
+ PixelHeight = 1236
9
+ PixelWidth = 602
10
+ ProfileName = "Color LCD"
11
+ kCGImageDestinationAllowAlpha = true
12
+ {Exif} = dict(
13
+ PixelXDimension = 602
14
+ PixelYDimension = 1236
15
+ UserComment = "Screenshot"
16
+ )
17
+ {PNG} = dict(
18
+ InterlaceType = 0
19
+ XPixelsPerMeter = 5669
20
+ YPixelsPerMeter = 5669
21
+ )
22
+ {TIFF} = dict(
23
+ ResolutionUnit = 2
24
+ XResolution = 144
25
+ YResolution = 144
26
+ )
27
+ )
28
+ """
2
29
  import ctypes as ct
3
30
  import ctypes.util
4
31
  import dataclasses as dc
@@ -114,7 +141,7 @@ def cfstring_to_string(cf_string: CFStringRef) -> str:
114
141
  max_size = cf.CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1
115
142
  buffer = ct.create_string_buffer(max_size)
116
143
 
117
- if success := cf.CFStringGetCString(cf_string, buffer, max_size, kCFStringEncodingUTF8): # noqa
144
+ if not (success := cf.CFStringGetCString(cf_string, buffer, max_size, kCFStringEncodingUTF8)): # noqa
118
145
  return ''
119
146
 
120
147
  return buffer.value.decode('utf-8')
@@ -142,6 +169,7 @@ class DarwinClipboardItem:
142
169
  def get_darwin_clipboard_data(
143
170
  *,
144
171
  types: ta.Container[str | None] | None = None,
172
+ skip_types: ta.Container[str | None] | None = None,
145
173
  strict: bool = False,
146
174
  types_only: bool = False,
147
175
  ) -> list[DarwinClipboardItem]:
@@ -179,6 +207,8 @@ def get_darwin_clipboard_data(
179
207
 
180
208
  if types is not None and data_type_str not in types:
181
209
  continue
210
+ if skip_types is not None and data_type_str in skip_types:
211
+ continue
182
212
 
183
213
  if types_only:
184
214
  lst.append(DarwinClipboardItem(
@@ -188,10 +218,14 @@ def get_darwin_clipboard_data(
188
218
  continue
189
219
 
190
220
  data = CFDataRef()
221
+
222
+ # FIXME: dumps to stderr lol:
223
+ # data_type_str = 'public.heics'
191
224
  if status := aps.PasteboardCopyItemFlavorData(pasteboard, item_id, data_type, ct.byref(data)):
192
225
  if not strict:
193
226
  continue
194
227
  raise StatusDarwinClipboardError('PasteboardCopyItemFlavorData', status)
228
+
195
229
  if not data:
196
230
  continue
197
231
 
@@ -221,8 +255,8 @@ def get_darwin_clipboard_data(
221
255
 
222
256
 
223
257
  def _main() -> None:
224
- for i in get_darwin_clipboard_data():
225
- print(i)
258
+ for i in get_darwin_clipboard_data(skip_types={'public.heics'}):
259
+ print(f'type: {i.type}, len: {len(i.data) if i.data is not None else None}')
226
260
 
227
261
 
228
262
  if __name__ == '__main__':
@@ -1 +0,0 @@
1
- # @omlish-lite
@@ -0,0 +1,82 @@
1
+ """
2
+ NOTE: This cannot be auto-imported as @omlish-lite usage of other modules in this package requires it be importable on
3
+ 8.
4
+ """
5
+ import dataclasses as dc
6
+ import typing as ta
7
+
8
+ from omlish import lang
9
+ from omlish import marshal as msh
10
+ from omlish import matchfns as mfs
11
+ from omlish import reflect as rfl
12
+
13
+ from .requires import RequiresMarkerItem
14
+ from .requires import RequiresMarkerList
15
+ from .requires import RequiresNode
16
+ from .requires import RequiresOp
17
+ from .requires import RequiresValue
18
+ from .requires import RequiresVariable
19
+
20
+
21
+ ##
22
+
23
+
24
+ class MarshalRequiresMarkerList(lang.NotInstantiable, lang.Final):
25
+ pass
26
+
27
+
28
+ @dc.dataclass(frozen=True)
29
+ class RequiresMarkerListMarshaler(msh.Marshaler):
30
+ item_m: msh.Marshaler
31
+ node_m: msh.Marshaler
32
+
33
+ def marshal(self, ctx: msh.MarshalContext, o: ta.Any) -> msh.Value:
34
+ def inner(c: ta.Any) -> ta.Any:
35
+ if isinstance(c, str):
36
+ return c
37
+ elif isinstance(c, RequiresMarkerItem):
38
+ return self.item_m.marshal(ctx, c)
39
+ elif isinstance(c, ta.Iterable):
40
+ return [inner(e) for e in c]
41
+ else:
42
+ raise TypeError(c)
43
+ return [inner(e) for e in o]
44
+
45
+
46
+ class RequiresMarkerListMarshalerFactory(msh.MarshalerFactoryMatchClass):
47
+ @mfs.simple(lambda _, ctx, rty: rty is MarshalRequiresMarkerList)
48
+ def _build(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
49
+ return RequiresMarkerListMarshaler(
50
+ ctx.make(RequiresMarkerItem),
51
+ ctx.make(RequiresNode),
52
+ )
53
+
54
+
55
+ ##
56
+
57
+
58
+ @lang.static_init
59
+ def _install_standard_marshalling() -> None:
60
+ requires_node_poly = msh.Polymorphism(
61
+ RequiresNode,
62
+ [
63
+ msh.Impl(RequiresVariable, 'variable'),
64
+ msh.Impl(RequiresValue, 'value'),
65
+ msh.Impl(RequiresOp, 'op'),
66
+ ],
67
+ )
68
+ msh.STANDARD_MARSHALER_FACTORIES[0:0] = [
69
+ msh.PolymorphismMarshalerFactory(requires_node_poly),
70
+ msh.PolymorphismUnionMarshalerFactory(requires_node_poly.impls, allow_partial=True),
71
+ RequiresMarkerListMarshalerFactory(),
72
+
73
+ ]
74
+ msh.STANDARD_UNMARSHALER_FACTORIES[0:0] = [
75
+ msh.PolymorphismUnmarshalerFactory(requires_node_poly),
76
+ ]
77
+
78
+ msh.GLOBAL_REGISTRY.register(
79
+ RequiresMarkerList,
80
+ msh.ReflectOverride(MarshalRequiresMarkerList),
81
+ identity=True,
82
+ )
omdev/packaging/names.py CHANGED
@@ -1,3 +1,4 @@
1
+ # @omlish-lite
1
2
  # Copyright (c) Donald Stufft and individual contributors.
2
3
  # All rights reserved.
3
4
  #
@@ -1,3 +1,4 @@
1
+ # @omlish-lite
1
2
  # Copyright (c) Donald Stufft and individual contributors.
2
3
  # All rights reserved.
3
4
  #
@@ -194,10 +195,9 @@ class RequiresTokenizer:
194
195
  self.read()
195
196
 
196
197
 
198
+ @dc.dataclass(frozen=True)
197
199
  class RequiresNode:
198
- def __init__(self, value: str) -> None:
199
- super().__init__()
200
- self.value = value
200
+ value: str
201
201
 
202
202
  def __str__(self) -> str:
203
203
  return self.value
@@ -209,27 +209,36 @@ class RequiresNode:
209
209
  raise NotImplementedError
210
210
 
211
211
 
212
+ @dc.dataclass(frozen=True)
212
213
  class RequiresVariable(RequiresNode):
213
214
  def serialize(self) -> str:
214
215
  return str(self)
215
216
 
216
217
 
218
+ @dc.dataclass(frozen=True)
217
219
  class RequiresValue(RequiresNode):
218
220
  def serialize(self) -> str:
219
221
  return f'"{self}"'
220
222
 
221
223
 
224
+ @dc.dataclass(frozen=True)
222
225
  class RequiresOp(RequiresNode):
223
226
  def serialize(self) -> str:
224
227
  return str(self)
225
228
 
226
229
 
227
230
  RequiresMarkerVar = ta.Union['RequiresVariable', 'RequiresValue']
228
- RequiresMarkerItem = ta.Tuple['RequiresMarkerVar', 'RequiresOp', 'RequiresMarkerVar']
231
+
229
232
  RequiresMarkerAtom = ta.Union['RequiresMarkerItem', ta.Sequence['RequiresMarkerAtom']]
230
233
  RequiresMarkerList = ta.Sequence[ta.Union['RequiresMarkerList', 'RequiresMarkerAtom', str]]
231
234
 
232
235
 
236
+ class RequiresMarkerItem(ta.NamedTuple):
237
+ l: ta.Union[RequiresVariable, RequiresValue]
238
+ op: RequiresOp
239
+ r: ta.Union[RequiresVariable, RequiresValue]
240
+
241
+
233
242
  class ParsedRequirement(ta.NamedTuple):
234
243
  name: str
235
244
  url: str
@@ -441,7 +450,7 @@ def _parse_requires_marker_item(tokenizer: RequiresTokenizer) -> RequiresMarkerI
441
450
  tokenizer.consume('WS')
442
451
  marker_var_right = _parse_requires_marker_var(tokenizer)
443
452
  tokenizer.consume('WS')
444
- return (marker_var_left, marker_op, marker_var_right)
453
+ return RequiresMarkerItem(marker_var_left, marker_op, marker_var_right)
445
454
 
446
455
 
447
456
  def _parse_requires_marker_var(tokenizer: RequiresTokenizer) -> RequiresMarkerVar:
@@ -1,3 +1,4 @@
1
+ # @omlish-lite
1
2
  # Copyright (c) Donald Stufft and individual contributors.
2
3
  # All rights reserved.
3
4
  #
@@ -1,3 +1,4 @@
1
+ # @omlish-lite
1
2
  # Copyright (c) Donald Stufft and individual contributors.
2
3
  # All rights reserved.
3
4
  #
omdev/ptk/apps/ncdu.py CHANGED
@@ -73,8 +73,10 @@ class NcduApp:
73
73
  self._kb.add(k)(self.move_up)
74
74
  for k in ['down', 'n']:
75
75
  self._kb.add(k)(self.move_down)
76
- self._kb.add('enter')(self.enter_directory)
77
- self._kb.add('backspace')(self.go_back)
76
+ for k in ['right', 'enter']:
77
+ self._kb.add(k)(self.enter_directory)
78
+ for k in ['left', 'backspace']:
79
+ self._kb.add(k)(self.go_back)
78
80
 
79
81
  self._layout = ptk.Layout(ptk.Frame(self._text_area))
80
82
 
File without changes
@@ -0,0 +1,11 @@
1
+ from ..cli import CliModule
2
+
3
+
4
+ # @omlish-manifest
5
+ _CLI_MODULE = CliModule('pycharm', __name__)
6
+
7
+
8
+ if __name__ == '__main__':
9
+ from .cli import _main
10
+
11
+ _main()
omdev/pycharm/cli.py ADDED
@@ -0,0 +1,94 @@
1
+ import inspect
2
+ import os.path
3
+ import subprocess
4
+ import sys
5
+ import tempfile
6
+
7
+ from omlish import argparse as ap
8
+ from omlish.diag.pycharm import get_pycharm_version
9
+
10
+
11
+ _DARWIN_OPEN_SCRIPT = """
12
+ tell application "PyCharm"
13
+ activate
14
+ open "{dir}"
15
+ end tell
16
+ return
17
+ """
18
+
19
+
20
+ _LINUX_OPEN_SCRIPT = """
21
+ # Check if PyCharm is already running
22
+ if pgrep -x "pycharm.sh" > /dev/null; then
23
+ echo "PyCharm is already running. Opening project..."
24
+
25
+ # Bring PyCharm to the foreground
26
+ wmctrl -a "PyCharm"
27
+
28
+ # Simulate the keyboard shortcut to open a new project
29
+ xdotool key --delay 100 ctrl+shift+a
30
+ xdotool type "$PROJECT_PATH"
31
+ xdotool key Return
32
+
33
+ else
34
+ echo "Starting PyCharm with project..."
35
+ nohup pycharm.sh "$PROJECT_PATH" > /dev/null 2>&1 &
36
+ fi
37
+ """
38
+
39
+
40
+ class Cli(ap.Cli):
41
+ @ap.command()
42
+ def version(self) -> None:
43
+ print(get_pycharm_version())
44
+
45
+ @ap.command(
46
+ ap.arg('python-exe'),
47
+ ap.arg('args', nargs=ap.REMAINDER),
48
+ )
49
+ def runhack(self) -> int:
50
+ if not os.path.isfile(exe := self.args.python_exe):
51
+ raise FileNotFoundError(exe)
52
+
53
+ from omlish.diag._pycharm import runhack # noqa
54
+ src = inspect.getsource(runhack)
55
+
56
+ src_file = tempfile.mktemp(__package__ + '-runhack') # noqa
57
+ with open(src_file, 'w') as f:
58
+ f.write(src)
59
+
60
+ proc = subprocess.run([exe, src_file, *self.args.args], check=False)
61
+ return proc.returncode
62
+
63
+ @ap.command(
64
+ ap.arg('dir', nargs='?'),
65
+ )
66
+ def open(self) -> None:
67
+ dir = os.path.abspath(self.args.dir or '.') # noqa
68
+
69
+ if (plat := sys.platform) == 'darwin':
70
+ if '"' in dir:
71
+ raise ValueError(dir)
72
+
73
+ scpt_src = _DARWIN_OPEN_SCRIPT.format(dir=dir)
74
+
75
+ scpt_file = tempfile.mktemp(__package__ + '-pycharm-open') # noqa
76
+ with open(scpt_file, 'w') as f:
77
+ f.write(scpt_src)
78
+
79
+ subprocess.check_call(['osascript', scpt_file])
80
+
81
+ elif plat == 'linux':
82
+ # FIXME:
83
+ raise NotImplementedError
84
+
85
+ else:
86
+ raise OSError(plat)
87
+
88
+
89
+ def _main() -> None:
90
+ Cli().call_and_exit()
91
+
92
+
93
+ if __name__ == '__main__':
94
+ _main()
omdev/scripts/execrss.py CHANGED
@@ -16,7 +16,17 @@ _CLI_MODULE = {'$omdev.cli.types.CliModule': {
16
16
 
17
17
 
18
18
  def _main() -> None:
19
- [src] = sys.argv[1:]
19
+ if len(sys.argv) == 2:
20
+ pre = None
21
+ [src] = sys.argv[1:]
22
+ elif len(sys.argv) == 3:
23
+ [pre, src] = sys.argv[1:]
24
+ else:
25
+ raise Exception('Invalid arguments')
26
+
27
+ if pre:
28
+ exec(pre)
29
+
20
30
  start = _get_rss()
21
31
  exec(src)
22
32
  end = _get_rss()
omdev/scripts/exectime.py CHANGED
@@ -12,7 +12,17 @@ _CLI_MODULE = {'$omdev.cli.types.CliModule': {
12
12
 
13
13
 
14
14
  def _main() -> None:
15
- [src] = sys.argv[1:]
15
+ if len(sys.argv) == 2:
16
+ pre = None
17
+ [src] = sys.argv[1:]
18
+ elif len(sys.argv) == 3:
19
+ [pre, src] = sys.argv[1:]
20
+ else:
21
+ raise Exception('Invalid arguments')
22
+
23
+ if pre:
24
+ exec(pre)
25
+
16
26
  co = compile(src, '<string>', 'exec')
17
27
  start = time.time_ns()
18
28
  exec(co)
omdev/scripts/interp.py CHANGED
@@ -51,7 +51,7 @@ VersionCmpLocalType = ta.Union['NegativeInfinityVersionType', _VersionCmpLocalTy
51
51
  VersionCmpKey = ta.Tuple[int, ta.Tuple[int, ...], VersionCmpPrePostDevType, VersionCmpPrePostDevType, VersionCmpPrePostDevType, VersionCmpLocalType] # noqa
52
52
  VersionComparisonMethod = ta.Callable[[VersionCmpKey, VersionCmpKey], bool]
53
53
 
54
- # ../../../omlish/lite/check.py
54
+ # ../../../omlish/lite/cached.py
55
55
  T = ta.TypeVar('T')
56
56
 
57
57
  # ../../packaging/specifiers.py
@@ -471,7 +471,7 @@ def canonicalize_version(
471
471
  # ../../../omlish/lite/cached.py
472
472
 
473
473
 
474
- class cached_nullary: # noqa
474
+ class _cached_nullary: # noqa
475
475
  def __init__(self, fn):
476
476
  super().__init__()
477
477
  self._fn = fn
@@ -488,6 +488,10 @@ class cached_nullary: # noqa
488
488
  return bound
489
489
 
490
490
 
491
+ def cached_nullary(fn: ta.Callable[..., T]) -> ta.Callable[..., T]:
492
+ return _cached_nullary(fn)
493
+
494
+
491
495
  ########################################
492
496
  # ../../../omlish/lite/check.py
493
497
 
@@ -1692,6 +1696,24 @@ def subprocess_try_output_str(*args: str, **kwargs: ta.Any) -> ta.Optional[str]:
1692
1696
  return out.decode().strip() if out is not None else None
1693
1697
 
1694
1698
 
1699
+ ##
1700
+
1701
+
1702
+ def subprocess_close(
1703
+ proc: subprocess.Popen,
1704
+ timeout: ta.Optional[float] = None,
1705
+ ) -> None:
1706
+ # TODO: terminate, sleep, kill
1707
+ if proc.stdout:
1708
+ proc.stdout.close()
1709
+ if proc.stderr:
1710
+ proc.stderr.close()
1711
+ if proc.stdin:
1712
+ proc.stdin.close()
1713
+
1714
+ proc.wait(timeout)
1715
+
1716
+
1695
1717
  ########################################
1696
1718
  # ../inspect.py
1697
1719
 
@@ -90,7 +90,7 @@ TomlParseFloat = ta.Callable[[str], ta.Any]
90
90
  TomlKey = ta.Tuple[str, ...]
91
91
  TomlPos = int # ta.TypeAlias
92
92
 
93
- # ../../../omlish/lite/check.py
93
+ # ../../../omlish/lite/cached.py
94
94
  T = ta.TypeVar('T')
95
95
 
96
96
  # ../../packaging/specifiers.py
@@ -1862,7 +1862,7 @@ class WheelFile(zipfile.ZipFile):
1862
1862
  # ../../../omlish/lite/cached.py
1863
1863
 
1864
1864
 
1865
- class cached_nullary: # noqa
1865
+ class _cached_nullary: # noqa
1866
1866
  def __init__(self, fn):
1867
1867
  super().__init__()
1868
1868
  self._fn = fn
@@ -1879,6 +1879,10 @@ class cached_nullary: # noqa
1879
1879
  return bound
1880
1880
 
1881
1881
 
1882
+ def cached_nullary(fn: ta.Callable[..., T]) -> ta.Callable[..., T]:
1883
+ return _cached_nullary(fn)
1884
+
1885
+
1882
1886
  ########################################
1883
1887
  # ../../../omlish/lite/check.py
1884
1888
 
@@ -3235,7 +3239,7 @@ class DataclassObjMarshaler(ObjMarshaler):
3235
3239
  return {k: m.marshal(getattr(o, k)) for k, m in self.fs.items()}
3236
3240
 
3237
3241
  def unmarshal(self, o: ta.Any) -> ta.Any:
3238
- return self.ty(**{k: self.fs[k].unmarshal(v) for k, v in o.items() if self.nonstrict or k in self.fs})
3242
+ return self.ty(**{k: self.fs[k].unmarshal(v) for k, v in o.items() if not self.nonstrict or k in self.fs})
3239
3243
 
3240
3244
 
3241
3245
  @dc.dataclass(frozen=True)
@@ -3295,7 +3299,10 @@ class UuidObjMarshaler(ObjMarshaler):
3295
3299
  return uuid.UUID(o)
3296
3300
 
3297
3301
 
3298
- _OBJ_MARSHALERS: ta.Dict[ta.Any, ObjMarshaler] = {
3302
+ ##
3303
+
3304
+
3305
+ _DEFAULT_OBJ_MARSHALERS: ta.Dict[ta.Any, ObjMarshaler] = {
3299
3306
  **{t: NopObjMarshaler() for t in (type(None),)},
3300
3307
  **{t: CastObjMarshaler(t) for t in (int, float, str, bool)},
3301
3308
  **{t: Base64ObjMarshaler(t) for t in (bytes, bytearray)},
@@ -3324,20 +3331,19 @@ _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES: ta.Dict[ta.Any, type] = {
3324
3331
  }
3325
3332
 
3326
3333
 
3327
- def register_opj_marshaler(ty: ta.Any, m: ObjMarshaler) -> None:
3328
- if ty in _OBJ_MARSHALERS:
3329
- raise KeyError(ty)
3330
- _OBJ_MARSHALERS[ty] = m
3331
-
3332
-
3333
- def _make_obj_marshaler(ty: ta.Any) -> ObjMarshaler:
3334
+ def _make_obj_marshaler(
3335
+ ty: ta.Any,
3336
+ rec: ta.Callable[[ta.Any], ObjMarshaler],
3337
+ *,
3338
+ nonstrict_dataclasses: bool = False,
3339
+ ) -> ObjMarshaler:
3334
3340
  if isinstance(ty, type):
3335
3341
  if abc.ABC in ty.__bases__:
3336
3342
  impls = [ # type: ignore
3337
3343
  PolymorphicObjMarshaler.Impl(
3338
3344
  ity,
3339
3345
  ity.__qualname__,
3340
- get_obj_marshaler(ity),
3346
+ rec(ity),
3341
3347
  )
3342
3348
  for ity in deep_subclasses(ty)
3343
3349
  if abc.ABC not in ity.__bases__
@@ -3353,7 +3359,8 @@ def _make_obj_marshaler(ty: ta.Any) -> ObjMarshaler:
3353
3359
  if dc.is_dataclass(ty):
3354
3360
  return DataclassObjMarshaler(
3355
3361
  ty,
3356
- {f.name: get_obj_marshaler(f.type) for f in dc.fields(ty)},
3362
+ {f.name: rec(f.type) for f in dc.fields(ty)},
3363
+ nonstrict=nonstrict_dataclasses,
3357
3364
  )
3358
3365
 
3359
3366
  if is_generic_alias(ty):
@@ -3363,7 +3370,7 @@ def _make_obj_marshaler(ty: ta.Any) -> ObjMarshaler:
3363
3370
  pass
3364
3371
  else:
3365
3372
  k, v = ta.get_args(ty)
3366
- return MappingObjMarshaler(mt, get_obj_marshaler(k), get_obj_marshaler(v))
3373
+ return MappingObjMarshaler(mt, rec(k), rec(v))
3367
3374
 
3368
3375
  try:
3369
3376
  st = _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES[ta.get_origin(ty)]
@@ -3371,33 +3378,71 @@ def _make_obj_marshaler(ty: ta.Any) -> ObjMarshaler:
3371
3378
  pass
3372
3379
  else:
3373
3380
  [e] = ta.get_args(ty)
3374
- return IterableObjMarshaler(st, get_obj_marshaler(e))
3381
+ return IterableObjMarshaler(st, rec(e))
3375
3382
 
3376
3383
  if is_union_alias(ty):
3377
- return OptionalObjMarshaler(get_obj_marshaler(get_optional_alias_arg(ty)))
3384
+ return OptionalObjMarshaler(rec(get_optional_alias_arg(ty)))
3378
3385
 
3379
3386
  raise TypeError(ty)
3380
3387
 
3381
3388
 
3382
- def get_obj_marshaler(ty: ta.Any) -> ObjMarshaler:
3383
- try:
3384
- return _OBJ_MARSHALERS[ty]
3385
- except KeyError:
3386
- pass
3389
+ ##
3387
3390
 
3388
- p = ProxyObjMarshaler()
3389
- _OBJ_MARSHALERS[ty] = p
3390
- try:
3391
- m = _make_obj_marshaler(ty)
3392
- except Exception:
3393
- del _OBJ_MARSHALERS[ty]
3394
- raise
3395
- else:
3396
- p.m = m
3391
+
3392
+ _OBJ_MARSHALERS_LOCK = threading.RLock()
3393
+
3394
+ _OBJ_MARSHALERS: ta.Dict[ta.Any, ObjMarshaler] = dict(_DEFAULT_OBJ_MARSHALERS)
3395
+
3396
+ _OBJ_MARSHALER_PROXIES: ta.Dict[ta.Any, ProxyObjMarshaler] = {}
3397
+
3398
+
3399
+ def register_opj_marshaler(ty: ta.Any, m: ObjMarshaler) -> None:
3400
+ with _OBJ_MARSHALERS_LOCK:
3401
+ if ty in _OBJ_MARSHALERS:
3402
+ raise KeyError(ty)
3397
3403
  _OBJ_MARSHALERS[ty] = m
3404
+
3405
+
3406
+ def get_obj_marshaler(
3407
+ ty: ta.Any,
3408
+ *,
3409
+ no_cache: bool = False,
3410
+ **kwargs: ta.Any,
3411
+ ) -> ObjMarshaler:
3412
+ with _OBJ_MARSHALERS_LOCK:
3413
+ if not no_cache:
3414
+ try:
3415
+ return _OBJ_MARSHALERS[ty]
3416
+ except KeyError:
3417
+ pass
3418
+
3419
+ try:
3420
+ return _OBJ_MARSHALER_PROXIES[ty]
3421
+ except KeyError:
3422
+ pass
3423
+
3424
+ rec = functools.partial(
3425
+ get_obj_marshaler,
3426
+ no_cache=no_cache,
3427
+ **kwargs,
3428
+ )
3429
+
3430
+ p = ProxyObjMarshaler()
3431
+ _OBJ_MARSHALER_PROXIES[ty] = p
3432
+ try:
3433
+ m = _make_obj_marshaler(ty, rec, **kwargs)
3434
+ finally:
3435
+ del _OBJ_MARSHALER_PROXIES[ty]
3436
+ p.m = m
3437
+
3438
+ if not no_cache:
3439
+ _OBJ_MARSHALERS[ty] = m
3398
3440
  return m
3399
3441
 
3400
3442
 
3443
+ ##
3444
+
3445
+
3401
3446
  def marshal_obj(o: ta.Any, ty: ta.Any = None) -> ta.Any:
3402
3447
  return get_obj_marshaler(ty if ty is not None else type(o)).marshal(o)
3403
3448
 
@@ -3916,6 +3961,24 @@ def subprocess_try_output_str(*args: str, **kwargs: ta.Any) -> ta.Optional[str]:
3916
3961
  return out.decode().strip() if out is not None else None
3917
3962
 
3918
3963
 
3964
+ ##
3965
+
3966
+
3967
+ def subprocess_close(
3968
+ proc: subprocess.Popen,
3969
+ timeout: ta.Optional[float] = None,
3970
+ ) -> None:
3971
+ # TODO: terminate, sleep, kill
3972
+ if proc.stdout:
3973
+ proc.stdout.close()
3974
+ if proc.stderr:
3975
+ proc.stderr.close()
3976
+ if proc.stdin:
3977
+ proc.stdin.close()
3978
+
3979
+ proc.wait(timeout)
3980
+
3981
+
3919
3982
  ########################################
3920
3983
  # ../../interp/inspect.py
3921
3984
 
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env python3
2
+ # @omlish-script
3
+ """
4
+ TODO:
5
+ - can xargs just do this lol
6
+ """
7
+ import argparse
8
+ import os
9
+ import subprocess
10
+ import sys
11
+ import tempfile
12
+
13
+
14
+ def _main() -> None:
15
+ parser = argparse.ArgumentParser()
16
+ parser.add_argument('-I', '--replstr', default='%')
17
+ parser.add_argument('-Q', '--stdout-silenced', action='store_true')
18
+ parser.add_argument('-E', '--stdout-to-stderr', action='store_true')
19
+ parser.add_argument('-c', '--cat', action='store_true')
20
+ parser.add_argument('-k', '--keep', action='store_true')
21
+ parser.add_argument('--read-size', type=int, default=0x4000)
22
+ args, rest = parser.parse_known_args()
23
+
24
+ fd, tmp_file = tempfile.mkstemp()
25
+ os.close(fd)
26
+
27
+ argv = [tmp_file if a == args.replstr else a for a in rest]
28
+
29
+ kw: dict = {}
30
+ if args.stdout_silenced:
31
+ kw.update(stdout=open('/dev/null', 'wb')) # noqa
32
+ elif args.stdout_to_stderr:
33
+ kw.update(stdout=sys.stderr)
34
+
35
+ subprocess.check_call(argv, **kw)
36
+
37
+ if args.cat:
38
+ try:
39
+ with open(tmp_file, 'rb') as f:
40
+ while buf := f.read(args.read_size):
41
+ sys.stdout.buffer.write(buf)
42
+ finally:
43
+ if not args.keep:
44
+ os.unlink(tmp_file)
45
+
46
+ else:
47
+ print(tmp_file)
48
+
49
+
50
+ # @omlish-manifest
51
+ _CLI_MODULE = {'$omdev.cli.types.CliModule': {
52
+ 'cmd_name': 'tmpexec',
53
+ 'mod_name': __name__,
54
+ }}
55
+
56
+
57
+ if __name__ == '__main__':
58
+ _main()
omdev/tools/git.py CHANGED
@@ -61,38 +61,42 @@ class Cli(ap.Cli):
61
61
  accepts_unknown=True,
62
62
  )
63
63
  def clone(self) -> None:
64
- out_dir: str
65
-
66
- if (m := self._GITHUB_PAT.fullmatch(self.args.repo)):
67
- user = m.group('user')
68
- repo = m.group('repo')
69
-
70
- os.makedirs(user, 0o755, exist_ok=True)
71
-
72
- subprocess.check_call([
73
- 'git',
74
- 'clone',
75
- *self.unknown_args,
76
- *self.args.args,
77
- f'https://github.com/{user}/{repo}.git',
78
- os.path.join(user, repo),
79
- ])
80
-
81
- out_dir = os.path.join(user, repo)
82
-
83
- else:
84
- parsed = urllib.parse.urlparse(self.args.repo)
85
- out_dir = parsed.path.split('/')[-1]
86
-
87
- subprocess.check_call([
88
- 'git',
89
- 'clone',
90
- *self.unknown_args,
91
- *self.args.args,
92
- self.args.repo,
93
- ])
94
-
95
- print(out_dir)
64
+ # And expected usage is `cd $(om git clone foo/bar)` and an empty cd arg will return to the previous directory,
65
+ # so always output at least a . so it'll cd to the current dir at least lol - it still runs even if the proc
66
+ # fails.
67
+ out_dir = '.'
68
+ try:
69
+ if (m := self._GITHUB_PAT.fullmatch(self.args.repo)):
70
+ user = m.group('user')
71
+ repo = m.group('repo')
72
+
73
+ os.makedirs(user, 0o755, exist_ok=True)
74
+
75
+ subprocess.check_call([
76
+ 'git',
77
+ 'clone',
78
+ *self.unknown_args,
79
+ *self.args.args,
80
+ f'git@github.com:{user}/{repo}.git',
81
+ os.path.join(user, repo),
82
+ ])
83
+
84
+ out_dir = os.path.join(user, repo)
85
+
86
+ else:
87
+ parsed = urllib.parse.urlparse(self.args.repo)
88
+ out_dir = parsed.path.split('/')[-1]
89
+
90
+ subprocess.check_call([
91
+ 'git',
92
+ 'clone',
93
+ *self.unknown_args,
94
+ *self.args.args,
95
+ self.args.repo,
96
+ ])
97
+
98
+ finally:
99
+ print(out_dir)
96
100
 
97
101
  @ap.command(
98
102
  ap.arg('rev', nargs='?', default='HEAD'),
omdev/tools/pip.py CHANGED
@@ -1,18 +1,35 @@
1
+ """
2
+ TODO:
3
+ - https://github.com/pypa/pip/blob/420435903ff2fc694d6950a47b896427ecaed78f/src/pip/_internal/req/req_file.py ?
4
+ """
5
+ import contextlib
1
6
  import importlib.metadata
2
7
  import io
8
+ import os.path
3
9
  import sys
10
+ import typing as ta
4
11
  import urllib.request
5
- import xml.etree.ElementTree as ET # noqa
6
12
 
7
13
  from omlish import argparse as ap
8
14
  from omlish import check
15
+ from omlish import lang
16
+ from omlish import marshal as msh
17
+ from omlish.formats import json
9
18
 
10
19
  from ..cli import CliModule
20
+ from ..packaging import marshal as _ # noqa
11
21
  from ..packaging.names import canonicalize_name
22
+ from ..packaging.requires import ParsedRequirement
12
23
  from ..packaging.requires import RequiresVariable
13
24
  from ..packaging.requires import parse_requirement
14
25
 
15
26
 
27
+ if ta.TYPE_CHECKING:
28
+ import xml.etree.ElementTree as ET # noqa
29
+ else:
30
+ ET = lang.proxy_import('xml.etree.ElementTree')
31
+
32
+
16
33
  PYPI_URL = 'https://pypi.org/'
17
34
 
18
35
 
@@ -84,6 +101,65 @@ class Cli(ap.Cli):
84
101
  if not uses_by_req.get(d):
85
102
  print(d)
86
103
 
104
+ @ap.command(
105
+ ap.arg('files', nargs='*'),
106
+ ap.arg('-r', '--follow-requirements', action='store_true'),
107
+ ap.arg('-j', '--json', action='store_true'),
108
+ ap.arg('-b', '--bare', action='store_true'),
109
+ )
110
+ def parse(self) -> None:
111
+ def print_req(req: ParsedRequirement) -> None:
112
+ if self.args.json:
113
+ req_m = msh.marshal(req)
114
+ print(json.dumps(req_m))
115
+
116
+ elif self.args.bare:
117
+ print(req.name)
118
+
119
+ else:
120
+ print(f'{req.name}{req.specifier or ""}')
121
+
122
+ #
123
+
124
+ seen_files: set[str] = set()
125
+
126
+ def do_file(file: ta.TextIO | str) -> None:
127
+ if isinstance(file, str) and file in seen_files:
128
+ return
129
+
130
+ with contextlib.ExitStack() as es:
131
+ f: ta.TextIO
132
+ if isinstance(file, str):
133
+ f = es.enter_context(open(file))
134
+ else:
135
+ f = file
136
+
137
+ for l in f:
138
+ if '#' in l:
139
+ l = l.partition('#')[0]
140
+
141
+ if not (l := l.strip()):
142
+ continue
143
+
144
+ if l.startswith('git+'):
145
+ continue # FIXME
146
+
147
+ elif l.startswith('-r'): # noqa
148
+ if self.args.follow_requirements:
149
+ base_dir = os.path.dirname(file) if isinstance(file, str) else '.'
150
+ r_file = os.path.join(base_dir, l[2:].strip())
151
+ do_file(r_file)
152
+
153
+ else:
154
+ req = parse_requirement(l)
155
+ print_req(req)
156
+
157
+ if self.args.files:
158
+ for file in self.args.files:
159
+ do_file(file)
160
+ else:
161
+ do_file(sys.stdin)
162
+
87
163
 
88
164
  # @omlish-manifest
89
165
  _CLI_MODULE = CliModule('pip', __name__)
omdev/tools/qr.py ADDED
@@ -0,0 +1,79 @@
1
+ """
2
+ https://segno.readthedocs.io/en/stable/comparison-qrcode-libs.html
3
+ - https://github.com/nayuki/QR-Code-generator
4
+ - https://github.com/heuer/segno/
5
+ - https://github.com/lincolnloop/python-qrcode
6
+ """
7
+ import argparse
8
+ import os
9
+ import subprocess
10
+ import sys
11
+ import tempfile
12
+ import typing as ta
13
+
14
+ from omlish import lang
15
+
16
+ from ..cli import CliModule
17
+
18
+
19
+ if ta.TYPE_CHECKING:
20
+ import segno
21
+ else:
22
+ segno = lang.proxy_import('segno')
23
+
24
+
25
+ def _main() -> None:
26
+ parser = argparse.ArgumentParser()
27
+ parser.add_argument('content', nargs='?')
28
+
29
+ parser.add_argument('-x', '--target-size', type=int)
30
+
31
+ parser.add_argument('-o', '--output')
32
+ parser.add_argument('-O', '--open', action='store_true')
33
+
34
+ parser.add_argument(
35
+ '--error', '-e',
36
+ help=(
37
+ 'Error correction level: '
38
+ '"L": 7%% (default), '
39
+ '"M": 15%%, '
40
+ '"Q": 25%%, '
41
+ '"H": 30%%, '
42
+ '"-": no error correction (used for M1 symbols)'
43
+ ),
44
+ choices=('L', 'M', 'Q', 'H', '-'),
45
+ )
46
+ args = parser.parse_args()
47
+
48
+ if (content := args.content) is None:
49
+ content = sys.stdin.read()
50
+
51
+ qr = segno.make(content)
52
+
53
+ if (tx := args.target_size) is not None:
54
+ sz = max(*qr.symbol_size())
55
+ sc = max(float(tx) / sz, 1)
56
+ else:
57
+ sc = 1
58
+
59
+ if args.output is not None:
60
+ out_file = args.output
61
+ else:
62
+ fd, out_file = tempfile.mkstemp(suffix='-qrcode.png')
63
+ os.close(fd)
64
+
65
+ qr.save(out_file, scale=sc)
66
+
67
+ if args.output is None:
68
+ print(out_file)
69
+
70
+ if args.open:
71
+ subprocess.check_call(['open', out_file])
72
+
73
+
74
+ # @omlish-manifest
75
+ _CLI_MODULE = CliModule('qr', __name__)
76
+
77
+
78
+ if __name__ == '__main__':
79
+ _main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omdev
3
- Version: 0.0.0.dev101
3
+ Version: 0.0.0.dev112
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.dev101
15
+ Requires-Dist: omlish ==0.0.0.dev112
16
16
  Provides-Extra: all
17
17
  Requires-Dist: black ~=24.10 ; extra == 'all'
18
18
  Requires-Dist: pycparser ~=2.22 ; extra == 'all'
@@ -23,6 +23,7 @@ Requires-Dist: markdown ~=3.7 ; extra == 'all'
23
23
  Requires-Dist: mypy ~=1.11 ; extra == 'all'
24
24
  Requires-Dist: gprof2dot ~=2024.6 ; extra == 'all'
25
25
  Requires-Dist: prompt-toolkit ~=3.0 ; extra == 'all'
26
+ Requires-Dist: segno ~=1.6 ; extra == 'all'
26
27
  Requires-Dist: tokenize-rt ~=6.1 ; extra == 'all'
27
28
  Requires-Dist: wheel ~=0.44 ; extra == 'all'
28
29
  Provides-Extra: black
@@ -40,6 +41,8 @@ Provides-Extra: prof
40
41
  Requires-Dist: gprof2dot ~=2024.6 ; extra == 'prof'
41
42
  Provides-Extra: ptk
42
43
  Requires-Dist: prompt-toolkit ~=3.0 ; extra == 'ptk'
44
+ Provides-Extra: qr
45
+ Requires-Dist: segno ~=1.6 ; extra == 'qr'
43
46
  Provides-Extra: tokens
44
47
  Requires-Dist: tokenize-rt ~=6.1 ; extra == 'tokens'
45
48
  Provides-Extra: wheel
@@ -1,5 +1,5 @@
1
- omdev/.manifests.json,sha256=nBS0fk7qpXG5VCITHxGUgJgh8Ghd3LyckoYCcfwb8Qc,6713
2
- omdev/__about__.py,sha256=ON7EnhbxbwLsMj60wkd9OEYPloXZ7jmnMMzeLg44LXY,1225
1
+ omdev/.manifests.json,sha256=CttiykwDkNVtWsqk7xCLY0o7eUxPVTJvfS5enx6xg5g,7479
2
+ omdev/__about__.py,sha256=n5x-SO70OgbDQFzQ1d7sZDVMsnkQc4PxQZPFaIQFa0E,1281
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
@@ -60,14 +60,14 @@ omdev/cexts/_distutils/compilers/unixccompiler.py,sha256=o1h8QuyupLntv4F21_XjzAZ
60
60
  omdev/cli/__init__.py,sha256=V_l6VP1SZMlJbO-8CJwSuO9TThOy2S_oaPepNYgIrbE,37
61
61
  omdev/cli/__main__.py,sha256=mOJpgc07o0r5luQ1DlX4tk2PqZkgmbwPbdzJ3KmtjgQ,138
62
62
  omdev/cli/_pathhack.py,sha256=kxqb2kHap68Lkh8b211rDbcgj06hidBiAKA3f9posyc,2119
63
- omdev/cli/clicli.py,sha256=ShTlK2vjFPqnyF9SPTwXd4nRyb6XjCVPQIT4PTGdTL4,2879
63
+ omdev/cli/clicli.py,sha256=oD54mXX-j9UeeCIW2640m8ip5LtAqQvT0hJRbl1zmf8,2874
64
64
  omdev/cli/install.py,sha256=C-W171YlIHt4Cfok-nWSMbHwWhqF_PFqq2HixFttYx8,4460
65
65
  omdev/cli/main.py,sha256=nD3bW3MkI0KuDSLpX_PTnl-lBnm4hIxVqczvvMHtupo,7058
66
66
  omdev/cli/managers.py,sha256=BV98_n30Jj63OJrFgRoVZRfICxMLXEZKoEn4rMj9LV4,1160
67
67
  omdev/cli/types.py,sha256=bqKw9SbtBtAip2vF9v4khh0CqKG6LBr6n9VzWBz7AJE,474
68
68
  omdev/clipboard/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
69
  omdev/clipboard/clipboard.py,sha256=CmnozkRljJ9UQDHLfCS8wKU0Xg-HfbsAkagAfMEias0,567
70
- omdev/clipboard/darwin.py,sha256=Nq4SsAEJdIof_mgMTderdeQyuiyI0hlHUxVuom4YAcE,6415
70
+ omdev/clipboard/darwin.py,sha256=zKPmI4mdTTo5ixbOVIBt6OnZE6BrpXgTPf0Tgz_-ds0,7556
71
71
  omdev/interp/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
72
72
  omdev/interp/__main__.py,sha256=GMCqeGYltgt5dlJzHxY9gqisa8cRkrPfmZYuZnjg4WI,162
73
73
  omdev/interp/cli.py,sha256=sh7PZQoLletUViw1Y9OXNr9ekyNZ6YyxYuOQ_n9hyqU,2072
@@ -89,11 +89,12 @@ omdev/manifests/load.py,sha256=LtEsluDdd8CkNGj0QGBxee3twBn095Fru0xz2mtr7uk,4788
89
89
  omdev/manifests/types.py,sha256=Jv6PAdVLPb9Hh4y6vDhPlWuMNBBViin1bC_u83jfsH4,234
90
90
  omdev/mypy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
91
  omdev/mypy/debug.py,sha256=WcZw-3Z1njg_KFGqi3DB6RuqbBa3dLArJnjVCuY1Mn0,3003
92
- omdev/packaging/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
93
- omdev/packaging/names.py,sha256=lwws9dgClio0_-w6fZcihOKxx4FPkrHUxum918KjZO8,2513
94
- omdev/packaging/requires.py,sha256=VQ-rRDK4_w2R-0xMTbLCwhvZwkO-qgS8uEMbRhNmfOw,15598
95
- omdev/packaging/specifiers.py,sha256=6Odf9e6farwlPRsD_YqwTfYKG-BXn_dIcKtqfkhfodI,17432
96
- omdev/packaging/versions.py,sha256=ei2eopEsJq3zSMJmezK1nzZgikgCdxFtnF3f69nCRZQ,12246
92
+ omdev/packaging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
93
+ omdev/packaging/marshal.py,sha256=mWRuZ_okYxRJXylKFQLQpC8Pp7xjkUEfWYNzQIS5A2c,2376
94
+ omdev/packaging/names.py,sha256=-a7AykFPVR1i6EYJepbe3ABRrZQ_tPPmK5olzbn9HLI,2528
95
+ omdev/packaging/requires.py,sha256=kyyVCM0RyaKqmXd6tU5zf0QjWvCLQMNV_ev5hvOee_o,15731
96
+ omdev/packaging/specifiers.py,sha256=X8xOcwRLXTQYx5mYAS3ijqoTLlCtYESyUu4fX9bvblY,17447
97
+ omdev/packaging/versions.py,sha256=K4eUOUvLmYcR4aeUywekeWTBqAvZchrIxLf7dl07MS4,12261
97
98
  omdev/precheck/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
99
  omdev/precheck/__main__.py,sha256=UEuS4z5-heIrwTtB-ONe1KeXJdqj8tYXMqWMpuO10so,165
99
100
  omdev/precheck/base.py,sha256=a_lGoFM-QhL8u8XDUYFhb-feEyfPbP4j8lcmNO51sHY,732
@@ -104,7 +105,10 @@ omdev/precheck/manifests.py,sha256=YfXqt6u0hlFXY0QkBMec6V_6Y9T4eCVAmrJDkQkB13U,7
104
105
  omdev/precheck/scripts.py,sha256=Xw9kkQzlDd_2V9av9qlaNpNZG9jZdy3TTo7x60MeR2I,1273
105
106
  omdev/ptk/__init__.py,sha256=StAwXQ96e8Xkkg7ciR9oBBhcSgqHT76vhoZML82BuY0,447
106
107
  omdev/ptk/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
- omdev/ptk/apps/ncdu.py,sha256=ov6AEjne2NyVE45XiAtteq5SmbxXHQkUsybuu5KSwRQ,4479
108
+ omdev/ptk/apps/ncdu.py,sha256=dOkEJoc2Wjv1u_Uge7Vpei_LvXldoPP5833Eia355tc,4548
109
+ omdev/pycharm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
110
+ omdev/pycharm/__main__.py,sha256=hUPp11D024eMdT86BxXiRVtF7AGBk5W6Zn8_mEHSksY,163
111
+ omdev/pycharm/cli.py,sha256=XDR3fYUnGdK2oys3IKs7QrGbYwXUiMba16DNXdMVlAA,2209
108
112
  omdev/pyproject/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
109
113
  omdev/pyproject/__main__.py,sha256=gn3Rl1aYPYdiTtEqa9ifi0t-e4ZwPY0vhJ4UXvYdJDY,165
110
114
  omdev/pyproject/cexts.py,sha256=x13piOOnNrYbA17qZLDVuR0p1sqhgEwpk4FtImX-klM,4281
@@ -114,31 +118,33 @@ omdev/pyproject/pkg.py,sha256=WB9k3zEpHSAR24H09kikgAnLMWUz-bk9f0aB-2L_ITw,14560
114
118
  omdev/pyproject/reqs.py,sha256=8feZ71YnGzwKbLK4zO28CDQeNcZIIuq6cnkBhs6M-7E,2406
115
119
  omdev/scripts/__init__.py,sha256=MKCvUAEQwsIvwLixwtPlpBqmkMXLCnjjXyAXvVpDwVk,91
116
120
  omdev/scripts/bumpversion.py,sha256=Kn7fo73Hs8uJh3Hi3EIyLOlzLPWAC6dwuD_lZ3cIzuY,1064
117
- omdev/scripts/execrss.py,sha256=hJTWBig_-XqKIj1DphYTfeVDtdQTM1XUl-Hvzs2x9iY,451
118
- omdev/scripts/exectime.py,sha256=dBdn3KV2jR6tCrzGvb9dTl2uGe2vNpLxmHMtExmnaiM,410
121
+ omdev/scripts/execrss.py,sha256=mR0G0wERBYtQmVIn63lCIIFb5zkCM6X_XOENDFYDBKc,651
122
+ omdev/scripts/exectime.py,sha256=sFb376GflU6s9gNX-2-we8hgH6w5MuQNS9g6i4SqJIo,610
119
123
  omdev/scripts/importtrace.py,sha256=Jbo3Yk2RAbE8_tJ97iTcVNpoxCJxrRb2tl1W_CV3NG0,14067
120
- omdev/scripts/interp.py,sha256=ls04OE3g_TpiK5_inRfOzUvBGUtBgSt5vnkqC3eZhTM,72076
121
- omdev/scripts/pyproject.py,sha256=0etqlpe2wL2lRLKgRo6X5llzpvM-I7AHbu1oWqdV-6M,164318
124
+ omdev/scripts/interp.py,sha256=U6mU2RPZjwcBhn4Vl4SrAyDUFcf7bBxBnPY5FHCxosw,72496
125
+ omdev/scripts/pyproject.py,sha256=RNWsO9-cu6MUXuWFT1Y200euUu6WcAC4orwGEUoGVWA,165526
122
126
  omdev/scripts/slowcat.py,sha256=lssv4yrgJHiWfOiHkUut2p8E8Tq32zB-ujXESQxFFHY,2728
127
+ omdev/scripts/tmpexec.py,sha256=WTYcf56Tj2qjYV14AWmV8SfT0u6Y8eIU6cKgQRvEK3c,1442
123
128
  omdev/toml/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
124
129
  omdev/toml/parser.py,sha256=84bn09uhYHwQGyfww6Rw6y1RxPAE_HDltODOSakcqDM,29186
125
130
  omdev/toml/writer.py,sha256=lk3on3YXVbWuLJa-xsOzOhs1bBAT1vXqw4mBbluZl_w,3040
126
131
  omdev/tools/__init__.py,sha256=iVJAOQ0viGTQOm0DLX4uZLro-9jOioYJGLg9s0kDx1A,78
127
132
  omdev/tools/doc.py,sha256=mv9XfitzqXl3vFHSenv01xHCxWf8g03rUAb_sqoty98,2556
128
133
  omdev/tools/docker.py,sha256=k2BrVvFYwyGov064CPHd_HWo9aqR1zHc2UeEsVwPth4,6827
129
- omdev/tools/git.py,sha256=1Oa2AgdZIJZ2eusso9yFzkd9zLWH3d4lTiVFzwg0uDM,3808
134
+ omdev/tools/git.py,sha256=IARrfL9R9BHpmTBia3svbPeCzf_4qlCCbOsLpohsfUI,4184
130
135
  omdev/tools/importscan.py,sha256=QeGjR3UGcuuuDUiisFuAXWHlcKJScGxGEcU6tfOh2CM,4069
131
136
  omdev/tools/mkrelimp.py,sha256=wsJAjTIf3nqcSfnT9TkDpS1VUOoM9W2Az5tZdWuzyLM,4054
132
137
  omdev/tools/notebook.py,sha256=M8Xi_gfZdlahnyFLtp0RBgYZPSHWQStMMDYZc71Zync,3494
133
- omdev/tools/pip.py,sha256=-jR5q3w4sHqntxCLExFCBNIARB788FUsAbJ62PK2sBU,2774
138
+ omdev/tools/pip.py,sha256=_O7WAACQ1F1ffH4ogZHcppT4P8VQxWQchJMLn9FvsJc,5073
134
139
  omdev/tools/prof.py,sha256=8ZU9x_Dq8eT2ZFwU9sJpDIvxcIn9qBc8y2ELKPb5e5M,1382
140
+ omdev/tools/qr.py,sha256=tm68lPwEAkEwIL2sUKPKBYfwwPtjVWG1DBZwur8_jY8,1737
135
141
  omdev/tools/sqlrepl.py,sha256=tmFZh80-xsGM62dyQ7_UGLebChrj7IHbIPYBWDJMgVk,5741
136
142
  omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
143
  omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
138
144
  omdev/tools/pawk/pawk.py,sha256=Eckymn22GfychCQcQi96BFqRo_LmiJ-EPhC8TTUJdB4,11446
139
- omdev-0.0.0.dev101.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
140
- omdev-0.0.0.dev101.dist-info/METADATA,sha256=OiY35acSdRnovqpJlehySG023oUI01sfFyDXuZXY_6M,1704
141
- omdev-0.0.0.dev101.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
142
- omdev-0.0.0.dev101.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
143
- omdev-0.0.0.dev101.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
144
- omdev-0.0.0.dev101.dist-info/RECORD,,
145
+ omdev-0.0.0.dev112.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
146
+ omdev-0.0.0.dev112.dist-info/METADATA,sha256=VeCQ5RyISLmbtXUOxqiBvvzJW3kHbcsb8l6KjNrg0C8,1810
147
+ omdev-0.0.0.dev112.dist-info/WHEEL,sha256=a7TGlA-5DaHMRrarXjVbQagU3Man_dCnGIWMJr5kRWo,91
148
+ omdev-0.0.0.dev112.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
149
+ omdev-0.0.0.dev112.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
150
+ omdev-0.0.0.dev112.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5