omdev 0.0.0.dev80__tar.gz → 0.0.0.dev82__tar.gz

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.

Files changed (140) hide show
  1. {omdev-0.0.0.dev80/omdev.egg-info → omdev-0.0.0.dev82}/PKG-INFO +2 -2
  2. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/.manifests.json +12 -0
  3. omdev-0.0.0.dev82/omdev/clipboard/clipboard.py +23 -0
  4. omdev-0.0.0.dev82/omdev/clipboard/darwin.py +229 -0
  5. omdev-0.0.0.dev82/omdev/precheck/__init__.py +0 -0
  6. omdev-0.0.0.dev82/omdev/scripts/slowcat.py +121 -0
  7. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82/omdev.egg-info}/PKG-INFO +2 -2
  8. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev.egg-info/SOURCES.txt +4 -0
  9. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev.egg-info/requires.txt +1 -1
  10. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/pyproject.toml +2 -2
  11. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/LICENSE +0 -0
  12. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/MANIFEST.in +0 -0
  13. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/README.rst +0 -0
  14. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/__about__.py +0 -0
  15. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/__init__.py +0 -0
  16. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/amalg/__init__.py +0 -0
  17. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/amalg/__main__.py +0 -0
  18. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/amalg/amalg.py +0 -0
  19. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/antlr/__init__.py +0 -0
  20. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/antlr/_antlr/__init__.py +0 -0
  21. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/antlr/consts.py +0 -0
  22. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/antlr/gen.py +0 -0
  23. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/bracepy.py +0 -0
  24. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/__init__.py +0 -0
  25. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/compute/__init__.py +0 -0
  26. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/compute/cache.py +0 -0
  27. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/compute/contexts.py +0 -0
  28. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/compute/currents.py +0 -0
  29. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/compute/fns.py +0 -0
  30. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/compute/resolvers.py +0 -0
  31. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/compute/storage.py +0 -0
  32. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/compute/types.py +0 -0
  33. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/data/__init__.py +0 -0
  34. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/data/actions.py +0 -0
  35. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/data/cache.py +0 -0
  36. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/data/consts.py +0 -0
  37. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/data/defaults.py +0 -0
  38. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/data/manifests.py +0 -0
  39. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cache/data/specs.py +0 -0
  40. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/__init__.py +0 -0
  41. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_boilerplate.cc +0 -0
  42. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/LICENSE +0 -0
  43. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/__init__.py +0 -0
  44. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/build_ext.py +0 -0
  45. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
  46. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
  47. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/compilers/options.py +0 -0
  48. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
  49. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/dir_util.py +0 -0
  50. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/errors.py +0 -0
  51. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/extension.py +0 -0
  52. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/file_util.py +0 -0
  53. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/modified.py +0 -0
  54. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/spawn.py +0 -0
  55. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/sysconfig.py +0 -0
  56. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/util.py +0 -0
  57. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/_distutils/version.py +0 -0
  58. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/build.py +0 -0
  59. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/cmake.py +0 -0
  60. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/importhook.py +0 -0
  61. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/magic.py +0 -0
  62. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cexts/scan.py +0 -0
  63. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/classdot.py +0 -0
  64. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cli/__init__.py +0 -0
  65. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cli/__main__.py +0 -0
  66. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cli/_pathhack.py +0 -0
  67. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cli/clicli.py +0 -0
  68. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cli/install.py +0 -0
  69. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cli/main.py +0 -0
  70. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cli/managers.py +0 -0
  71. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cli/types.py +0 -0
  72. {omdev-0.0.0.dev80/omdev/mypy → omdev-0.0.0.dev82/omdev/clipboard}/__init__.py +0 -0
  73. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/cmake.py +0 -0
  74. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/findimports.py +0 -0
  75. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/findmagic.py +0 -0
  76. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/git.py +0 -0
  77. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/imgur.py +0 -0
  78. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/interp/__init__.py +0 -0
  79. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/interp/__main__.py +0 -0
  80. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/interp/cli.py +0 -0
  81. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/interp/inspect.py +0 -0
  82. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/interp/providers.py +0 -0
  83. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/interp/pyenv.py +0 -0
  84. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/interp/resolvers.py +0 -0
  85. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/interp/standalone.py +0 -0
  86. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/interp/system.py +0 -0
  87. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/interp/types.py +0 -0
  88. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/manifests/__init__.py +0 -0
  89. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/manifests/build.py +0 -0
  90. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/manifests/load.py +0 -0
  91. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/manifests/types.py +0 -0
  92. {omdev-0.0.0.dev80/omdev/precheck → omdev-0.0.0.dev82/omdev/mypy}/__init__.py +0 -0
  93. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/mypy/debug.py +0 -0
  94. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/packaging/__init__.py +0 -0
  95. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/packaging/names.py +0 -0
  96. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/packaging/requires.py +0 -0
  97. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/packaging/specifiers.py +0 -0
  98. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/packaging/versions.py +0 -0
  99. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/precheck/__main__.py +0 -0
  100. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/precheck/base.py +0 -0
  101. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/precheck/git.py +0 -0
  102. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/precheck/lite.py +0 -0
  103. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/precheck/main.py +0 -0
  104. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/precheck/manifests.py +0 -0
  105. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/precheck/scripts.py +0 -0
  106. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/pyproject/__init__.py +0 -0
  107. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/pyproject/__main__.py +0 -0
  108. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/pyproject/cexts.py +0 -0
  109. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/pyproject/cli.py +0 -0
  110. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/pyproject/configs.py +0 -0
  111. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/pyproject/pkg.py +0 -0
  112. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/pyproject/reqs.py +0 -0
  113. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/revisions.py +0 -0
  114. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/scripts/__init__.py +0 -0
  115. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/scripts/bumpversion.py +0 -0
  116. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/scripts/execrss.py +0 -0
  117. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/scripts/exectime.py +0 -0
  118. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/scripts/importtrace.py +0 -0
  119. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/scripts/interp.py +0 -0
  120. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/scripts/pyproject.py +0 -0
  121. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/secrets.py +0 -0
  122. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tokens.py +0 -0
  123. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/toml/__init__.py +0 -0
  124. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/toml/parser.py +0 -0
  125. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/toml/writer.py +0 -0
  126. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tools/__init__.py +0 -0
  127. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tools/dockertools.py +0 -0
  128. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tools/gittools.py +0 -0
  129. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tools/importscan.py +0 -0
  130. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tools/mkrelimp.py +0 -0
  131. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tools/nbtools.py +0 -0
  132. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tools/piptools.py +0 -0
  133. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tools/proftools.py +0 -0
  134. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tools/rsttool.py +0 -0
  135. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/tools/sqlrepl.py +0 -0
  136. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev/wheelfile.py +0 -0
  137. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev.egg-info/dependency_links.txt +0 -0
  138. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev.egg-info/entry_points.txt +0 -0
  139. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/omdev.egg-info/top_level.txt +0 -0
  140. {omdev-0.0.0.dev80 → omdev-0.0.0.dev82}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omdev
