1# Copyright 2024 The Bazel Authors. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"" 16 17load("@rules_testing//lib:test_suite.bzl", "test_suite") 18load("//python/private:glob_excludes.bzl", "glob_excludes") # buildifier: disable=bzl-visibility 19load("//python/private/pypi:whl_library_targets.bzl", "whl_library_targets") # buildifier: disable=bzl-visibility 20 21_tests = [] 22 23def _test_filegroups(env): 24 calls = [] 25 26 def glob(match, *, allow_empty): 27 env.expect.that_bool(allow_empty).equals(True) 28 return match 29 30 whl_library_targets( 31 name = "", 32 dep_template = "", 33 native = struct( 34 filegroup = lambda **kwargs: calls.append(kwargs), 35 glob = glob, 36 ), 37 rules = struct(), 38 ) 39 40 env.expect.that_collection(calls).contains_exactly([ 41 { 42 "name": "dist_info", 43 "srcs": ["site-packages/*.dist-info/**"], 44 "visibility": ["//visibility:public"], 45 }, 46 { 47 "name": "data", 48 "srcs": ["data/**"], 49 "visibility": ["//visibility:public"], 50 }, 51 { 52 "name": "whl", 53 "srcs": [""], 54 "data": [], 55 "visibility": ["//visibility:public"], 56 }, 57 ]) # buildifier: @unsorted-dict-items 58 59_tests.append(_test_filegroups) 60 61def _test_platforms(env): 62 calls = [] 63 64 whl_library_targets( 65 name = "", 66 dep_template = None, 67 dependencies_by_platform = { 68 "@//python/config_settings:is_python_3.9": ["py39_dep"], 69 "@platforms//cpu:aarch64": ["arm_dep"], 70 "@platforms//os:windows": ["win_dep"], 71 "cp310_linux_ppc": ["py310_linux_ppc_dep"], 72 "cp39_anyos_aarch64": ["py39_arm_dep"], 73 "cp39_linux_anyarch": ["py39_linux_dep"], 74 "linux_x86_64": ["linux_intel_dep"], 75 }, 76 filegroups = {}, 77 native = struct( 78 config_setting = lambda **kwargs: calls.append(kwargs), 79 ), 80 rules = struct(), 81 ) 82 83 env.expect.that_collection(calls).contains_exactly([ 84 { 85 "name": "is_python_3.10_linux_ppc", 86 "flag_values": { 87 "@rules_python//python/config_settings:python_version_major_minor": "3.10", 88 }, 89 "constraint_values": [ 90 "@platforms//cpu:ppc", 91 "@platforms//os:linux", 92 ], 93 "visibility": ["//visibility:private"], 94 }, 95 { 96 "name": "is_python_3.9_anyos_aarch64", 97 "flag_values": { 98 "@rules_python//python/config_settings:python_version_major_minor": "3.9", 99 }, 100 "constraint_values": ["@platforms//cpu:aarch64"], 101 "visibility": ["//visibility:private"], 102 }, 103 { 104 "name": "is_python_3.9_linux_anyarch", 105 "flag_values": { 106 "@rules_python//python/config_settings:python_version_major_minor": "3.9", 107 }, 108 "constraint_values": ["@platforms//os:linux"], 109 "visibility": ["//visibility:private"], 110 }, 111 { 112 "name": "is_linux_x86_64", 113 "constraint_values": [ 114 "@platforms//cpu:x86_64", 115 "@platforms//os:linux", 116 ], 117 "visibility": ["//visibility:private"], 118 }, 119 ]) # buildifier: @unsorted-dict-items 120 121_tests.append(_test_platforms) 122 123def _test_copy(env): 124 calls = [] 125 126 whl_library_targets( 127 name = "", 128 dep_template = None, 129 dependencies_by_platform = {}, 130 filegroups = {}, 131 copy_files = {"file_src": "file_dest"}, 132 copy_executables = {"exec_src": "exec_dest"}, 133 native = struct(), 134 rules = struct( 135 copy_file = lambda **kwargs: calls.append(kwargs), 136 ), 137 ) 138 139 env.expect.that_collection(calls).contains_exactly([ 140 { 141 "name": "file_dest.copy", 142 "out": "file_dest", 143 "src": "file_src", 144 "visibility": ["//visibility:public"], 145 }, 146 { 147 "is_executable": True, 148 "name": "exec_dest.copy", 149 "out": "exec_dest", 150 "src": "exec_src", 151 "visibility": ["//visibility:public"], 152 }, 153 ]) 154 155_tests.append(_test_copy) 156 157def _test_entrypoints(env): 158 calls = [] 159 160 whl_library_targets( 161 name = "", 162 dep_template = None, 163 dependencies_by_platform = {}, 164 filegroups = {}, 165 entry_points = { 166 "fizz": "buzz.py", 167 }, 168 native = struct(), 169 rules = struct( 170 py_binary = lambda **kwargs: calls.append(kwargs), 171 ), 172 ) 173 174 env.expect.that_collection(calls).contains_exactly([ 175 { 176 "name": "rules_python_wheel_entry_point_fizz", 177 "srcs": ["buzz.py"], 178 "deps": [":pkg"], 179 "imports": ["."], 180 "visibility": ["//visibility:public"], 181 }, 182 ]) # buildifier: @unsorted-dict-items 183 184_tests.append(_test_entrypoints) 185 186def _test_whl_and_library_deps(env): 187 filegroup_calls = [] 188 py_library_calls = [] 189 190 whl_library_targets( 191 name = "foo.whl", 192 dep_template = "@pypi_{name}//:{target}", 193 dependencies = ["foo", "bar-baz"], 194 dependencies_by_platform = { 195 "@//python/config_settings:is_python_3.9": ["py39_dep"], 196 "@platforms//cpu:aarch64": ["arm_dep"], 197 "@platforms//os:windows": ["win_dep"], 198 "cp310_linux_ppc": ["py310_linux_ppc_dep"], 199 "cp39_anyos_aarch64": ["py39_arm_dep"], 200 "cp39_linux_anyarch": ["py39_linux_dep"], 201 "linux_x86_64": ["linux_intel_dep"], 202 }, 203 data_exclude = [], 204 tags = ["tag1", "tag2"], 205 # Overrides for testing 206 filegroups = {}, 207 native = struct( 208 filegroup = lambda **kwargs: filegroup_calls.append(kwargs), 209 config_setting = lambda **_: None, 210 glob = _glob, 211 select = _select, 212 ), 213 rules = struct( 214 py_library = lambda **kwargs: py_library_calls.append(kwargs), 215 ), 216 ) 217 218 env.expect.that_collection(filegroup_calls).contains_exactly([ 219 { 220 "name": "whl", 221 "srcs": ["foo.whl"], 222 "data": [ 223 "@pypi_bar_baz//:whl", 224 "@pypi_foo//:whl", 225 ] + _select( 226 { 227 Label("//python/config_settings:is_python_3.9"): ["@pypi_py39_dep//:whl"], 228 "@platforms//cpu:aarch64": ["@pypi_arm_dep//:whl"], 229 "@platforms//os:windows": ["@pypi_win_dep//:whl"], 230 ":is_python_3.10_linux_ppc": ["@pypi_py310_linux_ppc_dep//:whl"], 231 ":is_python_3.9_anyos_aarch64": ["@pypi_py39_arm_dep//:whl"], 232 ":is_python_3.9_linux_anyarch": ["@pypi_py39_linux_dep//:whl"], 233 ":is_linux_x86_64": ["@pypi_linux_intel_dep//:whl"], 234 "//conditions:default": [], 235 }, 236 ), 237 "visibility": ["//visibility:public"], 238 }, 239 ]) # buildifier: @unsorted-dict-items 240 env.expect.that_collection(py_library_calls).contains_exactly([ 241 { 242 "name": "pkg", 243 "srcs": _glob( 244 ["site-packages/**/*.py"], 245 exclude = [], 246 allow_empty = True, 247 ), 248 "data": [] + _glob( 249 ["site-packages/**/*"], 250 exclude = [ 251 "**/*.py", 252 "**/*.pyc", 253 "**/*.pyc.*", 254 "**/*.dist-info/RECORD", 255 ] + glob_excludes.version_dependent_exclusions(), 256 ), 257 "imports": ["site-packages"], 258 "deps": [ 259 "@pypi_bar_baz//:pkg", 260 "@pypi_foo//:pkg", 261 ] + _select( 262 { 263 Label("//python/config_settings:is_python_3.9"): ["@pypi_py39_dep//:pkg"], 264 "@platforms//cpu:aarch64": ["@pypi_arm_dep//:pkg"], 265 "@platforms//os:windows": ["@pypi_win_dep//:pkg"], 266 ":is_python_3.10_linux_ppc": ["@pypi_py310_linux_ppc_dep//:pkg"], 267 ":is_python_3.9_anyos_aarch64": ["@pypi_py39_arm_dep//:pkg"], 268 ":is_python_3.9_linux_anyarch": ["@pypi_py39_linux_dep//:pkg"], 269 ":is_linux_x86_64": ["@pypi_linux_intel_dep//:pkg"], 270 "//conditions:default": [], 271 }, 272 ), 273 "tags": ["tag1", "tag2"], 274 "visibility": ["//visibility:public"], 275 }, 276 ]) # buildifier: @unsorted-dict-items 277 278_tests.append(_test_whl_and_library_deps) 279 280def _test_group(env): 281 alias_calls = [] 282 py_library_calls = [] 283 284 whl_library_targets( 285 name = "foo.whl", 286 dep_template = "@pypi_{name}//:{target}", 287 dependencies = ["foo", "bar-baz", "qux"], 288 dependencies_by_platform = { 289 "linux_x86_64": ["box", "box-amd64"], 290 "windows_x86_64": ["fox"], 291 "@platforms//os:linux": ["box"], # buildifier: disable=unsorted-dict-items to check that we sort inside the test 292 }, 293 tags = [], 294 entry_points = {}, 295 data_exclude = [], 296 group_name = "qux", 297 group_deps = ["foo", "fox", "qux"], 298 # Overrides for testing 299 filegroups = {}, 300 native = struct( 301 config_setting = lambda **_: None, 302 glob = _glob, 303 alias = lambda **kwargs: alias_calls.append(kwargs), 304 select = _select, 305 ), 306 rules = struct( 307 py_library = lambda **kwargs: py_library_calls.append(kwargs), 308 ), 309 ) 310 311 env.expect.that_collection(alias_calls).contains_exactly([ 312 {"name": "pkg", "actual": "@pypi__groups//:qux_pkg", "visibility": ["//visibility:public"]}, 313 {"name": "whl", "actual": "@pypi__groups//:qux_whl", "visibility": ["//visibility:public"]}, 314 ]) # buildifier: @unsorted-dict-items 315 env.expect.that_collection(py_library_calls).contains_exactly([ 316 { 317 "name": "_pkg", 318 "srcs": _glob(["site-packages/**/*.py"], exclude = [], allow_empty = True), 319 "data": [] + _glob( 320 ["site-packages/**/*"], 321 exclude = [ 322 "**/*.py", 323 "**/*.pyc", 324 "**/*.pyc.*", 325 "**/*.dist-info/RECORD", 326 ] + glob_excludes.version_dependent_exclusions(), 327 ), 328 "imports": ["site-packages"], 329 "deps": ["@pypi_bar_baz//:pkg"] + _select({ 330 "@platforms//os:linux": ["@pypi_box//:pkg"], 331 ":is_linux_x86_64": ["@pypi_box//:pkg", "@pypi_box_amd64//:pkg"], 332 "//conditions:default": [], 333 }), 334 "tags": [], 335 "visibility": ["@pypi__groups//:__pkg__"], 336 }, 337 ]) # buildifier: @unsorted-dict-items 338 339_tests.append(_test_group) 340 341def _glob(*args, **kwargs): 342 return [struct( 343 glob = args, 344 kwargs = kwargs, 345 )] 346 347def _select(*args, **kwargs): 348 """We need to have this mock select because we still need to support bazel 6.""" 349 return [struct( 350 select = args, 351 kwargs = kwargs, 352 )] 353 354def whl_library_targets_test_suite(name): 355 """create the test suite. 356 357 args: 358 name: the name of the test suite 359 """ 360 test_suite(name = name, basic_tests = _tests) 361