add glob support for rsyncignore. add command line option for rsyncignore

This commit is contained in:
Anatoly Bubenkov
2013-12-05 15:19:31 +01:00
parent 8146b27671
commit f4b86f0127
6 changed files with 50 additions and 26 deletions

View File

@@ -14,8 +14,14 @@ syntax:glob
*.class *.class
*.orig *.orig
*.sublime-*
.Python
build/ build/
dist/ dist/
include/
lib/
bin/
pytest_xdist.egg-info pytest_xdist.egg-info
issue/ issue/
3rdparty/ 3rdparty/

View File

@@ -1,9 +1,7 @@
1.10 unreleased 1.10 unreleased
------------------------- -------------------------
- ignore pyc files, dot files and directories for changes (editors write tmp/swap - add glob support for rsyncignores, add command line option to pass additional rsyncignores
files etc., which also affects mtime of directory)
- fix pytest issue382 - produce "pytest_runtest_logstart" event again - fix pytest issue382 - produce "pytest_runtest_logstart" event again
in master. Thanks Aron Curzon. in master. Thanks Aron Curzon.

View File

@@ -46,6 +46,11 @@ class TestDistOptions:
assert nm.roots assert nm.roots
assert testdir.tmpdir in nm.roots assert testdir.tmpdir in nm.roots
def test_getrsyncignore(self, testdir):
config = testdir.parseconfigure('--rsyncignore=fo*')
nm = NodeManager(config, specs=[execnet.XSpec("popen//chdir=qwe")])
assert 'fo*' in nm.rsyncoptions['ignores']
def test_getrsyncdirs_with_conftest(self, testdir): def test_getrsyncdirs_with_conftest(self, testdir):
p = py.path.local() p = py.path.local()
for bn in 'x y z'.split(): for bn in 'x y z'.split():

View File

@@ -113,7 +113,7 @@ class TestHRSync:
source.ensure(".svn", "entries") source.ensure(".svn", "entries")
source.ensure(".somedotfile", "moreentries") source.ensure(".somedotfile", "moreentries")
source.ensure("somedir", "editfile~") source.ensure("somedir", "editfile~")
syncer = HostRSync(source) syncer = HostRSync(source, ignores=NodeManager.DEFAULT_IGNORES)
l = list(source.visit(rec=syncer.filter, l = list(source.visit(rec=syncer.filter,
fil=syncer.filter)) fil=syncer.filter))
assert len(l) == 3 assert len(l) == 3
@@ -197,10 +197,11 @@ class TestNodeManager:
dir5 = source.ensure("dir5", "dir6", "bogus") dir5 = source.ensure("dir5", "dir6", "bogus")
dirf = source.ensure("dir5", "file") dirf = source.ensure("dir5", "file")
dir2.ensure("hello") dir2.ensure("hello")
dirfoo = source.ensure("foo", "bar")
source.join("tox.ini").write(py.std.textwrap.dedent(""" source.join("tox.ini").write(py.std.textwrap.dedent("""
[pytest] [pytest]
rsyncdirs = dir1 dir5 rsyncdirs = dir1 dir5
rsyncignore = dir1/dir2 dir5/dir6 rsyncignore = dir1/dir2 dir5/dir6 foo*
""")) """))
config = testdir.parseconfig(source) config = testdir.parseconfig(source)
nodemanager = NodeManager(config, ["popen//chdir=%s" % dest]) nodemanager = NodeManager(config, ["popen//chdir=%s" % dest])
@@ -210,6 +211,7 @@ class TestNodeManager:
assert not dest.join("dir1", "dir2").check() assert not dest.join("dir1", "dir2").check()
assert dest.join("dir5","file").check() assert dest.join("dir5","file").check()
assert not dest.join("dir6").check() assert not dest.join("dir6").check()
assert not dest.join('foo').check()
def test_optimise_popen(self, testdir, mysetup): def test_optimise_popen(self, testdir, mysetup):
source, dest = mysetup.source, mysetup.dest source, dest = mysetup.source, mysetup.dest

View File

