[svn r63147] get rid of old method for specifying remote execution places.
--HG-- branch : trunk
This commit is contained in:
parent
9cd41c91bd
commit
a4c14e83f0
|
@ -27,8 +27,8 @@ version = "1.0.0a1"
|
||||||
|
|
||||||
initpkg(__name__,
|
initpkg(__name__,
|
||||||
description = "pylib and py.test: agile development and test support library",
|
description = "pylib and py.test: agile development and test support library",
|
||||||
revision = int('$LastChangedRevision: 63144 $'.split(':')[1][:-1]),
|
revision = int('$LastChangedRevision: 63147 $'.split(':')[1][:-1]),
|
||||||
lastchangedate = '$LastChangedDate: 2009-03-20 16:36:45 +0100 (Fri, 20 Mar 2009) $',
|
lastchangedate = '$LastChangedDate: 2009-03-20 17:28:14 +0100 (Fri, 20 Mar 2009) $',
|
||||||
version = version,
|
version = version,
|
||||||
url = "http://pylib.org",
|
url = "http://pylib.org",
|
||||||
download_url = "http://codespeak.net/py/0.9.2/download.html",
|
download_url = "http://codespeak.net/py/0.9.2/download.html",
|
||||||
|
@ -151,7 +151,6 @@ initpkg(__name__,
|
||||||
'execnet.SocketGateway' : ('./execnet/register.py', 'SocketGateway'),
|
'execnet.SocketGateway' : ('./execnet/register.py', 'SocketGateway'),
|
||||||
'execnet.PopenGateway' : ('./execnet/register.py', 'PopenGateway'),
|
'execnet.PopenGateway' : ('./execnet/register.py', 'PopenGateway'),
|
||||||
'execnet.SshGateway' : ('./execnet/register.py', 'SshGateway'),
|
'execnet.SshGateway' : ('./execnet/register.py', 'SshGateway'),
|
||||||
'execnet.GatewaySpec' : ('./execnet/gwmanage.py', 'GatewaySpec'),
|
|
||||||
'execnet.XSpec' : ('./execnet/xspec.py', 'XSpec'),
|
'execnet.XSpec' : ('./execnet/xspec.py', 'XSpec'),
|
||||||
'execnet.makegateway' : ('./execnet/xspec.py', 'makegateway'),
|
'execnet.makegateway' : ('./execnet/xspec.py', 'makegateway'),
|
||||||
'execnet.MultiGateway' : ('./execnet/multi.py', 'MultiGateway'),
|
'execnet.MultiGateway' : ('./execnet/multi.py', 'MultiGateway'),
|
||||||
|
|
|
@ -37,9 +37,11 @@ def getspecssh(config=None):
|
||||||
if not py.path.local.sysfind("ssh"):
|
if not py.path.local.sysfind("ssh"):
|
||||||
py.test.skip("command not found: ssh")
|
py.test.skip("command not found: ssh")
|
||||||
return spec
|
return spec
|
||||||
|
py.test.skip("need '--gx ssh=...'")
|
||||||
|
|
||||||
def getsocketspec(config=None):
|
def getsocketspec(config=None):
|
||||||
xspecs = getgspecs(config)
|
xspecs = getgspecs(config)
|
||||||
for spec in xspecs:
|
for spec in xspecs:
|
||||||
if spec.socket:
|
if spec.socket:
|
||||||
return spec
|
return spec
|
||||||
|
py.test.skip("need '--gx socket=...'")
|
||||||
|
|
|
@ -1,105 +1,19 @@
|
||||||
"""
|
"""
|
||||||
instantiating, managing and rsyncing to hosts
|
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 py
|
||||||
import sys, os
|
import sys, os
|
||||||
from py.__.test.dsession.masterslave import MasterNode
|
|
||||||
from py.__.test import event
|
|
||||||
from py.__.execnet.channel import RemoteError
|
from py.__.execnet.channel import RemoteError
|
||||||
|
|
||||||
NO_ENDMARKER_WANTED = object()
|
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:
|
class GatewayManager:
|
||||||
RemoteError = RemoteError
|
RemoteError = RemoteError
|
||||||
|
|
||||||
def __init__(self, specs):
|
def __init__(self, specs):
|
||||||
self.specs = [GatewaySpec(spec) for spec in specs]
|
self.specs = [py.execnet.XSpec(spec) for spec in specs]
|
||||||
self.gateways = []
|
self.gateways = []
|
||||||
|
|
||||||
def trace(self, msg):
|
def trace(self, msg):
|
||||||
|
@ -111,7 +25,7 @@ class GatewayManager:
|
||||||
def makegateways(self):
|
def makegateways(self):
|
||||||
assert not self.gateways
|
assert not self.gateways
|
||||||
for spec in self.specs:
|
for spec in self.specs:
|
||||||
gw = spec.makegateway()
|
gw = py.execnet.makegateway(spec)
|
||||||
self.gateways.append(gw)
|
self.gateways.append(gw)
|
||||||
gw.id = "[%s]" % len(self.gateways)
|
gw.id = "[%s]" % len(self.gateways)
|
||||||
self.notify("gwmanage_newgateway", gw)
|
self.notify("gwmanage_newgateway", gw)
|
||||||
|
@ -121,7 +35,7 @@ class GatewayManager:
|
||||||
self.makegateways()
|
self.makegateways()
|
||||||
l = []
|
l = []
|
||||||
for gw in self.gateways:
|
for gw in self.gateways:
|
||||||
if gw.spec.inplacelocal():
|
if gw.spec._samefilesystem():
|
||||||
if inplacelocal:
|
if inplacelocal:
|
||||||
l.append(gw)
|
l.append(gw)
|
||||||
else:
|
else:
|
||||||
|
@ -150,15 +64,14 @@ class GatewayManager:
|
||||||
seen = {}
|
seen = {}
|
||||||
for gateway in self.gateways:
|
for gateway in self.gateways:
|
||||||
spec = gateway.spec
|
spec = gateway.spec
|
||||||
if not spec.inplacelocal():
|
if not spec._samefilesystem():
|
||||||
key = spec.type, spec.address, spec.joinpath
|
if spec in seen:
|
||||||
if key in seen:
|
|
||||||
continue
|
continue
|
||||||
def finished():
|
def finished():
|
||||||
if notify:
|
if notify:
|
||||||
notify("rsyncrootready", spec, source)
|
notify("rsyncrootready", spec, source)
|
||||||
rsync.add_target_host(gateway, finished=finished)
|
rsync.add_target_host(gateway, finished=finished)
|
||||||
seen[key] = gateway
|
seen[spec] = gateway
|
||||||
if seen:
|
if seen:
|
||||||
self.notify("gwmanage_rsyncstart", source=source, gateways=seen.values())
|
self.notify("gwmanage_rsyncstart", source=source, gateways=seen.values())
|
||||||
rsync.send()
|
rsync.send()
|
||||||
|
@ -203,5 +116,5 @@ class HostRSync(py.execnet.RSync):
|
||||||
def _report_send_file(self, gateway, modified_rel_path):
|
def _report_send_file(self, gateway, modified_rel_path):
|
||||||
if self._verbose:
|
if self._verbose:
|
||||||
path = os.path.basename(self._sourcedir) + "/" + modified_rel_path
|
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)
|
print '%s:%s <= %s' % (gateway.remoteaddress, remotepath, path)
|
||||||
|
|
|
@ -37,7 +37,7 @@ class TestGatewayManagerPopen:
|
||||||
assert not len(hm.gateways)
|
assert not len(hm.gateways)
|
||||||
|
|
||||||
def test_hostmanager_rsync_popen_with_path(self, source, dest):
|
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()
|
hm.makegateways()
|
||||||
source.ensure("dir1", "dir2", "hello")
|
source.ensure("dir1", "dir2", "hello")
|
||||||
l = []
|
l = []
|
||||||
|
@ -51,7 +51,7 @@ class TestGatewayManagerPopen:
|
||||||
assert dest.join("dir1", "dir2", 'hello').check()
|
assert dest.join("dir1", "dir2", 'hello').check()
|
||||||
|
|
||||||
def test_hostmanage_rsync_same_popen_twice(self, source, dest, eventrecorder):
|
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()
|
hm.makegateways()
|
||||||
source.ensure("dir1", "dir2", "hello")
|
source.ensure("dir1", "dir2", "hello")
|
||||||
hm.rsync(source)
|
hm.rsync(source)
|
||||||
|
@ -65,7 +65,7 @@ class TestGatewayManagerPopen:
|
||||||
|
|
||||||
def test_multi_chdir_popen_with_path(self, testdir):
|
def test_multi_chdir_popen_with_path(self, testdir):
|
||||||
import os
|
import os
|
||||||
hm = GatewayManager(["popen::hello"] * 2)
|
hm = GatewayManager(["popen//chdir=hello"] * 2)
|
||||||
testdir.tmpdir.chdir()
|
testdir.tmpdir.chdir()
|
||||||
hellopath = testdir.tmpdir.mkdir("hello")
|
hellopath = testdir.tmpdir.mkdir("hello")
|
||||||
hm.makegateways()
|
hm.makegateways()
|
||||||
|
@ -122,8 +122,7 @@ class TestHRSync:
|
||||||
assert 'somedir' in basenames
|
assert 'somedir' in basenames
|
||||||
|
|
||||||
def test_hrsync_one_host(self, source, dest):
|
def test_hrsync_one_host(self, source, dest):
|
||||||
spec = py.execnet.GatewaySpec("popen::%s" % dest)
|
gw = py.execnet.makegateway("popen//chdir=%s" % dest)
|
||||||
gw = spec.makegateway()
|
|
||||||
finished = []
|
finished = []
|
||||||
rsync = HostRSync(source)
|
rsync = HostRSync(source)
|
||||||
rsync.add_target_host(gw, finished=lambda: finished.append(1))
|
rsync.add_target_host(gw, finished=lambda: finished.append(1))
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
|
@ -4,23 +4,23 @@ XSpec = py.execnet.XSpec
|
||||||
|
|
||||||
class TestXSpec:
|
class TestXSpec:
|
||||||
def test_attributes(self):
|
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.socket == "192.168.102.2:8888"
|
||||||
assert spec.python == "c:/this/python2.5"
|
assert spec.python == "c:/this/python2.5"
|
||||||
assert spec.path == "d:\hello"
|
assert spec.chdir == "d:\hello"
|
||||||
assert spec.xyz is None
|
assert not hasattr(spec, 'xyz')
|
||||||
|
|
||||||
py.test.raises(AttributeError, "spec._hello")
|
py.test.raises(AttributeError, "spec._hello")
|
||||||
|
|
||||||
spec = XSpec("socket=192.168.102.2:8888//python=python2.5")
|
spec = XSpec("socket=192.168.102.2:8888//python=python2.5")
|
||||||
assert spec.socket == "192.168.102.2:8888"
|
assert spec.socket == "192.168.102.2:8888"
|
||||||
assert spec.python == "python2.5"
|
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.ssh == "user@host"
|
||||||
assert spec.python == "/usr/bin/python2.5"
|
assert spec.python == "/usr/bin/python2.5"
|
||||||
assert spec.path == "/hello/this"
|
assert spec.chdir == "/hello/this"
|
||||||
|
|
||||||
spec = XSpec("popen")
|
spec = XSpec("popen")
|
||||||
assert spec.popen == True
|
assert spec.popen == True
|
||||||
|
@ -28,7 +28,17 @@ class TestXSpec:
|
||||||
def test__samefilesystem(self):
|
def test__samefilesystem(self):
|
||||||
assert XSpec("popen")._samefilesystem()
|
assert XSpec("popen")._samefilesystem()
|
||||||
assert XSpec("popen//python=123")._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:
|
class TestMakegateway:
|
||||||
def test_popen(self):
|
def test_popen(self):
|
||||||
|
|
|
@ -9,22 +9,36 @@ class XSpec:
|
||||||
* keys are not allowed to start with underscore
|
* keys are not allowed to start with underscore
|
||||||
* if no "=value" is given, assume a boolean True value
|
* if no "=value" is given, assume a boolean True value
|
||||||
"""
|
"""
|
||||||
def __init__(self, *strings):
|
# XXX for now we are very restrictive about actually allowed key-values
|
||||||
for string in strings:
|
popen = ssh = socket = python = chdir = None
|
||||||
|
|
||||||
|
def __init__(self, string):
|
||||||
|
self._spec = string
|
||||||
for keyvalue in string.split("//"):
|
for keyvalue in string.split("//"):
|
||||||
i = keyvalue.find("=")
|
i = keyvalue.find("=")
|
||||||
if i == -1:
|
if i == -1:
|
||||||
setattr(self, keyvalue, True)
|
key, value = keyvalue, True
|
||||||
else:
|
else:
|
||||||
setattr(self, keyvalue[:i], keyvalue[i+1:])
|
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 __getattr__(self, name):
|
def __hash__(self):
|
||||||
if name[0] == "_":
|
return hash(self._spec)
|
||||||
raise AttributeError(name)
|
def __eq__(self, other):
|
||||||
return None
|
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):
|
def _samefilesystem(self):
|
||||||
return bool(self.popen and not self.path)
|
return bool(self.popen and not self.chdir)
|
||||||
|
|
||||||
def makegateway(spec):
|
def makegateway(spec):
|
||||||
if not isinstance(spec, XSpec):
|
if not isinstance(spec, XSpec):
|
||||||
|
|
Loading…
Reference in New Issue