xref: /aosp_15_r20/external/bazelbuild-rules_python/examples/bzlmod/whl_mods/pip_whl_mods_test.py (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1#!/usr/bin/env python3
2# Copyright 2023 The Bazel Authors. All rights reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
17import os
18import platform
19import subprocess
20import sys
21import unittest
22from pathlib import Path
23
24from python.runfiles import runfiles
25
26
27class PipWhlModsTest(unittest.TestCase):
28    maxDiff = None
29
30    @staticmethod
31    def _get_bazel_pkg_dir_name(env_var: str) -> str:
32        a_file = Path(os.environ.get(env_var).split(" ")[0])
33        head = a_file
34        while head.parent.name:
35            head = head.parent
36
37        return head.name
38
39    @classmethod
40    def setUpClass(cls):
41        cls._wheel_pkg_dir = cls._get_bazel_pkg_dir_name("WHEEL_PKG")
42        cls._requests_pkg_dir = cls._get_bazel_pkg_dir_name("REQUESTS_PKG")
43
44    def wheel_pkg_dir(self) -> Path:
45        return self._wheel_pkg
46
47    def test_build_content_and_data(self):
48        r = runfiles.Create()
49        rpath = r.Rlocation(
50            "{}/generated_file.txt".format(
51                self._wheel_pkg_dir,
52            ),
53        )
54        generated_file = Path(rpath)
55        self.assertTrue(generated_file.exists())
56
57        content = generated_file.read_text().rstrip()
58        self.assertEqual(content, "Hello world from build content file")
59
60    def test_copy_files(self):
61        r = runfiles.Create()
62        rpath = r.Rlocation(
63            "{}/copied_content/file.txt".format(
64                self._wheel_pkg_dir,
65            )
66        )
67        copied_file = Path(rpath)
68        self.assertTrue(copied_file.exists())
69
70        content = copied_file.read_text().rstrip()
71        self.assertEqual(content, "Hello world from copied file")
72
73    def test_copy_executables(self):
74        executable_name = (
75            "executable.exe" if platform.system() == "windows" else "executable.py"
76        )
77
78        r = runfiles.Create()
79        rpath = r.Rlocation(
80            "{}/copied_content/{}".format(
81                self._wheel_pkg_dir,
82                executable_name,
83            )
84        )
85        executable = Path(rpath)
86        self.assertTrue(executable.exists())
87
88        proc = subprocess.run(
89            [sys.executable, str(executable)],
90            check=True,
91            stdout=subprocess.PIPE,
92            stderr=subprocess.PIPE,
93        )
94        stdout = proc.stdout.decode("utf-8").strip()
95        self.assertEqual(stdout, "Hello world from copied executable")
96
97    def test_data_exclude_glob(self):
98        current_wheel_version = "0.40.0"
99
100        r = runfiles.Create()
101        dist_info_dir = "{}/site-packages/wheel-{}.dist-info".format(
102            self._wheel_pkg_dir,
103            current_wheel_version,
104        )
105
106        # Note: `METADATA` is important as it's consumed by https://docs.python.org/3/library/importlib.metadata.html
107        # `METADATA` is expected to be there to show dist-info files are included in the runfiles.
108        metadata_path = r.Rlocation("{}/METADATA".format(dist_info_dir))
109
110        # However, `WHEEL` was explicitly excluded, so it should be missing
111        wheel_path = r.Rlocation("{}/WHEEL".format(dist_info_dir))
112
113        self.assertTrue(Path(metadata_path).exists(), f"Could not find {metadata_path}")
114        self.assertFalse(
115            Path(wheel_path).exists(), f"Expected to not find {wheel_path}"
116        )
117
118    def test_extra(self):
119        # This test verifies that annotations work correctly for pip packages with extras
120        # specified, in this case requests[security].
121        r = runfiles.Create()
122        rpath = r.Rlocation(
123            "{}/generated_file.txt".format(
124                self._requests_pkg_dir,
125            ),
126        )
127        generated_file = Path(rpath)
128        self.assertTrue(generated_file.exists())
129
130        content = generated_file.read_text().rstrip()
131        self.assertEqual(content, "Hello world from requests")
132
133    def test_patches(self):
134        current_wheel_version = "2.25.1"
135
136        # This test verifies that the patches are applied to the wheel.
137        r = runfiles.Create()
138        metadata_path = "{}/site-packages/requests-{}.dist-info/METADATA".format(
139            self._requests_pkg_dir,
140            current_wheel_version,
141        )
142
143        metadata = Path(r.Rlocation(metadata_path))
144        self.assertIn(
145            "Summary: Python HTTP for Humans. Patched.",
146            metadata.read_text().splitlines(),
147        )
148
149
150if __name__ == "__main__":
151    unittest.main()
152