1# Copyright 2023 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://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, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""Generate a Python wheel for a pw_python_package or pw_python_distribution.""" 15 16import argparse 17import hashlib 18from pathlib import Path 19import shutil 20import subprocess 21import sys 22 23try: 24 from pw_build.python_package import PythonPackage 25 26except ImportError: 27 # Load from python_package from this directory if pw_build is not available. 28 from python_package import PythonPackage # type: ignore 29 30 31def _parse_args() -> argparse.Namespace: 32 parser = argparse.ArgumentParser(description=__doc__) 33 parser.add_argument( 34 '--package-dir', 35 type=Path, 36 required=True, 37 help='Path to the root gn build dir.', 38 ) 39 parser.add_argument( 40 '--out-dir', 41 type=Path, 42 required=True, 43 help='requirement file to generate', 44 ) 45 parser.add_argument( 46 '--generate-hashes', 47 action='store_true', 48 help='Generate sha256 sums for the requirements.txt file.', 49 ) 50 return parser.parse_args() 51 52 53def main( 54 package_dir: Path, 55 out_dir: Path, 56 generate_hashes: bool, 57) -> int: 58 """Build a Python wheel.""" 59 60 # Delete existing wheels from the out dir, there may be stale versions. 61 shutil.rmtree(out_dir, ignore_errors=True) 62 out_dir.mkdir(parents=True, exist_ok=True) 63 64 # Find the target package name and version. 65 pkg = PythonPackage( 66 sources=[], 67 setup_sources=[package_dir / 'setup.cfg'], 68 tests=[], 69 inputs=[], 70 ) 71 requirement_lines = f'{pkg.package_name}=={pkg.package_version}' 72 73 # Build the wheel. 74 subprocess.run( 75 [ 76 sys.executable, 77 "-m", 78 "build", 79 str(package_dir), 80 "--wheel", 81 "--no-isolation", 82 "--outdir", 83 str(out_dir), 84 ], 85 check=True, 86 ) 87 88 if generate_hashes: 89 # Cacluate the sha256 90 for wheel_path in out_dir.glob('**/*.whl'): 91 wheel_sha256 = hashlib.sha256() 92 wheel_sha256.update(wheel_path.read_bytes()) 93 sha256 = wheel_sha256.hexdigest() 94 requirement_lines += ' \\\n ' 95 requirement_lines += f'--hash=sha256:{sha256}' 96 break 97 98 # Save a requirements file for this wheel and hash value. 99 requirement_file = out_dir / 'requirements.txt' 100 requirement_file.write_text(requirement_lines, encoding='utf-8') 101 102 return 0 103 104 105if __name__ == '__main__': 106 sys.exit(main(**vars(_parse_args()))) 107