omdev 0.0.0.dev114__py3-none-any.whl → 0.0.0.dev115__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
@@ -51,7 +51,7 @@
51
51
  "module": ".cli.clicli",
52
52
  "attr": "_CLI_MODULE",
53
53
  "file": "omdev/cli/clicli.py",
54
- "line": 111,
54
+ "line": 113,
55
55
  "value": {
56
56
  "$.cli.types.CliModule": {
57
57
  "cmd_name": "cli",
omdev/cli/clicli.py CHANGED
@@ -89,6 +89,8 @@ class CliCli(ap.Cli):
89
89
  print('Continue with reinstall? (ctrl-c to cancel)')
90
90
  input()
91
91
 
92
+ #
93
+
92
94
  if self.args.local:
93
95
  install_src = inspect.getsource(install)
94
96
  else:
omdev/cli/main.py CHANGED
@@ -1,6 +1,5 @@
1
1
  """
2
2
  TODO:
3
- - py/foo - root command 'py'
4
3
  - cache ldr.discover() somehow if in uvx/pipx - very slow
5
4
  - <venv-root>/.omdev-cli-manifest-cache.json - {pkg_name: manifests_json}
6
5
  - allow manually specifying manifest packages
@@ -1,23 +1,74 @@
1
- """
2
- https://askubuntu.com/questions/11925/a-command-line-clipboard-copy-and-paste-utility
1
+ """ https://askubuntu.com/questions/11925/a-command-line-clipboard-copy-and-paste-utility
3
2
  """
4
3
  import abc
4
+ import dataclasses as dc
5
5
  import subprocess
6
+ import typing as ta
7
+
8
+ from omlish import lang
9
+
10
+
11
+ ##
12
+
13
+
14
+ @dc.dataclass(frozen=True)
15
+ class ClipboardContents(lang.Abstract):
16
+ pass
17
+
18
+
19
+ @dc.dataclass(frozen=True)
20
+ class TextClipboardContents(ClipboardContents):
21
+ s: str
22
+
23
+
24
+ @dc.dataclass(frozen=True)
25
+ class ImageClipboardContents(ClipboardContents):
26
+ b: bytes
27
+
28
+
29
+ ##
6
30
 
7
31
 
8
32
  class Clipboard(abc.ABC):
9
33
  @abc.abstractmethod
10
- def get(self) -> str:
34
+ def get(self) -> list[ClipboardContents]:
11
35
  raise NotImplementedError
12
36
 
13
37
  @abc.abstractmethod
14
- def put(self, s: str) -> None:
38
+ def put(self, c: ClipboardContents) -> None:
15
39
  raise NotImplementedError
16
40
 
17
41
 
18
- class DarwinClipboard(Clipboard):
19
- def get(self) -> str:
20
- return subprocess.check_output(['pbpaste']).decode('utf-8')
42
+ ##
43
+
44
+
45
+ class TextCommandClipboard(Clipboard, lang.Abstract):
46
+ @property
47
+ @abc.abstractmethod
48
+ def _get_cmd(self) -> ta.Sequence[str]:
49
+ raise NotImplementedError
50
+
51
+ def get(self) -> list[ClipboardContents]:
52
+ s = subprocess.check_output(self._get_cmd).decode()
53
+ return [TextClipboardContents(s)]
54
+
55
+ @property
56
+ @abc.abstractmethod
57
+ def _put_cmd(self) -> ta.Sequence[str]:
58
+ raise NotImplementedError
59
+
60
+ def put(self, c: ClipboardContents) -> None:
61
+ if isinstance(c, TextClipboardContents):
62
+ subprocess.run(self._put_cmd, input=c.s.encode(), check=True)
63
+ else:
64
+ raise TypeError(c)
65
+
66
+
67
+ class XclipLinuxClipboard(TextCommandClipboard):
68
+ _get_cmd = ('xclip', '-selection', 'clipboard', '-o')
69
+ _put_cmd = ('xclip', '-selection', 'clipboard')
70
+
21
71
 
22
- def put(self, s: str) -> None:
23
- subprocess.run(['pbcopy'], input=s.encode('utf-8'), check=True)
72
+ class PbcopyDarwinClipboard(TextCommandClipboard):
73
+ _get_cmd = ('pbpaste',)
74
+ _put_cmd = ('pbcopy',)
@@ -1,31 +1,4 @@
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
- """
29
2
  import ctypes as ct
30
3
  import ctypes.util
31
4
  import dataclasses as dc
@@ -34,6 +7,11 @@ import typing as ta
34
7
 
35
8
  from omlish import check
36
9
 
10
+ from .clipboard import Clipboard
11
+ from .clipboard import ClipboardContents
12
+ from .clipboard import ImageClipboardContents
13
+ from .clipboard import TextClipboardContents
14
+
37
15
 
38
16
  ##
39
17
 
@@ -254,6 +232,32 @@ def get_darwin_clipboard_data(
254
232
  ##
255
233
 
256
234
 
235
+ _TEXT_TYPE = 'public.utf8-plain-text'
236
+ _IMAGE_TYPE = 'public.png'
237
+
238
+
239
+ class CfDarwinClipboard(Clipboard):
240
+
241
+ def get(self) -> list[ClipboardContents]:
242
+ ret: list[ClipboardContents] = []
243
+ for i in get_darwin_clipboard_data(types={_TEXT_TYPE, _IMAGE_TYPE}):
244
+ if i.type == _TEXT_TYPE:
245
+ if i.data is not None:
246
+ ret.append(TextClipboardContents(i.data.decode('utf-8')))
247
+ elif i.type == _IMAGE_TYPE:
248
+ if i.data is not None:
249
+ ret.append(ImageClipboardContents(i.data))
250
+ else:
251
+ raise KeyError(i.type)
252
+ return ret
253
+
254
+ def put(self, c: ClipboardContents) -> None:
255
+ raise TypeError(self)
256
+
257
+
258
+ ##
259
+
260
+
257
261
  def _main() -> None:
258
262
  for i in get_darwin_clipboard_data(skip_types={'public.heics'}):
259
263
  print(f'type: {i.type}, len: {len(i.data) if i.data is not None else None}')
@@ -0,0 +1,301 @@
1
+ # ruff: noqa: RUF012
2
+ # flake8: noqa: E302 E305
3
+ import ctypes as ct
4
+ import ctypes.util
5
+ import sys
6
+
7
+
8
+ ##
9
+
10
+
11
+ if getattr(sys, 'platform') != 'linux':
12
+ raise OSError(sys.platform)
13
+
14
+
15
+ ##
16
+ # x11
17
+
18
+ x11 = ct.CDLL(ct.util.find_library('X11'))
19
+
20
+ #
21
+
22
+ Atom = ct.c_ulong
23
+ Bool = ct.c_int
24
+ Display = ct.c_void_p
25
+ Status = ct.c_int
26
+ Time = ct.c_ulong
27
+ Window = ct.c_ulong
28
+
29
+ #
30
+
31
+ class XEvent(ct.Structure):
32
+ _fields_ = [
33
+ ('type', ct.c_int),
34
+ ('xselection', ct.c_ulong * 24), # noqa
35
+ ]
36
+
37
+ #
38
+
39
+ x11.XCloseDisplay.argtypes = [Display]
40
+ x11.XCloseDisplay.restype = None
41
+
42
+ x11.XConvertSelection.argtypes = [Display, Atom, Atom, Atom, Window, Time]
43
+ x11.XConvertSelection.restype = None
44
+
45
+ x11.XCreateSimpleWindow.argtypes = [
46
+ Display,
47
+ Window,
48
+ ct.c_int,
49
+ ct.c_int,
50
+ ct.c_uint,
51
+ ct.c_uint,
52
+ ct.c_uint,
53
+ ct.c_ulong,
54
+ ct.c_ulong,
55
+ ]
56
+ x11.XCreateSimpleWindow.restype = Window
57
+
58
+ x11.XDefaultScreen.argtypes = [Display]
59
+ x11.XDefaultScreen.restype = ct.c_int
60
+
61
+ x11.XDestroyWindow.argtypes = [Display, Window]
62
+ x11.XDestroyWindow.restype = None
63
+
64
+ x11.XFlush.argtypes = [Display]
65
+ x11.XFlush.restype = None
66
+
67
+ x11.XFree.argtypes = [ct.c_void_p]
68
+ x11.XFree.restype = None
69
+
70
+ x11.XGetWindowProperty.argtypes = [
71
+ Display,
72
+ Window,
73
+ Atom,
74
+ ct.c_long,
75
+ ct.c_long,
76
+ Bool,
77
+ Atom,
78
+ ct.POINTER(Atom),
79
+ ct.POINTER(ct.c_int),
80
+ ct.POINTER(ct.c_ulong),
81
+ ct.POINTER(ct.c_ulong),
82
+ ct.POINTER(ct.c_void_p),
83
+ ]
84
+ x11.XGetWindowProperty.restype = Status
85
+
86
+ x11.XInternAtom.argtypes = [Display, ct.c_char_p, Bool]
87
+ x11.XInternAtom.restype = Atom
88
+
89
+ x11.XNextEvent.argtypes = [Display, ct.POINTER(XEvent)]
90
+ x11.XNextEvent.restype = None
91
+
92
+ x11.XOpenDisplay.argtypes = [ct.c_char_p]
93
+ x11.XOpenDisplay.restype = Display
94
+
95
+ x11.XRootWindow.argtypes = [Display, ct.c_int]
96
+ x11.XRootWindow.restype = Window
97
+
98
+
99
+ ##
100
+
101
+
102
+ def atom_to_string(display, atom) -> str:
103
+ x11.XGetAtomName.argtypes = [Display, Atom]
104
+ x11.XGetAtomName.restype = ct.c_char_p
105
+ return x11.XGetAtomName(display, atom).decode('utf-8')
106
+
107
+
108
+ ##
109
+
110
+
111
+ def get_clipboard_text(display, window):
112
+ clipboard = x11.XInternAtom(display, b'CLIPBOARD', False)
113
+ utf8_string = x11.XInternAtom(display, b'UTF8_STRING', False)
114
+ target_property = x11.XInternAtom(display, b'XSEL_DATA', False)
115
+
116
+ x11.XConvertSelection(
117
+ display,
118
+ clipboard,
119
+ utf8_string,
120
+ target_property,
121
+ window,
122
+ 0,
123
+ )
124
+ x11.XFlush(display)
125
+
126
+ event = XEvent()
127
+ x11.XNextEvent(display, ct.byref(event))
128
+
129
+ if event.type != 31: # SelectionNotify event type
130
+ print('Failed to receive SelectionNotify event')
131
+ return
132
+
133
+ if event.xselection[4] == 0: # None
134
+ print('No clipboard data available')
135
+ return
136
+
137
+ actual_type = Atom()
138
+ actual_format = ct.c_int()
139
+ nitems = ct.c_ulong()
140
+ bytes_after = ct.c_ulong()
141
+ data = ct.c_void_p()
142
+
143
+ status = x11.XGetWindowProperty(
144
+ display,
145
+ window,
146
+ target_property,
147
+ 0,
148
+ ~0,
149
+ False,
150
+ 0,
151
+ ct.byref(actual_type),
152
+ ct.byref(actual_format),
153
+ ct.byref(nitems),
154
+ ct.byref(bytes_after),
155
+ ct.byref(data),
156
+ )
157
+ try:
158
+ if status != 0 or not data:
159
+ print('Failed to get clipboard data')
160
+ return
161
+
162
+ clipboard_text = ct.cast(data, ct.c_char_p).value
163
+ print(f'Clipboard text: {clipboard_text.decode("utf-8") if clipboard_text else ""}')
164
+
165
+ finally:
166
+ x11.XFree(data)
167
+
168
+
169
+ def get_clipboard_image(display, window):
170
+ clipboard = x11.XInternAtom(display, b'CLIPBOARD', False)
171
+ target_property = x11.XInternAtom(display, b'XSEL_DATA', False)
172
+ targets_atom = x11.XInternAtom(display, b'TARGETS', False)
173
+
174
+ x11.XConvertSelection(
175
+ display,
176
+ clipboard,
177
+ targets_atom,
178
+ target_property,
179
+ window,
180
+ 0,
181
+ )
182
+ x11.XFlush(display)
183
+
184
+ event = XEvent()
185
+ x11.XNextEvent(display, ct.byref(event))
186
+
187
+ if event.type != 31 or event.xselection[4] == 0:
188
+ print('Failed to receive SelectionNotify event for image')
189
+ return
190
+
191
+ actual_type = Atom()
192
+ actual_format = ct.c_int()
193
+ nitems = ct.c_ulong()
194
+ bytes_after = ct.c_ulong()
195
+ data = ct.c_void_p()
196
+
197
+ status = x11.XGetWindowProperty(
198
+ display,
199
+ window,
200
+ target_property,
201
+ 0,
202
+ ~0,
203
+ False,
204
+ 4,
205
+ ct.byref(actual_type),
206
+ ct.byref(actual_format),
207
+ ct.byref(nitems),
208
+ ct.byref(bytes_after),
209
+ ct.byref(data),
210
+ )
211
+ try:
212
+ if status != 0 or not data:
213
+ print('Failed to get available targets')
214
+ return
215
+
216
+ png_atom = x11.XInternAtom(display, b'image/png', False)
217
+ atoms = ct.cast(data, ct.POINTER(Atom))
218
+ for i in range(nitems.value):
219
+ if atoms[i] != png_atom:
220
+ continue
221
+
222
+ x11.XConvertSelection(
223
+ display,
224
+ clipboard,
225
+ png_atom,
226
+ target_property,
227
+ window,
228
+ 0,
229
+ )
230
+ x11.XFlush(display)
231
+ x11.XNextEvent(display, ct.byref(event))
232
+
233
+ if event.type != 31 or event.xselection[4] == 0:
234
+ print('Failed to receive SelectionNotify event for PNG image')
235
+ return
236
+
237
+ status = x11.XGetWindowProperty(
238
+ display,
239
+ window,
240
+ target_property,
241
+ 0,
242
+ ~0,
243
+ False,
244
+ 0,
245
+ ct.byref(actual_type),
246
+ ct.byref(actual_format),
247
+ ct.byref(nitems),
248
+ ct.byref(bytes_after),
249
+ ct.byref(data),
250
+ )
251
+
252
+ if status == 0 and data:
253
+ data_bytes = ct.string_at(data.value, nitems.value) # type: ignore
254
+
255
+ print(f'Clipboard image: {len(data_bytes)} bytes')
256
+
257
+ return
258
+
259
+ print('No image data available on clipboard')
260
+
261
+ finally:
262
+ if data:
263
+ x11.XFree(data)
264
+
265
+
266
+ ##
267
+
268
+
269
+ def main() -> None:
270
+ display = x11.XOpenDisplay(None)
271
+ try:
272
+ if not display:
273
+ print('Failed to open X display')
274
+ return
275
+
276
+ screen = x11.XDefaultScreen(display)
277
+ window = x11.XCreateSimpleWindow(
278
+ display,
279
+ x11.XRootWindow(display, screen),
280
+ 0,
281
+ 0,
282
+ 1,
283
+ 1,
284
+ 0,
285
+ 0,
286
+ 0,
287
+ )
288
+ try:
289
+ get_clipboard_text(display, window)
290
+ get_clipboard_image(display, window)
291
+
292
+ finally:
293
+ x11.XDestroyWindow(display, window)
294
+
295
+ finally:
296
+ if display:
297
+ x11.XCloseDisplay(display)
298
+
299
+
300
+ if __name__ == '__main__':
301
+ main()
omdev/git.py CHANGED
@@ -228,7 +228,7 @@ untracked file, this is reported as ? as well.
228
228
  """ # noqa
229
229
 
230
230
 
231
- class GitStatusLineState(enum.Enum):
231
+ class GitStatusState(enum.Enum):
232
232
  UNMODIFIED = ' '
233
233
  MODIFIED = 'M'
234
234
  FILE_TYPE_CHANGED = 'T'
@@ -242,16 +242,16 @@ class GitStatusLineState(enum.Enum):
242
242
  SUBMODULE_MODIFIED_CONTENT = 'm'
243
243
 
244
244
 
245
- _EXTRA_UNMERGED_GIT_STATUS_LINE_STATES: ta.FrozenSet[ta.Tuple[GitStatusLineState, GitStatusLineState]] = frozenset([
246
- (GitStatusLineState.ADDED, GitStatusLineState.ADDED),
247
- (GitStatusLineState.DELETED, GitStatusLineState.DELETED),
245
+ _EXTRA_UNMERGED_GIT_STATUS_STATES: ta.FrozenSet[ta.Tuple[GitStatusState, GitStatusState]] = frozenset([
246
+ (GitStatusState.ADDED, GitStatusState.ADDED),
247
+ (GitStatusState.DELETED, GitStatusState.DELETED),
248
248
  ])
249
249
 
250
250
 
251
251
  @dc.dataclass(frozen=True)
252
- class GitStatusLine:
253
- x: GitStatusLineState
254
- y: GitStatusLineState
252
+ class GitStatusItem:
253
+ x: GitStatusState
254
+ y: GitStatusState
255
255
 
256
256
  a: str
257
257
  b: ta.Optional[str]
@@ -259,9 +259,9 @@ class GitStatusLine:
259
259
  @property
260
260
  def is_unmerged(self) -> bool:
261
261
  return (
262
- self.x is GitStatusLineState.UPDATED_BUT_UNMERGED or
263
- self.y is GitStatusLineState.UPDATED_BUT_UNMERGED or
264
- (self.x, self.y) in _EXTRA_UNMERGED_GIT_STATUS_LINE_STATES
262
+ self.x is GitStatusState.UPDATED_BUT_UNMERGED or
263
+ self.y is GitStatusState.UPDATED_BUT_UNMERGED or
264
+ (self.x, self.y) in _EXTRA_UNMERGED_GIT_STATUS_STATES
265
265
  )
266
266
 
267
267
  def __repr__(self) -> str:
@@ -275,7 +275,7 @@ class GitStatusLine:
275
275
  )
276
276
 
277
277
 
278
- def parse_git_status_line(l: str) -> GitStatusLine:
278
+ def parse_git_status_line(l: str) -> GitStatusItem:
279
279
  if len(l) < 3 or l[2] != ' ':
280
280
  raise ValueError(l)
281
281
  x, y = l[0], l[1]
@@ -289,25 +289,25 @@ def parse_git_status_line(l: str) -> GitStatusLine:
289
289
  else:
290
290
  raise ValueError(l)
291
291
 
292
- return GitStatusLine(
293
- GitStatusLineState(x),
294
- GitStatusLineState(y),
292
+ return GitStatusItem(
293
+ GitStatusState(x),
294
+ GitStatusState(y),
295
295
  a,
296
296
  b,
297
297
  )
298
298
 
299
299
 
300
- class GitStatus(ta.Sequence[GitStatusLine]):
301
- def __init__(self, lines: ta.Iterable[GitStatusLine]) -> None:
300
+ class GitStatus(ta.Sequence[GitStatusItem]):
301
+ def __init__(self, lines: ta.Iterable[GitStatusItem]) -> None:
302
302
  super().__init__()
303
303
 
304
304
  self._lst = list(lines)
305
305
 
306
- by_x: ta.Dict[GitStatusLineState, list[GitStatusLine]] = {}
307
- by_y: ta.Dict[GitStatusLineState, list[GitStatusLine]] = {}
306
+ by_x: ta.Dict[GitStatusState, list[GitStatusItem]] = {}
307
+ by_y: ta.Dict[GitStatusState, list[GitStatusItem]] = {}
308
308
 
309
- by_a: ta.Dict[str, GitStatusLine] = {}
310
- by_b: ta.Dict[str, GitStatusLine] = {}
309
+ by_a: ta.Dict[str, GitStatusItem] = {}
310
+ by_b: ta.Dict[str, GitStatusItem] = {}
311
311
 
312
312
  for l in self._lst:
313
313
  by_x.setdefault(l.x, []).append(l)
@@ -332,7 +332,7 @@ class GitStatus(ta.Sequence[GitStatusLine]):
332
332
 
333
333
  #
334
334
 
335
- def __iter__(self) -> ta.Iterator[GitStatusLine]:
335
+ def __iter__(self) -> ta.Iterator[GitStatusItem]:
336
336
  return iter(self._lst)
337
337
 
338
338
  def __getitem__(self, index):
@@ -344,19 +344,19 @@ class GitStatus(ta.Sequence[GitStatusLine]):
344
344
  #
345
345
 
346
346
  @property
347
- def by_x(self) -> ta.Mapping[GitStatusLineState, ta.Sequence[GitStatusLine]]:
347
+ def by_x(self) -> ta.Mapping[GitStatusState, ta.Sequence[GitStatusItem]]:
348
348
  return self._by_x
349
349
 
350
350
  @property
351
- def by_y(self) -> ta.Mapping[GitStatusLineState, ta.Sequence[GitStatusLine]]:
351
+ def by_y(self) -> ta.Mapping[GitStatusState, ta.Sequence[GitStatusItem]]:
352
352
  return self._by_y
353
353
 
354
354
  @property
355
- def by_a(self) -> ta.Mapping[str, GitStatusLine]:
355
+ def by_a(self) -> ta.Mapping[str, GitStatusItem]:
356
356
  return self._by_a
357
357
 
358
358
  @property
359
- def by_b(self) -> ta.Mapping[str, GitStatusLine]:
359
+ def by_b(self) -> ta.Mapping[str, GitStatusItem]:
360
360
  return self._by_b
361
361
 
362
362
  #
@@ -367,11 +367,11 @@ class GitStatus(ta.Sequence[GitStatusLine]):
367
367
 
368
368
  @property
369
369
  def has_staged(self) -> bool:
370
- return any(l.x != GitStatusLineState.UNMODIFIED for l in self._lst)
370
+ return any(l.x != GitStatusState.UNMODIFIED for l in self._lst)
371
371
 
372
372
  @property
373
373
  def has_dirty(self) -> bool:
374
- return any(l.y != GitStatusLineState.UNMODIFIED for l in self._lst)
374
+ return any(l.y != GitStatusState.UNMODIFIED for l in self._lst)
375
375
 
376
376
 
377
377
  def parse_git_status(s: str) -> GitStatus:
omdev/pip.py CHANGED
@@ -30,7 +30,7 @@ def lookup_latest_package_version(
30
30
  pypi_url: str = DEFAULT_PYPI_URL,
31
31
  ) -> str:
32
32
  pkg_name = check.non_empty_str(package)
33
- with urllib.request.urlopen(f'{pypi_url}rss/project/{pkg_name}/releases.xml') as resp: # noqa
33
+ with urllib.request.urlopen(f'{pypi_url.rstrip("/")}/rss/project/{pkg_name}/releases.xml') as resp: # noqa
34
34
  rss = resp.read()
35
35
  doc = ET.parse(io.BytesIO(rss)) # noqa
36
36
  latest = check.not_none(doc.find('./channel/item/title')).text
omdev/pycharm/cli.py CHANGED
@@ -1,6 +1,9 @@
1
1
  """
2
2
  TODO:
3
3
  - PyCharm.app/Contents/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_constants.py -> USE_LOW_IMPACT_MONITORING
4
+ - DISPLAY=":1" - ls /tmp/.X11-unix/X1 ?
5
+ - https://unix.stackexchange.com/questions/17255/is-there-a-command-to-list-all-open-displays-on-a-machine
6
+ - w -oush
4
7
  """
5
8
  import inspect
6
9
  import os.path
@@ -22,20 +25,19 @@ return
22
25
 
23
26
 
24
27
  _LINUX_OPEN_SCRIPT = """
25
- # Check if PyCharm is already running
26
- if pgrep -x "pycharm.sh" > /dev/null; then
27
- echo "PyCharm is already running. Opening project..."
28
+ # sudo apt install xdotool wmctrl
28
29
 
29
- # Bring PyCharm to the foreground
30
- wmctrl -a "PyCharm"
30
+ # wmctrl -lx
31
+ # 0x03000054 0 jetbrains-pycharm.jetbrains-pycharm spinlock-ws omlish - cli.py
32
+ # wmctrl -i -a 0x03000054
31
33
 
32
- # Simulate the keyboard shortcut to open a new project
33
- xdotool key --delay 100 ctrl+shift+a
34
- xdotool type "$PROJECT_PATH"
34
+ if pgrep -x "pycharm.sh" > /dev/null; then
35
+ # export DISPLAY=":1"
36
+ wmctrl -x -a jetbrains-pycharm.jetbrains-pycharm
37
+ xdotool key --delay 20 alt+f alt+o
38
+ xdotool type --delay 10 "$(pwd)"
35
39
  xdotool key Return
36
-
37
40
  else
38
- echo "Starting PyCharm with project..."
39
41
  nohup pycharm.sh "$PROJECT_PATH" > /dev/null 2>&1 &
40
42
  fi
41
43
  """
omdev/pyproject/cli.py CHANGED
@@ -382,20 +382,26 @@ def _build_parser() -> argparse.ArgumentParser:
382
382
 
383
383
  subparsers = parser.add_subparsers()
384
384
 
385
- parser_resolve = subparsers.add_parser('venv')
386
- parser_resolve.add_argument('name')
387
- parser_resolve.add_argument('-e', '--docker-env', action='append')
388
- parser_resolve.add_argument('cmd', nargs='?')
389
- parser_resolve.add_argument('args', nargs=argparse.REMAINDER)
390
- parser_resolve.set_defaults(func=_venv_cmd)
391
-
392
- parser_resolve = subparsers.add_parser('pkg')
393
- parser_resolve.add_argument('-b', '--build', action='store_true')
394
- parser_resolve.add_argument('-r', '--revision', action='store_true')
395
- parser_resolve.add_argument('-j', '--jobs', type=int)
396
- parser_resolve.add_argument('cmd', nargs='?')
397
- parser_resolve.add_argument('args', nargs=argparse.REMAINDER)
398
- parser_resolve.set_defaults(func=_pkg_cmd)
385
+ #
386
+
387
+ parser_venv = subparsers.add_parser('venv')
388
+ parser_venv.add_argument('name')
389
+ parser_venv.add_argument('-e', '--docker-env', action='append')
390
+ parser_venv.add_argument('cmd', nargs='?')
391
+ parser_venv.add_argument('args', nargs=argparse.REMAINDER)
392
+ parser_venv.set_defaults(func=_venv_cmd)
393
+
394
+ #
395
+
396
+ parser_pkg = subparsers.add_parser('pkg')
397
+ parser_pkg.add_argument('-b', '--build', action='store_true')
398
+ parser_pkg.add_argument('-r', '--revision', action='store_true')
399
+ parser_pkg.add_argument('-j', '--jobs', type=int)
400
+ parser_pkg.add_argument('cmd', nargs='?')
401
+ parser_pkg.add_argument('args', nargs=argparse.REMAINDER)
402
+ parser_pkg.set_defaults(func=_pkg_cmd)
403
+
404
+ #
399
405
 
400
406
  return parser
401
407
 
@@ -3978,7 +3978,7 @@ untracked file, this is reported as ? as well.
3978
3978
  """ # noqa
3979
3979
 
3980
3980
 
3981
- class GitStatusLineState(enum.Enum):
3981
+ class GitStatusState(enum.Enum):
3982
3982
  UNMODIFIED = ' '
3983
3983
  MODIFIED = 'M'
3984
3984
  FILE_TYPE_CHANGED = 'T'
@@ -3992,16 +3992,16 @@ class GitStatusLineState(enum.Enum):
3992
3992
  SUBMODULE_MODIFIED_CONTENT = 'm'
3993
3993
 
3994
3994
 
3995
- _EXTRA_UNMERGED_GIT_STATUS_LINE_STATES: ta.FrozenSet[ta.Tuple[GitStatusLineState, GitStatusLineState]] = frozenset([
3996
- (GitStatusLineState.ADDED, GitStatusLineState.ADDED),
3997
- (GitStatusLineState.DELETED, GitStatusLineState.DELETED),
3995
+ _EXTRA_UNMERGED_GIT_STATUS_STATES: ta.FrozenSet[ta.Tuple[GitStatusState, GitStatusState]] = frozenset([
3996
+ (GitStatusState.ADDED, GitStatusState.ADDED),
3997
+ (GitStatusState.DELETED, GitStatusState.DELETED),
3998
3998
  ])
3999
3999
 
4000
4000
 
4001
4001
  @dc.dataclass(frozen=True)
4002
- class GitStatusLine:
4003
- x: GitStatusLineState
4004
- y: GitStatusLineState
4002
+ class GitStatusItem:
4003
+ x: GitStatusState
4004
+ y: GitStatusState
4005
4005
 
4006
4006
  a: str
4007
4007
  b: ta.Optional[str]
@@ -4009,9 +4009,9 @@ class GitStatusLine:
4009
4009
  @property
4010
4010
  def is_unmerged(self) -> bool:
4011
4011
  return (
4012
- self.x is GitStatusLineState.UPDATED_BUT_UNMERGED or
4013
- self.y is GitStatusLineState.UPDATED_BUT_UNMERGED or
4014
- (self.x, self.y) in _EXTRA_UNMERGED_GIT_STATUS_LINE_STATES
4012
+ self.x is GitStatusState.UPDATED_BUT_UNMERGED or
4013
+ self.y is GitStatusState.UPDATED_BUT_UNMERGED or
4014
+ (self.x, self.y) in _EXTRA_UNMERGED_GIT_STATUS_STATES
4015
4015
  )
4016
4016
 
4017
4017
  def __repr__(self) -> str:
@@ -4025,7 +4025,7 @@ class GitStatusLine:
4025
4025
  )
4026
4026
 
4027
4027
 
4028
- def parse_git_status_line(l: str) -> GitStatusLine:
4028
+ def parse_git_status_line(l: str) -> GitStatusItem:
4029
4029
  if len(l) < 3 or l[2] != ' ':
4030
4030
  raise ValueError(l)
4031
4031
  x, y = l[0], l[1]
@@ -4039,25 +4039,25 @@ def parse_git_status_line(l: str) -> GitStatusLine:
4039
4039
  else:
4040
4040
  raise ValueError(l)
4041
4041
 
4042
- return GitStatusLine(
4043
- GitStatusLineState(x),
4044
- GitStatusLineState(y),
4042
+ return GitStatusItem(
4043
+ GitStatusState(x),
4044
+ GitStatusState(y),
4045
4045
  a,
4046
4046
  b,
4047
4047
  )
4048
4048
 
4049
4049
 
4050
- class GitStatus(ta.Sequence[GitStatusLine]):
4051
- def __init__(self, lines: ta.Iterable[GitStatusLine]) -> None:
4050
+ class GitStatus(ta.Sequence[GitStatusItem]):
4051
+ def __init__(self, lines: ta.Iterable[GitStatusItem]) -> None:
4052
4052
  super().__init__()
4053
4053
 
4054
4054
  self._lst = list(lines)
4055
4055
 
4056
- by_x: ta.Dict[GitStatusLineState, list[GitStatusLine]] = {}
4057
- by_y: ta.Dict[GitStatusLineState, list[GitStatusLine]] = {}
4056
+ by_x: ta.Dict[GitStatusState, list[GitStatusItem]] = {}
4057
+ by_y: ta.Dict[GitStatusState, list[GitStatusItem]] = {}
4058
4058
 
4059
- by_a: ta.Dict[str, GitStatusLine] = {}
4060
- by_b: ta.Dict[str, GitStatusLine] = {}
4059
+ by_a: ta.Dict[str, GitStatusItem] = {}
4060
+ by_b: ta.Dict[str, GitStatusItem] = {}
4061
4061
 
4062
4062
  for l in self._lst:
4063
4063
  by_x.setdefault(l.x, []).append(l)
@@ -4082,7 +4082,7 @@ class GitStatus(ta.Sequence[GitStatusLine]):
4082
4082
 
4083
4083
  #
4084
4084
 
4085
- def __iter__(self) -> ta.Iterator[GitStatusLine]:
4085
+ def __iter__(self) -> ta.Iterator[GitStatusItem]:
4086
4086
  return iter(self._lst)
4087
4087
 
4088
4088
  def __getitem__(self, index):
@@ -4094,19 +4094,19 @@ class GitStatus(ta.Sequence[GitStatusLine]):
4094
4094
  #
4095
4095
 
4096
4096
  @property
4097
- def by_x(self) -> ta.Mapping[GitStatusLineState, ta.Sequence[GitStatusLine]]:
4097
+ def by_x(self) -> ta.Mapping[GitStatusState, ta.Sequence[GitStatusItem]]:
4098
4098
  return self._by_x
4099
4099
 
4100
4100
  @property
4101
- def by_y(self) -> ta.Mapping[GitStatusLineState, ta.Sequence[GitStatusLine]]:
4101
+ def by_y(self) -> ta.Mapping[GitStatusState, ta.Sequence[GitStatusItem]]:
4102
4102
  return self._by_y
4103
4103
 
4104
4104
  @property
4105
- def by_a(self) -> ta.Mapping[str, GitStatusLine]:
4105
+ def by_a(self) -> ta.Mapping[str, GitStatusItem]:
4106
4106
  return self._by_a
4107
4107
 
4108
4108
  @property
4109
- def by_b(self) -> ta.Mapping[str, GitStatusLine]:
4109
+ def by_b(self) -> ta.Mapping[str, GitStatusItem]:
4110
4110
  return self._by_b
4111
4111
 
4112
4112
  #
@@ -4117,11 +4117,11 @@ class GitStatus(ta.Sequence[GitStatusLine]):
4117
4117
 
4118
4118
  @property
4119
4119
  def has_staged(self) -> bool:
4120
- return any(l.x != GitStatusLineState.UNMODIFIED for l in self._lst)
4120
+ return any(l.x != GitStatusState.UNMODIFIED for l in self._lst)
4121
4121
 
4122
4122
  @property
4123
4123
  def has_dirty(self) -> bool:
4124
- return any(l.y != GitStatusLineState.UNMODIFIED for l in self._lst)
4124
+ return any(l.y != GitStatusState.UNMODIFIED for l in self._lst)
4125
4125
 
4126
4126
 
4127
4127
  def parse_git_status(s: str) -> GitStatus:
@@ -5977,20 +5977,26 @@ def _build_parser() -> argparse.ArgumentParser:
5977
5977
 
5978
5978
  subparsers = parser.add_subparsers()
5979
5979
 
5980
- parser_resolve = subparsers.add_parser('venv')
5981
- parser_resolve.add_argument('name')
5982
- parser_resolve.add_argument('-e', '--docker-env', action='append')
5983
- parser_resolve.add_argument('cmd', nargs='?')
5984
- parser_resolve.add_argument('args', nargs=argparse.REMAINDER)
5985
- parser_resolve.set_defaults(func=_venv_cmd)
5986
-
5987
- parser_resolve = subparsers.add_parser('pkg')
5988
- parser_resolve.add_argument('-b', '--build', action='store_true')
5989
- parser_resolve.add_argument('-r', '--revision', action='store_true')
5990
- parser_resolve.add_argument('-j', '--jobs', type=int)
5991
- parser_resolve.add_argument('cmd', nargs='?')
5992
- parser_resolve.add_argument('args', nargs=argparse.REMAINDER)
5993
- parser_resolve.set_defaults(func=_pkg_cmd)
5980
+ #
5981
+
5982
+ parser_venv = subparsers.add_parser('venv')
5983
+ parser_venv.add_argument('name')
5984
+ parser_venv.add_argument('-e', '--docker-env', action='append')
5985
+ parser_venv.add_argument('cmd', nargs='?')
5986
+ parser_venv.add_argument('args', nargs=argparse.REMAINDER)
5987
+ parser_venv.set_defaults(func=_venv_cmd)
5988
+
5989
+ #
5990
+
5991
+ parser_pkg = subparsers.add_parser('pkg')
5992
+ parser_pkg.add_argument('-b', '--build', action='store_true')
5993
+ parser_pkg.add_argument('-r', '--revision', action='store_true')
5994
+ parser_pkg.add_argument('-j', '--jobs', type=int)
5995
+ parser_pkg.add_argument('cmd', nargs='?')
5996
+ parser_pkg.add_argument('args', nargs=argparse.REMAINDER)
5997
+ parser_pkg.set_defaults(func=_pkg_cmd)
5998
+
5999
+ #
5994
6000
 
5995
6001
  return parser
5996
6002
 
omdev/tools/git.py CHANGED
@@ -10,7 +10,7 @@ from omlish import logs
10
10
  from omlish.formats import json
11
11
 
12
12
  from ..cli import CliModule
13
- from ..git import GitStatusLine
13
+ from ..git import GitStatusItem
14
14
  from ..git import get_git_status
15
15
 
16
16
 
@@ -134,24 +134,24 @@ class Cli(ap.Cli):
134
134
  def status(self) -> None:
135
135
  st = get_git_status()
136
136
 
137
- def gsl_dct(gsl: GitStatusLine) -> ta.Mapping[str, ta.Any]:
137
+ def gsi_dct(gsi: GitStatusItem) -> ta.Mapping[str, ta.Any]:
138
138
  return {
139
- 'x': gsl.x.name,
140
- 'y': gsl.y.name,
141
- 'a': gsl.a,
142
- **({'b': gsl.b} if gsl.b is not None else {}),
139
+ 'x': gsi.x.name.lower(),
140
+ 'y': gsi.y.name.lower(),
141
+ 'a': gsi.a,
142
+ **({'b': gsi.b} if gsi.b is not None else {}),
143
143
  }
144
144
 
145
- def gsl_dct_lst(gsls: ta.Iterable[GitStatusLine]) -> ta.Sequence[ta.Mapping[str, ta.Any]]:
146
- return [gsl_dct(gsl) for gsl in sorted(gsls, key=lambda gsl: gsl.a)]
145
+ def gsi_dct_lst(gsis: ta.Iterable[GitStatusItem]) -> ta.Sequence[ta.Mapping[str, ta.Any]]:
146
+ return [gsi_dct(gsi) for gsi in sorted(gsis, key=lambda gsi: gsi.a)]
147
147
 
148
148
  if self.args.verbose:
149
149
  dct = {
150
- 'by_x': {x.name: gsl_dct_lst(lst) for x, lst in st.by_x.items()},
151
- 'by_y': {y.name: gsl_dct_lst(lst) for y, lst in st.by_x.items()},
150
+ 'by_x': {x.name.lower(): gsi_dct_lst(lst) for x, lst in st.by_x.items()},
151
+ 'by_y': {y.name.lower(): gsi_dct_lst(lst) for y, lst in st.by_x.items()},
152
152
 
153
- 'by_a': {a: gsl_dct(gsl) for a, gsl in sorted(st.by_a.items(), key=lambda t: t[0])},
154
- 'by_b': {b: gsl_dct(gsl) for b, gsl in sorted(st.by_b.items(), key=lambda t: t[0])},
153
+ 'by_a': {a: gsi_dct(gsi) for a, gsi in sorted(st.by_a.items(), key=lambda t: t[0])},
154
+ 'by_b': {b: gsi_dct(gsi) for b, gsi in sorted(st.by_b.items(), key=lambda t: t[0])},
155
155
 
156
156
  'has_unmerged': st.has_unmerged,
157
157
  'has_staged': st.has_staged,
@@ -161,7 +161,7 @@ class Cli(ap.Cli):
161
161
  print(json.dumps_pretty(dct))
162
162
 
163
163
  else:
164
- print(json.dumps_pretty([gsl_dct(gsl) for gsl in st]))
164
+ print(json.dumps_pretty([gsi_dct(gsi) for gsi in st]))
165
165
 
166
166
  @ap.command(
167
167
  ap.arg('-m', '--message', default='--'),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omdev
3
- Version: 0.0.0.dev114
3
+ Version: 0.0.0.dev115
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.dev114
15
+ Requires-Dist: omlish ==0.0.0.dev115
16
16
  Provides-Extra: all
17
17
  Requires-Dist: black ~=24.10 ; extra == 'all'
18
18
  Requires-Dist: pycparser ~=2.22 ; extra == 'all'
@@ -1,13 +1,13 @@
1
- omdev/.manifests.json,sha256=asjeEXptONz5RkbuMIgHMDGB8QlWRazdWpFEVMznbPM,7479
1
+ omdev/.manifests.json,sha256=mSpMkoQh9IOKLSsixXby-ZC6cGmi6giOt5oZsd5w_AM,7479
2
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
6
6
  omdev/cmake.py,sha256=Diy2ry65806dQP125DAstD3w46z_wszMH7PwC2-6iik,4578
7
7
  omdev/findimports.py,sha256=2t8QP852saEEJFeXySEzhi_nxRSxghlkXz2jVdvy08M,2392
8
- omdev/git.py,sha256=B3gnqL75OZqwMvANdZL3cyah6izdM5bZfPJhG134lD0,10520
8
+ omdev/git.py,sha256=J2EqU8iZvldGD85X5nIYj6ARiedsFZFMuV2L66f8kSQ,10434
9
9
  omdev/imgur.py,sha256=il12R3t19tALolteYCZywvcdQUEOcgvPyUYgWtKiqt4,2993
10
- omdev/pip.py,sha256=gRg07NCEjTquOQwnKKgXqfn_YGElO5Pi7hmrAh-AVvQ,2105
10
+ omdev/pip.py,sha256=7cZ_IOpekQvgPm_gKnX3Pr8xjqUid50PPScTlZCYVlM,2118
11
11
  omdev/revisions.py,sha256=U657hf4zeEN32y3g4CzqCAodx_HlfkHj2cIIKALNFDo,5009
12
12
  omdev/secrets.py,sha256=bcquaBIDKqX4UIKOzUuKrX7nxVCenj67rRHIMIrd9bk,540
13
13
  omdev/tokens.py,sha256=GusxQ1Cd_eiScuR8XTTtc9QFhOgYviYGBZmFnn3Hj7s,756
@@ -18,7 +18,6 @@ omdev/amalg/amalg.py,sha256=b5lo2EZno62_5HbQV-TSMcsLe5ztm4vz3QrJ1-h_ppo,15140
18
18
  omdev/antlr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  omdev/antlr/consts.py,sha256=8pR6r0m0P3hAiyiAoJZ-nptd2GYbZ98mxwPL9cpaRuw,279
20
20
  omdev/antlr/gen.py,sha256=QnPyVWUrJYqHoOc3XsXA8fJdoiwAj6pyUwdG-DVrIeA,2953
21
- omdev/antlr/_antlr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
21
  omdev/cache/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
22
  omdev/cache/compute/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
23
  omdev/cache/compute/cache.py,sha256=FA6tZWoQpE8D8Os3abdtfT90juzkqBmESjJE3WQXZtQ,3623
@@ -61,14 +60,15 @@ omdev/cexts/_distutils/compilers/unixccompiler.py,sha256=o1h8QuyupLntv4F21_XjzAZ
61
60
  omdev/cli/__init__.py,sha256=V_l6VP1SZMlJbO-8CJwSuO9TThOy2S_oaPepNYgIrbE,37
62
61
  omdev/cli/__main__.py,sha256=mOJpgc07o0r5luQ1DlX4tk2PqZkgmbwPbdzJ3KmtjgQ,138
63
62
  omdev/cli/_pathhack.py,sha256=kxqb2kHap68Lkh8b211rDbcgj06hidBiAKA3f9posyc,2119
64
- omdev/cli/clicli.py,sha256=OOxlCg7yoV1f8X9MUzl-k26p3PRSqJmGD6TrimYPFv8,2923
63
+ omdev/cli/clicli.py,sha256=K_3OgtB6sIBbzT-E6Uq-wM9vfoNgI3B0JmWzPU7v24E,2934
65
64
  omdev/cli/install.py,sha256=C-W171YlIHt4Cfok-nWSMbHwWhqF_PFqq2HixFttYx8,4460
66
- omdev/cli/main.py,sha256=nD3bW3MkI0KuDSLpX_PTnl-lBnm4hIxVqczvvMHtupo,7058
65
+ omdev/cli/main.py,sha256=p00ZoNIOlQW6GjyzryoIweQnC-a8tDx59S8EQYJ4uLY,7028
67
66
  omdev/cli/managers.py,sha256=BV98_n30Jj63OJrFgRoVZRfICxMLXEZKoEn4rMj9LV4,1160
68
67
  omdev/cli/types.py,sha256=bqKw9SbtBtAip2vF9v4khh0CqKG6LBr6n9VzWBz7AJE,474
69
68
  omdev/clipboard/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- omdev/clipboard/clipboard.py,sha256=CmnozkRljJ9UQDHLfCS8wKU0Xg-HfbsAkagAfMEias0,567
71
- omdev/clipboard/darwin.py,sha256=zKPmI4mdTTo5ixbOVIBt6OnZE6BrpXgTPf0Tgz_-ds0,7556
69
+ omdev/clipboard/clipboard.py,sha256=9HFpcijpn0XDTI89ZRm2WA1G7O4HsTdVXZHqMULu3N0,1630
70
+ omdev/clipboard/darwin_cf.py,sha256=SDUMfQtT_IJeDEwmsnxe6YyrZS5tPh_7ujkk1dg65Hg,7688
71
+ omdev/clipboard/linux_x.py,sha256=oa-mxMRNaZJOdBAZ8Nki-CAGIb63X8OFUTXKjmiwfSo,6718
72
72
  omdev/interp/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
73
73
  omdev/interp/__main__.py,sha256=GMCqeGYltgt5dlJzHxY9gqisa8cRkrPfmZYuZnjg4WI,162
74
74
  omdev/interp/cli.py,sha256=sh7PZQoLletUViw1Y9OXNr9ekyNZ6YyxYuOQ_n9hyqU,2072
@@ -109,11 +109,11 @@ omdev/ptk/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
109
  omdev/ptk/apps/ncdu.py,sha256=dOkEJoc2Wjv1u_Uge7Vpei_LvXldoPP5833Eia355tc,4548
110
110
  omdev/pycharm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
111
  omdev/pycharm/__main__.py,sha256=hUPp11D024eMdT86BxXiRVtF7AGBk5W6Zn8_mEHSksY,163
112
- omdev/pycharm/cli.py,sha256=WyUlFuG4jAmd7pB5tnZJ54FH1y1orDX3sjB1EWgbmmQ,2343
112
+ omdev/pycharm/cli.py,sha256=gfAgBL3REb3hmtRRRck18mCDGwQQ4kDLhYuP1CP66rY,2478
113
113
  omdev/pyproject/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
114
114
  omdev/pyproject/__main__.py,sha256=gn3Rl1aYPYdiTtEqa9ifi0t-e4ZwPY0vhJ4UXvYdJDY,165
115
115
  omdev/pyproject/cexts.py,sha256=x13piOOnNrYbA17qZLDVuR0p1sqhgEwpk4FtImX-klM,4281
116
- omdev/pyproject/cli.py,sha256=kw0Jyzywwt6QOc6QHDevWW9p85aXT7jvVFFb8Sb_EAU,11365
116
+ omdev/pyproject/cli.py,sha256=U2pOOqXvqw8RbdcgKryv-MUeHT6QqSwL-dhnDjgyz0U,11340
117
117
  omdev/pyproject/configs.py,sha256=K9H5cGwVLgHi8wKwtYvlXHZ9ThtmnI4jo8JAb-t1-70,2859
118
118
  omdev/pyproject/pkg.py,sha256=WB9k3zEpHSAR24H09kikgAnLMWUz-bk9f0aB-2L_ITw,14560
119
119
  omdev/pyproject/reqs.py,sha256=8feZ71YnGzwKbLK4zO28CDQeNcZIIuq6cnkBhs6M-7E,2406
@@ -123,7 +123,7 @@ omdev/scripts/execrss.py,sha256=mR0G0wERBYtQmVIn63lCIIFb5zkCM6X_XOENDFYDBKc,651
123
123
  omdev/scripts/exectime.py,sha256=sFb376GflU6s9gNX-2-we8hgH6w5MuQNS9g6i4SqJIo,610
124
124
  omdev/scripts/importtrace.py,sha256=Jbo3Yk2RAbE8_tJ97iTcVNpoxCJxrRb2tl1W_CV3NG0,14067
125
125
  omdev/scripts/interp.py,sha256=U6mU2RPZjwcBhn4Vl4SrAyDUFcf7bBxBnPY5FHCxosw,72496
126
- omdev/scripts/pyproject.py,sha256=e2Ncxiju1GinYaXa_PJ3qAyiOApWepS-_uWjcKcJwtw,173682
126
+ omdev/scripts/pyproject.py,sha256=a1qGCJCkvvZX-cwlqVOsf2kBaBRqQIEb9fQN-zEhH_Y,173571
127
127
  omdev/scripts/slowcat.py,sha256=lssv4yrgJHiWfOiHkUut2p8E8Tq32zB-ujXESQxFFHY,2728
128
128
  omdev/scripts/tmpexec.py,sha256=WTYcf56Tj2qjYV14AWmV8SfT0u6Y8eIU6cKgQRvEK3c,1442
129
129
  omdev/toml/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
@@ -132,7 +132,7 @@ omdev/toml/writer.py,sha256=lk3on3YXVbWuLJa-xsOzOhs1bBAT1vXqw4mBbluZl_w,3040
132
132
  omdev/tools/__init__.py,sha256=iVJAOQ0viGTQOm0DLX4uZLro-9jOioYJGLg9s0kDx1A,78
133
133
  omdev/tools/doc.py,sha256=mv9XfitzqXl3vFHSenv01xHCxWf8g03rUAb_sqoty98,2556
134
134
  omdev/tools/docker.py,sha256=k2BrVvFYwyGov064CPHd_HWo9aqR1zHc2UeEsVwPth4,6827
135
- omdev/tools/git.py,sha256=sj3I8chXVzcZQyBIP8trq5_96EOXNTmu5YPOWePkR9A,5995
135
+ omdev/tools/git.py,sha256=AXNZDM-VtpC0ePJKtkjxJi_X9hUyobKrX9WSBOocmzY,6027
136
136
  omdev/tools/importscan.py,sha256=QeGjR3UGcuuuDUiisFuAXWHlcKJScGxGEcU6tfOh2CM,4069
137
137
  omdev/tools/mkrelimp.py,sha256=wsJAjTIf3nqcSfnT9TkDpS1VUOoM9W2Az5tZdWuzyLM,4054
138
138
  omdev/tools/notebook.py,sha256=M8Xi_gfZdlahnyFLtp0RBgYZPSHWQStMMDYZc71Zync,3494
@@ -143,9 +143,9 @@ omdev/tools/sqlrepl.py,sha256=tmFZh80-xsGM62dyQ7_UGLebChrj7IHbIPYBWDJMgVk,5741
143
143
  omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
144
144
  omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
145
145
  omdev/tools/pawk/pawk.py,sha256=Eckymn22GfychCQcQi96BFqRo_LmiJ-EPhC8TTUJdB4,11446
146
- omdev-0.0.0.dev114.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
147
- omdev-0.0.0.dev114.dist-info/METADATA,sha256=AuvmLYtU1KklORHYLnpp8MhgEiwN4CPvzsiuxKhdwkQ,1810
148
- omdev-0.0.0.dev114.dist-info/WHEEL,sha256=a7TGlA-5DaHMRrarXjVbQagU3Man_dCnGIWMJr5kRWo,91
149
- omdev-0.0.0.dev114.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
150
- omdev-0.0.0.dev114.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
151
- omdev-0.0.0.dev114.dist-info/RECORD,,
146
+ omdev-0.0.0.dev115.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
147
+ omdev-0.0.0.dev115.dist-info/METADATA,sha256=fgJ9LOYnfKey8bhvfz6se4nT582TnO8jD3p6zdXBtCg,1810
148
+ omdev-0.0.0.dev115.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
149
+ omdev-0.0.0.dev115.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
150
+ omdev-0.0.0.dev115.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
151
+ omdev-0.0.0.dev115.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.4.0)
2
+ Generator: setuptools (75.5.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
File without changes