| import json | |
| import pathlib | |
| import tempfile | |
| import unittest | |
| from merger import merge_modules_mappings | |
| class MergerTest(unittest.TestCase): | |
| _tmpdir: tempfile.TemporaryDirectory | |
| def setUp(self) -> None: | |
| super().setUp() | |
| self._tmpdir = tempfile.TemporaryDirectory() | |
| def tearDown(self) -> None: | |
| super().tearDown() | |
| self._tmpdir.cleanup() | |
| del self._tmpdir | |
| @property | |
| def tmppath(self) -> pathlib.Path: | |
| return pathlib.Path(self._tmpdir.name) | |
| def make_input(self, mapping: dict[str, str]) -> pathlib.Path: | |
| _fd, file = tempfile.mkstemp(suffix=".json", dir=self._tmpdir.name) | |
| path = pathlib.Path(file) | |
| path.write_text(json.dumps(mapping)) | |
| return path | |
| def test_merger(self): | |
| output_path = self.tmppath / "output.json" | |
| merge_modules_mappings( | |
| [ | |
| self.make_input( | |
| { | |
| "_pytest": "pytest", | |
| "_pytest.__init__": "pytest", | |
| "_pytest._argcomplete": "pytest", | |
| "_pytest.config.argparsing": "pytest", | |
| } | |
| ), | |
| self.make_input({"django_types": "django_types"}), | |
| ], | |
| output_path, | |
| ) | |
| self.assertEqual( | |
| { | |
| "_pytest": "pytest", | |
| "django_types": "django_types", | |
| }, | |
| json.loads(output_path.read_text()), | |
| ) | |
| def test_merger_keeps_distinct_namespace_package_submodules(self): | |
| # Regression test for https://github.com/bazel-contrib/rules_python/issues/3528. | |
| # | |
| # Two wheels ("bosdyn_client" and "bosdyn_orbit") both contribute to the | |
| # "bosdyn" namespace package, each shipping their own "bosdyn" entry | |
| # (from the namespace package's __init__.py) alongside their own | |
| # wheel-specific submodule. Since https://github.com/bazel-contrib/rules_python/pull/3415, | |
| # each wheel's mapping is generated (and, before this fix, simplified) | |
| # independently, so the merge must not let one wheel's "bosdyn" entry | |
| # clobber the other's more specific submodule entries. | |
| output_path = self.tmppath / "output.json" | |
| merge_modules_mappings( | |
| [ | |
| self.make_input( | |
| { | |
| "bosdyn": "bosdyn_client", | |
| "bosdyn.client": "bosdyn_client", | |
| "bosdyn.client.control": "bosdyn_client", | |
| } | |
| ), | |
| self.make_input( | |
| { | |
| "bosdyn": "bosdyn_orbit", | |
| "bosdyn.orbit": "bosdyn_orbit", | |
| "bosdyn.orbit.util": "bosdyn_orbit", | |
| } | |
| ), | |
| ], | |
| output_path, | |
| ) | |
| # "bosdyn.orbit"/"bosdyn.orbit.util" are redundant with the top-level | |
| # "bosdyn" -> "bosdyn_orbit" entry and get collapsed away, but | |
| # "bosdyn.client" must survive since it resolves to a different wheel | |
| # than the top-level "bosdyn" entry. | |
| self.assertEqual( | |
| { | |
| "bosdyn": "bosdyn_orbit", | |
| "bosdyn.client": "bosdyn_client", | |
| }, | |
| json.loads(output_path.read_text()), | |
| ) | |
| if __name__ == "__main__": | |
| unittest.main() |