[Python-modules-commits] [python-spur] 05/13: Handle reading using pty in Python >= 3.4
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 090a23aaef653539d9ec10794996f8664779bff4
Author: Michael Williamson <mike at zwobble.org>
Date: Sun Dec 27 23:04:41 2015 +0000
Handle reading using pty in Python >= 3.4
---
spur/io.py | 51 ++++++++++++++++++++++++++++-----------------------
spur/local.py | 18 ++++++++----------
spur/ssh.py | 6 +++---
3 files changed, 39 insertions(+), 36 deletions(-)
diff --git a/spur/io.py b/spur/io.py
index 04190f8..11f4e93 100644
--- a/spur/io.py
+++ b/spur/io.py
@@ -1,23 +1,27 @@
import threading
+import os
class IoHandler(object):
- def __init__(self, in_out_pairs):
- self._handlers = [
- _output_handler(file_in, file_out)
- for file_in, file_out
- in in_out_pairs
- ]
+ def __init__(self, channels):
+ self._handlers = list(map(_output_handler, channels))
def wait(self):
return [handler.wait() for handler in self._handlers]
-def _output_handler(file_in, file_out):
- if file_out is None:
- return _ReadOutputAtEnd(file_in)
+class Channel(object):
+ def __init__(self, file_in, file_out, is_pty=False):
+ self.file_in = file_in
+ self.file_out = file_out
+ self.is_pty = is_pty
+
+
+def _output_handler(channel):
+ if channel.file_out is None and not channel.is_pty:
+ return _ReadOutputAtEnd(channel.file_in)
else:
- return _ContinuousReader(file_in, file_out)
+ return _ContinuousReader(channel)
class _ReadOutputAtEnd(object):
@@ -25,20 +29,14 @@ class _ReadOutputAtEnd(object):
self._file_in = file_in
def wait(self):
- try:
- return self._file_in.read()
- except IOError:
- # TODO: is there a more elegant fix?
- # Attempting to read from a pty master that has received nothing
- # seems to raise an IOError when reading
- # See: http://bugs.python.org/issue5380
- return b""
+ return self._file_in.read()
class _ContinuousReader(object):
- def __init__(self, file_in, file_out):
- self._file_in = file_in
- self._file_out = file_out
+ def __init__(self, channel):
+ self._file_in = channel.file_in
+ self._file_out = channel.file_out
+ self._is_pty = channel.is_pty
self._output = b""
self._thread = threading.Thread(target=self._capture_output)
@@ -52,9 +50,16 @@ class _ContinuousReader(object):
def _capture_output(self):
output_buffer = []
while True:
- output = self._file_in.read(1)
+ try:
+ output = self._file_in.read(1)
+ except IOError:
+ if self._is_pty:
+ output = b""
+ else:
+ raise
if output:
- self._file_out.write(output)
+ if self._file_out is not None:
+ self._file_out.write(output)
output_buffer.append(output)
else:
self._output = b"".join(output_buffer)
diff --git a/spur/local.py b/spur/local.py
index a4045e1..77e840b 100644
--- a/spur/local.py
+++ b/spur/local.py
@@ -14,7 +14,7 @@ except ImportError:
from spur.tempdir import create_temporary_dir
from spur.files import FileOperations
import spur.results
-from .io import IoHandler
+from .io import IoHandler, Channel
from .errors import NoSuchCommandError
@@ -79,6 +79,7 @@ class LocalShell(object):
def close_slave_on_exit():
process.wait()
+ # TODO: ensure the IO handler has finished before closing
os.close(slave)
thread = threading.Thread(target=close_slave_on_exit)
@@ -94,10 +95,10 @@ class LocalShell(object):
process,
allow_error=allow_error,
process_stdin=process_stdin,
- process_stdout=process_stdout,
- process_stderr=process_stderr,
- stdout=stdout,
- stderr=stderr
+ channels=[
+ Channel(process_stdout, stdout, is_pty=use_pty),
+ Channel(process_stderr, stderr, is_pty=use_pty),
+ ]
)
if store_pid:
spur_process.pid = process.pid
@@ -140,16 +141,13 @@ class LocalShell(object):
class LocalProcess(object):
- def __init__(self, subprocess, allow_error, process_stdin, process_stdout, process_stderr, stdout, stderr):
+ def __init__(self, subprocess, allow_error, process_stdin, channels):
self._subprocess = subprocess
self._allow_error = allow_error
self._process_stdin = process_stdin
self._result = None
- self._io = IoHandler([
- (process_stdout, stdout),
- (process_stderr, stderr),
- ])
+ self._io = IoHandler(channels)
def is_running(self):
return self._subprocess.poll() is None
diff --git a/spur/ssh.py b/spur/ssh.py
index 49f3efe..5fb20f3 100644
--- a/spur/ssh.py
+++ b/spur/ssh.py
@@ -17,7 +17,7 @@ import paramiko
from spur.tempdir import create_temporary_dir
from spur.files import FileOperations
import spur.results
-from .io import IoHandler
+from .io import IoHandler, Channel
from .errors import NoSuchCommandError
@@ -341,8 +341,8 @@ class SshProcess(object):
self._result = None
self._io = IoHandler([
- (self._stdout, stdout),
- (self._stderr, stderr),
+ Channel(self._stdout, stdout),
+ Channel(self._stderr, stderr),
])
def is_running(self):
--
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