[Python-modules-commits] [python-spur] 07/13: Add encoding argument
Ruben Undheim
rubund-guest at moszumanska.debian.org
Sun Jan 3 10:38:51 UTC 2016
This is an automated email from the git hooks/post-receive script.
rubund-guest pushed a commit to branch master
in repository python-spur.
commit 3712bc82083ca8cec12113a38f1427e5fbb33360
Author: Michael Williamson <mike at zwobble.org>
Date: Mon Dec 28 11:01:14 2015 +0000
Add encoding argument
---
README.rst | 13 +++++++++----
spur/io.py | 26 +++++++++++++++++++++++---
spur/local.py | 9 +++++----
spur/results.py | 24 ++++++++++++++++--------
spur/ssh.py | 6 ++++--
tests/process_test_set.py | 16 ++++++++++++++++
6 files changed, 73 insertions(+), 21 deletions(-)
diff --git a/README.rst b/README.rst
index 2b784c6..d358d11 100644
--- a/README.rst
+++ b/README.rst
@@ -107,8 +107,8 @@ Optional arguments:
Shell interface
---------------
-run(command, cwd, update\_env, store\_pid, allow\_error, stdout, stderr)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+run(command, cwd, update\_env, store\_pid, allow\_error, stdout, stderr, encoding)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run a command and wait for it to complete. The command is expected to be
a list of strings. Returns an instance of ``ExecutionResult``.
@@ -145,12 +145,17 @@ Optional arguments:
* ``stderr`` -- if not ``None``, anything the command prints to
standard error during its execution will also be written to
``stderr`` using ``stderr.write``.
+* ``encoding`` -- if set, this is used to decode any output.
+ By default, any output is treated as raw bytes.
+ If set, the raw bytes are decoded before writing to
+ the passed ``stdout`` and ``stderr`` arguments (if set)
+ and before setting the output attributes on the result.
``shell.run(*args, **kwargs)`` should behave similarly to
``shell.spawn(*args, **kwargs).wait_for_result()``
-spawn(command, cwd, update\_env, store\_pid, allow\_error, stdout, stderr)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+spawn(command, cwd, update\_env, store\_pid, allow\_error, stdout, stderr, encoding)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Behaves the same as ``run`` except that ``spawn`` immediately returns an
object representing the running process.
diff --git a/spur/io.py b/spur/io.py
index 11f4e93..50e4ff7 100644
--- a/spur/io.py
+++ b/spur/io.py
@@ -3,8 +3,11 @@ import os
class IoHandler(object):
- def __init__(self, channels):
- self._handlers = list(map(_output_handler, channels))
+ def __init__(self, channels, encoding):
+ self._handlers = [
+ _output_handler(channel, encoding)
+ for channel in channels
+ ]
def wait(self):
return [handler.wait() for handler in self._handlers]
@@ -17,7 +20,24 @@ class Channel(object):
self.is_pty = is_pty
-def _output_handler(channel):
+def _output_handler(channel, encoding):
+ bytes_handler = _bytes_output_handler(channel)
+ if encoding is None:
+ return bytes_handler
+ else:
+ return _EncodedOutputHandler(bytes_handler, encoding)
+
+
+class _EncodedOutputHandler(object):
+ def __init__(self, bytes_handler, encoding):
+ self._bytes_handler = bytes_handler
+ self._encoding = encoding
+
+ def wait(self):
+ return self._bytes_handler.wait().decode(self._encoding)
+
+
+def _bytes_output_handler(channel):
if channel.file_out is None and not channel.is_pty:
return _ReadOutputAtEnd(channel.file_in)
else:
diff --git a/spur/local.py b/spur/local.py
index 77e840b..c1a7d07 100644
--- a/spur/local.py
+++ b/spur/local.py
@@ -44,6 +44,7 @@ class LocalShell(object):
allow_error = kwargs.pop("allow_error", False)
store_pid = kwargs.pop("store_pid", False)
use_pty = kwargs.pop("use_pty", False)
+ encoding = kwargs.pop("encoding", None)
if use_pty:
if pty is None:
raise ValueError("use_pty is not supported when the pty module cannot be imported")
@@ -95,10 +96,10 @@ class LocalShell(object):
process,
allow_error=allow_error,
process_stdin=process_stdin,
- channels=[
+ io_handler=IoHandler([
Channel(process_stdout, stdout, is_pty=use_pty),
Channel(process_stderr, stderr, is_pty=use_pty),
- ]
+ ], encoding=encoding)
)
if store_pid:
spur_process.pid = process.pid
@@ -141,13 +142,13 @@ class LocalShell(object):
class LocalProcess(object):
- def __init__(self, subprocess, allow_error, process_stdin, channels):
+ def __init__(self, subprocess, allow_error, process_stdin, io_handler):
self._subprocess = subprocess
self._allow_error = allow_error
self._process_stdin = process_stdin
self._result = None
- self._io = IoHandler(channels)
+ self._io = io_handler
def is_running(self):
return self._subprocess.poll() is None
diff --git a/spur/results.py b/spur/results.py
index e3cfd1f..1aaaee9 100644
--- a/spur/results.py
+++ b/spur/results.py
@@ -1,4 +1,6 @@
-import locale
+from __future__ import unicode_literals
+
+import sys
def result(return_code, allow_error, output, stderr_output):
@@ -25,17 +27,23 @@ class ExecutionResult(object):
class RunProcessError(RuntimeError):
def __init__(self, return_code, output, stderr_output):
- message = "return code: {0}\noutput: {1}\nstderr output: {2}".format(
- return_code, _bytes_repr(output), _bytes_repr(stderr_output))
+ message = "return code: {0}\noutput:{1}\nstderr output:{2}".format(
+ return_code, _render_output(output), _render_output(stderr_output))
super(type(self), self).__init__(message)
self.return_code = return_code
self.output = output
self.stderr_output = stderr_output
-def _bytes_repr(raw_bytes):
- result = repr(raw_bytes)
- if result.startswith("b"):
- return result
+def _render_output(output):
+ if isinstance(output, unicode):
+ return "\n" + output
else:
- return "b" + result
+ result = repr(output)
+ if result.startswith("b"):
+ return " " + result
+ else:
+ return " b" + result
+
+if sys.version_info[0] >= 3:
+ unicode = str
diff --git a/spur/ssh.py b/spur/ssh.py
index 5fb20f3..38319e5 100644
--- a/spur/ssh.py
+++ b/spur/ssh.py
@@ -163,6 +163,7 @@ class SshShell(object):
allow_error = kwargs.pop("allow_error", False)
store_pid = kwargs.pop("store_pid", False)
use_pty = kwargs.pop("use_pty", False)
+ encoding = kwargs.pop("encoding", None)
command_in_cwd = self._shell_type.generate_run_command(command, *args, store_pid=store_pid, **kwargs)
try:
channel = self._get_ssh_transport().open_session()
@@ -189,6 +190,7 @@ class SshShell(object):
process_stdout=process_stdout,
stdout=stdout,
stderr=stderr,
+ encoding=encoding,
shell=self,
)
if store_pid:
@@ -331,7 +333,7 @@ def escape_sh(value):
class SshProcess(object):
- def __init__(self, channel, allow_error, process_stdout, stdout, stderr, shell):
+ def __init__(self, channel, allow_error, process_stdout, stdout, stderr, encoding, shell):
self._channel = channel
self._allow_error = allow_error
self._stdin = channel.makefile('wb')
@@ -343,7 +345,7 @@ class SshProcess(object):
self._io = IoHandler([
Channel(self._stdout, stdout),
Channel(self._stderr, stderr),
- ])
+ ], encoding=encoding)
def is_running(self):
return not self._channel.exit_status_ready()
diff --git a/tests/process_test_set.py b/tests/process_test_set.py
index 56bed8c..9cbb5b1 100644
--- a/tests/process_test_set.py
+++ b/tests/process_test_set.py
@@ -46,6 +46,11 @@ class ProcessTestSet(object):
assert_equal(b"hello\n", result.stderr_output)
@test
+ def output_bytes_are_decoded_if_encoding_is_set(shell):
+ result = shell.run(["bash", "-c", r'echo -e "\u2603"'], encoding="utf8")
+ assert_equal(_u("☃\n"), result.output)
+
+ @test
def cwd_of_run_can_be_set(shell):
result = shell.run(["pwd"], cwd="/")
assert_equal(b"/\n", result.output)
@@ -87,6 +92,17 @@ class ProcessTestSet(object):
)
@test
+ def exception_message_contains_output_as_string_if_encoding_is_set(shell):
+ try:
+ shell.run(["sh", "-c", "echo starting; echo failed! 1>&2; exit 1"], encoding="ascii")
+ assert_true(False)
+ except spur.RunProcessError as error:
+ assert_equal(
+ """return code: 1\noutput:\nstarting\n\nstderr output:\nfailed!\n""",
+ error.args[0]
+ )
+
+ @test
def exception_message_shows_unicode_bytes(shell):
try:
shell.run(["sh", "-c", _u("echo ‽; exit 1")])
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-spur.git
More information about the Python-modules-commits
mailing list