[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:
fijal 2007-01-29 14:06:19 +01:00
parent e921ad8af9
commit acfbbcb7ff
8 changed files with 94 additions and 52 deletions

View File

@ -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()

View File

@ -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

View File

@ -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))

View File

@ -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()

View File

@ -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)

View File

@ -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")))

View File

@ -179,4 +179,3 @@ def test_pidinfo():
os._exit(0)
# check if this really exits
py.test.raises(OSError, "os.waitpid(pid, 0)")

View File

@ -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):