[svn r63147] get rid of old method for specifying remote execution places.

--HG--
branch : trunk
This commit is contained in:
hpk 2009-03-20 17:28:14 +01:00
parent 9cd41c91bd
commit a4c14e83f0
7 changed files with 60 additions and 224 deletions

View File

@ -27,8 +27,8 @@ version = "1.0.0a1"
initpkg(__name__,
description = "pylib and py.test: agile development and test support library",
revision = int('$LastChangedRevision: 63144 $'.split(':')[1][:-1]),
lastchangedate = '$LastChangedDate: 2009-03-20 16:36:45 +0100 (Fri, 20 Mar 2009) $',
revision = int('$LastChangedRevision: 63147 $'.split(':')[1][:-1]),
lastchangedate = '$LastChangedDate: 2009-03-20 17:28:14 +0100 (Fri, 20 Mar 2009) $',
version = version,
url = "http://pylib.org",
download_url = "http://codespeak.net/py/0.9.2/download.html",
@ -151,7 +151,6 @@ initpkg(__name__,
'execnet.SocketGateway' : ('./execnet/register.py', 'SocketGateway'),
'execnet.PopenGateway' : ('./execnet/register.py', 'PopenGateway'),
'execnet.SshGateway' : ('./execnet/register.py', 'SshGateway'),
'execnet.GatewaySpec' : ('./execnet/gwmanage.py', 'GatewaySpec'),
'execnet.XSpec' : ('./execnet/xspec.py', 'XSpec'),
'execnet.makegateway' : ('./execnet/xspec.py', 'makegateway'),
'execnet.MultiGateway' : ('./execnet/multi.py', 'MultiGateway'),

View File

@ -37,9 +37,11 @@ def getspecssh(config=None):
if not py.path.local.sysfind("ssh"):
py.test.skip("command not found: ssh")
return spec
py.test.skip("need '--gx ssh=...'")
def getsocketspec(config=None):
xspecs = getgspecs(config)
for spec in xspecs:
if spec.socket:
return spec
py.test.skip("need '--gx socket=...'")

View File

@ -1,105 +1,19 @@
"""
instantiating, managing and rsyncing to hosts
Host specification strings and implied gateways:
socket:hostname:port:path SocketGateway
popen[-executable][:path] PopenGateway
[ssh:]spec:path SshGateway
* [SshGateway]
on hostspec.makeconnection() a Host object
will be created which has an instantiated gateway.
the remote side will be chdir()ed to the specified path.
if no path was specified, do no chdir() at all.
"""
import py
import sys, os
from py.__.test.dsession.masterslave import MasterNode
from py.__.test import event
from py.__.execnet.channel import RemoteError
NO_ENDMARKER_WANTED = object()
class GatewaySpec(object):
python = None
def __init__(self, spec, defaultjoinpath="pyexecnetcache"):
self._spec = spec
if spec == "popen" or spec.startswith("popen:"):
parts = spec.split(":", 2)
self.type = self.address = parts.pop(0)
if parts:
python = parts.pop(0)
# XXX XXX XXX do better GWSPEC that can deal
# with "C:"
if py.std.sys.platform == "win32" and len(python) == 1:
python = "%s:%s" %(python, parts.pop(0))
self.python = python
if parts:
self.joinpath = parts.pop(0)
else:
self.joinpath = ""
if not self.python:
self.python = py.std.sys.executable
elif spec.startswith("socket:"):
parts = spec[7:].split(":", 2)
self.address = parts.pop(0)
if parts:
port = int(parts.pop(0))
self.address = self.address, port
self.joinpath = parts and parts.pop(0) or ""
self.type = "socket"
else:
if spec.startswith("ssh:"):
spec = spec[4:]
parts = spec.split(":", 2)
self.address = parts.pop(0)
self.python = parts and parts.pop(0) or "python"
self.joinpath = parts and parts.pop(0) or ""
self.type = "ssh"
if not self.joinpath and not self.inplacelocal():
self.joinpath = defaultjoinpath
def inplacelocal(self):
return bool(self.type == "popen" and not self.joinpath)
def __str__(self):
return "<GatewaySpec %s>" % self._spec
__repr__ = __str__
def makegateway(self, waitclose=True):
if self.type == "popen":
gw = py.execnet.PopenGateway(python=self.python)
elif self.type == "socket":
gw = py.execnet.SocketGateway(*self.address)
elif self.type == "ssh":
gw = py.execnet.SshGateway(self.address, remotepython=self.python)
if self.joinpath:
channel = gw.remote_exec("""
import os
path = %r
try:
os.chdir(path)
except OSError:
os.mkdir(path)
os.chdir(path)
""" % self.joinpath)
if waitclose:
channel.waitclose()
else:
if waitclose:
gw.remote_exec("").waitclose()
gw.spec = self
return gw
class GatewayManager:
RemoteError = RemoteError
def __init__(self, specs):
self.specs = [GatewaySpec(spec) for spec in specs]
self.specs = [py.execnet.XSpec(spec) for spec in specs]
self.gateways = []
def trace(self, msg):
@ -111,7 +25,7 @@ class GatewayManager:
def makegateways(self):
assert not self.gateways
for spec in self.specs:
gw = spec.makegateway()
gw = py.execnet.makegateway(spec)
self.gateways.append(gw)
gw.id = "[%s]" % len(self.gateways)
self.notify("gwmanage_newgateway", gw)
@ -121,7 +35,7 @@ class GatewayManager:
self.makegateways()
l = []
for gw in self.gateways:
if gw.spec.inplacelocal():
if gw.spec._samefilesystem():
if inplacelocal:
l.append(gw)
else:
@ -150,15 +64,14 @@ class GatewayManager:
seen = {}
for gateway in self.gateways:
spec = gateway.spec
if not spec.inplacelocal():
key = spec.type, spec.address, spec.joinpath
if key in seen:
if not spec._samefilesystem():
if spec in seen:
continue
def finished():
if notify:
notify("rsyncrootready", spec, source)
rsync.add_target_host(gateway, finished=finished)
seen[key] = gateway
seen[spec] = gateway
if seen:
self.notify("gwmanage_rsyncstart", source=source, gateways=seen.values())
rsync.send()
@ -203,5 +116,5 @@ class HostRSync(py.execnet.RSync):
def _report_send_file(self, gateway, modified_rel_path):
if self._verbose:
path = os.path.basename(self._sourcedir) + "/" + modified_rel_path
remotepath = gateway.spec.joinpath
remotepath = gateway.spec.chdir
print '%s:%s <= %s' % (gateway.remoteaddress, remotepath, path)

View File

@ -37,7 +37,7 @@ class TestGatewayManagerPopen:
assert not len(hm.gateways)
def test_hostmanager_rsync_popen_with_path(self, source, dest):
hm = GatewayManager(["popen::%s" %dest] * 1)
hm = GatewayManager(["popen//chdir=%s" %dest] * 1)
hm.makegateways()
source.ensure("dir1", "dir2", "hello")
l = []
@ -51,7 +51,7 @@ class TestGatewayManagerPopen:
assert dest.join("dir1", "dir2", 'hello').check()
def test_hostmanage_rsync_same_popen_twice(self, source, dest, eventrecorder):
hm = GatewayManager(["popen::%s" %dest] * 2)
hm = GatewayManager(["popen//chdir=%s" %dest] * 2)
hm.makegateways()
source.ensure("dir1", "dir2", "hello")
hm.rsync(source)
@ -65,7 +65,7 @@ class TestGatewayManagerPopen:
def test_multi_chdir_popen_with_path(self, testdir):
import os
hm = GatewayManager(["popen::hello"] * 2)
hm = GatewayManager(["popen//chdir=hello"] * 2)
testdir.tmpdir.chdir()
hellopath = testdir.tmpdir.mkdir("hello")
hm.makegateways()
@ -122,8 +122,7 @@ class TestHRSync:
assert 'somedir' in basenames
def test_hrsync_one_host(self, source, dest):
spec = py.execnet.GatewaySpec("popen::%s" % dest)
gw = spec.makegateway()
gw = py.execnet.makegateway("popen//chdir=%s" % dest)
finished = []
rsync = HostRSync(source)
rsync.add_target_host(gw, finished=lambda: finished.append(1))

View File

@ -1,101 +0,0 @@
"""
tests for py.execnet.GatewaySpec
"""
import py
class TestGatewaySpec:
"""
socket:hostname:port:path SocketGateway
popen[-executable][:path] PopenGateway
[ssh:]spec:path SshGateway
* [SshGateway]
"""
def test_popen(self):
for python in ('', 'python2.4'):
for joinpath in ('', 'abc', 'ab:cd', '/x/y'):
s = ":".join(["popen", python, joinpath])
print s
spec = py.execnet.GatewaySpec(s)
assert spec.address == "popen"
assert spec.python == (python or py.std.sys.executable)
assert spec.joinpath == joinpath
assert spec.type == "popen"
spec2 = py.execnet.GatewaySpec("popen" + joinpath)
self._equality(spec, spec2)
def test_ssh(self):
for prefix in ('ssh', ''): # ssh is default
for hostpart in ('x.y', 'xyz@x.y'):
for python in ('python', 'python2.5'):
for joinpath in ('', 'abc', 'ab:cd', '/tmp'):
specstring = ":".join([prefix, hostpart, python, joinpath])
if specstring[0] == ":":
specstring = specstring[1:]
print specstring
spec = py.execnet.GatewaySpec(specstring)
assert spec.address == hostpart
assert spec.python == python
if joinpath:
assert spec.joinpath == joinpath
else:
assert spec.joinpath == "pyexecnetcache"
assert spec.type == "ssh"
spec2 = py.execnet.GatewaySpec(specstring)
self._equality(spec, spec2)
def test_socket(self):
for hostpart in ('x.y', 'x', 'popen'):
for port in ":80", ":1000":
for joinpath in ('', ':abc', ':abc:de'):
spec = py.execnet.GatewaySpec("socket:" + hostpart + port + joinpath)
assert spec.address == (hostpart, int(port[1:]))
if joinpath[1:]:
assert spec.joinpath == joinpath[1:]
else:
assert spec.joinpath == "pyexecnetcache"
assert spec.type == "socket"
spec2 = py.execnet.GatewaySpec("socket:" + hostpart + port + joinpath)
self._equality(spec, spec2)
def _equality(self, spec1, spec2):
assert spec1 != spec2
assert hash(spec1) != hash(spec2)
assert not (spec1 == spec2)
class TestGatewaySpecAPI:
def test_popen_nopath_makegateway(self, testdir):
spec = py.execnet.GatewaySpec("popen")
gw = spec.makegateway()
p = gw.remote_exec("import os; channel.send(os.getcwd())").receive()
curdir = py.std.os.getcwd()
assert curdir == p
gw.exit()
def test_popen_makegateway(self, testdir):
spec = py.execnet.GatewaySpec("popen::" + str(testdir.tmpdir))
gw = spec.makegateway()
p = gw.remote_exec("import os; channel.send(os.getcwd())").receive()
assert spec.joinpath == p
gw.exit()
def test_popen_makegateway_python(self, testdir):
spec = py.execnet.GatewaySpec("popen:%s" % py.std.sys.executable)
gw = spec.makegateway()
res = gw.remote_exec("import sys ; channel.send(sys.executable)").receive()
assert py.std.sys.executable == py.std.sys.executable
gw.exit()
def test_ssh(self, specssh):
sshhost = specssh.ssh
spec = py.execnet.GatewaySpec("ssh:" + sshhost)
gw = spec.makegateway()
p = gw.remote_exec("import os ; channel.send(os.getcwd())").receive()
gw.exit()
@py.test.mark.xfail("implement socketserver test scenario")
def test_socketgateway(self):
gw = py.execnet.PopenGateway()
spec = py.execnet.GatewaySpec("ssh:" + sshhost)

View File

@ -4,23 +4,23 @@ XSpec = py.execnet.XSpec
class TestXSpec:
def test_attributes(self):
spec = XSpec("socket=192.168.102.2:8888//python=c:/this/python2.5//path=d:\hello")
spec = XSpec("socket=192.168.102.2:8888//python=c:/this/python2.5//chdir=d:\hello")
assert spec.socket == "192.168.102.2:8888"
assert spec.python == "c:/this/python2.5"
assert spec.path == "d:\hello"
assert spec.xyz is None
assert spec.chdir == "d:\hello"
assert not hasattr(spec, 'xyz')
py.test.raises(AttributeError, "spec._hello")
spec = XSpec("socket=192.168.102.2:8888//python=python2.5")
assert spec.socket == "192.168.102.2:8888"
assert spec.python == "python2.5"
assert spec.path is None
assert spec.chdir is None
spec = XSpec("ssh=user@host//path=/hello/this//python=/usr/bin/python2.5")
spec = XSpec("ssh=user@host//chdir=/hello/this//python=/usr/bin/python2.5")
assert spec.ssh == "user@host"
assert spec.python == "/usr/bin/python2.5"
assert spec.path == "/hello/this"
assert spec.chdir == "/hello/this"
spec = XSpec("popen")
assert spec.popen == True
@ -28,7 +28,17 @@ class TestXSpec:
def test__samefilesystem(self):
assert XSpec("popen")._samefilesystem()
assert XSpec("popen//python=123")._samefilesystem()
assert not XSpec("popen//path=hello")._samefilesystem()
assert not XSpec("popen//chdir=hello")._samefilesystem()
def test__spec_spec(self):
for x in ("popen", "popen//python=this"):
assert XSpec(x)._spec == x
def test_hash_equality(self):
assert XSpec("popen") == XSpec("popen")
assert hash(XSpec("popen")) == hash(XSpec("popen"))
assert XSpec("popen//python=123") != XSpec("popen")
assert hash(XSpec("socket=hello:8080")) != hash(XSpec("popen"))
class TestMakegateway:
def test_popen(self):

View File

@ -9,22 +9,36 @@ class XSpec:
* keys are not allowed to start with underscore
* if no "=value" is given, assume a boolean True value
"""
def __init__(self, *strings):
for string in strings:
for keyvalue in string.split("//"):
i = keyvalue.find("=")
if i == -1:
setattr(self, keyvalue, True)
else:
setattr(self, keyvalue[:i], keyvalue[i+1:])
# XXX for now we are very restrictive about actually allowed key-values
popen = ssh = socket = python = chdir = None
def __getattr__(self, name):
if name[0] == "_":
raise AttributeError(name)
return None
def __init__(self, string):
self._spec = string
for keyvalue in string.split("//"):
i = keyvalue.find("=")
if i == -1:
key, value = keyvalue, True
else:
key, value = keyvalue[:i], keyvalue[i+1:]
# XXX be restrictive for now
if key not in XSpec.__dict__:
raise AttributeError("%r not a valid attribute" % key)
setattr(self, key, value)
def __hash__(self):
return hash(self._spec)
def __eq__(self, other):
return self._spec == getattr(other, '_spec', None)
def __ne__(self, other):
return self._spec != getattr(other, '_spec', None)
#def __getattr__(self, name):
# if name[0] == "_":
# raise AttributeError(name)
# return None
def _samefilesystem(self):
return bool(self.popen and not self.path)
return bool(self.popen and not self.chdir)
def makegateway(spec):
if not isinstance(spec, XSpec):