New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix assertion rewriting module detection for egg dists #6313
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Fix assertion rewriting for egg-based distributions and ``editable`` installs (``pip install --editable``). |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -630,16 +630,67 @@ def __repr__(self): | |
|
||
|
||
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: | ||
is_simple_module = "/" not in fn and fn.endswith(".py") | ||
is_package = fn.count("/") == 1 and fn.endswith("__init__.py") | ||
if is_simple_module: | ||
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: | ||
package_name = os.path.dirname(fn) | ||
seen_some = True | ||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should not do this arbitrarily -- perhaps a better approach would be to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's just a comment, we are not hard-coding |
||
# 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: | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmm the existing code seems to be a pre-PEP420 world, I wonder if we could update this to not be so dependent on
__init__.py
filesThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, pytest itself doesn't seem to support this and AFAIR many tools were struggling to add support to this as well...