1*60517a1eSAndroid Build Coastguard Worker# Copyright 2018 The Bazel Authors. All rights reserved. 2*60517a1eSAndroid Build Coastguard Worker# 3*60517a1eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*60517a1eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*60517a1eSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*60517a1eSAndroid Build Coastguard Worker# 7*60517a1eSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*60517a1eSAndroid Build Coastguard Worker# 9*60517a1eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*60517a1eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*60517a1eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*60517a1eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*60517a1eSAndroid Build Coastguard Worker# limitations under the License. 14*60517a1eSAndroid Build Coastguard Worker 15*60517a1eSAndroid Build Coastguard Workerimport hashlib 16*60517a1eSAndroid Build Coastguard Workerimport os 17*60517a1eSAndroid Build Coastguard Workerimport platform 18*60517a1eSAndroid Build Coastguard Workerimport stat 19*60517a1eSAndroid Build Coastguard Workerimport subprocess 20*60517a1eSAndroid Build Coastguard Workerimport unittest 21*60517a1eSAndroid Build Coastguard Workerimport zipfile 22*60517a1eSAndroid Build Coastguard Worker 23*60517a1eSAndroid Build Coastguard Workerfrom python.runfiles import runfiles 24*60517a1eSAndroid Build Coastguard Worker 25*60517a1eSAndroid Build Coastguard Worker 26*60517a1eSAndroid Build Coastguard Workerclass WheelTest(unittest.TestCase): 27*60517a1eSAndroid Build Coastguard Worker maxDiff = None 28*60517a1eSAndroid Build Coastguard Worker 29*60517a1eSAndroid Build Coastguard Worker def setUp(self): 30*60517a1eSAndroid Build Coastguard Worker super().setUp() 31*60517a1eSAndroid Build Coastguard Worker self.runfiles = runfiles.Create() 32*60517a1eSAndroid Build Coastguard Worker 33*60517a1eSAndroid Build Coastguard Worker def _get_path(self, filename): 34*60517a1eSAndroid Build Coastguard Worker runfiles_path = os.path.join("rules_python/examples/wheel", filename) 35*60517a1eSAndroid Build Coastguard Worker path = self.runfiles.Rlocation(runfiles_path) 36*60517a1eSAndroid Build Coastguard Worker # The runfiles API can return None if the path doesn't exist or 37*60517a1eSAndroid Build Coastguard Worker # can't be resolved. 38*60517a1eSAndroid Build Coastguard Worker if not path: 39*60517a1eSAndroid Build Coastguard Worker raise AssertionError(f"Runfiles failed to resolve {runfiles_path}") 40*60517a1eSAndroid Build Coastguard Worker elif not os.path.exists(path): 41*60517a1eSAndroid Build Coastguard Worker # A non-None value doesn't mean the file actually exists, though 42*60517a1eSAndroid Build Coastguard Worker raise AssertionError( 43*60517a1eSAndroid Build Coastguard Worker f"Path {path} does not exist (from runfiles path {runfiles_path}" 44*60517a1eSAndroid Build Coastguard Worker ) 45*60517a1eSAndroid Build Coastguard Worker else: 46*60517a1eSAndroid Build Coastguard Worker return path 47*60517a1eSAndroid Build Coastguard Worker 48*60517a1eSAndroid Build Coastguard Worker def assertFileSha256Equal(self, filename, want): 49*60517a1eSAndroid Build Coastguard Worker hash = hashlib.sha256() 50*60517a1eSAndroid Build Coastguard Worker with open(filename, "rb") as f: 51*60517a1eSAndroid Build Coastguard Worker while True: 52*60517a1eSAndroid Build Coastguard Worker buf = f.read(2**20) 53*60517a1eSAndroid Build Coastguard Worker if not buf: 54*60517a1eSAndroid Build Coastguard Worker break 55*60517a1eSAndroid Build Coastguard Worker hash.update(buf) 56*60517a1eSAndroid Build Coastguard Worker self.assertEqual(want, hash.hexdigest()) 57*60517a1eSAndroid Build Coastguard Worker 58*60517a1eSAndroid Build Coastguard Worker def assertAllEntriesHasReproducibleMetadata(self, zf): 59*60517a1eSAndroid Build Coastguard Worker for zinfo in zf.infolist(): 60*60517a1eSAndroid Build Coastguard Worker self.assertEqual(zinfo.date_time, (1980, 1, 1, 0, 0, 0), msg=zinfo.filename) 61*60517a1eSAndroid Build Coastguard Worker self.assertEqual(zinfo.create_system, 3, msg=zinfo.filename) 62*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 63*60517a1eSAndroid Build Coastguard Worker zinfo.external_attr, 64*60517a1eSAndroid Build Coastguard Worker (stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO | stat.S_IFREG) << 16, 65*60517a1eSAndroid Build Coastguard Worker msg=zinfo.filename, 66*60517a1eSAndroid Build Coastguard Worker ) 67*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 68*60517a1eSAndroid Build Coastguard Worker zinfo.compress_type, zipfile.ZIP_DEFLATED, msg=zinfo.filename 69*60517a1eSAndroid Build Coastguard Worker ) 70*60517a1eSAndroid Build Coastguard Worker 71*60517a1eSAndroid Build Coastguard Worker def test_py_library_wheel(self): 72*60517a1eSAndroid Build Coastguard Worker filename = self._get_path("example_minimal_library-0.0.1-py3-none-any.whl") 73*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 74*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 75*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 76*60517a1eSAndroid Build Coastguard Worker zf.namelist(), 77*60517a1eSAndroid Build Coastguard Worker [ 78*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/module_with_data.py", 79*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/simple_module.py", 80*60517a1eSAndroid Build Coastguard Worker "example_minimal_library-0.0.1.dist-info/WHEEL", 81*60517a1eSAndroid Build Coastguard Worker "example_minimal_library-0.0.1.dist-info/METADATA", 82*60517a1eSAndroid Build Coastguard Worker "example_minimal_library-0.0.1.dist-info/RECORD", 83*60517a1eSAndroid Build Coastguard Worker ], 84*60517a1eSAndroid Build Coastguard Worker ) 85*60517a1eSAndroid Build Coastguard Worker self.assertFileSha256Equal( 86*60517a1eSAndroid Build Coastguard Worker filename, "79a4e9c1838c0631d5d8fa49a26efd6e9a364f6b38d9597c0f6df112271a0e28" 87*60517a1eSAndroid Build Coastguard Worker ) 88*60517a1eSAndroid Build Coastguard Worker 89*60517a1eSAndroid Build Coastguard Worker def test_py_package_wheel(self): 90*60517a1eSAndroid Build Coastguard Worker filename = self._get_path( 91*60517a1eSAndroid Build Coastguard Worker "example_minimal_package-0.0.1-py3-none-any.whl", 92*60517a1eSAndroid Build Coastguard Worker ) 93*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 94*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 95*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 96*60517a1eSAndroid Build Coastguard Worker zf.namelist(), 97*60517a1eSAndroid Build Coastguard Worker [ 98*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/data.txt", 99*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/module_with_data.py", 100*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/simple_module.py", 101*60517a1eSAndroid Build Coastguard Worker "examples/wheel/main.py", 102*60517a1eSAndroid Build Coastguard Worker "example_minimal_package-0.0.1.dist-info/WHEEL", 103*60517a1eSAndroid Build Coastguard Worker "example_minimal_package-0.0.1.dist-info/METADATA", 104*60517a1eSAndroid Build Coastguard Worker "example_minimal_package-0.0.1.dist-info/RECORD", 105*60517a1eSAndroid Build Coastguard Worker ], 106*60517a1eSAndroid Build Coastguard Worker ) 107*60517a1eSAndroid Build Coastguard Worker self.assertFileSha256Equal( 108*60517a1eSAndroid Build Coastguard Worker filename, "b4815a1d3a17cc6a5ce717ed42b940fa7788cb5168f5c1de02f5f50abed7083e" 109*60517a1eSAndroid Build Coastguard Worker ) 110*60517a1eSAndroid Build Coastguard Worker 111*60517a1eSAndroid Build Coastguard Worker def test_customized_wheel(self): 112*60517a1eSAndroid Build Coastguard Worker filename = self._get_path( 113*60517a1eSAndroid Build Coastguard Worker "example_customized-0.0.1-py3-none-any.whl", 114*60517a1eSAndroid Build Coastguard Worker ) 115*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 116*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 117*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 118*60517a1eSAndroid Build Coastguard Worker zf.namelist(), 119*60517a1eSAndroid Build Coastguard Worker [ 120*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/data.txt", 121*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/module_with_data.py", 122*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/simple_module.py", 123*60517a1eSAndroid Build Coastguard Worker "examples/wheel/main.py", 124*60517a1eSAndroid Build Coastguard Worker "example_customized-0.0.1.dist-info/WHEEL", 125*60517a1eSAndroid Build Coastguard Worker "example_customized-0.0.1.dist-info/METADATA", 126*60517a1eSAndroid Build Coastguard Worker "example_customized-0.0.1.dist-info/entry_points.txt", 127*60517a1eSAndroid Build Coastguard Worker "example_customized-0.0.1.dist-info/NOTICE", 128*60517a1eSAndroid Build Coastguard Worker "example_customized-0.0.1.dist-info/README", 129*60517a1eSAndroid Build Coastguard Worker "example_customized-0.0.1.dist-info/RECORD", 130*60517a1eSAndroid Build Coastguard Worker ], 131*60517a1eSAndroid Build Coastguard Worker ) 132*60517a1eSAndroid Build Coastguard Worker record_contents = zf.read("example_customized-0.0.1.dist-info/RECORD") 133*60517a1eSAndroid Build Coastguard Worker wheel_contents = zf.read("example_customized-0.0.1.dist-info/WHEEL") 134*60517a1eSAndroid Build Coastguard Worker metadata_contents = zf.read("example_customized-0.0.1.dist-info/METADATA") 135*60517a1eSAndroid Build Coastguard Worker entry_point_contents = zf.read( 136*60517a1eSAndroid Build Coastguard Worker "example_customized-0.0.1.dist-info/entry_points.txt" 137*60517a1eSAndroid Build Coastguard Worker ) 138*60517a1eSAndroid Build Coastguard Worker 139*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 140*60517a1eSAndroid Build Coastguard Worker record_contents, 141*60517a1eSAndroid Build Coastguard Worker # The entries are guaranteed to be sorted. 142*60517a1eSAndroid Build Coastguard Worker b"""\ 143*60517a1eSAndroid Build Coastguard Workerexamples/wheel/lib/data.txt,sha256=9vJKEdfLu8bZRArKLroPZJh1XKkK3qFMXiM79MBL2Sg,12 144*60517a1eSAndroid Build Coastguard Workerexamples/wheel/lib/module_with_data.py,sha256=8s0Khhcqz3yVsBKv2IB5u4l4TMKh7-c_V6p65WVHPms,637 145*60517a1eSAndroid Build Coastguard Workerexamples/wheel/lib/simple_module.py,sha256=z2hwciab_XPNIBNH8B1Q5fYgnJvQTeYf0ZQJpY8yLLY,637 146*60517a1eSAndroid Build Coastguard Workerexamples/wheel/main.py,sha256=sgg5iWN_9inYBjm6_Zw27hYdmo-l24fA-2rfphT-IlY,909 147*60517a1eSAndroid Build Coastguard Workerexample_customized-0.0.1.dist-info/WHEEL,sha256=sobxWSyDDkdg_rinUth-jxhXHqoNqlmNMJY3aTZn2Us,91 148*60517a1eSAndroid Build Coastguard Workerexample_customized-0.0.1.dist-info/METADATA,sha256=QYQcDJFQSIqan8eiXqL67bqsUfgEAwf2hoK_Lgi1S-0,559 149*60517a1eSAndroid Build Coastguard Workerexample_customized-0.0.1.dist-info/entry_points.txt,sha256=pqzpbQ8MMorrJ3Jp0ntmpZcuvfByyqzMXXi2UujuXD0,137 150*60517a1eSAndroid Build Coastguard Workerexample_customized-0.0.1.dist-info/NOTICE,sha256=Xpdw-FXET1IRgZ_wTkx1YQfo1-alET0FVf6V1LXO4js,76 151*60517a1eSAndroid Build Coastguard Workerexample_customized-0.0.1.dist-info/README,sha256=WmOFwZ3Jga1bHG3JiGRsUheb4UbLffUxyTdHczS27-o,40 152*60517a1eSAndroid Build Coastguard Workerexample_customized-0.0.1.dist-info/RECORD,, 153*60517a1eSAndroid Build Coastguard Worker""", 154*60517a1eSAndroid Build Coastguard Worker ) 155*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 156*60517a1eSAndroid Build Coastguard Worker wheel_contents, 157*60517a1eSAndroid Build Coastguard Worker b"""\ 158*60517a1eSAndroid Build Coastguard WorkerWheel-Version: 1.0 159*60517a1eSAndroid Build Coastguard WorkerGenerator: bazel-wheelmaker 1.0 160*60517a1eSAndroid Build Coastguard WorkerRoot-Is-Purelib: true 161*60517a1eSAndroid Build Coastguard WorkerTag: py3-none-any 162*60517a1eSAndroid Build Coastguard Worker""", 163*60517a1eSAndroid Build Coastguard Worker ) 164*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 165*60517a1eSAndroid Build Coastguard Worker metadata_contents, 166*60517a1eSAndroid Build Coastguard Worker b"""\ 167*60517a1eSAndroid Build Coastguard WorkerMetadata-Version: 2.1 168*60517a1eSAndroid Build Coastguard WorkerName: example_customized 169*60517a1eSAndroid Build Coastguard WorkerAuthor: Example Author with non-ascii characters: \xc5\xbc\xc3\xb3\xc5\x82w 170*60517a1eSAndroid Build Coastguard WorkerAuthor-email: [email protected] 171*60517a1eSAndroid Build Coastguard WorkerHome-page: www.example.com 172*60517a1eSAndroid Build Coastguard WorkerLicense: Apache 2.0 173*60517a1eSAndroid Build Coastguard WorkerDescription-Content-Type: text/markdown 174*60517a1eSAndroid Build Coastguard WorkerSummary: A one-line summary of this test package 175*60517a1eSAndroid Build Coastguard WorkerProject-URL: Bug Tracker, www.example.com/issues 176*60517a1eSAndroid Build Coastguard WorkerProject-URL: Documentation, www.example.com/docs 177*60517a1eSAndroid Build Coastguard WorkerClassifier: License :: OSI Approved :: Apache Software License 178*60517a1eSAndroid Build Coastguard WorkerClassifier: Intended Audience :: Developers 179*60517a1eSAndroid Build Coastguard WorkerRequires-Dist: pytest 180*60517a1eSAndroid Build Coastguard WorkerVersion: 0.0.1 181*60517a1eSAndroid Build Coastguard Worker 182*60517a1eSAndroid Build Coastguard WorkerThis is a sample description of a wheel. 183*60517a1eSAndroid Build Coastguard Worker""", 184*60517a1eSAndroid Build Coastguard Worker ) 185*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 186*60517a1eSAndroid Build Coastguard Worker entry_point_contents, 187*60517a1eSAndroid Build Coastguard Worker b"""\ 188*60517a1eSAndroid Build Coastguard Worker[console_scripts] 189*60517a1eSAndroid Build Coastguard Workeranother = foo.bar:baz 190*60517a1eSAndroid Build Coastguard Workercustomized_wheel = examples.wheel.main:main 191*60517a1eSAndroid Build Coastguard Worker 192*60517a1eSAndroid Build Coastguard Worker[group2] 193*60517a1eSAndroid Build Coastguard Workerfirst = first.main:f 194*60517a1eSAndroid Build Coastguard Workersecond = second.main:s""", 195*60517a1eSAndroid Build Coastguard Worker ) 196*60517a1eSAndroid Build Coastguard Worker self.assertFileSha256Equal( 197*60517a1eSAndroid Build Coastguard Worker filename, "27f3038be6e768d28735441a1bc567eca2213bd3568d18b22a414e6399a2d48e" 198*60517a1eSAndroid Build Coastguard Worker ) 199*60517a1eSAndroid Build Coastguard Worker 200*60517a1eSAndroid Build Coastguard Worker def test_filename_escaping(self): 201*60517a1eSAndroid Build Coastguard Worker filename = self._get_path( 202*60517a1eSAndroid Build Coastguard Worker "file_name_escaping-0.0.1rc1+ubuntu.r7-py3-none-any.whl", 203*60517a1eSAndroid Build Coastguard Worker ) 204*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 205*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 206*60517a1eSAndroid Build Coastguard Worker zf.namelist(), 207*60517a1eSAndroid Build Coastguard Worker [ 208*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/data.txt", 209*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/module_with_data.py", 210*60517a1eSAndroid Build Coastguard Worker "examples/wheel/lib/simple_module.py", 211*60517a1eSAndroid Build Coastguard Worker "examples/wheel/main.py", 212*60517a1eSAndroid Build Coastguard Worker # PEP calls for replacing only in the archive filename. 213*60517a1eSAndroid Build Coastguard Worker # Alas setuptools also escapes in the dist-info directory 214*60517a1eSAndroid Build Coastguard Worker # name, so let's be compatible. 215*60517a1eSAndroid Build Coastguard Worker "file_name_escaping-0.0.1rc1+ubuntu.r7.dist-info/WHEEL", 216*60517a1eSAndroid Build Coastguard Worker "file_name_escaping-0.0.1rc1+ubuntu.r7.dist-info/METADATA", 217*60517a1eSAndroid Build Coastguard Worker "file_name_escaping-0.0.1rc1+ubuntu.r7.dist-info/RECORD", 218*60517a1eSAndroid Build Coastguard Worker ], 219*60517a1eSAndroid Build Coastguard Worker ) 220*60517a1eSAndroid Build Coastguard Worker metadata_contents = zf.read( 221*60517a1eSAndroid Build Coastguard Worker "file_name_escaping-0.0.1rc1+ubuntu.r7.dist-info/METADATA" 222*60517a1eSAndroid Build Coastguard Worker ) 223*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 224*60517a1eSAndroid Build Coastguard Worker metadata_contents, 225*60517a1eSAndroid Build Coastguard Worker b"""\ 226*60517a1eSAndroid Build Coastguard WorkerMetadata-Version: 2.1 227*60517a1eSAndroid Build Coastguard WorkerName: File--Name-Escaping 228*60517a1eSAndroid Build Coastguard WorkerVersion: 0.0.1rc1+ubuntu.r7 229*60517a1eSAndroid Build Coastguard Worker 230*60517a1eSAndroid Build Coastguard WorkerUNKNOWN 231*60517a1eSAndroid Build Coastguard Worker""", 232*60517a1eSAndroid Build Coastguard Worker ) 233*60517a1eSAndroid Build Coastguard Worker 234*60517a1eSAndroid Build Coastguard Worker def test_custom_package_root_wheel(self): 235*60517a1eSAndroid Build Coastguard Worker filename = self._get_path( 236*60517a1eSAndroid Build Coastguard Worker "examples_custom_package_root-0.0.1-py3-none-any.whl", 237*60517a1eSAndroid Build Coastguard Worker ) 238*60517a1eSAndroid Build Coastguard Worker 239*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 240*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 241*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 242*60517a1eSAndroid Build Coastguard Worker zf.namelist(), 243*60517a1eSAndroid Build Coastguard Worker [ 244*60517a1eSAndroid Build Coastguard Worker "wheel/lib/data.txt", 245*60517a1eSAndroid Build Coastguard Worker "wheel/lib/module_with_data.py", 246*60517a1eSAndroid Build Coastguard Worker "wheel/lib/simple_module.py", 247*60517a1eSAndroid Build Coastguard Worker "wheel/main.py", 248*60517a1eSAndroid Build Coastguard Worker "examples_custom_package_root-0.0.1.dist-info/WHEEL", 249*60517a1eSAndroid Build Coastguard Worker "examples_custom_package_root-0.0.1.dist-info/METADATA", 250*60517a1eSAndroid Build Coastguard Worker "examples_custom_package_root-0.0.1.dist-info/entry_points.txt", 251*60517a1eSAndroid Build Coastguard Worker "examples_custom_package_root-0.0.1.dist-info/RECORD", 252*60517a1eSAndroid Build Coastguard Worker ], 253*60517a1eSAndroid Build Coastguard Worker ) 254*60517a1eSAndroid Build Coastguard Worker 255*60517a1eSAndroid Build Coastguard Worker record_contents = zf.read( 256*60517a1eSAndroid Build Coastguard Worker "examples_custom_package_root-0.0.1.dist-info/RECORD" 257*60517a1eSAndroid Build Coastguard Worker ).decode("utf-8") 258*60517a1eSAndroid Build Coastguard Worker 259*60517a1eSAndroid Build Coastguard Worker # Ensure RECORD files do not have leading forward slashes 260*60517a1eSAndroid Build Coastguard Worker for line in record_contents.splitlines(): 261*60517a1eSAndroid Build Coastguard Worker self.assertFalse(line.startswith("/")) 262*60517a1eSAndroid Build Coastguard Worker self.assertFileSha256Equal( 263*60517a1eSAndroid Build Coastguard Worker filename, "f034b3278781f4df32a33df70d794bb94170b450e477c8bd9cd42d2d922476ae" 264*60517a1eSAndroid Build Coastguard Worker ) 265*60517a1eSAndroid Build Coastguard Worker 266*60517a1eSAndroid Build Coastguard Worker def test_custom_package_root_multi_prefix_wheel(self): 267*60517a1eSAndroid Build Coastguard Worker filename = self._get_path( 268*60517a1eSAndroid Build Coastguard Worker "example_custom_package_root_multi_prefix-0.0.1-py3-none-any.whl", 269*60517a1eSAndroid Build Coastguard Worker ) 270*60517a1eSAndroid Build Coastguard Worker 271*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 272*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 273*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 274*60517a1eSAndroid Build Coastguard Worker zf.namelist(), 275*60517a1eSAndroid Build Coastguard Worker [ 276*60517a1eSAndroid Build Coastguard Worker "data.txt", 277*60517a1eSAndroid Build Coastguard Worker "module_with_data.py", 278*60517a1eSAndroid Build Coastguard Worker "simple_module.py", 279*60517a1eSAndroid Build Coastguard Worker "main.py", 280*60517a1eSAndroid Build Coastguard Worker "example_custom_package_root_multi_prefix-0.0.1.dist-info/WHEEL", 281*60517a1eSAndroid Build Coastguard Worker "example_custom_package_root_multi_prefix-0.0.1.dist-info/METADATA", 282*60517a1eSAndroid Build Coastguard Worker "example_custom_package_root_multi_prefix-0.0.1.dist-info/RECORD", 283*60517a1eSAndroid Build Coastguard Worker ], 284*60517a1eSAndroid Build Coastguard Worker ) 285*60517a1eSAndroid Build Coastguard Worker 286*60517a1eSAndroid Build Coastguard Worker record_contents = zf.read( 287*60517a1eSAndroid Build Coastguard Worker "example_custom_package_root_multi_prefix-0.0.1.dist-info/RECORD" 288*60517a1eSAndroid Build Coastguard Worker ).decode("utf-8") 289*60517a1eSAndroid Build Coastguard Worker 290*60517a1eSAndroid Build Coastguard Worker # Ensure RECORD files do not have leading forward slashes 291*60517a1eSAndroid Build Coastguard Worker for line in record_contents.splitlines(): 292*60517a1eSAndroid Build Coastguard Worker self.assertFalse(line.startswith("/")) 293*60517a1eSAndroid Build Coastguard Worker self.assertFileSha256Equal( 294*60517a1eSAndroid Build Coastguard Worker filename, "ff19f5e4540948247742716338bb4194d619cb56df409045d1a99f265ce8e36c" 295*60517a1eSAndroid Build Coastguard Worker ) 296*60517a1eSAndroid Build Coastguard Worker 297*60517a1eSAndroid Build Coastguard Worker def test_custom_package_root_multi_prefix_reverse_order_wheel(self): 298*60517a1eSAndroid Build Coastguard Worker filename = self._get_path( 299*60517a1eSAndroid Build Coastguard Worker "example_custom_package_root_multi_prefix_reverse_order-0.0.1-py3-none-any.whl", 300*60517a1eSAndroid Build Coastguard Worker ) 301*60517a1eSAndroid Build Coastguard Worker 302*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 303*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 304*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 305*60517a1eSAndroid Build Coastguard Worker zf.namelist(), 306*60517a1eSAndroid Build Coastguard Worker [ 307*60517a1eSAndroid Build Coastguard Worker "lib/data.txt", 308*60517a1eSAndroid Build Coastguard Worker "lib/module_with_data.py", 309*60517a1eSAndroid Build Coastguard Worker "lib/simple_module.py", 310*60517a1eSAndroid Build Coastguard Worker "main.py", 311*60517a1eSAndroid Build Coastguard Worker "example_custom_package_root_multi_prefix_reverse_order-0.0.1.dist-info/WHEEL", 312*60517a1eSAndroid Build Coastguard Worker "example_custom_package_root_multi_prefix_reverse_order-0.0.1.dist-info/METADATA", 313*60517a1eSAndroid Build Coastguard Worker "example_custom_package_root_multi_prefix_reverse_order-0.0.1.dist-info/RECORD", 314*60517a1eSAndroid Build Coastguard Worker ], 315*60517a1eSAndroid Build Coastguard Worker ) 316*60517a1eSAndroid Build Coastguard Worker 317*60517a1eSAndroid Build Coastguard Worker record_contents = zf.read( 318*60517a1eSAndroid Build Coastguard Worker "example_custom_package_root_multi_prefix_reverse_order-0.0.1.dist-info/RECORD" 319*60517a1eSAndroid Build Coastguard Worker ).decode("utf-8") 320*60517a1eSAndroid Build Coastguard Worker 321*60517a1eSAndroid Build Coastguard Worker # Ensure RECORD files do not have leading forward slashes 322*60517a1eSAndroid Build Coastguard Worker for line in record_contents.splitlines(): 323*60517a1eSAndroid Build Coastguard Worker self.assertFalse(line.startswith("/")) 324*60517a1eSAndroid Build Coastguard Worker self.assertFileSha256Equal( 325*60517a1eSAndroid Build Coastguard Worker filename, "4331e378ea8b8148409ae7c02177e4eb24d151a85ef937bb44b79ff5258d634b" 326*60517a1eSAndroid Build Coastguard Worker ) 327*60517a1eSAndroid Build Coastguard Worker 328*60517a1eSAndroid Build Coastguard Worker def test_python_requires_wheel(self): 329*60517a1eSAndroid Build Coastguard Worker filename = self._get_path( 330*60517a1eSAndroid Build Coastguard Worker "example_python_requires_in_a_package-0.0.1-py3-none-any.whl", 331*60517a1eSAndroid Build Coastguard Worker ) 332*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 333*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 334*60517a1eSAndroid Build Coastguard Worker metadata_contents = zf.read( 335*60517a1eSAndroid Build Coastguard Worker "example_python_requires_in_a_package-0.0.1.dist-info/METADATA" 336*60517a1eSAndroid Build Coastguard Worker ) 337*60517a1eSAndroid Build Coastguard Worker # The entries are guaranteed to be sorted. 338*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 339*60517a1eSAndroid Build Coastguard Worker metadata_contents, 340*60517a1eSAndroid Build Coastguard Worker b"""\ 341*60517a1eSAndroid Build Coastguard WorkerMetadata-Version: 2.1 342*60517a1eSAndroid Build Coastguard WorkerName: example_python_requires_in_a_package 343*60517a1eSAndroid Build Coastguard WorkerRequires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* 344*60517a1eSAndroid Build Coastguard WorkerVersion: 0.0.1 345*60517a1eSAndroid Build Coastguard Worker 346*60517a1eSAndroid Build Coastguard WorkerUNKNOWN 347*60517a1eSAndroid Build Coastguard Worker""", 348*60517a1eSAndroid Build Coastguard Worker ) 349*60517a1eSAndroid Build Coastguard Worker self.assertFileSha256Equal( 350*60517a1eSAndroid Build Coastguard Worker filename, "b34676828f93da8cd898d50dcd4f36e02fe273150e213aacb999310a05f5f38c" 351*60517a1eSAndroid Build Coastguard Worker ) 352*60517a1eSAndroid Build Coastguard Worker 353*60517a1eSAndroid Build Coastguard Worker def test_python_abi3_binary_wheel(self): 354*60517a1eSAndroid Build Coastguard Worker arch = "amd64" 355*60517a1eSAndroid Build Coastguard Worker if platform.system() != "Windows": 356*60517a1eSAndroid Build Coastguard Worker arch = subprocess.check_output(["uname", "-m"]).strip().decode() 357*60517a1eSAndroid Build Coastguard Worker # These strings match the strings from py_wheel() in BUILD 358*60517a1eSAndroid Build Coastguard Worker os_strings = { 359*60517a1eSAndroid Build Coastguard Worker "Linux": "manylinux2014", 360*60517a1eSAndroid Build Coastguard Worker "Darwin": "macosx_11_0", 361*60517a1eSAndroid Build Coastguard Worker "Windows": "win", 362*60517a1eSAndroid Build Coastguard Worker } 363*60517a1eSAndroid Build Coastguard Worker os_string = os_strings[platform.system()] 364*60517a1eSAndroid Build Coastguard Worker filename = self._get_path( 365*60517a1eSAndroid Build Coastguard Worker f"example_python_abi3_binary_wheel-0.0.1-cp38-abi3-{os_string}_{arch}.whl", 366*60517a1eSAndroid Build Coastguard Worker ) 367*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 368*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 369*60517a1eSAndroid Build Coastguard Worker metadata_contents = zf.read( 370*60517a1eSAndroid Build Coastguard Worker "example_python_abi3_binary_wheel-0.0.1.dist-info/METADATA" 371*60517a1eSAndroid Build Coastguard Worker ) 372*60517a1eSAndroid Build Coastguard Worker # The entries are guaranteed to be sorted. 373*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 374*60517a1eSAndroid Build Coastguard Worker metadata_contents, 375*60517a1eSAndroid Build Coastguard Worker b"""\ 376*60517a1eSAndroid Build Coastguard WorkerMetadata-Version: 2.1 377*60517a1eSAndroid Build Coastguard WorkerName: example_python_abi3_binary_wheel 378*60517a1eSAndroid Build Coastguard WorkerRequires-Python: >=3.8 379*60517a1eSAndroid Build Coastguard WorkerVersion: 0.0.1 380*60517a1eSAndroid Build Coastguard Worker 381*60517a1eSAndroid Build Coastguard WorkerUNKNOWN 382*60517a1eSAndroid Build Coastguard Worker""", 383*60517a1eSAndroid Build Coastguard Worker ) 384*60517a1eSAndroid Build Coastguard Worker wheel_contents = zf.read( 385*60517a1eSAndroid Build Coastguard Worker "example_python_abi3_binary_wheel-0.0.1.dist-info/WHEEL" 386*60517a1eSAndroid Build Coastguard Worker ) 387*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 388*60517a1eSAndroid Build Coastguard Worker wheel_contents.decode(), 389*60517a1eSAndroid Build Coastguard Worker f"""\ 390*60517a1eSAndroid Build Coastguard WorkerWheel-Version: 1.0 391*60517a1eSAndroid Build Coastguard WorkerGenerator: bazel-wheelmaker 1.0 392*60517a1eSAndroid Build Coastguard WorkerRoot-Is-Purelib: false 393*60517a1eSAndroid Build Coastguard WorkerTag: cp38-abi3-{os_string}_{arch} 394*60517a1eSAndroid Build Coastguard Worker""", 395*60517a1eSAndroid Build Coastguard Worker ) 396*60517a1eSAndroid Build Coastguard Worker 397*60517a1eSAndroid Build Coastguard Worker def test_rule_creates_directory_and_is_included_in_wheel(self): 398*60517a1eSAndroid Build Coastguard Worker filename = self._get_path( 399*60517a1eSAndroid Build Coastguard Worker "use_rule_with_dir_in_outs-0.0.1-py3-none-any.whl", 400*60517a1eSAndroid Build Coastguard Worker ) 401*60517a1eSAndroid Build Coastguard Worker 402*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 403*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 404*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 405*60517a1eSAndroid Build Coastguard Worker zf.namelist(), 406*60517a1eSAndroid Build Coastguard Worker [ 407*60517a1eSAndroid Build Coastguard Worker "examples/wheel/main.py", 408*60517a1eSAndroid Build Coastguard Worker "examples/wheel/someDir/foo.py", 409*60517a1eSAndroid Build Coastguard Worker "use_rule_with_dir_in_outs-0.0.1.dist-info/WHEEL", 410*60517a1eSAndroid Build Coastguard Worker "use_rule_with_dir_in_outs-0.0.1.dist-info/METADATA", 411*60517a1eSAndroid Build Coastguard Worker "use_rule_with_dir_in_outs-0.0.1.dist-info/RECORD", 412*60517a1eSAndroid Build Coastguard Worker ], 413*60517a1eSAndroid Build Coastguard Worker ) 414*60517a1eSAndroid Build Coastguard Worker self.assertFileSha256Equal( 415*60517a1eSAndroid Build Coastguard Worker filename, "ac9216bd54dcae1a6270c35fccf8a73b0be87c1b026c28e963b7c76b2f9b722b" 416*60517a1eSAndroid Build Coastguard Worker ) 417*60517a1eSAndroid Build Coastguard Worker 418*60517a1eSAndroid Build Coastguard Worker def test_rule_expands_workspace_status_keys_in_wheel_metadata(self): 419*60517a1eSAndroid Build Coastguard Worker filename = self._get_path( 420*60517a1eSAndroid Build Coastguard Worker "example_minimal_library{BUILD_USER}-0.1.{BUILD_TIMESTAMP}-py3-none-any.whl" 421*60517a1eSAndroid Build Coastguard Worker ) 422*60517a1eSAndroid Build Coastguard Worker 423*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 424*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 425*60517a1eSAndroid Build Coastguard Worker metadata_file = None 426*60517a1eSAndroid Build Coastguard Worker for f in zf.namelist(): 427*60517a1eSAndroid Build Coastguard Worker self.assertNotIn("{BUILD_TIMESTAMP}", f) 428*60517a1eSAndroid Build Coastguard Worker self.assertNotIn("{BUILD_USER}", f) 429*60517a1eSAndroid Build Coastguard Worker if os.path.basename(f) == "METADATA": 430*60517a1eSAndroid Build Coastguard Worker metadata_file = f 431*60517a1eSAndroid Build Coastguard Worker self.assertIsNotNone(metadata_file) 432*60517a1eSAndroid Build Coastguard Worker 433*60517a1eSAndroid Build Coastguard Worker version = None 434*60517a1eSAndroid Build Coastguard Worker name = None 435*60517a1eSAndroid Build Coastguard Worker with zf.open(metadata_file) as fp: 436*60517a1eSAndroid Build Coastguard Worker for line in fp: 437*60517a1eSAndroid Build Coastguard Worker if line.startswith(b"Version:"): 438*60517a1eSAndroid Build Coastguard Worker version = line.decode().split()[-1] 439*60517a1eSAndroid Build Coastguard Worker if line.startswith(b"Name:"): 440*60517a1eSAndroid Build Coastguard Worker name = line.decode().split()[-1] 441*60517a1eSAndroid Build Coastguard Worker self.assertIsNotNone(version) 442*60517a1eSAndroid Build Coastguard Worker self.assertIsNotNone(name) 443*60517a1eSAndroid Build Coastguard Worker self.assertNotIn("{BUILD_TIMESTAMP}", version) 444*60517a1eSAndroid Build Coastguard Worker self.assertNotIn("{BUILD_USER}", name) 445*60517a1eSAndroid Build Coastguard Worker 446*60517a1eSAndroid Build Coastguard Worker def test_requires_file_and_extra_requires_files(self): 447*60517a1eSAndroid Build Coastguard Worker filename = self._get_path("requires_files-0.0.1-py3-none-any.whl") 448*60517a1eSAndroid Build Coastguard Worker 449*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 450*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 451*60517a1eSAndroid Build Coastguard Worker metadata_file = None 452*60517a1eSAndroid Build Coastguard Worker for f in zf.namelist(): 453*60517a1eSAndroid Build Coastguard Worker if os.path.basename(f) == "METADATA": 454*60517a1eSAndroid Build Coastguard Worker metadata_file = f 455*60517a1eSAndroid Build Coastguard Worker self.assertIsNotNone(metadata_file) 456*60517a1eSAndroid Build Coastguard Worker 457*60517a1eSAndroid Build Coastguard Worker requires = [] 458*60517a1eSAndroid Build Coastguard Worker with zf.open(metadata_file) as fp: 459*60517a1eSAndroid Build Coastguard Worker for line in fp: 460*60517a1eSAndroid Build Coastguard Worker if line.startswith(b"Requires-Dist:"): 461*60517a1eSAndroid Build Coastguard Worker requires.append(line.decode("utf-8").strip()) 462*60517a1eSAndroid Build Coastguard Worker 463*60517a1eSAndroid Build Coastguard Worker print(requires) 464*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 465*60517a1eSAndroid Build Coastguard Worker [ 466*60517a1eSAndroid Build Coastguard Worker "Requires-Dist: tomli>=2.0.0", 467*60517a1eSAndroid Build Coastguard Worker "Requires-Dist: starlark", 468*60517a1eSAndroid Build Coastguard Worker "Requires-Dist: pyyaml!=6.0.1,>=6.0.0; extra == 'example'", 469*60517a1eSAndroid Build Coastguard Worker 'Requires-Dist: toml; ((python_version == "3.11" or python_version == "3.12") and python_version != "3.8") and extra == \'example\'', 470*60517a1eSAndroid Build Coastguard Worker 'Requires-Dist: wheel; (python_version == "3.11" or python_version == "3.12") and extra == \'example\'', 471*60517a1eSAndroid Build Coastguard Worker ], 472*60517a1eSAndroid Build Coastguard Worker requires, 473*60517a1eSAndroid Build Coastguard Worker ) 474*60517a1eSAndroid Build Coastguard Worker 475*60517a1eSAndroid Build Coastguard Worker def test_minimal_data_files(self): 476*60517a1eSAndroid Build Coastguard Worker filename = self._get_path("minimal_data_files-0.0.1-py3-none-any.whl") 477*60517a1eSAndroid Build Coastguard Worker 478*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 479*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 480*60517a1eSAndroid Build Coastguard Worker metadata_file = None 481*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 482*60517a1eSAndroid Build Coastguard Worker zf.namelist(), 483*60517a1eSAndroid Build Coastguard Worker [ 484*60517a1eSAndroid Build Coastguard Worker "minimal_data_files-0.0.1.dist-info/WHEEL", 485*60517a1eSAndroid Build Coastguard Worker "minimal_data_files-0.0.1.dist-info/METADATA", 486*60517a1eSAndroid Build Coastguard Worker "minimal_data_files-0.0.1.data/data/target/path/README.md", 487*60517a1eSAndroid Build Coastguard Worker "minimal_data_files-0.0.1.data/scripts/NOTICE", 488*60517a1eSAndroid Build Coastguard Worker "minimal_data_files-0.0.1.dist-info/RECORD", 489*60517a1eSAndroid Build Coastguard Worker ], 490*60517a1eSAndroid Build Coastguard Worker ) 491*60517a1eSAndroid Build Coastguard Worker 492*60517a1eSAndroid Build Coastguard Worker def test_extra_requires(self): 493*60517a1eSAndroid Build Coastguard Worker filename = self._get_path("extra_requires-0.0.1-py3-none-any.whl") 494*60517a1eSAndroid Build Coastguard Worker 495*60517a1eSAndroid Build Coastguard Worker with zipfile.ZipFile(filename) as zf: 496*60517a1eSAndroid Build Coastguard Worker self.assertAllEntriesHasReproducibleMetadata(zf) 497*60517a1eSAndroid Build Coastguard Worker metadata_file = None 498*60517a1eSAndroid Build Coastguard Worker for f in zf.namelist(): 499*60517a1eSAndroid Build Coastguard Worker if os.path.basename(f) == "METADATA": 500*60517a1eSAndroid Build Coastguard Worker metadata_file = f 501*60517a1eSAndroid Build Coastguard Worker self.assertIsNotNone(metadata_file) 502*60517a1eSAndroid Build Coastguard Worker 503*60517a1eSAndroid Build Coastguard Worker requires = [] 504*60517a1eSAndroid Build Coastguard Worker with zf.open(metadata_file) as fp: 505*60517a1eSAndroid Build Coastguard Worker for line in fp: 506*60517a1eSAndroid Build Coastguard Worker if line.startswith(b"Requires-Dist:"): 507*60517a1eSAndroid Build Coastguard Worker requires.append(line.decode("utf-8").strip()) 508*60517a1eSAndroid Build Coastguard Worker 509*60517a1eSAndroid Build Coastguard Worker print(requires) 510*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 511*60517a1eSAndroid Build Coastguard Worker [ 512*60517a1eSAndroid Build Coastguard Worker "Requires-Dist: tomli>=2.0.0", 513*60517a1eSAndroid Build Coastguard Worker "Requires-Dist: starlark", 514*60517a1eSAndroid Build Coastguard Worker 'Requires-Dist: pytest; python_version != "3.8"', 515*60517a1eSAndroid Build Coastguard Worker "Requires-Dist: pyyaml!=6.0.1,>=6.0.0; extra == 'example'", 516*60517a1eSAndroid Build Coastguard Worker 'Requires-Dist: toml; ((python_version == "3.11" or python_version == "3.12") and python_version != "3.8") and extra == \'example\'', 517*60517a1eSAndroid Build Coastguard Worker 'Requires-Dist: wheel; (python_version == "3.11" or python_version == "3.12") and extra == \'example\'', 518*60517a1eSAndroid Build Coastguard Worker ], 519*60517a1eSAndroid Build Coastguard Worker requires, 520*60517a1eSAndroid Build Coastguard Worker ) 521*60517a1eSAndroid Build Coastguard Worker 522*60517a1eSAndroid Build Coastguard Worker 523*60517a1eSAndroid Build Coastguard Workerif __name__ == "__main__": 524*60517a1eSAndroid Build Coastguard Worker unittest.main() 525