Commits

Ronny Pfannschmidt committed 9a39658

split out io creation for popen/ssh gateways

Comments (0)

Files changed (1)

io-creation-split

 # HG changeset patch
-# Parent f7b824707b223e53db69d87d9d5fd711797dd5ff
+# Parent 42f530f0f479c03e695741971c01741e1402763c
+
+diff --git a/execnet/gateway.py b/execnet/gateway.py
+--- a/execnet/gateway.py
++++ b/execnet/gateway.py
+@@ -218,35 +218,19 @@ def _source_of_function(function):
+ 
+     return source
+ 
+-class PopenCmdGateway(Gateway):
++class PopenGatewayBase(Gateway):
+     _remotesetup = "io = init_popen_io()"
+-    def __init__(self, args, id):
+-        from subprocess import Popen, PIPE
+-        io = Popen2IOMaster(args)
+-        super(PopenCmdGateway, self).__init__(io=io, id=id)
++    def __init__(self, io, id):
++        super(PopenGatewayBase, self).__init__(io=io, id=id)
+         # fix for jython 2.5.1
+         if io.popen.pid is None:
+             io.popen.pid = self.remote_exec(
+                 "import os; channel.send(os.getpid())").receive()
+ 
+-popen_bootstrapline = "import sys;exec(eval(sys.stdin.readline()))"
+-class PopenGateway(PopenCmdGateway):
++class PopenGateway(PopenGatewayBase):
+     """ This Gateway provides interaction with a newly started
+         python subprocess.
+     """
+-    def __init__(self, id, python=None, spec=None):
+-        """ instantiate a gateway to a subprocess
+-            started with the given 'python' executable.
+-        """
+-        if not python:
+-            python = sys.executable
+-        args = [str(python), '-u']
+-        if spec is not None and spec.dont_write_bytecode:
+-            args.append("-B")
+-        # Slight gymnastics in ordering these arguments because CPython (as of
+-        # 2.7.1) ignores -B if you provide `python -c "something" -B`
+-        args.extend(['-c', popen_bootstrapline])
+-        super(PopenGateway, self).__init__(args, id=id)
+ 
+     def _remote_bootstrap_gateway(self, io):
+         sendexec(io,
+@@ -267,25 +251,11 @@ def sendexec(io, *sources):
+ class HostNotFound(Exception):
+     pass
+ 
+-class SshGateway(PopenCmdGateway):
++class SshGateway(PopenGatewayBase):
+     """ This Gateway provides interaction with a remote Python process,
+         established via the 'ssh' command line binary.
+         The remote side needs to have a Python interpreter executable.
+     """
+-    def __init__(self, sshaddress, id, remotepython=None, ssh_config=None):
+-        """ instantiate a remote ssh process with the
+-            given 'sshaddress' and remotepython version.
+-            you may specify an ssh_config file.
+-        """
+-        self.remoteaddress = sshaddress
+-        if remotepython is None:
+-            remotepython = "python"
+-        args = ['ssh', '-C' ]
+-        if ssh_config is not None:
+-            args.extend(['-F', str(ssh_config)])
+-        remotecmd = '%s -c "%s"' %(remotepython, popen_bootstrapline)
+-        args.extend([sshaddress, remotecmd])
+-        super(SshGateway, self).__init__(args, id=id)
+ 
+     def _remote_bootstrap_gateway(self, io):
+         try:
+diff --git a/execnet/gateway_io.py b/execnet/gateway_io.py
+--- a/execnet/gateway_io.py
++++ b/execnet/gateway_io.py
+@@ -53,8 +53,35 @@ def killpid(pid):
+ 
+ 
+ 
++popen_bootstrapline = "import sys;exec(eval(sys.stdin.readline()))"
+ 
+ 
++def popen_args(spec):
++    python = spec.python or sys.executable
++    args = [str(python), '-u']
++    if spec is not None and spec.dont_write_bytecode:
++        args.append("-B")
++    # Slight gymnastics in ordering these arguments because CPython (as of
++    # 2.7.1) ignores -B if you provide `python -c "something" -B`
++    args.extend(['-c', popen_bootstrapline])
++    return args
+ 
++def ssh_args(spec):
++    remotepython = spec.python or 'python'
++    args = ['ssh', '-C' ]
++    if spec.ssh_config is not None:
++        args.extend(['-F', str(spec.ssh_config)])
++    remotecmd = '%s -c "%s"' %(remotepython, popen_bootstrapline)
++    args.extend([spec.ssh, remotecmd])
++    return args
+ 
+ 
++
++def create_io(spec):
++    if spec.popen:
++        args = popen_args(spec)
++        return Popen2IOMaster(args)
++    if spec.ssh:
++        args = ssh_args(spec)
++        return Popen2IOMaster(args)
++
+diff --git a/execnet/multi.py b/execnet/multi.py
+--- a/execnet/multi.py
++++ b/execnet/multi.py
+@@ -7,7 +7,7 @@ Managing Gateway Groups and interactions
+ import os, sys, atexit
+ import execnet
+ from execnet import XSpec
+-from execnet import gateway
++from execnet import gateway, gateway_io
+ from execnet.gateway_base import queue, reraise, trace, TimeoutError
+ 
+ NO_ENDMARKER_WANTED = object()
+@@ -75,10 +75,11 @@ class Group:
+             spec = XSpec(spec)
+         self.allocate_id(spec)
+         if spec.popen:
+-            gw = gateway.PopenGateway(python=spec.python, id=spec.id, spec=spec)
++            io = gateway_io.create_io(spec)
++            gw = gateway.PopenGateway(io, spec.id)
+         elif spec.ssh:
+-            gw = gateway.SshGateway(spec.ssh, remotepython=spec.python,
+-                                    ssh_config=spec.ssh_config, id=spec.id)
++            io = gateway_io.create_io(spec)
++            gw = gateway.SshGateway(io, spec.id)
+         elif spec.socket:
+             assert not spec.python, (
+                 "socket: specifying python executables not yet supported")
+diff --git a/testing/test_basics.py b/testing/test_basics.py
+--- a/testing/test_basics.py
++++ b/testing/test_basics.py
+@@ -2,7 +2,7 @@
+ import py
+ import sys, os, subprocess, inspect
+ import execnet
+-from execnet import gateway_base, gateway
++from execnet import gateway_base, gateway, gateway_io
+ from execnet.gateway_base import Message, Channel, ChannelFactory, serialize, \
+         Unserializer, Popen2IO
+ 
+@@ -16,7 +16,7 @@ def test_errors_on_execnet():
+     assert hasattr(execnet, 'TimeoutError')
+ 
+ def test_subprocess_interaction(anypython):
+-    line = gateway.popen_bootstrapline
++    line = gateway_io.popen_bootstrapline
+     compile(line, 'xyz', 'exec')
+     args = [str(anypython), '-c', line]
+     popen = subprocess.Popen(args, bufsize=0, universal_newlines=True,