Merge pull request #4738 from pstradomski/master

Fix "ValueError: Plugin already registered" exceptions when running in build directories that symlink to actual source.
This commit is contained in:
Bruno Oliveira 2019-02-08 19:57:14 -02:00 committed by GitHub
commit 32c6d4f603
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 1 deletions

1
changelog/526.bugfix.rst Normal file
View File

@ -0,0 +1 @@
Fix "ValueError: Plugin already registered" exceptions when running in build directories that symlink to actual source.

View File

@ -408,7 +408,10 @@ class PytestPluginManager(PluginManager):
continue continue
conftestpath = parent.join("conftest.py") conftestpath = parent.join("conftest.py")
if conftestpath.isfile(): if conftestpath.isfile():
mod = self._importconftest(conftestpath) # Use realpath to avoid loading the same conftest twice
# with build systems that create build directories containing
# symlinks to actual files.
mod = self._importconftest(conftestpath.realpath())
clist.append(mod) clist.append(mod)
self._dirpath2confmods[directory] = clist self._dirpath2confmods[directory] = clist
return clist return clist

View File

@ -244,6 +244,42 @@ def test_conftest_symlink(testdir):
assert result.ret == EXIT_OK assert result.ret == EXIT_OK
@pytest.mark.skipif(
not hasattr(py.path.local, "mksymlinkto"),
reason="symlink not available on this platform",
)
def test_conftest_symlink_files(testdir):
"""Check conftest.py loading when running in directory with symlinks."""
real = testdir.tmpdir.mkdir("real")
source = {
"app/test_foo.py": "def test1(fixture): pass",
"app/__init__.py": "",
"app/conftest.py": textwrap.dedent(
"""
import pytest
print("conftest_loaded")
@pytest.fixture
def fixture():
print("fixture_used")
"""
),
}
testdir.makepyfile(**{"real/%s" % k: v for k, v in source.items()})
# Create a build directory that contains symlinks to actual files
# but doesn't symlink actual directories.
build = testdir.tmpdir.mkdir("build")
build.mkdir("app")
for f in source:
build.join(f).mksymlinkto(real.join(f))
build.chdir()
result = testdir.runpytest("-vs", "app/test_foo.py")
result.stdout.fnmatch_lines(["*conftest_loaded*", "PASSED"])
assert result.ret == EXIT_OK
def test_no_conftest(testdir): def test_no_conftest(testdir):
testdir.makeconftest("assert 0") testdir.makeconftest("assert 0")
result = testdir.runpytest("--noconftest") result = testdir.runpytest("--noconftest")