omdev 0.0.0.dev114__tar.gz → 0.0.0.dev116__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.
- {omdev-0.0.0.dev114/omdev.egg-info → omdev-0.0.0.dev116}/PKG-INFO +2 -2
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/.manifests.json +2 -2
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cli/clicli.py +2 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cli/main.py +0 -1
- omdev-0.0.0.dev116/omdev/clipboard/clipboard.py +74 -0
- omdev-0.0.0.dev114/omdev/clipboard/darwin.py → omdev-0.0.0.dev116/omdev/clipboard/darwin_cf.py +31 -27
- omdev-0.0.0.dev116/omdev/clipboard/linux_x.py +301 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/git.py +27 -27
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/pip.py +1 -1
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/pycharm/cli.py +12 -10
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/pyproject/cli.py +20 -14
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/scripts/pyproject.py +47 -41
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/git.py +32 -18
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116/omdev.egg-info}/PKG-INFO +2 -2
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev.egg-info/SOURCES.txt +2 -2
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev.egg-info/requires.txt +1 -1
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/pyproject.toml +2 -2
- omdev-0.0.0.dev114/omdev/clipboard/clipboard.py +0 -23
- omdev-0.0.0.dev114/omdev/tools/pawk/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/LICENSE +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/README.rst +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/__about__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/amalg/amalg.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/antlr/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/antlr/consts.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/antlr/gen.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/bracepy.py +0 -0
- {omdev-0.0.0.dev114/omdev/antlr/_antlr → omdev-0.0.0.dev116/omdev/cache}/__init__.py +0 -0
- {omdev-0.0.0.dev114/omdev/cache → omdev-0.0.0.dev116/omdev/cache/compute}/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/compute/cache.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/compute/contexts.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/compute/currents.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/compute/fns.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/compute/resolvers.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/compute/storage.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/compute/types.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/data/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/data/cache.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/data/defaults.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.0.dev114/omdev/cache/compute → omdev-0.0.0.dev116/omdev/cexts}/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/build.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/classdot.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cli/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cli/__main__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cli/_pathhack.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cli/install.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cli/managers.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cli/types.py +0 -0
- {omdev-0.0.0.dev114/omdev/cexts → omdev-0.0.0.dev116/omdev/clipboard}/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/findimports.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/imgur.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/interp/providers.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/interp/pyenv.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/interp/standalone.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/interp/system.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/magic/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/magic/find.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/magic/magic.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/magic/prepare.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/magic/styles.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/manifests/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/manifests/build.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/manifests/load.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/manifests/types.py +0 -0
- {omdev-0.0.0.dev114/omdev/clipboard → omdev-0.0.0.dev116/omdev/mypy}/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev114/omdev/mypy → omdev-0.0.0.dev116/omdev/packaging}/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/packaging/marshal.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/packaging/names.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/packaging/requires.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/packaging/specifiers.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/packaging/versions.py +0 -0
- {omdev-0.0.0.dev114/omdev/packaging → omdev-0.0.0.dev116/omdev/precheck}/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/precheck/base.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/precheck/git.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/precheck/lite.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/precheck/main.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/precheck/manifests.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/precheck/scripts.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/ptk/__init__.py +0 -0
- {omdev-0.0.0.dev114/omdev/precheck → omdev-0.0.0.dev116/omdev/ptk/apps}/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/ptk/apps/ncdu.py +0 -0
- {omdev-0.0.0.dev114/omdev/ptk/apps → omdev-0.0.0.dev116/omdev/pycharm}/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/pycharm/__main__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/revisions.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/scripts/bumpversion.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/scripts/execrss.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/scripts/exectime.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/scripts/importtrace.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/scripts/slowcat.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/scripts/tmpexec.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/secrets.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tokens.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/toml/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/toml/parser.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/toml/writer.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/doc.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/docker.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/importscan.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/mkrelimp.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/notebook.py +0 -0
- {omdev-0.0.0.dev114/omdev/pycharm → omdev-0.0.0.dev116/omdev/tools/pawk}/__init__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/pawk/__main__.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/pawk/pawk.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/pip.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/prof.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/qr.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev/wheelfile.py +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev.egg-info/entry_points.txt +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev114 → omdev-0.0.0.dev116}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev116
|
|
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.
|
|
15
|
+
Requires-Dist: omlish==0.0.0.dev116
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: black~=24.10; extra == "all"
|
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"module": ".cli.clicli",
|
|
52
52
|
"attr": "_CLI_MODULE",
|
|
53
53
|
"file": "omdev/cli/clicli.py",
|
|
54
|
-
"line":
|
|
54
|
+
"line": 113,
|
|
55
55
|
"value": {
|
|
56
56
|
"$.cli.types.CliModule": {
|
|
57
57
|
"cmd_name": "cli",
|
|
@@ -243,7 +243,7 @@
|
|
|
243
243
|
"module": ".tools.git",
|
|
244
244
|
"attr": "_CLI_MODULE",
|
|
245
245
|
"file": "omdev/tools/git.py",
|
|
246
|
-
"line":
|
|
246
|
+
"line": 196,
|
|
247
247
|
"value": {
|
|
248
248
|
"$.cli.types.CliModule": {
|
|
249
249
|
"cmd_name": "git",
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
""" https://askubuntu.com/questions/11925/a-command-line-clipboard-copy-and-paste-utility
|
|
2
|
+
"""
|
|
3
|
+
import abc
|
|
4
|
+
import dataclasses as dc
|
|
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
|
+
##
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Clipboard(abc.ABC):
|
|
33
|
+
@abc.abstractmethod
|
|
34
|
+
def get(self) -> list[ClipboardContents]:
|
|
35
|
+
raise NotImplementedError
|
|
36
|
+
|
|
37
|
+
@abc.abstractmethod
|
|
38
|
+
def put(self, c: ClipboardContents) -> None:
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
|
|
41
|
+
|
|
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
|
+
|
|
71
|
+
|
|
72
|
+
class PbcopyDarwinClipboard(TextCommandClipboard):
|
|
73
|
+
_get_cmd = ('pbpaste',)
|
|
74
|
+
_put_cmd = ('pbcopy',)
|
omdev-0.0.0.dev114/omdev/clipboard/darwin.py → omdev-0.0.0.dev116/omdev/clipboard/darwin_cf.py
RENAMED
|
@@ -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()
|
|
@@ -228,7 +228,7 @@ untracked file, this is reported as ? as well.
|
|
|
228
228
|
""" # noqa
|
|
229
229
|
|
|
230
230
|
|
|
231
|
-
class
|
|
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
|
-
|
|
246
|
-
(
|
|
247
|
-
(
|
|
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
|
|
253
|
-
x:
|
|
254
|
-
y:
|
|
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
|
|
263
|
-
self.y is
|
|
264
|
-
(self.x, self.y) in
|
|
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) ->
|
|
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
|
|
293
|
-
|
|
294
|
-
|
|
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[
|
|
301
|
-
def __init__(self, lines: ta.Iterable[
|
|
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[
|
|
307
|
-
by_y: ta.Dict[
|
|
306
|
+
by_x: ta.Dict[GitStatusState, list[GitStatusItem]] = {}
|
|
307
|
+
by_y: ta.Dict[GitStatusState, list[GitStatusItem]] = {}
|
|
308
308
|
|
|
309
|
-
by_a: ta.Dict[str,
|
|
310
|
-
by_b: ta.Dict[str,
|
|
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[
|
|
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[
|
|
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[
|
|
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,
|
|
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,
|
|
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 !=
|
|
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 !=
|
|
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:
|
|
@@ -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
|
|
@@ -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
|
-
#
|
|
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
|
-
|
|
30
|
-
|
|
30
|
+
# wmctrl -lx
|
|
31
|
+
# 0x03000054 0 jetbrains-pycharm.jetbrains-pycharm spinlock-ws omlish - cli.py
|
|
32
|
+
# wmctrl -i -a 0x03000054
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
"""
|