diff --git a/mitogen/core.py b/mitogen/core.py index e5a714f3..e369a48a 100644 --- a/mitogen/core.py +++ b/mitogen/core.py @@ -26,8 +26,6 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -import cPickle -import cStringIO import collections import errno import fcntl @@ -40,7 +38,6 @@ import signal import socket import struct import sys -import thread import threading import time import traceback @@ -48,6 +45,16 @@ import warnings import weakref import zlib +try: + import cPickle +except ImportError: + import pickle as cPickle + +try: + from cStringIO import StringIO as BytesIO +except ImportError: + from io import BytesIO + # TODO: usage of 'import' after setting __name__, but before fixing up # sys.modules generates a warning. This happens when profiling = True. warnings.filterwarnings('ignore', @@ -69,6 +76,12 @@ ALLOCATE_ID = 105 SHUTDOWN = 106 LOAD_MODULE = 107 +PY3 = sys.version_info > (3,) +if PY3: + b = lambda s: s.encode('latin-1') +else: + b = str + CHUNK_SIZE = 131072 _tls = threading.local() @@ -344,9 +357,12 @@ class Message(object): _vv and IOLOG.debug('%r.unpickle()', self) obj = self._unpickled if obj is Message._unpickled: - fp = cStringIO.StringIO(self.data) + fp = BytesIO(self.data) unpickler = cPickle.Unpickler(fp) - unpickler.find_global = self._find_global + try: + unpickler.find_global = self._find_global + except AttributeError: + unpickler.find_class = self._find_global try: # Must occur off the broker thread. @@ -679,7 +695,10 @@ class Importer(object): flags = 0x4000 source = self.get_source(fullname) code = compile(source, mod.__file__, 'exec', flags, True) - exec code in vars(mod) + if PY3: + exec(code, vars(mod)) + else: + exec('exec code in vars(mod)') return mod def get_filename(self, fullname): @@ -1154,7 +1173,7 @@ class Waker(BasicStream): self._broker.shutdown() def defer(self, func, *args, **kwargs): - if thread.get_ident() == self.broker_ident: + if threading.currentThread().ident == self.broker_ident: _vv and IOLOG.debug('%r.defer() [immediate]', self) return func(*args, **kwargs) @@ -1169,7 +1188,7 @@ class Waker(BasicStream): # of tearing itself down, the waker fd may already have been closed, so # ignore EBADF here. try: - self.transmit_side.write(' ') + self.transmit_side.write(b(' ')) except OSError: e = sys.exc_info()[1] if e[0] != errno.EBADF: diff --git a/mitogen/parent.py b/mitogen/parent.py index f1974907..c100c4fd 100644 --- a/mitogen/parent.py +++ b/mitogen/parent.py @@ -26,7 +26,6 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -import cStringIO import fcntl import getpass import inspect @@ -43,6 +42,11 @@ import time import types import zlib +try: + from cStringIO import StringIO as BytesIO +except ImportError: + from io import BytesIO + if sys.version_info < (2, 7, 11): from mitogen.compat import tokenize else: @@ -97,7 +101,7 @@ def is_immediate_child(msg, stream): def minimize_source(source): """Remove most comments and docstrings from Python source code. """ - tokens = tokenize.generate_tokens(cStringIO.StringIO(source).readline) + tokens = tokenize.generate_tokens(BytesIO(source).readline) tokens = strip_comments(tokens) tokens = strip_docstrings(tokens) tokens = reindent(tokens) diff --git a/mitogen/ssh.py b/mitogen/ssh.py index 15e9ac02..0507bb51 100644 --- a/mitogen/ssh.py +++ b/mitogen/ssh.py @@ -30,10 +30,14 @@ Functionality to allow establishing new slave contexts over an SSH connection. """ -import commands import logging import time +try: + from shlex import quote as shlex_quote +except ImportError: + from pipes import quote as shlex_quote + import mitogen.parent @@ -108,7 +112,7 @@ class Stream(mitogen.parent.Stream): bits += self.ssh_args bits.append(self.hostname) base = super(Stream, self).get_boot_command() - return bits + [commands.mkarg(s).strip() for s in base] + return bits + [shlex_quote(s).strip() for s in base] def connect(self): super(Stream, self).connect()