3
- Version: 0.0.0.dev80
3
+ Version: 0.0.0.dev82
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.dev80
15
+ Requires-Dist: omlish==0.0.0.dev82
16
16
  Provides-Extra: all
17
17
  Requires-Dist: black~=24.10; extra == "all"
18
18
  Requires-Dist: pycparser~=2.22; extra == "all"
@@ -167,6 +167,18 @@
167
167
  }
168
168
  }
169
169
  },
170
+ {
171
+ "module": ".scripts.slowcat",
172
+ "attr": "_CLI_MODULE",
173
+ "file": "omdev/scripts/slowcat.py",
174
+ "line": 113,
175
+ "value": {
176
+ "$.cli.types.CliModule": {
177
+ "cmd_name": "slowcat",
178
+ "mod_name": "omdev.scripts.slowcat"
179
+ }
180
+ }
181
+ },
170
182
  {
171
183
  "module": ".tools.dockertools",
172
184
  "attr": "_CLI_MODULE",
@@ -0,0 +1,23 @@
1
+ """
2
+ https://askubuntu.com/questions/11925/a-command-line-clipboard-copy-and-paste-utility
3
+ """
4
+ import abc
5
+ import subprocess
6
+
7
+
8
+ class Clipboard(abc.ABC):
9
+ @abc.abstractmethod
10
+ def get(self) -> str:
11
+ raise NotImplementedError
12
+
13
+ @abc.abstractmethod
14
+ def put(self, s: str) -> None:
15
+ raise NotImplementedError
16
+
17
+
18
+ class DarwinClipboard(Clipboard):
19
+ def get(self) -> str:
20
+ return subprocess.check_output(['pbpaste']).decode('utf-8')
21
+
22
+ def put(self, s: str) -> None:
23
+ subprocess.run(['pbcopy'], input=s.encode('utf-8'), check=True)
@@ -0,0 +1,229 @@
1
+ # ruff: noqa: N802 N816
2
+ import ctypes as ct
3
+ import ctypes.util
4
+ import dataclasses as dc
5
+ import sys
6
+ import typing as ta
7
+
8
+ from omlish import check
9
+
10
+
11
+ ##
12
+
13
+
14
+ if getattr(sys, 'platform') != 'darwin':
15
+ raise OSError(sys.platform)
16
+
17
+
18
+ ##
19
+ # CoreFoundation
20
+
21
+ cf = ct.cdll.LoadLibrary(check.not_none(ct.util.find_library('CoreFoundation')))
22
+
23
+ #
24
+
25
+ CFArrayRef = ct.c_void_p
26
+ CFDataRef = ct.c_void_p
27
+ CFIndex = ct.c_long
28
+ CFStringEncoding = ct.c_uint32
29
+ CFStringRef = ct.c_void_p
30
+ CFTypeID = ct.c_ulong
31
+
32
+ #
33
+
34
+ cf.CFArrayGetCount.argtypes = [CFArrayRef]
35
+ cf.CFArrayGetCount.restype = CFIndex
36
+
37
+ cf.CFArrayGetValueAtIndex.argtypes = [CFArrayRef, CFIndex]
38
+ cf.CFArrayGetValueAtIndex.restype = CFStringRef
39
+
40
+ cf.CFDataGetBytePtr.argtypes = [CFDataRef]
41
+ cf.CFDataGetBytePtr.restype = ct.POINTER(ct.c_uint8)
42
+
43
+ cf.CFDataGetLength.argtypes = [CFDataRef]
44
+ cf.CFDataGetLength.restype = CFIndex
45
+
46
+ cf.CFGetTypeID.argtypes = [ct.c_void_p]
47
+ cf.CFGetTypeID.restype = CFTypeID
48
+
49
+ cf.CFRelease.argtypes = [ct.c_void_p]
50
+ cf.CFRelease.restype = None
51
+
52
+ cf.CFStringCreateWithCString.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_int32]
53
+ cf.CFStringCreateWithCString.restype = CFStringRef
54
+
55
+ cf.CFStringGetCString.argtypes = [CFStringRef, ct.c_char_p, ct.c_long, ct.c_uint32]
56
+ cf.CFStringGetCString.restype = ct.c_bool
57
+
58
+ cf.CFStringGetLength.argtypes = [CFStringRef]
59
+ cf.CFStringGetLength.restype = CFIndex
60
+
61
+ cf.CFStringGetMaximumSizeForEncoding.argtypes = [CFIndex, CFStringEncoding]
62
+ cf.CFStringGetMaximumSizeForEncoding.restype = CFIndex
63
+
64
+ cf.CFStringGetTypeID.argtypes = []
65
+ cf.CFStringGetTypeID.restype = CFTypeID
66
+
67
+
68
+ ##
69
+ # ApplicationServices
70
+
71
+ aps = ct.cdll.LoadLibrary(check.not_none(ct.util.find_library('ApplicationServices')))
72
+
73
+ #
74
+
75
+ OSStatus = ct.c_int32
76
+
77
+ PasteboardItemID = ct.c_ulong
78
+ PasteboardRef = ct.c_void_p
79
+
80
+ #
81
+
82
+ aps.PasteboardCopyItemFlavorData.argtypes = [PasteboardRef, PasteboardItemID, CFStringRef, ct.POINTER(CFDataRef)]
83
+ aps.PasteboardCopyItemFlavorData.restype = OSStatus
84
+
85
+ aps.PasteboardCopyItemFlavors.argtypes = [PasteboardRef, PasteboardItemID, ct.POINTER(CFArrayRef)]
86
+ aps.PasteboardCopyItemFlavors.restype = OSStatus
87
+
88
+ aps.PasteboardCreate.argtypes = [CFStringRef, ct.POINTER(PasteboardRef)]
89
+ aps.PasteboardCreate.restype = OSStatus
90
+
91
+ aps.PasteboardGetItemCount.argtypes = [PasteboardRef, ct.POINTER(ct.c_ulong)]
92
+ aps.PasteboardGetItemCount.restype = OSStatus
93
+
94
+ aps.PasteboardGetItemIdentifier.argtypes = [PasteboardRef, ct.c_ulong, ct.POINTER(PasteboardItemID)]
95
+ aps.PasteboardGetItemIdentifier.restype = OSStatus
96
+
97
+
98
+ ##
99
+
100
+
101
+ def CFSTR(string):
102
+ return cf.CFStringCreateWithCString(None, string.encode('utf-8'), 0)
103
+
104
+
105
+ kCFStringEncodingUTF8 = 0x08000100
106
+ kPasteboardClipboard = CFSTR('com.apple.pasteboard.clipboard')
107
+
108
+
109
+ def cfstring_to_string(cf_string: CFStringRef) -> str:
110
+ if not cf_string:
111
+ return ''
112
+
113
+ length = cf.CFStringGetLength(cf_string)
114
+ max_size = cf.CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1
115
+ buffer = ct.create_string_buffer(max_size)
116
+
117
+ if success := cf.CFStringGetCString(cf_string, buffer, max_size, kCFStringEncodingUTF8): # noqa
118
+ return ''
119
+
120
+ return buffer.value.decode('utf-8')
121
+
122
+
123
+ ##
124
+
125
+
126
+ class OsxClipboardError(Exception):
127
+ pass
128
+
129
+
130
+ @dc.dataclass(frozen=True)
131
+ class StatusOsxClipboardError(OsxClipboardError):
132
+ fn: str
133
+ status: int
134
+
135
+
136
+ @dc.dataclass(frozen=True)
137
+ class OsxClipboardItem:
138
+ type: str | None
139
+ data: bytes | None
140
+
141
+
142
+ def get_osx_clipboard_data(
143
+ *,
144
+ types: ta.Container[str | None] | None = None,
145
+ strict: bool = False,
146
+ types_only: bool = False,
147
+ ) -> list[OsxClipboardItem]:
148
+ lst: list[OsxClipboardItem] = []
149
+
150
+ pasteboard = PasteboardRef()
151
+ if status := aps.PasteboardCreate(kPasteboardClipboard, ct.byref(pasteboard)):
152
+ raise StatusOsxClipboardError('PasteboardCreate', status)
153
+
154
+ try:
155
+ item_count = ct.c_ulong(0)
156
+ if status := aps.PasteboardGetItemCount(pasteboard, ct.byref(item_count)):
157
+ raise StatusOsxClipboardError('PasteboardGetItemCount', status)
158
+
159
+ for i in range(1, item_count.value + 1):
160
+ item_id = PasteboardItemID()
161
+ if status := aps.PasteboardGetItemIdentifier(pasteboard, i, ct.byref(item_id)):
162
+ raise StatusOsxClipboardError('PasteboardGetItemIdentifier', status)
163
+
164
+ data_types = CFArrayRef()
165
+ if status := aps.PasteboardCopyItemFlavors(pasteboard, item_id, ct.byref(data_types)):
166
+ raise StatusOsxClipboardError('PasteboardCopyItemFlavors', status)
167
+ if not data_types:
168
+ continue
169
+
170
+ try:
171
+ type_count = cf.CFArrayGetCount(data_types)
172
+ for j in range(type_count):
173
+ data_type = cf.CFArrayGetValueAtIndex(data_types, j)
174
+
175
+ if cf.CFGetTypeID(data_type) == cf.CFStringGetTypeID():
176
+ data_type_str = cfstring_to_string(data_type)
177
+ else:
178
+ data_type_str = None
179
+
180
+ if types is not None and data_type_str not in types:
181
+ continue
182
+
183
+ if types_only:
184
+ lst.append(OsxClipboardItem(
185
+ type=data_type_str,
186
+ data=None,
187
+ ))
188
+ continue
189
+
190
+ data = CFDataRef()
191
+ if status := aps.PasteboardCopyItemFlavorData(pasteboard, item_id, data_type, ct.byref(data)):
192
+ if not strict:
193
+ continue
194
+ raise StatusOsxClipboardError('PasteboardCopyItemFlavorData', status)
195
+ if not data:
196
+ continue
197
+
198
+ try:
199
+ data_size = cf.CFDataGetLength(data)
200
+ data_ptr = cf.CFDataGetBytePtr(data)
201
+ data_bytes = ct.string_at(data_ptr, data_size)
202
+
203
+ lst.append(OsxClipboardItem(
204
+ type=data_type_str,
205
+ data=data_bytes,
206
+ ))
207
+
208
+ finally:
209
+ cf.CFRelease(data)
210
+
211
+ finally:
212
+ cf.CFRelease(data_types)
213
+
214
+ finally:
215
+ cf.CFRelease(pasteboard)
216
+
217
+ return lst
218
+
219
+
220
+ ##
221
+
222
+
223
+ def _main() -> None:
224
+ for i in get_osx_clipboard_data():
225
+ print(i)
226
+
227
+
228
+ if __name__ == '__main__':
229
+ _main()
File without changes
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env python3
2
+ # @omlish-script
3
+ import argparse
4
+ import contextlib
5
+ import os
6
+ import random
7
+ import sys
8
+ import time
9
+ import typing as ta
10
+
11
+
12
+ T = ta.TypeVar('T')
13
+
14
+
15
+ DEFAULT_SLEEP_N = 128
16
+ DEFAULT_SLEEP_S = .5
17
+
18
+
19
+ def _main() -> None:
20
+ parser = argparse.ArgumentParser()
21
+
22
+ parser.add_argument('files', nargs='*')
23
+
24
+ parser.add_argument('-b', '--buffer-size', type=int, default=0x4000)
25
+
26
+ parser.add_argument('--initial-sleep')
27
+
28
+ parser.add_argument('--sleep-n')
29
+ parser.add_argument('--sleep-s')
30
+
31
+ args = parser.parse_args()
32
+
33
+ #
34
+
35
+ def parse_range(s: str, d: T) -> tuple[T, T]:
36
+ if not s:
37
+ return d, d
38
+ elif '-' in s:
39
+ l, r = map(type(d), s.split('-'))
40
+ return l, r
41
+ else:
42
+ l = r = type(d)(s) # type: ignore
43
+ return l, r
44
+
45
+ sleep_s_min, sleep_s_max = parse_range(args.sleep_s, DEFAULT_SLEEP_S)
46
+ sleep_n_min, sleep_n_max = parse_range(args.sleep_n, DEFAULT_SLEEP_N)
47
+
48
+ #
49
+
50
+ in_files: list
51
+ if args.files:
52
+ in_files = args.files
53
+ else:
54
+ in_files = [sys.stdin.buffer]
55
+
56
+ #
57
+
58
+ of = sys.stdout.buffer
59
+
60
+ #
61
+
62
+ def next_sleep() -> int:
63
+ if sleep_n_min != sleep_n_max:
64
+ o = random.randint(sleep_n_min, sleep_n_max)
65
+ else:
66
+ o = sleep_n_min
67
+ return n + o
68
+
69
+ def do_sleep() -> None:
70
+ if sleep_s_min != sleep_s_max:
71
+ s = random.uniform(sleep_s_min, sleep_s_max)
72
+ else:
73
+ s = sleep_s_min
74
+ time.sleep(s)
75
+
76
+ #
77
+
78
+ if args.initial_sleep:
79
+ do_sleep()
80
+
81
+ n = 0
82
+ ns = next_sleep()
83
+
84
+ for in_file in in_files:
85
+ with contextlib.ExitStack() as es:
86
+ if isinstance(in_file, str):
87
+ fo = es.enter_context(open(in_file, 'rb'))
88
+ else:
89
+ fo = in_file
90
+
91
+ fd = fo.fileno()
92
+ while buf := os.read(fd, args.buffer_size):
93
+ p = 0
94
+ while p < len(buf):
95
+ c = ns - n
96
+ r = len(buf) - p
97
+ if r >= c:
98
+ r = c
99
+ sleep = True
100
+ else:
101
+ sleep = False
102
+
103
+ of.write(buf[p:p + r])
104
+ of.flush()
105
+
106
+ n += len(buf)
107
+ p += r
108
+ if sleep:
109
+ do_sleep()
110
+ ns = next_sleep()
111
+
112
+
113
+ # @omlish-manifest
114
+ _CLI_MODULE = {'$omdev.cli.types.CliModule': {
115
+ 'cmd_name': 'slowcat',
116
+ 'mod_name': __name__,
117
+ }}
118
+
119
+
120
+ if __name__ == '__main__':
121
+ _main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omdev
3
- Version: 0.0.0.dev80
3
+ Version: 0.0.0.dev82
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.dev80
15
+ Requires-Dist: omlish==0.0.0.dev82
16
16
  Provides-Extra: all
