@@ -630,16 +630,67 @@ def __repr__(self):
630
630
631
631
632
632
def _iter_rewritable_modules (package_files ):
633
+ """
634
+ Given an iterable of file names in a source distribution, return the "names" that should
635
+ be marked for assertion rewrite (for example the package "pytest_mock/__init__.py" should
636
+ be added as "pytest_mock" in the assertion rewrite mechanism.
637
+
638
+ This function has to deal with dist-info based distributions and egg based distributions
639
+ (which are still very much in use for "editable" installs).
640
+
641
+ Here are the file names as seen in a dist-info based distribution:
642
+
643
+ pytest_mock/__init__.py
644
+ pytest_mock/_version.py
645
+ pytest_mock/plugin.py
646
+ pytest_mock.egg-info/PKG-INFO
647
+
648
+ Here are the file names as seen in an egg based distribution:
649
+
650
+ src/pytest_mock/__init__.py
651
+ src/pytest_mock/_version.py
652
+ src/pytest_mock/plugin.py
653
+ src/pytest_mock.egg-info/PKG-INFO
654
+ LICENSE
655
+ setup.py
656
+
657
+ We have to take in account those two distribution flavors in order to determine which
658
+ names should be considered for assertion rewriting.
659
+
660
+ More information:
661
+ https://github.com/pytest-dev/pytest-mock/issues/167
662
+ """
663
+ package_files = list (package_files )
664
+ seen_some = False
633
665
for fn in package_files :
634
666
is_simple_module = "/" not in fn and fn .endswith (".py" )
635
667
is_package = fn .count ("/" ) == 1 and fn .endswith ("__init__.py" )
636
668
if is_simple_module :
637
669
module_name , _ = os .path .splitext (fn )
638
- yield module_name
670
+ # we ignore "setup.py" at the root of the distribution
671
+ if module_name != "setup" :
672
+ seen_some = True
673
+ yield module_name
639
674
elif is_package :
640
675
package_name = os .path .dirname (fn )
676
+ seen_some = True
641
677
yield package_name
642
678
679
+ if not seen_some :
680
+ # at this point we did not find any packages or modules suitable for assertion
681
+ # rewriting, so we try again by stripping the first path component (to account for
682
+ # "src" based source trees for example)
683
+ # this approach lets us have the common case continue to be fast, as egg-distributions
684
+ # are rarer
685
+ new_package_files = []
686
+ for fn in package_files :
687
+ parts = fn .split ("/" )
688
+ new_fn = "/" .join (parts [1 :])
689
+ if new_fn :
690
+ new_package_files .append (new_fn )
691
+ if new_package_files :
692
+ yield from _iter_rewritable_modules (new_package_files )
693
+
643
694
644
695
class Config :
645
696
"""
0 commit comments