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 def package_path(self) -> str: 31 return "rules_python~override~pip~" 32 33 def wheel_pkg_dir(self) -> str: 34 env = os.environ.get("WHEEL_PKG_DIR") 35 self.assertIsNotNone(env) 36 return env 37 38 def test_build_content_and_data(self): 39 r = runfiles.Create() 40 rpath = r.Rlocation( 41 "{}{}/generated_file.txt".format( 42 self.package_path(), 43 self.wheel_pkg_dir(), 44 ), 45 ) 46 generated_file = Path(rpath) 47 self.assertTrue(generated_file.exists()) 48 49 content = generated_file.read_text().rstrip() 50 self.assertEqual(content, "Hello world from build content file") 51 52 def test_copy_files(self): 53 r = runfiles.Create() 54 rpath = r.Rlocation( 55 "{}{}/copied_content/file.txt".format( 56 self.package_path(), 57 self.wheel_pkg_dir(), 58 ) 59 ) 60 copied_file = Path(rpath) 61 self.assertTrue(copied_file.exists()) 62 63 content = copied_file.read_text().rstrip() 64 self.assertEqual(content, "Hello world from copied file") 65 66 def test_copy_executables(self): 67 r = runfiles.Create() 68 rpath = r.Rlocation( 69 "{}{}/copied_content/executable{}".format( 70 self.package_path(), 71 self.wheel_pkg_dir(), 72 ".exe" if platform.system() == "windows" else ".py", 73 ) 74 ) 75 executable = Path(rpath) 76 self.assertTrue(executable.exists()) 77 78 proc = subprocess.run( 79 [sys.executable, str(executable)], 80 check=True, 81 stdout=subprocess.PIPE, 82 stderr=subprocess.PIPE, 83 ) 84 stdout = proc.stdout.decode("utf-8").strip() 85 self.assertEqual(stdout, "Hello world from copied executable") 86 87 def test_data_exclude_glob(self): 88 current_wheel_version = "0.40.0" 89 90 r = runfiles.Create() 91 dist_info_dir = "{}{}/site-packages/wheel-{}.dist-info".format( 92 self.package_path(), 93 self.wheel_pkg_dir(), 94 current_wheel_version, 95 ) 96 97 # Note: `METADATA` is important as it's consumed by https://docs.python.org/3/library/importlib.metadata.html 98 # `METADATA` is expected to be there to show dist-info files are included in the runfiles. 99 metadata_path = r.Rlocation("{}/METADATA".format(dist_info_dir)) 100 101 # However, `WHEEL` was explicitly excluded, so it should be missing 102 wheel_path = r.Rlocation("{}/WHEEL".format(dist_info_dir)) 103 104 self.assertTrue(Path(metadata_path).exists()) 105 self.assertFalse(Path(wheel_path).exists()) 106 107 def requests_pkg_dir(self) -> str: 108 env = os.environ.get("REQUESTS_PKG_DIR") 109 self.assertIsNotNone(env) 110 return env 111 112 def test_extra(self): 113 # This test verifies that annotations work correctly for pip packages with extras 114 # specified, in this case requests[security]. 115 r = runfiles.Create() 116 rpath = r.Rlocation( 117 "{}{}/generated_file.txt".format( 118 self.package_path(), 119 self.requests_pkg_dir(), 120 ), 121 ) 122 generated_file = Path(rpath) 123 self.assertTrue(generated_file.exists()) 124 125 content = generated_file.read_text().rstrip() 126 self.assertEqual(content, "Hello world from requests") 127 128 129if __name__ == "__main__": 130 unittest.main() 131