mirror of
https://github.com/not-kennethreitz/envoy.git
synced 2026-06-05 23:20:19 +00:00
Backward-compatible Port to Python 3
- Keeps Python 2.7 and 2.6 compatibility
- Is not compatible with Python 2.5, as the original code never was.
This is due to two problems:
1. Use of the `Thread.is_alive()` method. Python 2.5 only
provides `Thread.isAlive()`.
2. Use of the `Popen.terminate()` and `Popen.kill()` methods,
which only exist in Python >= 2.6
This commit is contained in:
+2
-2
@@ -1,3 +1,3 @@
|
||||
from core import *
|
||||
from .core import *
|
||||
|
||||
from core import __version__
|
||||
from .core import __version__
|
||||
|
||||
+10
-4
@@ -8,6 +8,7 @@ This module provides envoy awesomeness.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shlex
|
||||
import subprocess
|
||||
import threading
|
||||
@@ -43,8 +44,13 @@ class Command(object):
|
||||
stderr=subprocess.PIPE,
|
||||
bufsize=0,
|
||||
)
|
||||
|
||||
self.out, self.err = self.process.communicate(self.data)
|
||||
if sys.version_info[0] >= 3:
|
||||
self.out, self.err = self.process.communicate(
|
||||
input = bytes(self.data, "UTF-8") if self.data else None
|
||||
)
|
||||
else:
|
||||
self.out, self.err = self.process.communicate(self.data)
|
||||
|
||||
|
||||
thread = threading.Thread(target=target)
|
||||
thread.start()
|
||||
@@ -139,7 +145,7 @@ def expand_args(command):
|
||||
"""Parses command strings and returns a Popen-ready list."""
|
||||
|
||||
# Prepare arguments.
|
||||
if isinstance(command, basestring):
|
||||
if isinstance(command, str):
|
||||
splitter = shlex.shlex(command)
|
||||
splitter.whitespace = '|'
|
||||
splitter.whitespace_split = True
|
||||
@@ -152,7 +158,7 @@ def expand_args(command):
|
||||
else:
|
||||
break
|
||||
|
||||
command = map(shlex.split, command)
|
||||
command = list(map(shlex.split, command))
|
||||
|
||||
return command
|
||||
|
||||
|
||||
+26
-26
@@ -80,7 +80,7 @@ try:
|
||||
import errno
|
||||
import traceback
|
||||
import signal
|
||||
except ImportError, e:
|
||||
except ImportError as e:
|
||||
raise ImportError (str(e) + """
|
||||
|
||||
A critical module was not found. Probably this operating system does not
|
||||
@@ -217,8 +217,8 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
|
||||
else:
|
||||
child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile, cwd=cwd, env=env)
|
||||
if events is not None:
|
||||
patterns = events.keys()
|
||||
responses = events.values()
|
||||
patterns = list(events.keys())
|
||||
responses = list(events.values())
|
||||
else:
|
||||
patterns=None # We assume that EOF or TIMEOUT will save us.
|
||||
responses=None
|
||||
@@ -227,16 +227,16 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
|
||||
while 1:
|
||||
try:
|
||||
index = child.expect (patterns)
|
||||
if type(child.after) in types.StringTypes:
|
||||
if type(child.after) in str:
|
||||
child_result_list.append(child.before + child.after)
|
||||
else: # child.after may have been a TIMEOUT or EOF, so don't cat those.
|
||||
child_result_list.append(child.before)
|
||||
if type(responses[index]) in types.StringTypes:
|
||||
if type(responses[index]) in str:
|
||||
child.send(responses[index])
|
||||
elif type(responses[index]) is types.FunctionType:
|
||||
callback_result = responses[index](locals())
|
||||
sys.stdout.flush()
|
||||
if type(callback_result) in types.StringTypes:
|
||||
if type(callback_result) in str:
|
||||
child.send(callback_result)
|
||||
elif callback_result:
|
||||
break
|
||||
@@ -519,7 +519,7 @@ class spawn (object):
|
||||
if self.use_native_pty_fork:
|
||||
try:
|
||||
self.pid, self.child_fd = pty.fork()
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
raise ExceptionPexpect('Error! pty.fork() failed: ' + str(e))
|
||||
else: # Use internal __fork_pty
|
||||
self.pid, self.child_fd = self.__fork_pty()
|
||||
@@ -574,11 +574,11 @@ class spawn (object):
|
||||
|
||||
parent_fd, child_fd = os.openpty()
|
||||
if parent_fd < 0 or child_fd < 0:
|
||||
raise ExceptionPexpect, "Error! Could not open pty with os.openpty()."
|
||||
raise ExceptionPexpect("Error! Could not open pty with os.openpty().")
|
||||
|
||||
pid = os.fork()
|
||||
if pid < 0:
|
||||
raise ExceptionPexpect, "Error! Failed os.fork()."
|
||||
raise ExceptionPexpect("Error! Failed os.fork().")
|
||||
elif pid == 0:
|
||||
# Child.
|
||||
os.close(parent_fd)
|
||||
@@ -615,7 +615,7 @@ class spawn (object):
|
||||
fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
|
||||
if fd >= 0:
|
||||
os.close(fd)
|
||||
raise ExceptionPexpect, "Error! We are not disconnected from a controlling tty."
|
||||
raise ExceptionPexpect("Error! We are not disconnected from a controlling tty.")
|
||||
except:
|
||||
# Good! We are disconnected from a controlling tty.
|
||||
pass
|
||||
@@ -623,14 +623,14 @@ class spawn (object):
|
||||
# Verify we can open child pty.
|
||||
fd = os.open(child_name, os.O_RDWR);
|
||||
if fd < 0:
|
||||
raise ExceptionPexpect, "Error! Could not open child pty, " + child_name
|
||||
raise ExceptionPexpect("Error! Could not open child pty, " + child_name)
|
||||
else:
|
||||
os.close(fd)
|
||||
|
||||
# Verify we now have a controlling tty.
|
||||
fd = os.open("/dev/tty", os.O_WRONLY)
|
||||
if fd < 0:
|
||||
raise ExceptionPexpect, "Error! Could not open controlling tty, /dev/tty"
|
||||
raise ExceptionPexpect("Error! Could not open controlling tty, /dev/tty")
|
||||
else:
|
||||
os.close(fd)
|
||||
|
||||
@@ -878,7 +878,7 @@ class spawn (object):
|
||||
|
||||
return self
|
||||
|
||||
def next (self): # File-like object.
|
||||
def __next__ (self): # File-like object.
|
||||
"""This is to support iterators over a file-like object.
|
||||
"""
|
||||
|
||||
@@ -1098,7 +1098,7 @@ class spawn (object):
|
||||
|
||||
try:
|
||||
pid, status = os.waitpid(self.pid, waitpid_options)
|
||||
except OSError, e: # No child processes
|
||||
except OSError as e: # No child processes
|
||||
if e[0] == errno.ECHILD:
|
||||
raise ExceptionPexpect ('isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?')
|
||||
else:
|
||||
@@ -1110,7 +1110,7 @@ class spawn (object):
|
||||
if pid == 0:
|
||||
try:
|
||||
pid, status = os.waitpid(self.pid, waitpid_options) ### os.WNOHANG) # Solaris!
|
||||
except OSError, e: # This should never happen...
|
||||
except OSError as e: # This should never happen...
|
||||
if e[0] == errno.ECHILD:
|
||||
raise ExceptionPexpect ('isalive() encountered condition that should never happen. There was no child process. Did someone else call waitpid() on our process?')
|
||||
else:
|
||||
@@ -1175,7 +1175,7 @@ class spawn (object):
|
||||
|
||||
if patterns is None:
|
||||
return []
|
||||
if type(patterns) is not types.ListType:
|
||||
if type(patterns) is not list:
|
||||
patterns = [patterns]
|
||||
|
||||
compile_flags = re.DOTALL # Allow dot to match \n
|
||||
@@ -1183,7 +1183,7 @@ class spawn (object):
|
||||
compile_flags = compile_flags | re.IGNORECASE
|
||||
compiled_pattern_list = []
|
||||
for p in patterns:
|
||||
if type(p) in types.StringTypes:
|
||||
if type(p) in str:
|
||||
compiled_pattern_list.append(re.compile(p, compile_flags))
|
||||
elif p is EOF:
|
||||
compiled_pattern_list.append(EOF)
|
||||
@@ -1301,7 +1301,7 @@ class spawn (object):
|
||||
This method is also useful when you don't want to have to worry about
|
||||
escaping regular expression characters that you want to match."""
|
||||
|
||||
if type(pattern_list) in types.StringTypes or pattern_list in (TIMEOUT, EOF):
|
||||
if type(pattern_list) in str or pattern_list in (TIMEOUT, EOF):
|
||||
pattern_list = [pattern_list]
|
||||
return self.expect_loop(searcher_string(pattern_list), timeout, searchwindowsize)
|
||||
|
||||
@@ -1343,7 +1343,7 @@ class spawn (object):
|
||||
incoming = incoming + c
|
||||
if timeout is not None:
|
||||
timeout = end_time - time.time()
|
||||
except EOF, e:
|
||||
except EOF as e:
|
||||
self.buffer = ''
|
||||
self.before = incoming
|
||||
self.after = EOF
|
||||
@@ -1356,7 +1356,7 @@ class spawn (object):
|
||||
self.match = None
|
||||
self.match_index = None
|
||||
raise EOF (str(e) + '\n' + str(self))
|
||||
except TIMEOUT, e:
|
||||
except TIMEOUT as e:
|
||||
self.buffer = incoming
|
||||
self.before = incoming
|
||||
self.after = TIMEOUT
|
||||
@@ -1380,7 +1380,7 @@ class spawn (object):
|
||||
"""This returns the terminal window size of the child tty. The return
|
||||
value is a tuple of (rows, cols). """
|
||||
|
||||
TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912L)
|
||||
TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912)
|
||||
s = struct.pack('HHHH', 0, 0, 0, 0)
|
||||
x = fcntl.ioctl(self.fileno(), TIOCGWINSZ, s)
|
||||
return struct.unpack('HHHH', x)[0:2]
|
||||
@@ -1401,7 +1401,7 @@ class spawn (object):
|
||||
# Newer versions of Linux have totally different values for TIOCSWINSZ.
|
||||
# Note that this fix is a hack.
|
||||
TIOCSWINSZ = getattr(termios, 'TIOCSWINSZ', -2146929561)
|
||||
if TIOCSWINSZ == 2148037735L: # L is not required in Python >= 2.2.
|
||||
if TIOCSWINSZ == 2148037735: # L is not required in Python >= 2.2.
|
||||
TIOCSWINSZ = -2146929561 # Same bits, but with sign.
|
||||
# Note, assume ws_xpixel and ws_ypixel are zero.
|
||||
s = struct.pack('HHHH', r, c, 0, 0)
|
||||
@@ -1502,7 +1502,7 @@ class spawn (object):
|
||||
while True:
|
||||
try:
|
||||
return select.select (iwtd, owtd, ewtd, timeout)
|
||||
except select.error, e:
|
||||
except select.error as e:
|
||||
if e[0] == errno.EINTR:
|
||||
# if we loop back we have to subtract the amount of time we already waited.
|
||||
if timeout is not None:
|
||||
@@ -1554,7 +1554,7 @@ class searcher_string (object):
|
||||
self.eof_index = -1
|
||||
self.timeout_index = -1
|
||||
self._strings = []
|
||||
for n, s in zip(range(len(strings)), strings):
|
||||
for n, s in zip(list(range(len(strings))), strings):
|
||||
if s is EOF:
|
||||
self.eof_index = n
|
||||
continue
|
||||
@@ -1648,7 +1648,7 @@ class searcher_re (object):
|
||||
self.eof_index = -1
|
||||
self.timeout_index = -1
|
||||
self._searches = []
|
||||
for n, s in zip(range(len(patterns)), patterns):
|
||||
for n, s in zip(list(range(len(patterns))), patterns):
|
||||
if s is EOF:
|
||||
self.eof_index = n
|
||||
continue
|
||||
@@ -1715,7 +1715,7 @@ def which(filename):
|
||||
if os.access (filename, os.X_OK):
|
||||
return filename
|
||||
|
||||
if not os.environ.has_key('PATH') or os.environ['PATH'] == '':
|
||||
if 'PATH' not in os.environ or os.environ['PATH'] == '':
|
||||
p = os.defpath
|
||||
else:
|
||||
p = os.environ['PATH']
|
||||
|
||||
@@ -35,10 +35,10 @@ setup(
|
||||
'Natural Language :: English',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2.5',
|
||||
# 'Programming Language :: Python :: 2.5',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
# 'Programming Language :: Python :: 3.0',
|
||||
# 'Programming Language :: Python :: 3.1',
|
||||
'Programming Language :: Python :: 3.0',
|
||||
'Programming Language :: Python :: 3.1',
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user