[svn r37533] Make distribution working with custom conftests at exact levels. This
is very explicit - dist_rsyncroots works only in that conftest directory. --HG-- branch : trunk
This commit is contained in:
parent
e921ad8af9
commit
acfbbcb7ff
|
@ -118,6 +118,14 @@ class Config(object):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return self.conftest.rget(name, path)
|
return self.conftest.rget(name, path)
|
||||||
|
|
||||||
|
def getvalue_from_confpath(self, name, path):
|
||||||
|
""" same as previous, but returns only value from explicit
|
||||||
|
conftest path
|
||||||
|
"""
|
||||||
|
if isinstance(path, str):
|
||||||
|
path = py.path.local(path)
|
||||||
|
return self.conftest.rget_path(name, path)
|
||||||
|
|
||||||
def initsession(self):
|
def initsession(self):
|
||||||
""" return an initialized session object. """
|
""" return an initialized session object. """
|
||||||
cls = self._getsessionclass()
|
cls = self._getsessionclass()
|
||||||
|
|
|
@ -11,6 +11,7 @@ class Conftest(object):
|
||||||
"""
|
"""
|
||||||
def __init__(self, path=None):
|
def __init__(self, path=None):
|
||||||
self._path2confmods = {}
|
self._path2confmods = {}
|
||||||
|
self._path2conftest_files = {} # direct cache of conftest files, to avoid confusion
|
||||||
if path is not None:
|
if path is not None:
|
||||||
self.setinitial([path])
|
self.setinitial([path])
|
||||||
|
|
||||||
|
@ -41,45 +42,62 @@ class Conftest(object):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
dp = path.dirpath()
|
dp = path.dirpath()
|
||||||
if dp == path:
|
if dp == path:
|
||||||
return [importconfig(defaultconftestpath)]
|
return [self.importconfig(defaultconftestpath)]
|
||||||
clist = self.getconftestmodules(dp)
|
clist = self.getconftestmodules(dp)
|
||||||
conftestpath = path.join("conftest.py")
|
conftestpath = path.join("conftest.py")
|
||||||
if conftestpath.check(file=1):
|
if conftestpath.check(file=1):
|
||||||
clist.append(importconfig(conftestpath))
|
clist.append(self.importconfig(conftestpath))
|
||||||
self._path2confmods[path] = clist
|
self._path2confmods[path] = clist
|
||||||
# be defensive: avoid changes from caller side to
|
# be defensive: avoid changes from caller side to
|
||||||
# affect us by always returning a copy of the actual list
|
# affect us by always returning a copy of the actual list
|
||||||
return clist[:]
|
return clist[:]
|
||||||
|
|
||||||
|
def getconftest(self, path):
|
||||||
|
""" Return a direct module of that path
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return self._path2conftest_files[path]
|
||||||
|
except KeyError:
|
||||||
|
conftestpath = path.join("conftest.py")
|
||||||
|
if conftestpath.check(file=1):
|
||||||
|
return self.importconfig(conftestpath)
|
||||||
|
raise AttributeError
|
||||||
|
# we raise here AttributeError to unify error reporting in case
|
||||||
|
# of lack of variable in conftest or lack of file, but we do not want to
|
||||||
|
# hide ImportError
|
||||||
|
|
||||||
# XXX no real use case, may probably go
|
# XXX no real use case, may probably go
|
||||||
#def lget(self, name, path=None):
|
#def lget(self, name, path=None):
|
||||||
# modules = self.getconftestmodules(path)
|
# modules = self.getconftestmodules(path)
|
||||||
# return self._get(name, modules)
|
# return self._get(name, modules)
|
||||||
|
|
||||||
def rget(self, name, path=None):
|
def rget(self, name, path=None):
|
||||||
return self._rget(name, path)[0]
|
|
||||||
|
|
||||||
def _rget(self, name, path=None):
|
|
||||||
modules = self.getconftestmodules(path)
|
modules = self.getconftestmodules(path)
|
||||||
modules.reverse()
|
modules.reverse()
|
||||||
return self._get(name, modules)
|
return self._get(name, modules)
|
||||||
|
|
||||||
def rget_with_confmod(self, name, path=None):
|
def rget_path(self, name, path):
|
||||||
return self._rget(name, path)
|
""" can raise AttributeError
|
||||||
|
"""
|
||||||
|
return getattr(self.getconftest(path), name)
|
||||||
|
|
||||||
def _get(self, name, modules):
|
def _get(self, name, modules):
|
||||||
for mod in modules:
|
for mod in modules:
|
||||||
try:
|
try:
|
||||||
return getattr(mod, name), mod
|
return getattr(mod, name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
raise KeyError, name
|
raise KeyError, name
|
||||||
|
|
||||||
def importconfig(configpath):
|
def importconfig(self, configpath):
|
||||||
|
# We could have used caching here, but it's redundant since
|
||||||
|
# they're cached on path anyway, so we use it only when doing rget_path
|
||||||
if not configpath.dirpath('__init__.py').check(file=1):
|
if not configpath.dirpath('__init__.py').check(file=1):
|
||||||
# HACK: we don't want any "globally" imported conftest.py,
|
# HACK: we don't want any "globally" imported conftest.py,
|
||||||
# prone to conflicts and subtle problems
|
# prone to conflicts and subtle problems
|
||||||
modname = str(configpath).replace('.', configpath.sep)
|
modname = str(configpath).replace('.', configpath.sep)
|
||||||
return configpath.pyimport(modname=modname)
|
mod = configpath.pyimport(modname=modname)
|
||||||
else:
|
else:
|
||||||
return configpath.pyimport()
|
mod = configpath.pyimport()
|
||||||
|
self._path2conftest_files[configpath.dirpath()] = mod
|
||||||
|
return mod
|
||||||
|
|
|
@ -41,20 +41,24 @@ class HostInfo(object):
|
||||||
class HostRSync(py.execnet.RSync):
|
class HostRSync(py.execnet.RSync):
|
||||||
""" An rsync wrapper which filters out *~, .svn/ and *.pyc
|
""" An rsync wrapper which filters out *~, .svn/ and *.pyc
|
||||||
"""
|
"""
|
||||||
def __init__(self, rsync_roots):
|
def __init__(self, config):
|
||||||
py.execnet.RSync.__init__(self, delete=True)
|
py.execnet.RSync.__init__(self, delete=True)
|
||||||
self.rsync_roots = rsync_roots
|
self.config = config
|
||||||
|
|
||||||
def filter(self, path):
|
def filter(self, path):
|
||||||
if path.endswith('.pyc') or path.endswith('~'):
|
if path.endswith('.pyc') or path.endswith('~'):
|
||||||
return False
|
return False
|
||||||
dir, base = os.path.split(path)
|
dir, base = os.path.split(path)
|
||||||
|
try:
|
||||||
|
rsync_roots = self.config.getvalue_from_confpath("dist_rsyncroots",
|
||||||
|
dir)
|
||||||
|
except AttributeError:
|
||||||
|
rsync_roots = None
|
||||||
if base == '.svn':
|
if base == '.svn':
|
||||||
return False
|
return False
|
||||||
if dir != self.sourcedir:
|
if rsync_roots is None:
|
||||||
return True
|
return True
|
||||||
else:
|
return base in rsync_roots
|
||||||
return self.rsync_roots is None or path in self.rsync_roots
|
|
||||||
|
|
||||||
class DummyGateway(object):
|
class DummyGateway(object):
|
||||||
pass
|
pass
|
||||||
|
@ -64,10 +68,9 @@ class HostOptions(object):
|
||||||
as different function parameters, mostly related to
|
as different function parameters, mostly related to
|
||||||
tests only
|
tests only
|
||||||
"""
|
"""
|
||||||
def __init__(self, rsync_roots=None, remote_python="python",
|
def __init__(self, remote_python="python",
|
||||||
optimise_localhost=True, do_sync=True,
|
optimise_localhost=True, do_sync=True,
|
||||||
create_gateways=True):
|
create_gateways=True):
|
||||||
self.rsync_roots = rsync_roots
|
|
||||||
self.remote_python = remote_python
|
self.remote_python = remote_python
|
||||||
self.optimise_localhost = optimise_localhost
|
self.optimise_localhost = optimise_localhost
|
||||||
self.do_sync = do_sync
|
self.do_sync = do_sync
|
||||||
|
@ -145,7 +148,7 @@ class HostManager(object):
|
||||||
rsynced = {}
|
rsynced = {}
|
||||||
|
|
||||||
if self.options.do_sync:
|
if self.options.do_sync:
|
||||||
rsync = HostRSync(self.options.rsync_roots)
|
rsync = HostRSync(self.config)
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
if not self.need_rsync(rsynced, host.hostname, host.relpath):
|
if not self.need_rsync(rsynced, host.hostname, host.relpath):
|
||||||
reporter(report.HostReady(host))
|
reporter(report.HostReady(host))
|
||||||
|
|
|
@ -150,7 +150,7 @@ class RSession(AbstractSession):
|
||||||
""" main loop for running tests. """
|
""" main loop for running tests. """
|
||||||
args = self.config.args
|
args = self.config.args
|
||||||
|
|
||||||
sshhosts, remotepython, rsync_roots = self.read_distributed_config()
|
sshhosts, remotepython = self.read_distributed_config()
|
||||||
reporter, startserverflag = self.init_reporter(reporter,
|
reporter, startserverflag = self.init_reporter(reporter,
|
||||||
sshhosts, RemoteReporter)
|
sshhosts, RemoteReporter)
|
||||||
reporter, checkfun = self.wrap_reporter(reporter)
|
reporter, checkfun = self.wrap_reporter(reporter)
|
||||||
|
@ -158,8 +158,7 @@ class RSession(AbstractSession):
|
||||||
reporter(report.TestStarted(sshhosts))
|
reporter(report.TestStarted(sshhosts))
|
||||||
|
|
||||||
done_dict = {}
|
done_dict = {}
|
||||||
hostopts = HostOptions(rsync_roots=rsync_roots,
|
hostopts = HostOptions(remote_python=remotepython,
|
||||||
remote_python=remotepython,
|
|
||||||
optimise_localhost=self.optimise_localhost)
|
optimise_localhost=self.optimise_localhost)
|
||||||
hostmanager = HostManager(sshhosts, self.config, hostopts)
|
hostmanager = HostManager(sshhosts, self.config, hostopts)
|
||||||
try:
|
try:
|
||||||
|
@ -194,26 +193,11 @@ class RSession(AbstractSession):
|
||||||
def read_distributed_config(self):
|
def read_distributed_config(self):
|
||||||
""" Read from conftest file the configuration of distributed testing
|
""" Read from conftest file the configuration of distributed testing
|
||||||
"""
|
"""
|
||||||
try:
|
|
||||||
conftest = self.config.conftest
|
|
||||||
value, mod = conftest.rget_with_confmod('dist_rsync_roots')
|
|
||||||
except KeyError:
|
|
||||||
rsync_roots = [self.config.topdir] # our best guess likely
|
|
||||||
else:
|
|
||||||
assert isinstance(value, (list,tuple)), value
|
|
||||||
base = py.path.local(mod.__file__).dirpath()
|
|
||||||
print "base", base
|
|
||||||
rsync_roots = [base.join(path, abs=True)
|
|
||||||
for path in value]
|
|
||||||
for root in rsync_roots:
|
|
||||||
assert root.check(dir=1)
|
|
||||||
#rsync_roots = value
|
|
||||||
print "rsync_roots", rsync_roots
|
|
||||||
sshhosts = [HostInfo(i) for i in
|
sshhosts = [HostInfo(i) for i in
|
||||||
self.config.getvalue("dist_hosts")]
|
self.config.getvalue("dist_hosts")]
|
||||||
parse_directories(sshhosts)
|
parse_directories(sshhosts)
|
||||||
remotepython = self.config.getvalue("dist_remotepython")
|
remotepython = self.config.getvalue("dist_remotepython")
|
||||||
return sshhosts, remotepython, rsync_roots
|
return sshhosts, remotepython
|
||||||
|
|
||||||
def dispatch_tests(self, nodes, reporter, checkfun, done_dict):
|
def dispatch_tests(self, nodes, reporter, checkfun, done_dict):
|
||||||
colitems = self.config.getcolitems()
|
colitems = self.config.getcolitems()
|
||||||
|
|
|
@ -161,8 +161,7 @@ class TestRSessionRemote:
|
||||||
teardown_events = []
|
teardown_events = []
|
||||||
|
|
||||||
config = py.test.config._reparse([])
|
config = py.test.config._reparse([])
|
||||||
opts = HostOptions(optimise_localhost=False,
|
opts = HostOptions(optimise_localhost=False)
|
||||||
rsync_roots=[py.path.local(py.__file__).dirpath()])
|
|
||||||
hm = HostManager(hosts, config, opts)
|
hm = HostManager(hosts, config, opts)
|
||||||
nodes = hm.init_hosts(setup_events.append)
|
nodes = hm.init_hosts(setup_events.append)
|
||||||
hm.teardown_hosts(teardown_events.append,
|
hm.teardown_hosts(teardown_events.append,
|
||||||
|
@ -189,8 +188,7 @@ class TestRSessionRemote:
|
||||||
allevents = []
|
allevents = []
|
||||||
|
|
||||||
config = py.test.config._reparse([])
|
config = py.test.config._reparse([])
|
||||||
opts = HostOptions(optimise_localhost=False,
|
opts = HostOptions(optimise_localhost=False)
|
||||||
rsync_roots=[py.path.local(py.__file__).dirpath()])
|
|
||||||
hm = HostManager(hosts, config, opts)
|
hm = HostManager(hosts, config, opts)
|
||||||
nodes = hm.init_hosts(allevents.append)
|
nodes = hm.init_hosts(allevents.append)
|
||||||
|
|
||||||
|
@ -237,8 +235,7 @@ class TestRSessionRemote:
|
||||||
from py.__.test.rsession.master import defaultconftestnames
|
from py.__.test.rsession.master import defaultconftestnames
|
||||||
defaultconftestnames.append("custom")
|
defaultconftestnames.append("custom")
|
||||||
try:
|
try:
|
||||||
opts = HostOptions(optimise_localhost=False,
|
opts = HostOptions(optimise_localhost=False)
|
||||||
rsync_roots=[py.path.local(py.__file__).dirpath()])
|
|
||||||
hm = HostManager(hosts, config, opts)
|
hm = HostManager(hosts, config, opts)
|
||||||
nodes = hm.init_hosts(allevents.append)
|
nodes = hm.init_hosts(allevents.append)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
""" RSync filter test
|
||||||
|
"""
|
||||||
|
|
||||||
|
import py
|
||||||
|
from py.__.test.rsession.hostmanage import HostRSync
|
||||||
|
|
||||||
|
def test_rsync():
|
||||||
|
tmpdir = py.test.ensuretemp("rsync_rsession")
|
||||||
|
tmpdir.ensure("a", dir=True)
|
||||||
|
tmpdir.ensure("b", dir=True)
|
||||||
|
tmpdir.ensure("conftest.py").write(py.code.Source("""
|
||||||
|
dist_rsyncroots = ['a']
|
||||||
|
"""))
|
||||||
|
tmpdir.join("a").ensure("x")
|
||||||
|
adir = tmpdir.join("a").ensure("xy", dir=True)
|
||||||
|
adir.ensure("conftest.py").write(py.code.Source("""
|
||||||
|
dist_rsyncroots = ['b', 'conftest.py']
|
||||||
|
"""))
|
||||||
|
adir.ensure("a", dir=True)
|
||||||
|
adir.ensure("b", dir=True)
|
||||||
|
config = py.test.config._reparse([str(tmpdir)])
|
||||||
|
h = HostRSync(config)
|
||||||
|
h.sourcedir = config.topdir
|
||||||
|
assert h.filter(str(tmpdir.join("a")))
|
||||||
|
assert not h.filter(str(tmpdir.join("b")))
|
||||||
|
assert h.filter(str(tmpdir.join("a").join("x")))
|
||||||
|
assert h.filter(str(adir.join("conftest.py")))
|
||||||
|
assert not h.filter(str(adir.join("a")))
|
||||||
|
assert h.filter(str(adir.join("b")))
|
|
@ -179,4 +179,3 @@ def test_pidinfo():
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
# check if this really exits
|
# check if this really exits
|
||||||
py.test.raises(OSError, "os.waitpid(pid, 0)")
|
py.test.raises(OSError, "os.waitpid(pid, 0)")
|
||||||
|
|
||||||
|
|
|
@ -67,9 +67,12 @@ class TestConftestValueAccessGlobal:
|
||||||
|
|
||||||
def test_value_access_path(self):
|
def test_value_access_path(self):
|
||||||
topdir = self.basedir.join("adir", "b")
|
topdir = self.basedir.join("adir", "b")
|
||||||
|
topdir.ensure("xx", dir=True)
|
||||||
conftest = Conftest(topdir)
|
conftest = Conftest(topdir)
|
||||||
_, mod = conftest.rget_with_confmod("a")
|
assert conftest.rget_path("a", topdir) == 1.5
|
||||||
assert py.path.local(mod.__file__).dirpath() == topdir
|
assert conftest.rget_path("a", topdir.dirpath()) == 1
|
||||||
|
py.test.raises(AttributeError, "conftest.rget_path('a', topdir.join('xx'))")
|
||||||
|
#assert py.path.local(mod.__file__).dirpath() == topdir
|
||||||
|
|
||||||
class TestConftestValueAccessInPackage(TestConftestValueAccessGlobal):
|
class TestConftestValueAccessInPackage(TestConftestValueAccessGlobal):
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
|
|
Loading…
Reference in New Issue