shelltastic 0.4.1__tar.gz → 0.4.2__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.
- {shelltastic-0.4.1 → shelltastic-0.4.2}/PKG-INFO +1 -1
- shelltastic-0.4.2/pyproject.toml +45 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/backend/__init__.py +6 -8
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/backend/base.py +8 -5
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/backend/default/common.py +91 -86
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/backend/default/remote.py +8 -4
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/frontend/common.py +2 -4
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/frontend/git.py +3 -5
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/frontend/shell.py +8 -7
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/host.py +1 -2
- shelltastic-0.4.1/pyproject.toml +0 -21
- {shelltastic-0.4.1 → shelltastic-0.4.2}/LICENSE +0 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/README.md +0 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/__init__.py +0 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/backend/default/__init__.py +0 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/backend/default/local.py +0 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/display.py +0 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/enum.py +0 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/exception.py +0 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/frontend/__init__.py +0 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/frontend/scp.py +0 -0
- {shelltastic-0.4.1 → shelltastic-0.4.2}/src/shelltastic/result.py +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "shelltastic"
|
|
3
|
+
version = "0.4.2"
|
|
4
|
+
description = "A fantastic shell command runner for python"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Bearmine" }
|
|
8
|
+
]
|
|
9
|
+
license = "MPL-2.0"
|
|
10
|
+
license-files = [
|
|
11
|
+
"LICENSE"
|
|
12
|
+
]
|
|
13
|
+
requires-python = ">=3.12"
|
|
14
|
+
dependencies = []
|
|
15
|
+
|
|
16
|
+
[project.urls]
|
|
17
|
+
Repository = "https://forge.bearmine.com/bearmine/shelltastic"
|
|
18
|
+
|
|
19
|
+
[build-system]
|
|
20
|
+
requires = ["uv_build>=0.11.18,<0.12.0"]
|
|
21
|
+
build-backend = "uv_build"
|
|
22
|
+
|
|
23
|
+
[tool.ruff.lint]
|
|
24
|
+
extend-select = [
|
|
25
|
+
"F", # Pyflakes rules
|
|
26
|
+
"W", # PyCodeStyle warnings
|
|
27
|
+
"E", # PyCodeStyle errors
|
|
28
|
+
"I", # Sort imports properly
|
|
29
|
+
"UP", # Warn if certain things can changed due to newer Python versions
|
|
30
|
+
"C4", # Catch incorrect use of comprehensions, dict, list, etc
|
|
31
|
+
"FA", # Enforce from __future__ import annotations
|
|
32
|
+
"ISC", # Good use of string concatenation
|
|
33
|
+
"ICN", # Use common import conventions
|
|
34
|
+
"RET", # Good return practices
|
|
35
|
+
"SIM", # Common simplification rules
|
|
36
|
+
"TID", # Some good import practices
|
|
37
|
+
"TC", # Enforce importing certain types in a TYPE_CHECKING block
|
|
38
|
+
"PTH", # Use pathlib instead of os.path
|
|
39
|
+
"TD", # Be diligent with TODO comments
|
|
40
|
+
"NPY", # Some numpy-specific things
|
|
41
|
+
"FURB", # Suggest more idiomatic Python patterns
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[tool.ruff.lint.pycodestyle]
|
|
45
|
+
max-line-length = 100
|
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
from typing import Type
|
|
2
|
-
|
|
3
1
|
from shelltastic.backend.base import LocalShellBackend, RemoteShellBackend
|
|
4
2
|
from shelltastic.backend.default.local import DefaultLocalBackend
|
|
5
3
|
from shelltastic.backend.default.remote import DefaultRemoteBackend
|
|
6
4
|
from shelltastic.host import Host
|
|
7
5
|
|
|
8
|
-
_default_local_backend:
|
|
9
|
-
_default_remote_backend:
|
|
6
|
+
_default_local_backend: type[LocalShellBackend] = DefaultLocalBackend
|
|
7
|
+
_default_remote_backend: type[RemoteShellBackend] = DefaultRemoteBackend
|
|
10
8
|
|
|
11
9
|
|
|
12
|
-
def register_default_local_backend(backend:
|
|
10
|
+
def register_default_local_backend(backend: type[LocalShellBackend]):
|
|
13
11
|
global _default_local_backend
|
|
14
12
|
_default_local_backend = backend
|
|
15
13
|
|
|
16
14
|
|
|
17
|
-
def register_default_remote_backend(backend:
|
|
15
|
+
def register_default_remote_backend(backend: type[RemoteShellBackend]):
|
|
18
16
|
global _default_remote_backend
|
|
19
17
|
_default_remote_backend = backend
|
|
20
18
|
|
|
21
19
|
|
|
22
20
|
def get_local_backend(
|
|
23
|
-
*, backend:
|
|
21
|
+
*, backend: type[LocalShellBackend] | None = None
|
|
24
22
|
) -> LocalShellBackend:
|
|
25
23
|
if backend:
|
|
26
24
|
return backend.local()
|
|
@@ -28,7 +26,7 @@ def get_local_backend(
|
|
|
28
26
|
|
|
29
27
|
|
|
30
28
|
def get_remote_backend(
|
|
31
|
-
host: Host, *, backend:
|
|
29
|
+
host: Host, *, backend: type[RemoteShellBackend] | None = None
|
|
32
30
|
) -> RemoteShellBackend:
|
|
33
31
|
if backend:
|
|
34
32
|
return backend.for_host(host)
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
|
-
from
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
from
|
|
8
|
-
|
|
9
|
-
from shelltastic.
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from shelltastic.display import IODisplay
|
|
10
|
+
from shelltastic.enum import CaptureMode, DisplayMode
|
|
11
|
+
from shelltastic.host import Host
|
|
12
|
+
from shelltastic.result import ShellResult
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
class ShellBackend(ABC):
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
import pathlib
|
|
5
4
|
import shlex
|
|
6
5
|
import subprocess
|
|
7
6
|
from multiprocessing.pool import ThreadPool
|
|
8
|
-
from typing import IO, Literal
|
|
7
|
+
from typing import IO, TYPE_CHECKING, Literal
|
|
9
8
|
|
|
10
9
|
from shelltastic import display
|
|
11
10
|
from shelltastic.backend.base import ShellBackend
|
|
12
11
|
from shelltastic.enum import CaptureMode, DisplayMode
|
|
13
12
|
from shelltastic.result import ShellResult
|
|
14
13
|
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
15
17
|
LOGGER = logging.getLogger(__name__)
|
|
16
18
|
|
|
17
19
|
|
|
@@ -23,67 +25,62 @@ def _output_and_collect(
|
|
|
23
25
|
|
|
24
26
|
if collect:
|
|
25
27
|
if display:
|
|
26
|
-
return_bytes =
|
|
28
|
+
return_bytes: bytes = b""
|
|
27
29
|
for line in io:
|
|
28
30
|
return_bytes += line
|
|
29
31
|
display.printbytes(line)
|
|
30
32
|
return return_bytes
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
return io.read()
|
|
34
|
+
|
|
35
|
+
if display:
|
|
36
|
+
for line in io:
|
|
37
|
+
display.printbytes(line)
|
|
38
|
+
|
|
39
|
+
return None
|
|
38
40
|
|
|
39
41
|
|
|
40
42
|
def _determine_subprocess_output_mode(
|
|
41
43
|
capture_mode: CaptureMode | None,
|
|
42
44
|
display_mode: DisplayMode | display.IODisplay | None,
|
|
43
45
|
output_name: Literal["stdout", "stderr"],
|
|
44
|
-
) -> int
|
|
45
|
-
# If DisplayMode is None, we act like
|
|
46
|
+
) -> int:
|
|
47
|
+
# If DisplayMode is None, we act like subprocess does
|
|
46
48
|
if display_mode is None:
|
|
47
49
|
if capture_mode == CaptureMode.PIPE:
|
|
48
50
|
return subprocess.PIPE
|
|
49
|
-
|
|
51
|
+
if capture_mode == CaptureMode.STDOUT:
|
|
50
52
|
return subprocess.STDOUT
|
|
51
|
-
|
|
53
|
+
if capture_mode == CaptureMode.DEVNULL:
|
|
52
54
|
return subprocess.DEVNULL
|
|
53
|
-
|
|
54
|
-
assert capture_mode is None
|
|
55
|
-
return None
|
|
55
|
+
return subprocess.PIPE
|
|
56
56
|
|
|
57
57
|
# Don't print
|
|
58
58
|
if display_mode == DisplayMode.DEVNULL:
|
|
59
59
|
if capture_mode == CaptureMode.PIPE:
|
|
60
60
|
return subprocess.PIPE
|
|
61
|
-
|
|
61
|
+
if capture_mode == CaptureMode.STDOUT:
|
|
62
62
|
if output_name == "stdout":
|
|
63
63
|
# stdout
|
|
64
64
|
return subprocess.PIPE
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
elif capture_mode == CaptureMode.DEVNULL:
|
|
69
|
-
return subprocess.DEVNULL
|
|
70
|
-
else:
|
|
71
|
-
assert capture_mode is None
|
|
65
|
+
# stderr
|
|
66
|
+
return subprocess.STDOUT
|
|
67
|
+
if capture_mode == CaptureMode.DEVNULL:
|
|
72
68
|
return subprocess.DEVNULL
|
|
69
|
+
assert capture_mode is None
|
|
70
|
+
return subprocess.DEVNULL
|
|
73
71
|
|
|
74
72
|
# Print Output
|
|
75
73
|
# display_mode == STDOUT, STDERR, LOG, or is an IODisplay
|
|
76
74
|
if capture_mode == CaptureMode.PIPE:
|
|
77
75
|
return subprocess.PIPE
|
|
78
|
-
|
|
76
|
+
if capture_mode == CaptureMode.STDOUT:
|
|
79
77
|
return subprocess.STDOUT
|
|
80
|
-
|
|
81
|
-
# We need to PIPE to be able to print the output
|
|
82
|
-
return subprocess.PIPE
|
|
83
|
-
else:
|
|
84
|
-
assert capture_mode is None
|
|
78
|
+
if capture_mode == CaptureMode.DEVNULL:
|
|
85
79
|
# We need to PIPE to be able to print the output
|
|
86
80
|
return subprocess.PIPE
|
|
81
|
+
assert capture_mode is None
|
|
82
|
+
# We need to PIPE to be able to print the output
|
|
83
|
+
return subprocess.PIPE
|
|
87
84
|
|
|
88
85
|
|
|
89
86
|
class CommonDefaultBackend(ShellBackend):
|
|
@@ -98,7 +95,7 @@ class CommonDefaultBackend(ShellBackend):
|
|
|
98
95
|
stderr: CaptureMode | None = None,
|
|
99
96
|
stdout_display: DisplayMode | display.IODisplay | None = None,
|
|
100
97
|
stderr_display: DisplayMode | display.IODisplay | None = None,
|
|
101
|
-
cwd: str |
|
|
98
|
+
cwd: str | Path | None = None,
|
|
102
99
|
echo_cmd: DisplayMode | display.IODisplay | bool | None = None,
|
|
103
100
|
**kwargs,
|
|
104
101
|
) -> ShellResult:
|
|
@@ -106,19 +103,13 @@ class CommonDefaultBackend(ShellBackend):
|
|
|
106
103
|
raise TypeError(f"Uknown argument/s {list(kwargs.keys())}")
|
|
107
104
|
|
|
108
105
|
# If cmd is a str, run as shell
|
|
109
|
-
|
|
110
|
-
shell = True
|
|
111
|
-
else:
|
|
112
|
-
shell = False
|
|
106
|
+
shell = isinstance(cmd, str)
|
|
113
107
|
|
|
114
108
|
# Echo command based on setting
|
|
115
109
|
# Defaults to DEBUG_LOG
|
|
116
110
|
# False to disable
|
|
117
111
|
if isinstance(echo_cmd, bool):
|
|
118
|
-
if echo_cmd
|
|
119
|
-
echo_cmd = DisplayMode.STDOUT
|
|
120
|
-
else:
|
|
121
|
-
echo_cmd = DisplayMode.DEVNULL
|
|
112
|
+
echo_cmd = DisplayMode.STDOUT if echo_cmd else DisplayMode.DEVNULL
|
|
122
113
|
|
|
123
114
|
if echo_cmd is None:
|
|
124
115
|
echo_cmd = DisplayMode.DEBUG_LOG
|
|
@@ -129,9 +120,9 @@ class CommonDefaultBackend(ShellBackend):
|
|
|
129
120
|
echo_display = display.from_mode(echo_cmd)
|
|
130
121
|
|
|
131
122
|
if isinstance(cmd, str):
|
|
132
|
-
echo_display.printline("%s> %s", cwd
|
|
123
|
+
echo_display.printline("%s> %s", cwd or "", cmd)
|
|
133
124
|
else:
|
|
134
|
-
echo_display.printline("%s> %s", cwd
|
|
125
|
+
echo_display.printline("%s> %s", cwd or "", shlex.join(cmd))
|
|
135
126
|
|
|
136
127
|
# Determine PIPE mode for stdout
|
|
137
128
|
stdout_sub_mode = _determine_subprocess_output_mode(
|
|
@@ -143,51 +134,65 @@ class CommonDefaultBackend(ShellBackend):
|
|
|
143
134
|
stderr, stderr_display, "stderr"
|
|
144
135
|
)
|
|
145
136
|
|
|
137
|
+
if stdout_display is None:
|
|
138
|
+
stdout_display = (
|
|
139
|
+
DisplayMode.STDOUT if stdout is None else DisplayMode.DEVNULL
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if stderr_display is None:
|
|
143
|
+
stderr_display = (
|
|
144
|
+
DisplayMode.STDERR if stderr is None else DisplayMode.DEVNULL
|
|
145
|
+
)
|
|
146
|
+
|
|
146
147
|
# Run subprocess command
|
|
147
|
-
with
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
148
|
+
with (
|
|
149
|
+
subprocess.Popen(
|
|
150
|
+
cmd,
|
|
151
|
+
shell=shell,
|
|
152
|
+
stdout=stdout_sub_mode,
|
|
153
|
+
stderr=stderr_sub_mode,
|
|
154
|
+
cwd=cwd,
|
|
155
|
+
) as popen,
|
|
156
|
+
ThreadPool(2) as display_pool,
|
|
157
|
+
):
|
|
158
|
+
# Print out and capture stdout
|
|
159
|
+
stdout_result = display_pool.apply_async(
|
|
160
|
+
_output_and_collect,
|
|
161
|
+
args=[
|
|
162
|
+
popen.stdout,
|
|
163
|
+
(
|
|
164
|
+
stdout_display
|
|
165
|
+
if isinstance(stdout_display, display.IODisplay)
|
|
166
|
+
else display.from_mode(stdout_display)
|
|
167
|
+
),
|
|
168
|
+
stdout is not None and stdout != CaptureMode.DEVNULL,
|
|
169
|
+
],
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# Print out and capture stderr
|
|
173
|
+
stderr_result = display_pool.apply_async(
|
|
174
|
+
_output_and_collect,
|
|
175
|
+
args=[
|
|
176
|
+
popen.stderr,
|
|
177
|
+
(
|
|
178
|
+
stderr_display
|
|
179
|
+
if isinstance(stderr_display, display.IODisplay)
|
|
180
|
+
else display.from_mode(stderr_display)
|
|
181
|
+
),
|
|
182
|
+
stderr is not None and stderr != CaptureMode.DEVNULL,
|
|
183
|
+
],
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Wait on command completion
|
|
187
|
+
returncode = popen.wait()
|
|
188
|
+
|
|
189
|
+
# Build our result
|
|
190
|
+
result = ShellResult(
|
|
191
|
+
cmd=cmd,
|
|
192
|
+
stdout=stdout_result.get(),
|
|
193
|
+
stderr=stderr_result.get(),
|
|
194
|
+
returncode=returncode,
|
|
195
|
+
)
|
|
191
196
|
|
|
192
197
|
# If check is True, raise exception if returncode is not 0
|
|
193
198
|
if check:
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
import pathlib
|
|
5
4
|
import shlex
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from shelltastic.backend.base import RemoteShellBackend
|
|
8
8
|
from shelltastic.backend.default.common import CommonDefaultBackend
|
|
9
9
|
from shelltastic.exception import ShellException, SSHConnectionError
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from shelltastic.host import Host
|
|
15
|
+
from shelltastic.result import ShellResult
|
|
12
16
|
|
|
13
17
|
LOGGER = logging.getLogger(__name__)
|
|
14
18
|
|
|
@@ -27,7 +31,7 @@ class DefaultRemoteBackend(CommonDefaultBackend, RemoteShellBackend):
|
|
|
27
31
|
cmd: str | list[str],
|
|
28
32
|
*,
|
|
29
33
|
subshell: bool = True,
|
|
30
|
-
cwd: str |
|
|
34
|
+
cwd: str | Path | None = None,
|
|
31
35
|
**kwargs,
|
|
32
36
|
) -> ShellResult:
|
|
33
37
|
"""
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import overload
|
|
3
3
|
|
|
4
4
|
from shelltastic.host import Host
|
|
5
5
|
|
|
@@ -12,10 +12,8 @@ class RemoteFrontend(ABC):
|
|
|
12
12
|
return self._host
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
T = TypeVar("T", bound=RemoteFrontend)
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
class RemoteFrontendFactory(Generic[T], ABC):
|
|
16
|
+
class RemoteFrontendFactory[T: RemoteFrontend](ABC):
|
|
19
17
|
__slots__ = ()
|
|
20
18
|
|
|
21
19
|
@overload
|
|
@@ -58,8 +58,7 @@ class GitFrontend:
|
|
|
58
58
|
stderr=CaptureMode.PIPE,
|
|
59
59
|
)
|
|
60
60
|
assert result.stdout is not None
|
|
61
|
-
|
|
62
|
-
return configs
|
|
61
|
+
return [i.strip() for i in result.stdout.decode().split("\n") if i.strip()]
|
|
63
62
|
|
|
64
63
|
def set_global_config(self, key: str, value: str | list[str]):
|
|
65
64
|
LOGGER.info(
|
|
@@ -89,10 +88,9 @@ class GitFrontend:
|
|
|
89
88
|
)
|
|
90
89
|
if response.returncode != 0:
|
|
91
90
|
return []
|
|
92
|
-
else:
|
|
93
|
-
assert response.stdout is not None
|
|
94
|
-
gitcredentials = response.stdout.decode()
|
|
95
91
|
|
|
92
|
+
assert response.stdout is not None
|
|
93
|
+
gitcredentials = response.stdout.decode()
|
|
96
94
|
return gitcredentials.splitlines()
|
|
97
95
|
|
|
98
96
|
|
|
@@ -2,14 +2,17 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import shutil
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
from shelltastic import backend
|
|
7
|
-
from shelltastic.backend.base import ShellBackend
|
|
8
|
-
from shelltastic.display import IODisplay
|
|
9
8
|
from shelltastic.enum import CaptureMode, DisplayMode, SystemType
|
|
10
9
|
from shelltastic.frontend.common import RemoteFrontend, RemoteFrontendFactory
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from shelltastic.backend.base import ShellBackend
|
|
13
|
+
from shelltastic.display import IODisplay
|
|
14
|
+
from shelltastic.host import Host
|
|
15
|
+
from shelltastic.result import ShellResult
|
|
13
16
|
|
|
14
17
|
|
|
15
18
|
class ShellFrontend:
|
|
@@ -35,9 +38,7 @@ class ShellFrontend:
|
|
|
35
38
|
stdout=CaptureMode.DEVNULL,
|
|
36
39
|
stderr=CaptureMode.DEVNULL,
|
|
37
40
|
)
|
|
38
|
-
|
|
39
|
-
return True
|
|
40
|
-
return False
|
|
41
|
+
return result.returncode == 0
|
|
41
42
|
|
|
42
43
|
def home_dir(self) -> Path:
|
|
43
44
|
"""Return the path to the current user's home directory"""
|
shelltastic-0.4.1/pyproject.toml
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
[project]
|
|
2
|
-
name = "shelltastic"
|
|
3
|
-
version = "0.4.1"
|
|
4
|
-
description = "A fantastic shell command runner for python"
|
|
5
|
-
readme = "README.md"
|
|
6
|
-
authors = [
|
|
7
|
-
{ name = "Bearmine" }
|
|
8
|
-
]
|
|
9
|
-
license = "MPL-2.0"
|
|
10
|
-
license-files = [
|
|
11
|
-
"LICENSE"
|
|
12
|
-
]
|
|
13
|
-
requires-python = ">=3.12"
|
|
14
|
-
dependencies = []
|
|
15
|
-
|
|
16
|
-
[project.urls]
|
|
17
|
-
Repository = "https://forge.bearmine.com/bearmine/shelltastic"
|
|
18
|
-
|
|
19
|
-
[build-system]
|
|
20
|
-
requires = ["uv_build>=0.11.18,<0.12.0"]
|
|
21
|
-
build-backend = "uv_build"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|