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])
| 949 | |
| 950 | |
| 951 | def _iter_rewritable_modules(package_files: Iterable[str]) -> Iterator[str]: |
| 952 | """Given an iterable of file names in a source distribution, return the "names" that should |
| 953 | be marked for assertion rewrite. |
| 954 | |
| 955 | For example the package "pytest_mock/__init__.py" should be added as "pytest_mock" in |
| 956 | the assertion rewrite mechanism. |
| 957 | |
| 958 | This function has to deal with dist-info based distributions and egg based distributions |
| 959 | (which are still very much in use for "editable" installs). |
| 960 | |
| 961 | Here are the file names as seen in a dist-info based distribution: |
| 962 | |
| 963 | pytest_mock/__init__.py |
| 964 | pytest_mock/_version.py |
| 965 | pytest_mock/plugin.py |
| 966 | pytest_mock.egg-info/PKG-INFO |
| 967 | |
| 968 | Here are the file names as seen in an egg based distribution: |
| 969 | |
| 970 | src/pytest_mock/__init__.py |
| 971 | src/pytest_mock/_version.py |
| 972 | src/pytest_mock/plugin.py |
| 973 | src/pytest_mock.egg-info/PKG-INFO |
| 974 | LICENSE |
| 975 | setup.py |
| 976 | |
| 977 | We have to take in account those two distribution flavors in order to determine which |
| 978 | names should be considered for assertion rewriting. |
| 979 | |
| 980 | More information: |
| 981 | https://github.com/pytest-dev/pytest-mock/issues/167 |
| 982 | """ |
| 983 | package_files = list(package_files) |
| 984 | seen_some = False |
| 985 | for fn in package_files: |
| 986 | is_simple_module = "/" not in fn and fn.endswith(".py") |
| 987 | is_package = fn.count("/") == 1 and fn.endswith("__init__.py") |
| 988 | if is_simple_module: |
| 989 | module_name, _ = os.path.splitext(fn) |
| 990 | # we ignore "setup.py" at the root of the distribution |
| 991 | # as well as editable installation finder modules made by setuptools |
| 992 | if module_name != "setup" and not module_name.startswith("__editable__"): |
| 993 | seen_some = True |
| 994 | yield module_name |
| 995 | elif is_package: |
| 996 | package_name = os.path.dirname(fn) |
| 997 | seen_some = True |
| 998 | yield package_name |
| 999 | |
| 1000 | if not seen_some: |
| 1001 | # At this point we did not find any packages or modules suitable for assertion |
| 1002 | # rewriting, so we try again by stripping the first path component (to account for |
| 1003 | # "src" based source trees for example). |
| 1004 | # This approach lets us have the common case continue to be fast, as egg-distributions |
| 1005 | # are rarer. |
| 1006 | new_package_files = [] |
| 1007 | for fn in package_files: |
| 1008 | parts = fn.split("/") |
searching dependent graphs…