Merge pull request #6313 from nicoddemus/egg-rewrite-6301
Fix assertion rewriting module detection for egg dists
This commit is contained in:
commit
7ff91d8127
|
@ -0,0 +1 @@
|
||||||
|
Fix assertion rewriting for egg-based distributions and ``editable`` installs (``pip install --editable``).
|
|
@ -630,16 +630,67 @@ notset = Notset()
|
||||||
|
|
||||||
|
|
||||||
def _iter_rewritable_modules(package_files):
|
def _iter_rewritable_modules(package_files):
|
||||||
|
"""
|
||||||
|
Given an iterable of file names in a source distribution, return the "names" that should
|
||||||
|
be marked for assertion rewrite (for example the package "pytest_mock/__init__.py" should
|
||||||
|
be added as "pytest_mock" in the assertion rewrite mechanism.
|
||||||
|
|
||||||
|
This function has to deal with dist-info based distributions and egg based distributions
|
||||||
|
(which are still very much in use for "editable" installs).
|
||||||
|
|
||||||
|
Here are the file names as seen in a dist-info based distribution:
|
||||||
|
|
||||||
|
pytest_mock/__init__.py
|
||||||
|
pytest_mock/_version.py
|
||||||
|
pytest_mock/plugin.py
|
||||||
|
pytest_mock.egg-info/PKG-INFO
|
||||||
|
|
||||||
|
Here are the file names as seen in an egg based distribution:
|
||||||
|
|
||||||
|
src/pytest_mock/__init__.py
|
||||||
|
src/pytest_mock/_version.py
|
||||||
|
src/pytest_mock/plugin.py
|
||||||
|
src/pytest_mock.egg-info/PKG-INFO
|
||||||
|
LICENSE
|
||||||
|
setup.py
|
||||||
|
|
||||||
|
We have to take in account those two distribution flavors in order to determine which
|
||||||
|
names should be considered for assertion rewriting.
|
||||||
|
|
||||||
|
More information:
|
||||||
|
https://github.com/pytest-dev/pytest-mock/issues/167
|
||||||
|
"""
|
||||||
|
package_files = list(package_files)
|
||||||
|
seen_some = False
|
||||||
for fn in package_files:
|
for fn in package_files:
|
||||||
is_simple_module = "/" not in fn and fn.endswith(".py")
|
is_simple_module = "/" not in fn and fn.endswith(".py")
|
||||||
is_package = fn.count("/") == 1 and fn.endswith("__init__.py")
|
is_package = fn.count("/") == 1 and fn.endswith("__init__.py")
|
||||||
if is_simple_module:
|
if is_simple_module:
|
||||||
module_name, _ = os.path.splitext(fn)
|
module_name, _ = os.path.splitext(fn)
|
||||||
yield module_name
|
# we ignore "setup.py" at the root of the distribution
|
||||||
|
if module_name != "setup":
|
||||||
|
seen_some = True
|
||||||
|
yield module_name
|
||||||
elif is_package:
|
elif is_package:
|
||||||
package_name = os.path.dirname(fn)
|
package_name = os.path.dirname(fn)
|
||||||
|
seen_some = True
|
||||||
yield package_name
|
yield package_name
|
||||||
|
|
||||||
|
if not seen_some:
|
||||||
|
# at this point we did not find any packages or modules suitable for assertion
|
||||||
|
# rewriting, so we try again by stripping the first path component (to account for
|
||||||
|
# "src" based source trees for example)
|
||||||
|
# this approach lets us have the common case continue to be fast, as egg-distributions
|
||||||
|
# are rarer
|
||||||
|
new_package_files = []
|
||||||
|
for fn in package_files:
|
||||||
|
parts = fn.split("/")
|
||||||
|
new_fn = "/".join(parts[1:])
|
||||||
|
if new_fn:
|
||||||
|
new_package_files.append(new_fn)
|
||||||
|
if new_package_files:
|
||||||
|
yield from _iter_rewritable_modules(new_package_files)
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -422,15 +422,21 @@ class TestConfigAPI:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"names, expected",
|
"names, expected",
|
||||||
[
|
[
|
||||||
|
# dist-info based distributions root are files as will be put in PYTHONPATH
|
||||||
(["bar.py"], ["bar"]),
|
(["bar.py"], ["bar"]),
|
||||||
(["foo", "bar.py"], []),
|
(["foo/bar.py"], ["bar"]),
|
||||||
(["foo", "bar.pyc"], []),
|
(["foo/bar.pyc"], []),
|
||||||
(["foo", "__init__.py"], ["foo"]),
|
(["foo/__init__.py"], ["foo"]),
|
||||||
(["foo", "bar", "__init__.py"], []),
|
(["bar/__init__.py", "xz.py"], ["bar", "xz"]),
|
||||||
|
(["setup.py"], []),
|
||||||
|
# egg based distributions root contain the files from the dist root
|
||||||
|
(["src/bar/__init__.py"], ["bar"]),
|
||||||
|
(["src/bar/__init__.py", "setup.py"], ["bar"]),
|
||||||
|
(["source/python/bar/__init__.py", "setup.py"], ["bar"]),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_iter_rewritable_modules(self, names, expected):
|
def test_iter_rewritable_modules(self, names, expected):
|
||||||
assert list(_iter_rewritable_modules(["/".join(names)])) == expected
|
assert list(_iter_rewritable_modules(names)) == expected
|
||||||
|
|
||||||
|
|
||||||
class TestConfigFromdictargs:
|
class TestConfigFromdictargs:
|
||||||
|
|
Loading…
Reference in New Issue