[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:
|
||||
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):
|
||||
""" return an initialized session object. """
|
||||
cls = self._getsessionclass()
|
||||
|
|
|
@ -11,6 +11,7 @@ class Conftest(object):
|
|||
"""
|
||||
def __init__(self, path=None):
|
||||
self._path2confmods = {}
|
||||
self._path2conftest_files = {} # direct cache of conftest files, to avoid confusion
|
||||
if path is not None:
|
||||
self.setinitial([path])
|
||||
|
||||
|
@ -41,45 +42,62 @@ class Conftest(object):
|
|||
except KeyError:
|
||||
dp = path.dirpath()
|
||||
if dp == path:
|
||||
return [importconfig(defaultconftestpath)]
|
||||
return [self.importconfig(defaultconftestpath)]
|
||||
clist = self.getconftestmodules(dp)
|
||||
conftestpath = path.join("conftest.py")
|
||||
if conftestpath.check(file=1):
|
||||
clist.append(importconfig(conftestpath))
|
||||
clist.append(self.importconfig(conftestpath))
|
||||
self._path2confmods[path] = clist
|
||||
# be defensive: avoid changes from caller side to
|
||||
# affect us by always returning a copy of the actual list
|
||||
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
|
||||
#def lget(self, name, path=None):
|
||||
# modules = self.getconftestmodules(path)
|
||||
# return self._get(name, modules)
|
||||
|
||||
def rget(self, name, path=None):
|
||||
return self._rget(name, path)[0]
|
||||
|
||||
def _rget(self, name, path=None):
|
||||
modules = self.getconftestmodules(path)
|
||||
modules.reverse()
|
||||
return self._get(name, modules)
|
||||
|
||||
def rget_with_confmod(self, name, path=None):
|
||||
return self._rget(name, path)
|
||||
def rget_path(self, name, path):
|
||||
""" can raise AttributeError
|
||||
"""
|
||||
return getattr(self.getconftest(path), name)
|
||||
|
||||
def _get(self, name, modules):
|
||||
for mod in modules:
|
||||
try:
|
||||
return getattr(mod, name), mod
|
||||
return getattr(mod, name)
|
||||
except AttributeError:
|
||||
continue
|
||||
raise KeyError, name
|
||||
|
||||
def importconfig(configpath):
|
||||
if not configpath.dirpath('__init__.py').check(file=1):
|
||||
# HACK: we don't want any "globally" imported conftest.py,
|
||||
# prone to conflicts and subtle problems
|
||||
modname = str(configpath).replace('.', configpath.sep)
|
||||
return configpath.pyimport(modname=modname)
|
||||
else:
|
||||
return configpath.pyimport()
|
||||
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):
|
||||
# HACK: we don't want any "globally" imported conftest.py,
|
||||
# prone to conflicts and subtle problems
|
||||
modname = str(configpath).replace('.', configpath.sep)
|
||||
mod = configpath.pyimport(modname=modname)
|
||||
else:
|
||||
mod = configpath.pyimport()
|
||||
self._path2conftest_files[configpath.dirpath()] = mod
|
||||
return mod
|
||||
|
|
|
@ -41,20 +41,24 @@ class HostInfo(object):
|
|||
class HostRSync(py.execnet.RSync):
|
||||
""" 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)
|
||||
self.rsync_roots = rsync_roots
|
||||
self.config = config
|
||||
|
||||
def filter(self, path):
|
||||
if path.endswith('.pyc') or path.endswith('~'):
|
||||
return False
|
||||
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':
|
||||
return False
|
||||
if dir != self.sourcedir:
|
||||
if rsync_roots is None:
|
||||
return True
|
||||
else:
|
||||
return self.rsync_roots is None or path in self.rsync_roots
|
||||
return base in rsync_roots
|
||||
|
||||
class DummyGateway(object):
|
||||
pass
|
||||
|
@ -64,10 +68,9 @@ class HostOptions(object):
|
|||
as different function parameters, mostly related to
|
||||
tests only
|
||||
"""
|
||||
def __init__(self, rsync_roots=None, remote_python="python",
|
||||
def __init__(self, remote_python="python",
|
||||
optimise_localhost=True, do_sync=True,
|
||||
create_gateways=True):
|
||||
self.rsync_roots = rsync_roots
|
||||
self.remote_python = remote_python
|
||||
self.optimise_localhost = optimise_localhost
|
||||
self.do_sync = do_sync
|
||||
|
@ -145,7 +148,7 @@ class HostManager(object):
|
|||
rsynced = {}
|
||||
|
||||
if self.options.do_sync:
|
||||
rsync = HostRSync(self.options.rsync_roots)
|
||||
rsync = HostRSync(self.config)
|
||||
for host in hosts:
|
||||
if not self.need_rsync(rsynced, host.hostname, host.relpath):
|
||||
reporter(report.HostReady(host))
|
||||
|
|
|
@ -150,7 +150,7 @@ class RSession(AbstractSession):
|
|||
""" main loop for running tests. """
|
||||
args = self.config.args
|
||||
|
||||
sshhosts, remotepython, rsync_roots = self.read_distributed_config()
|
||||
sshhosts, remotepython = self.read_distributed_config()
|
||||
reporter, startserverflag = self.init_reporter(reporter,
|
||||
sshhosts, RemoteReporter)
|
||||
reporter, checkfun = self.wrap_reporter(reporter)
|
||||
|
@ -158,8 +158,7 @@ class RSession(AbstractSession):
|
|||
reporter(report.TestStarted(sshhosts))
|
||||
|
||||
done_dict = {}
|
||||
hostopts = HostOptions(rsync_roots=rsync_roots,
|
||||
remote_python=remotepython,
|
||||
hostopts = HostOptions(remote_python=remotepython,
|
||||
optimise_localhost=self.optimise_localhost)
|
||||
hostmanager = HostManager(sshhosts, self.config, hostopts)
|
||||
try:
|
||||
|
@ -194,26 +193,11 @@ class RSession(AbstractSession):
|
|||
def read_distributed_config(self):
|
||||
""" 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
|
||||
self.config.getvalue("dist_hosts")]
|
||||
parse_directories(sshhosts)
|
||||
remotepython = self.config.getvalue("dist_remotepython")
|
||||
return sshhosts, remotepython, rsync_roots
|
||||
return sshhosts, remotepython
|
||||
|
||||
def dispatch_tests(self, nodes, reporter, checkfun, done_dict):
|
||||
colitems = self.config.getcolitems()
|
||||
|
|
|
@ -161,8 +161,7 @@ class TestRSessionRemote:
|
|||
teardown_events = []
|
||||
|
||||
config = py.test.config._reparse([])
|
||||
opts = HostOptions(optimise_localhost=False,
|
||||
rsync_roots=[py.path.local(py.__file__).dirpath()])
|
||||
opts = HostOptions(optimise_localhost=False)
|
||||
hm = HostManager(hosts, config, opts)
|
||||
nodes = hm.init_hosts(setup_events.append)
|
||||
hm.teardown_hosts(teardown_events.append,
|
||||
|
@ -189,8 +188,7 @@ class TestRSessionRemote:
|
|||
allevents = []
|
||||
|
||||
config = py.test.config._reparse([])
|
||||
opts = HostOptions(optimise_localhost=False,
|
||||
rsync_roots=[py.path.local(py.__file__).dirpath()])
|
||||
opts = HostOptions(optimise_localhost=False)
|
||||
hm = HostManager(hosts, config, opts)
|
||||
nodes = hm.init_hosts(allevents.append)
|
||||
|
||||
|
@ -237,8 +235,7 @@ class TestRSessionRemote:
|
|||
from py.__.test.rsession.master import defaultconftestnames
|
||||
defaultconftestnames.append("custom")
|
||||
try:
|
||||
opts = HostOptions(optimise_localhost=False,
|
||||
rsync_roots=[py.path.local(py.__file__).dirpath()])
|
||||
opts = HostOptions(optimise_localhost=False)
|
||||
hm = HostManager(hosts, config, opts)
|
||||
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)
|
||||
# check if this really exits
|
||||
py.test.raises(OSError, "os.waitpid(pid, 0)")
|
||||
|
||||
|
|
|
@ -67,9 +67,12 @@ class TestConftestValueAccessGlobal:
|
|||
|
||||
def test_value_access_path(self):
|
||||
topdir = self.basedir.join("adir", "b")
|
||||
topdir.ensure("xx", dir=True)
|
||||
conftest = Conftest(topdir)
|
||||
_, mod = conftest.rget_with_confmod("a")
|
||||
assert py.path.local(mod.__file__).dirpath() == topdir
|
||||
assert conftest.rget_path("a", topdir) == 1.5
|
||||
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):
|
||||
def setup_class(cls):
|
||||
|
|
Loading…
Reference in New Issue