libPyshell 0.2.1__tar.gz → 0.3.0__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.
- {libPyshell-0.2.1/libPyshell.egg-info → libPyshell-0.3.0}/PKG-INFO +5 -1
- {libPyshell-0.2.1 → libPyshell-0.3.0}/README.md +4 -0
- {libPyshell-0.2.1 → libPyshell-0.3.0/libPyshell.egg-info}/PKG-INFO +5 -1
- {libPyshell-0.2.1 → libPyshell-0.3.0}/setup.py +1 -1
- {libPyshell-0.2.1 → libPyshell-0.3.0}/src/__init__.py +44 -37
- {libPyshell-0.2.1 → libPyshell-0.3.0}/LICENSE +0 -0
- {libPyshell-0.2.1 → libPyshell-0.3.0}/MANIFEST.in +0 -0
- {libPyshell-0.2.1 → libPyshell-0.3.0}/libPyshell.egg-info/SOURCES.txt +0 -0
- {libPyshell-0.2.1 → libPyshell-0.3.0}/libPyshell.egg-info/dependency_links.txt +0 -0
- {libPyshell-0.2.1 → libPyshell-0.3.0}/libPyshell.egg-info/top_level.txt +0 -0
- {libPyshell-0.2.1 → libPyshell-0.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: libPyshell
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Support for writing shell scripts in Python
|
|
5
5
|
Home-page: https://github.com/skogsbaer/libPyshell
|
|
6
6
|
Author: Stefan Wehr
|
|
@@ -37,6 +37,10 @@ magicFiles = run(['grep', 'magic'] + files, captureStdout=splitLines, onError='i
|
|
|
37
37
|
|
|
38
38
|
## Changelog
|
|
39
39
|
|
|
40
|
+
* 0.3.0 (2024-02-01)
|
|
41
|
+
* uniform treatment when capturing stdout and stderr. This lead to changes to RunResult
|
|
42
|
+
and RunError which are slightly backwards incompatible.
|
|
43
|
+
|
|
40
44
|
* 0.2.0 (2024-01-29)
|
|
41
45
|
* Better static type information
|
|
42
46
|
|
|
@@ -26,6 +26,10 @@ magicFiles = run(['grep', 'magic'] + files, captureStdout=splitLines, onError='i
|
|
|
26
26
|
|
|
27
27
|
## Changelog
|
|
28
28
|
|
|
29
|
+
* 0.3.0 (2024-02-01)
|
|
30
|
+
* uniform treatment when capturing stdout and stderr. This lead to changes to RunResult
|
|
31
|
+
and RunError which are slightly backwards incompatible.
|
|
32
|
+
|
|
29
33
|
* 0.2.0 (2024-01-29)
|
|
30
34
|
* Better static type information
|
|
31
35
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: libPyshell
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Support for writing shell scripts in Python
|
|
5
5
|
Home-page: https://github.com/skogsbaer/libPyshell
|
|
6
6
|
Author: Stefan Wehr
|
|
@@ -37,6 +37,10 @@ magicFiles = run(['grep', 'magic'] + files, captureStdout=splitLines, onError='i
|
|
|
37
37
|
|
|
38
38
|
## Changelog
|
|
39
39
|
|
|
40
|
+
* 0.3.0 (2024-02-01)
|
|
41
|
+
* uniform treatment when capturing stdout and stderr. This lead to changes to RunResult
|
|
42
|
+
and RunError which are slightly backwards incompatible.
|
|
43
|
+
|
|
40
44
|
* 0.2.0 (2024-01-29)
|
|
41
45
|
* Better static type information
|
|
42
46
|
|
|
@@ -94,11 +94,12 @@ class RunResult:
|
|
|
94
94
|
attribute `stdout` contains the output printed in stdout (only if `run`
|
|
95
95
|
was invoked with `captureStdout=True`).
|
|
96
96
|
"""
|
|
97
|
-
def __init__(self, stdout: Any, exitcode: int):
|
|
97
|
+
def __init__(self, stdout: Any, stderr: Any, exitcode: int):
|
|
98
98
|
self.stdout = stdout
|
|
99
|
+
self.stderr = stderr
|
|
99
100
|
self.exitcode = exitcode
|
|
100
101
|
def __repr__(self):
|
|
101
|
-
return 'RunResult(exitcode=%d, stdout=%r)
|
|
102
|
+
return 'RunResult(exitcode=%d, stdout=%r, stderr=%r)' % (self.exitcode, self.stdout, self.stderr)
|
|
102
103
|
def __eq__(self, other: Any):
|
|
103
104
|
if type(other) is type(self):
|
|
104
105
|
return self.__dict__ == other.__dict__
|
|
@@ -127,14 +128,19 @@ class RunError(ShellError):
|
|
|
127
128
|
"""
|
|
128
129
|
def __init__(self, cmd: Union[str, list[str]],
|
|
129
130
|
exitcode: int,
|
|
130
|
-
|
|
131
|
+
stdout: Union[str,bytes],
|
|
132
|
+
stderr: Union[str,bytes]):
|
|
131
133
|
self.cmd = cmd
|
|
132
134
|
self.exitcode = exitcode
|
|
133
135
|
self.stderr = stderr
|
|
136
|
+
self.stdout = stdout
|
|
134
137
|
msg = 'Command ' + repr(self.cmd) + " failed with exit code " + str(self.exitcode)
|
|
135
138
|
if stderr:
|
|
136
139
|
msg = msg + '\nstderr:\n' + str(stderr)
|
|
137
140
|
super(RunError, self).__init__(msg)
|
|
141
|
+
def __repr__(self):
|
|
142
|
+
return 'RunError(cmd=%r, exitcode=%d, stdout=%r, stderr=%r)' % \
|
|
143
|
+
(self.cmd, self.exitcode, self.stdout, self.stderr)
|
|
138
144
|
|
|
139
145
|
def splitOn(splitter: str) -> Callable[[str], list[str]]:
|
|
140
146
|
"""Return a function that splits a string on the given splitter string.
|
|
@@ -224,25 +230,29 @@ def run(cmd: Union[list[str], str],
|
|
|
224
230
|
|
|
225
231
|
Starting with Python 3.5, the `subprocess` module defines a similar function.
|
|
226
232
|
|
|
227
|
-
>>> run('/bin/echo foo')
|
|
228
|
-
|
|
229
|
-
>>> run('/bin/echo -n foo', captureStdout=True)
|
|
230
|
-
|
|
231
|
-
>>> run('/bin/echo -n foo', captureStdout=lambda s: s + 'X')
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
True
|
|
236
|
-
|
|
237
|
-
True
|
|
233
|
+
>>> run('/bin/echo foo')
|
|
234
|
+
RunResult(exitcode=0, stdout='', stderr='')
|
|
235
|
+
>>> run('/bin/echo -n foo', captureStdout=True)
|
|
236
|
+
RunResult(exitcode=0, stdout='foo', stderr='')
|
|
237
|
+
>>> run('/bin/echo -n foo', captureStdout=lambda s: s + 'X')
|
|
238
|
+
RunResult(exitcode=0, stdout='fooX', stderr='')
|
|
239
|
+
>>> run('/bin/echo foo', captureStdout=False)
|
|
240
|
+
RunResult(exitcode=0, stdout='', stderr='')
|
|
241
|
+
>>> run('cat', captureStdout=True, input='blub')
|
|
242
|
+
RunResult(exitcode=0, stdout='blub', stderr='')
|
|
238
243
|
>>> try:
|
|
239
|
-
... run('false')
|
|
244
|
+
... run('/bin/echo -n foo 1>&2; /bin/echo -n bar; false', captureStdout=True, captureStderr=True)
|
|
240
245
|
... raise 'exception expected'
|
|
241
|
-
... except RunError:
|
|
242
|
-
...
|
|
246
|
+
... except RunError as e:
|
|
247
|
+
... print(repr(e))
|
|
243
248
|
...
|
|
244
|
-
|
|
245
|
-
|
|
249
|
+
RunError(cmd='/bin/echo -n foo 1>&2; /bin/echo -n bar; false', exitcode=1, stdout='bar', stderr='foo')
|
|
250
|
+
>>> run('false', onError='ignore')
|
|
251
|
+
RunResult(exitcode=1, stdout='', stderr='')
|
|
252
|
+
>>> run('/bin/echo -n foo; /bin/echo -n bar 1>&2', captureStdout=True, captureStderr=True)
|
|
253
|
+
RunResult(exitcode=0, stdout='foo', stderr='bar')
|
|
254
|
+
>>> run('/bin/echo -n foo 1>&2; /bin/echo -n bar', captureStderr=lambda s: s + 'X')
|
|
255
|
+
RunResult(exitcode=0, stdout='', stderr='fooX')
|
|
246
256
|
"""
|
|
247
257
|
if type(cmd) != str and type(cmd) != list:
|
|
248
258
|
raise ShellError('cmd parameter must be a string or a list')
|
|
@@ -253,9 +263,7 @@ def run(cmd: Union[list[str], str],
|
|
|
253
263
|
decodeErrorsStdout = decodeErrors
|
|
254
264
|
if decodeErrorsStderr is None:
|
|
255
265
|
decodeErrorsStderr = decodeErrors
|
|
256
|
-
|
|
257
|
-
stdoutIsProcFun = not stdoutIsFileLike and isinstance(captureStdout, Callable)
|
|
258
|
-
shouldReturnStdout = (stdoutIsProcFun or
|
|
266
|
+
shouldReturnStdout = (isinstance(captureStdout, Callable) or
|
|
259
267
|
(type(captureStdout) == bool and captureStdout))
|
|
260
268
|
stdout: _FILE = None
|
|
261
269
|
if shouldReturnStdout:
|
|
@@ -301,26 +309,25 @@ def run(cmd: Union[list[str], str],
|
|
|
301
309
|
cwd=cwd, env=popenEnv
|
|
302
310
|
)
|
|
303
311
|
(stdoutData, stderrData) = pipe.communicate(input=inputBytes)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if stderrData and encoding != 'raw':
|
|
307
|
-
stderrData = stderrData.decode(encoding, errors=decodeErrorsStderr)
|
|
312
|
+
stdoutData = massageOutput(stdoutData, encoding, decodeErrorsStdout, captureStdout)
|
|
313
|
+
stderrData = massageOutput(stderrData, encoding, decodeErrorsStderr, captureStderr)
|
|
308
314
|
exitcode = pipe.returncode
|
|
309
315
|
if onError == 'raise' and exitcode != 0:
|
|
310
|
-
|
|
311
|
-
if stderrToStdout:
|
|
312
|
-
d = stdoutData
|
|
313
|
-
err = RunError(cmd, exitcode, d)
|
|
316
|
+
err = RunError(cmd, exitcode, stdoutData, stderrData)
|
|
314
317
|
raise err
|
|
315
318
|
if onError == 'die' and exitcode != 0:
|
|
316
319
|
sys.exit(exitcode)
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
320
|
+
return RunResult(stdoutData, stderrData, exitcode)
|
|
321
|
+
|
|
322
|
+
def massageOutput(data: Any, encoding: str, decodeErrors: str,
|
|
323
|
+
capture: Union[bool,Callable[[str], Any],_FILE]):
|
|
324
|
+
if data and encoding != 'raw':
|
|
325
|
+
data = data.decode(encoding, errors=decodeErrors)
|
|
326
|
+
if not data:
|
|
327
|
+
data = ''
|
|
328
|
+
if isinstance(capture, Callable) and isinstance(data, str):
|
|
329
|
+
data = capture(data)
|
|
330
|
+
return data
|
|
324
331
|
|
|
325
332
|
# the quote function is stolen from https://hg.python.org/cpython/file/3.5/Lib/shlex.py
|
|
326
333
|
_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|