17
17
  Requires-Dist: black~=24.10; extra == "all"
18
18
  Requires-Dist: pycparser~=2.22; extra == "all"
@@ -76,6 +76,9 @@ omdev/cli/install.py
76
76
  omdev/cli/main.py
77
77
  omdev/cli/managers.py
78
78
  omdev/cli/types.py
79
+ omdev/clipboard/__init__.py
80
+ omdev/clipboard/clipboard.py
81
+ omdev/clipboard/darwin.py
79
82
  omdev/interp/__init__.py
80
83
  omdev/interp/__main__.py
81
84
  omdev/interp/cli.py
@@ -119,6 +122,7 @@ omdev/scripts/exectime.py
119
122
  omdev/scripts/importtrace.py
120
123
  omdev/scripts/interp.py
121
124
  omdev/scripts/pyproject.py
125
+ omdev/scripts/slowcat.py
122
126
  omdev/toml/__init__.py
123
127
  omdev/toml/parser.py
124
128
  omdev/toml/writer.py
@@ -1,4 +1,4 @@
1
- omlish==0.0.0.dev80
1
+ omlish==0.0.0.dev82
2
2
 
3
3
  [all]
4
4
  black~=24.10
@@ -12,7 +12,7 @@ authors = [
12
12
  urls = {source = 'https://github.com/wrmsr/omlish'}
13
13
  license = {text = 'BSD-3-Clause'}
14
14
  requires-python = '~=3.12'
15
- version = '0.0.0.dev80'
15
+ version = '0.0.0.dev82'
16
16
  classifiers = [
17
17
  'License :: OSI Approved :: BSD License',
18
18
  'Development Status :: 2 - Pre-Alpha',
@@ -22,7 +22,7 @@ classifiers = [
22
22
  ]
23
23
  description = 'omdev'
24
24
  dependencies = [
25
- 'omlish == 0.0.0.dev80',
25
+ 'omlish == 0.0.0.dev82',
26
26
  ]
27
27
 
28
28
  [project.optional-dependencies]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes