| import unittest |
| from unittest import mock |
| |
| from python.private.pypi.whl_installer import wheel |
| from python.private.pypi.whl_installer.platform import OS, Arch, Platform |
| |
| _HOST_INTERPRETER_FN = ( |
| "python.private.pypi.whl_installer.wheel.host_interpreter_minor_version" |
| ) |
| |
| |
| class DepsTest(unittest.TestCase): |
| def test_simple(self): |
| deps = wheel.Deps("foo", requires_dist=["bar"]) |
| |
| got = deps.build() |
| |
| self.assertIsInstance(got, wheel.FrozenDeps) |
| self.assertEqual(["bar"], got.deps) |
| self.assertEqual({}, got.deps_select) |
| |
| def test_can_add_os_specific_deps(self): |
| deps = wheel.Deps( |
| "foo", |
| requires_dist=[ |
| "bar", |
| "an_osx_dep; sys_platform=='darwin'", |
| "posix_dep; os_name=='posix'", |
| "win_dep; os_name=='nt'", |
| ], |
| platforms={ |
| Platform(os=OS.linux, arch=Arch.x86_64), |
| Platform(os=OS.osx, arch=Arch.x86_64), |
| Platform(os=OS.osx, arch=Arch.aarch64), |
| Platform(os=OS.windows, arch=Arch.x86_64), |
| }, |
| ) |
| |
| got = deps.build() |
| |
| self.assertEqual(["bar"], got.deps) |
| self.assertEqual( |
| { |
| "@platforms//os:linux": ["posix_dep"], |
| "@platforms//os:osx": ["an_osx_dep", "posix_dep"], |
| "@platforms//os:windows": ["win_dep"], |
| }, |
| got.deps_select, |
| ) |
| |
| def test_can_add_os_specific_deps_with_specific_python_version(self): |
| deps = wheel.Deps( |
| "foo", |
| requires_dist=[ |
| "bar", |
| "an_osx_dep; sys_platform=='darwin'", |
| "posix_dep; os_name=='posix'", |
| "win_dep; os_name=='nt'", |
| ], |
| platforms={ |
| Platform(os=OS.linux, arch=Arch.x86_64, minor_version=8), |
| Platform(os=OS.osx, arch=Arch.x86_64, minor_version=8), |
| Platform(os=OS.osx, arch=Arch.aarch64, minor_version=8), |
| Platform(os=OS.windows, arch=Arch.x86_64, minor_version=8), |
| }, |
| ) |
| |
| got = deps.build() |
| |
| self.assertEqual(["bar"], got.deps) |
| self.assertEqual( |
| { |
| "@platforms//os:linux": ["posix_dep"], |
| "@platforms//os:osx": ["an_osx_dep", "posix_dep"], |
| "@platforms//os:windows": ["win_dep"], |
| }, |
| got.deps_select, |
| ) |
| |
| def test_deps_are_added_to_more_specialized_platforms(self): |
| got = wheel.Deps( |
| "foo", |
| requires_dist=[ |
| "m1_dep; sys_platform=='darwin' and platform_machine=='arm64'", |
| "mac_dep; sys_platform=='darwin'", |
| ], |
| platforms={ |
| Platform(os=OS.osx, arch=Arch.x86_64), |
| Platform(os=OS.osx, arch=Arch.aarch64), |
| }, |
| ).build() |
| |
| self.assertEqual( |
| wheel.FrozenDeps( |
| deps=[], |
| deps_select={ |
| "osx_aarch64": ["m1_dep", "mac_dep"], |
| "@platforms//os:osx": ["mac_dep"], |
| }, |
| ), |
| got, |
| ) |
| |
| def test_deps_from_more_specialized_platforms_are_propagated(self): |
| got = wheel.Deps( |
| "foo", |
| requires_dist=[ |
| "a_mac_dep; sys_platform=='darwin'", |
| "m1_dep; sys_platform=='darwin' and platform_machine=='arm64'", |
| ], |
| platforms={ |
| Platform(os=OS.osx, arch=Arch.x86_64), |
| Platform(os=OS.osx, arch=Arch.aarch64), |
| }, |
| ).build() |
| |
| self.assertEqual([], got.deps) |
| self.assertEqual( |
| { |
| "osx_aarch64": ["a_mac_dep", "m1_dep"], |
| "@platforms//os:osx": ["a_mac_dep"], |
| }, |
| got.deps_select, |
| ) |
| |
| def test_non_platform_markers_are_added_to_common_deps(self): |
| got = wheel.Deps( |
| "foo", |
| requires_dist=[ |
| "bar", |
| "baz; implementation_name=='cpython'", |
| "m1_dep; sys_platform=='darwin' and platform_machine=='arm64'", |
| ], |
| platforms={ |
| Platform(os=OS.linux, arch=Arch.x86_64), |
| Platform(os=OS.osx, arch=Arch.x86_64), |
| Platform(os=OS.osx, arch=Arch.aarch64), |
| Platform(os=OS.windows, arch=Arch.x86_64), |
| }, |
| ).build() |
| |
| self.assertEqual(["bar", "baz"], got.deps) |
| self.assertEqual( |
| { |
| "osx_aarch64": ["m1_dep"], |
| }, |
| got.deps_select, |
| ) |
| |
| def test_self_is_ignored(self): |
| deps = wheel.Deps( |
| "foo", |
| requires_dist=[ |
| "bar", |
| "req_dep; extra == 'requests'", |
| "foo[requests]; extra == 'ssl'", |
| "ssl_lib; extra == 'ssl'", |
| ], |
| extras={"ssl"}, |
| ) |
| |
| got = deps.build() |
| |
| self.assertEqual(["bar", "req_dep", "ssl_lib"], got.deps) |
| self.assertEqual({}, got.deps_select) |
| |
| def test_self_dependencies_can_come_in_any_order(self): |
| deps = wheel.Deps( |
| "foo", |
| requires_dist=[ |
| "bar", |
| "baz; extra == 'feat'", |
| "foo[feat2]; extra == 'all'", |
| "foo[feat]; extra == 'feat2'", |
| "zdep; extra == 'all'", |
| ], |
| extras={"all"}, |
| ) |
| |
| got = deps.build() |
| |
| self.assertEqual(["bar", "baz", "zdep"], got.deps) |
| self.assertEqual({}, got.deps_select) |
| |
| def test_can_get_deps_based_on_specific_python_version(self): |
| requires_dist = [ |
| "bar", |
| "baz; python_version < '3.8'", |
| "posix_dep; os_name=='posix' and python_version >= '3.8'", |
| ] |
| |
| py38_deps = wheel.Deps( |
| "foo", |
| requires_dist=requires_dist, |
| platforms=[ |
| Platform(os=OS.linux, arch=Arch.x86_64, minor_version=8), |
| ], |
| ).build() |
| py37_deps = wheel.Deps( |
| "foo", |
| requires_dist=requires_dist, |
| platforms=[ |
| Platform(os=OS.linux, arch=Arch.x86_64, minor_version=7), |
| ], |
| ).build() |
| |
| self.assertEqual(["bar", "baz"], py37_deps.deps) |
| self.assertEqual({}, py37_deps.deps_select) |
| self.assertEqual(["bar"], py38_deps.deps) |
| self.assertEqual({"@platforms//os:linux": ["posix_dep"]}, py38_deps.deps_select) |
| |
| @mock.patch(_HOST_INTERPRETER_FN) |
| def test_no_version_select_when_single_version(self, mock_host_interpreter_version): |
| requires_dist = [ |
| "bar", |
| "baz; python_version >= '3.8'", |
| "posix_dep; os_name=='posix'", |
| "posix_dep_with_version; os_name=='posix' and python_version >= '3.8'", |
| "arch_dep; platform_machine=='x86_64' and python_version >= '3.8'", |
| ] |
| mock_host_interpreter_version.return_value = 7 |
| |
| self.maxDiff = None |
| |
| deps = wheel.Deps( |
| "foo", |
| requires_dist=requires_dist, |
| platforms=[ |
| Platform(os=os, arch=Arch.x86_64, minor_version=minor) |
| for minor in [8] |
| for os in [OS.linux, OS.windows] |
| ], |
| ) |
| got = deps.build() |
| |
| self.assertEqual(["bar", "baz"], got.deps) |
| self.assertEqual( |
| { |
| "@platforms//os:linux": ["posix_dep", "posix_dep_with_version"], |
| "linux_x86_64": ["arch_dep", "posix_dep", "posix_dep_with_version"], |
| "windows_x86_64": ["arch_dep"], |
| }, |
| got.deps_select, |
| ) |
| |
| @mock.patch(_HOST_INTERPRETER_FN) |
| def test_can_get_version_select(self, mock_host_interpreter_version): |
| requires_dist = [ |
| "bar", |
| "baz; python_version < '3.8'", |
| "baz_new; python_version >= '3.8'", |
| "posix_dep; os_name=='posix'", |
| "posix_dep_with_version; os_name=='posix' and python_version >= '3.8'", |
| "arch_dep; platform_machine=='x86_64' and python_version < '3.8'", |
| ] |
| mock_host_interpreter_version.return_value = 7 |
| |
| self.maxDiff = None |
| |
| deps = wheel.Deps( |
| "foo", |
| requires_dist=requires_dist, |
| platforms=[ |
| Platform(os=os, arch=Arch.x86_64, minor_version=minor) |
| for minor in [7, 8, 9] |
| for os in [OS.linux, OS.windows] |
| ], |
| ) |
| got = deps.build() |
| |
| self.assertEqual(["bar"], got.deps) |
| self.assertEqual( |
| { |
| "//conditions:default": ["baz"], |
| "@//python/config_settings:is_python_3.7": ["baz"], |
| "@//python/config_settings:is_python_3.8": ["baz_new"], |
| "@//python/config_settings:is_python_3.9": ["baz_new"], |
| "@platforms//os:linux": ["baz", "posix_dep"], |
| "cp37_linux_x86_64": ["arch_dep", "baz", "posix_dep"], |
| "cp37_windows_x86_64": ["arch_dep", "baz"], |
| "cp37_linux_anyarch": ["baz", "posix_dep"], |
| "cp38_linux_anyarch": [ |
| "baz_new", |
| "posix_dep", |
| "posix_dep_with_version", |
| ], |
| "cp39_linux_anyarch": [ |
| "baz_new", |
| "posix_dep", |
| "posix_dep_with_version", |
| ], |
| "linux_x86_64": ["arch_dep", "baz", "posix_dep"], |
| "windows_x86_64": ["arch_dep", "baz"], |
| }, |
| got.deps_select, |
| ) |
| |
| @mock.patch(_HOST_INTERPRETER_FN) |
| def test_deps_spanning_all_target_py_versions_are_added_to_common( |
| self, mock_host_version |
| ): |
| requires_dist = [ |
| "bar", |
| "baz (<2,>=1.11) ; python_version < '3.8'", |
| "baz (<2,>=1.14) ; python_version >= '3.8'", |
| ] |
| mock_host_version.return_value = 8 |
| |
| deps = wheel.Deps( |
| "foo", |
| requires_dist=requires_dist, |
| platforms=Platform.from_string(["cp37_*", "cp38_*", "cp39_*"]), |
| ) |
| got = deps.build() |
| |
| self.assertEqual(["bar", "baz"], got.deps) |
| self.assertEqual({}, got.deps_select) |
| |
| @mock.patch(_HOST_INTERPRETER_FN) |
| def test_deps_are_not_duplicated(self, mock_host_version): |
| mock_host_version.return_value = 7 |
| |
| # See an example in |
| # https://files.pythonhosted.org/packages/76/9e/db1c2d56c04b97981c06663384f45f28950a73d9acf840c4006d60d0a1ff/opencv_python-4.9.0.80-cp37-abi3-win32.whl.metadata |
| requires_dist = [ |
| "bar >=0.1.0 ; python_version < '3.7'", |
| "bar >=0.2.0 ; python_version >= '3.7'", |
| "bar >=0.4.0 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64'", |
| "bar >=0.4.0 ; python_version >= '3.9'", |
| "bar >=0.5.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64'", |
| "bar >=0.5.0 ; python_version >= '3.10' and platform_system == 'Darwin'", |
| "bar >=0.5.0 ; python_version >= '3.10'", |
| "bar >=0.6.0 ; python_version >= '3.11'", |
| ] |
| |
| deps = wheel.Deps( |
| "foo", |
| requires_dist=requires_dist, |
| platforms=Platform.from_string(["cp37_*", "cp310_*"]), |
| ) |
| got = deps.build() |
| |
| self.assertEqual(["bar"], got.deps) |
| self.assertEqual({}, got.deps_select) |
| |
| @mock.patch(_HOST_INTERPRETER_FN) |
| def test_deps_are_not_duplicated_when_encountering_platform_dep_first( |
| self, mock_host_version |
| ): |
| mock_host_version.return_value = 7 |
| |
| # Note, that we are sorting the incoming `requires_dist` and we need to ensure that we are not getting any |
| # issues even if the platform-specific line comes first. |
| requires_dist = [ |
| "bar >=0.4.0 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64'", |
| "bar >=0.5.0 ; python_version >= '3.9'", |
| ] |
| |
| deps = wheel.Deps( |
| "foo", |
| requires_dist=requires_dist, |
| platforms=Platform.from_string(["cp37_*", "cp310_*"]), |
| ) |
| got = deps.build() |
| |
| self.assertEqual(["bar"], got.deps) |
| self.assertEqual({}, got.deps_select) |
| |
| |
| if __name__ == "__main__": |
| unittest.main() |