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
(package_files: Iterable[str])
| 791 | |
| 792 | |
| 793 | def _iter_rewritable_modules(package_files: Iterable[str]) -> Iterator[str]: |
| 794 | """Given an iterable of file names in a source distribution, return the "names" that should |
| 795 | be marked for assertion rewrite. |
| 796 | |
| 797 | For example the package "pytest_mock/__init__.py" should be added as "pytest_mock" in |
| 798 | the assertion rewrite mechanism. |
| 799 | |
| 800 | This function has to deal with dist-info based distributions and egg based distributions |
| 801 | (which are still very much in use for "editable" installs). |
| 802 | |
| 803 | Here are the file names as seen in a dist-info based distribution: |
| 804 | |
| 805 | pytest_mock/__init__.py |
| 806 | pytest_mock/_version.py |
| 807 | pytest_mock/plugin.py |
| 808 | pytest_mock.egg-info/PKG-INFO |
| 809 | |
| 810 | Here are the file names as seen in an egg based distribution: |
| 811 | |
| 812 | src/pytest_mock/__init__.py |
| 813 | src/pytest_mock/_version.py |
| 814 | src/pytest_mock/plugin.py |
| 815 | src/pytest_mock.egg-info/PKG-INFO |
| 816 | LICENSE |
| 817 | setup.py |
| 818 | |
| 819 | We have to take in account those two distribution flavors in order to determine which |
| 820 | names should be considered for assertion rewriting. |
| 821 | |
| 822 | More information: |
| 823 | https://github.com/pytest-dev/pytest-mock/issues/167 |
| 824 | """ |
| 825 | package_files = list(package_files) |
| 826 | seen_some = False |
| 827 | for fn in package_files: |
| 828 | is_simple_module = "/" not in fn and fn.endswith(".py") |
| 829 | is_package = fn.count("/") == 1 and fn.endswith("__init__.py") |
| 830 | if is_simple_module: |
| 831 | module_name, _ = os.path.splitext(fn) |
| 832 | # we ignore "setup.py" at the root of the distribution |
| 833 | if module_name != "setup": |
| 834 | seen_some = True |
| 835 | yield module_name |
| 836 | elif is_package: |
| 837 | package_name = os.path.dirname(fn) |
| 838 | seen_some = True |
| 839 | yield package_name |
| 840 | |
| 841 | if not seen_some: |
| 842 | # At this point we did not find any packages or modules suitable for assertion |
| 843 | # rewriting, so we try again by stripping the first path component (to account for |
| 844 | # "src" based source trees for example). |
| 845 | # This approach lets us have the common case continue to be fast, as egg-distributions |
| 846 | # are rarer. |
| 847 | new_package_files = [] |
| 848 | for fn in package_files: |
| 849 | parts = fn.split("/") |
| 850 | new_fn = "/".join(parts[1:]) |