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
|
||||
*.orig
|
||||
|
||||
*.sublime-*
|
||||
.Python
|
||||
|
||||
build/
|
||||
dist/
|
||||
include/
|
||||
lib/
|
||||
bin/
|
||||
pytest_xdist.egg-info
|
||||
issue/
|
||||
3rdparty/
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
1.10 unreleased
|
||||
-------------------------
|
||||
|
||||
- ignore pyc files, dot files and directories for changes (editors write tmp/swap
|
||||
files etc., which also affects mtime of directory)
|
||||
|
||||
- add glob support for rsyncignores, add command line option to pass additional rsyncignores
|
||||
- fix pytest issue382 - produce "pytest_runtest_logstart" event again
|
||||
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**
|
||||
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
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
|
||||
@@ -46,6 +46,11 @@ class TestDistOptions:
|
||||
assert 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):
|
||||
p = py.path.local()
|
||||
for bn in 'x y z'.split():
|
||||
|
||||
@@ -113,7 +113,7 @@ class TestHRSync:
|
||||
source.ensure(".svn", "entries")
|
||||
source.ensure(".somedotfile", "moreentries")
|
||||
source.ensure("somedir", "editfile~")
|
||||
syncer = HostRSync(source)
|
||||
syncer = HostRSync(source, ignores=NodeManager.DEFAULT_IGNORES)
|
||||
l = list(source.visit(rec=syncer.filter,
|
||||
fil=syncer.filter))
|
||||
assert len(l) == 3
|
||||
@@ -197,12 +197,15 @@ class TestNodeManager:
|
||||
dir5 = source.ensure("dir5", "dir6", "bogus")
|
||||
dirf = source.ensure("dir5", "file")
|
||||
dir2.ensure("hello")
|
||||
dirfoo = source.ensure("foo", "bar")
|
||||
dirbar = source.ensure("bar", "foo")
|
||||
source.join("tox.ini").write(py.std.textwrap.dedent("""
|
||||
[pytest]
|
||||
rsyncdirs = dir1 dir5
|
||||
rsyncignore = dir1/dir2 dir5/dir6
|
||||
rsyncignore = dir1/dir2 dir5/dir6 foo*
|
||||
"""))
|
||||
config = testdir.parseconfig(source)
|
||||
config.option.rsyncignore = ['bar']
|
||||
nodemanager = NodeManager(config, ["popen//chdir=%s" % dest])
|
||||
nodemanager.makegateways()
|
||||
nodemanager.rsync_roots()
|
||||
@@ -210,6 +213,8 @@ class TestNodeManager:
|
||||
assert not dest.join("dir1", "dir2").check()
|
||||
assert dest.join("dir5","file").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):
|
||||
source, dest = mysetup.source, mysetup.dest
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import sys
|
||||
import py, pytest
|
||||
import py
|
||||
import pytest
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("xdist", "distributed and subprocess testing")
|
||||
@@ -28,12 +28,14 @@ def pytest_addoption(parser):
|
||||
group._addoption('-d',
|
||||
action="store_true", dest="distload", default=False,
|
||||
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.")
|
||||
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'
|
||||
' 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")
|
||||
parser.addini("looponfailroots", type="pathlist",
|
||||
help="directories to check for changes", default=[py.path.local()])
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import py, pytest
|
||||
import sys, os
|
||||
import fnmatch
|
||||
import os
|
||||
|
||||
import py
|
||||
import pytest
|
||||
import execnet
|
||||
import xdist.remote
|
||||
|
||||
@@ -7,6 +10,7 @@ from _pytest import runner # XXX load dynamically
|
||||
|
||||
class NodeManager(object):
|
||||
EXIT_TIMEOUT = 10
|
||||
DEFAULT_IGNORES = ['.*', '*.pyc', '*.pyo', '*~']
|
||||
def __init__(self, config, specs=None, defaultchdir="pyexecnetcache"):
|
||||
self.config = config
|
||||
self._nodesready = py.std.threading.Event()
|
||||
@@ -23,20 +27,17 @@ class NodeManager(object):
|
||||
self.group.allocate_id(spec)
|
||||
self.specs.append(spec)
|
||||
self.roots = self._getrsyncdirs()
|
||||
self.rsyncoptions = self._getrsyncoptions()
|
||||
|
||||
def rsync_roots(self):
|
||||
""" make sure that all remote gateways
|
||||
have the same set of roots in their
|
||||
current directory.
|
||||
"""
|
||||
options = {
|
||||
'ignores': self.config.getini("rsyncignore"),
|
||||
'verbose': self.config.option.verbose,
|
||||
}
|
||||
if self.roots:
|
||||
# send each rsync root
|
||||
for root in self.roots:
|
||||
self.rsync(root, **options)
|
||||
self.rsync(root, **self.rsyncoptions)
|
||||
|
||||
def makegateways(self):
|
||||
assert not list(self.group)
|
||||
@@ -98,6 +99,18 @@ class NodeManager(object):
|
||||
roots.append(root)
|
||||
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):
|
||||
""" perform rsync to all remote hosts.
|
||||
"""
|
||||
@@ -144,12 +157,10 @@ class HostRSync(execnet.RSync):
|
||||
|
||||
def filter(self, path):
|
||||
path = py.path.local(path)
|
||||
if not path.ext in ('.pyc', '.pyo'):
|
||||
if not path.basename.endswith('~'):
|
||||
if path.check(dotfile=0):
|
||||
for x in self._ignores:
|
||||
if path == x:
|
||||
break
|
||||
x = getattr(x, 'strpath', x)
|
||||
if fnmatch.fnmatch(path.basename, x) or fnmatch.fnmatch(path.strpath, x):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user