Merged in paylogic/pytest-xdist/rsyncignore-option (pull request #5)
add glob support for rsyncignore. add command line option for rsyncignore
This commit is contained in:
@@ -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/
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,13 @@ py.test references tests as a fully qualified python
|
|||||||
module path. **You will otherwise get strange errors**
|
module path. **You will otherwise get strange errors**
|
||||||
during setup of the remote side.
|
during setup of the remote side.
|
||||||
|
|
||||||
|
You can specify multiple ``--rsyncignore`` glob-patterns
|
||||||
|
to be ignored when file are sent to the remote side.
|
||||||
|
There are also internal ignores: .*, *.pyc, *.pyo, *~
|
||||||
|
Those you cannot override using rsyncignore command-line or
|
||||||
|
ini-file option(s).
|
||||||
|
|
||||||
|
|
||||||
Sending tests to remote Socket Servers
|
Sending tests to remote Socket Servers
|
||||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
|||||||
@@ -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():
|
||||||
|
|||||||
@@ -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,12 +197,15 @@ 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")
|
||||||
|
dirbar = source.ensure("bar", "foo")
|
||||||
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)
|
||||||
|
config.option.rsyncignore = ['bar']
|
||||||
nodemanager = NodeManager(config, ["popen//chdir=%s" % dest])
|
nodemanager = NodeManager(config, ["popen//chdir=%s" % dest])
|
||||||
nodemanager.makegateways()
|
nodemanager.makegateways()
|
||||||
nodemanager.rsync_roots()
|
nodemanager.rsync_roots()
|
||||||
@@ -210,6 +213,8 @@ 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()
|
||||||
|
assert not dest.join('bar').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
|
||||||
|
|||||||
@@ -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,12 +28,14 @@ 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="DIR",
|
||||||
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="GLOB",
|
||||||
|
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")
|
||||||
parser.addini('rsyncignore', 'list of (relative) paths to be ignored '
|
parser.addini('rsyncignore', 'list of (relative) glob-style paths to be ignored '
|
||||||
'for rsyncing.', type="pathlist")
|
'for rsyncing.', type="pathlist")
|
||||||
parser.addini("looponfailroots", type="pathlist",
|
parser.addini("looponfailroots", type="pathlist",
|
||||||
help="directories to check for changes", default=[py.path.local()])
|
help="directories to check for changes", default=[py.path.local()])
|
||||||
|
|||||||
@@ -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:
|
return False
|
||||||
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user