@@ -1,5 +1,5 @@
import sys import py
import py, pytest import pytest
def pytest_addoption(parser): def pytest_addoption(parser):
group = parser.getgroup("xdist", "distributed and subprocess testing") group = parser.getgroup("xdist", "distributed and subprocess testing")
@@ -28,8 +28,10 @@ def pytest_addoption(parser):
group._addoption('-d', group._addoption('-d',
action="store_true", dest="distload", default=False, action="store_true", dest="distload", default=False,
help="load-balance tests. shortcut for '--dist=load'") help="load-balance tests. shortcut for '--dist=load'")
group.addoption('--rsyncdir', action="append", default=[], metavar="dir1", group.addoption('--rsyncdir', action="append", default=[], metavar="rsyncdirs",
help="add directory for rsyncing to remote tx nodes.") help="add directory for rsyncing to remote tx nodes.")
group.addoption('--rsyncignore', action="append", default=[], metavar="rsyncignores",
help="add expression for ignores when rsyncing to remote tx nodes.")
parser.addini('rsyncdirs', 'list of (relative) paths to be rsynced for' parser.addini('rsyncdirs', 'list of (relative) paths to be rsynced for'
' remote distributed testing.', type="pathlist") ' remote distributed testing.', type="pathlist")

View File

@@ -1,5 +1,8 @@
import py, pytest import fnmatch
import sys, os import os
import py
import pytest
import execnet import execnet
import xdist.remote import xdist.remote
@@ -7,6 +10,7 @@ from _pytest import runner # XXX load dynamically
class NodeManager(object): class NodeManager(object):
EXIT_TIMEOUT = 10 EXIT_TIMEOUT = 10
DEFAULT_IGNORES = ['.*', '*.pyc', '*.pyo', '*~']
def __init__(self, config, specs=None, defaultchdir="pyexecnetcache"): def __init__(self, config, specs=None, defaultchdir="pyexecnetcache"):
self.config = config self.config = config
self._nodesready = py.std.threading.Event() self._nodesready = py.std.threading.Event()
@@ -23,20 +27,17 @@ class NodeManager(object):
self.group.allocate_id(spec) self.group.allocate_id(spec)
self.specs.append(spec) self.specs.append(spec)
self.roots = self._getrsyncdirs() self.roots = self._getrsyncdirs()
self.rsyncoptions = self._getrsyncoptions()
def rsync_roots(self): def rsync_roots(self):
""" make sure that all remote gateways """ make sure that all remote gateways
have the same set of roots in their have the same set of roots in their
current directory. current directory.
""" """
options = {
'ignores': self.config.getini("rsyncignore"),
'verbose': self.config.option.verbose,
}
if self.roots: if self.roots:
# send each rsync root # send each rsync root
for root in self.roots: for root in self.roots:
self.rsync(root, **options) self.rsync(root, **self.rsyncoptions)
def makegateways(self): def makegateways(self):
assert not list(self.group) assert not list(self.group)
@@ -98,6 +99,18 @@ class NodeManager(object):
roots.append(root) roots.append(root)
return roots return roots
def _getrsyncoptions(self):
"""Get options to be passed for rsync."""
ignores = list(self.DEFAULT_IGNORES)
ignores = self.config.option.rsyncignore
ignores += self.config.getini("rsyncignore")
return {
'ignores': ignores,
'verbose': self.config.option.verbose,
}
def rsync(self, source, notify=None, verbose=False, ignores=None): def rsync(self, source, notify=None, verbose=False, ignores=None):
""" perform rsync to all remote hosts. """ perform rsync to all remote hosts.
""" """
@@ -144,14 +157,12 @@ class HostRSync(execnet.RSync):
def filter(self, path): def filter(self, path):
path = py.path.local(path) path = py.path.local(path)
if not path.ext in ('.pyc', '.pyo'): for x in self._ignores:
if not path.basename.endswith('~'): x = getattr(x, 'strpath', x)
if path.check(dotfile=0): if fnmatch.fnmatch(path.basename, x) or fnmatch.fnmatch(path.strpath, x):
for x in self._ignores: break
if path == x: else:
break return True
else:
return True
def add_target_host(self, gateway, finished=None): def add_target_host(self, gateway, finished=None):
remotepath = os.path.basename(self._sourcedir) remotepath = os.path.basename(self._sourcedir)