1*60517a1eSAndroid Build Coastguard Worker# Copyright 2023 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 Worker"Implementation of py_package rule" 16*60517a1eSAndroid Build Coastguard Worker 17*60517a1eSAndroid Build Coastguard Workerdef _path_inside_wheel(input_file): 18*60517a1eSAndroid Build Coastguard Worker # input_file.short_path is sometimes relative ("../${repository_root}/foobar") 19*60517a1eSAndroid Build Coastguard Worker # which is not a valid path within a zip file. Fix that. 20*60517a1eSAndroid Build Coastguard Worker short_path = input_file.short_path 21*60517a1eSAndroid Build Coastguard Worker if short_path.startswith("..") and len(short_path) >= 3: 22*60517a1eSAndroid Build Coastguard Worker # Path separator. '/' on linux. 23*60517a1eSAndroid Build Coastguard Worker separator = short_path[2] 24*60517a1eSAndroid Build Coastguard Worker 25*60517a1eSAndroid Build Coastguard Worker # Consume '../' part. 26*60517a1eSAndroid Build Coastguard Worker short_path = short_path[3:] 27*60517a1eSAndroid Build Coastguard Worker 28*60517a1eSAndroid Build Coastguard Worker # Find position of next '/' and consume everything up to that character. 29*60517a1eSAndroid Build Coastguard Worker pos = short_path.find(separator) 30*60517a1eSAndroid Build Coastguard Worker short_path = short_path[pos + 1:] 31*60517a1eSAndroid Build Coastguard Worker return short_path 32*60517a1eSAndroid Build Coastguard Worker 33*60517a1eSAndroid Build Coastguard Workerdef _py_package_impl(ctx): 34*60517a1eSAndroid Build Coastguard Worker inputs = depset( 35*60517a1eSAndroid Build Coastguard Worker transitive = [dep[DefaultInfo].data_runfiles.files for dep in ctx.attr.deps] + 36*60517a1eSAndroid Build Coastguard Worker [dep[DefaultInfo].default_runfiles.files for dep in ctx.attr.deps], 37*60517a1eSAndroid Build Coastguard Worker ) 38*60517a1eSAndroid Build Coastguard Worker 39*60517a1eSAndroid Build Coastguard Worker # TODO: '/' is wrong on windows, but the path separator is not available in starlark. 40*60517a1eSAndroid Build Coastguard Worker # Fix this once ctx.configuration has directory separator information. 41*60517a1eSAndroid Build Coastguard Worker packages = [p.replace(".", "/") for p in ctx.attr.packages] 42*60517a1eSAndroid Build Coastguard Worker if not packages: 43*60517a1eSAndroid Build Coastguard Worker filtered_inputs = inputs 44*60517a1eSAndroid Build Coastguard Worker else: 45*60517a1eSAndroid Build Coastguard Worker filtered_files = [] 46*60517a1eSAndroid Build Coastguard Worker 47*60517a1eSAndroid Build Coastguard Worker # TODO: flattening depset to list gives poor performance, 48*60517a1eSAndroid Build Coastguard Worker for input_file in inputs.to_list(): 49*60517a1eSAndroid Build Coastguard Worker wheel_path = _path_inside_wheel(input_file) 50*60517a1eSAndroid Build Coastguard Worker for package in packages: 51*60517a1eSAndroid Build Coastguard Worker if wheel_path.startswith(package): 52*60517a1eSAndroid Build Coastguard Worker filtered_files.append(input_file) 53*60517a1eSAndroid Build Coastguard Worker filtered_inputs = depset(direct = filtered_files) 54*60517a1eSAndroid Build Coastguard Worker 55*60517a1eSAndroid Build Coastguard Worker return [DefaultInfo( 56*60517a1eSAndroid Build Coastguard Worker files = filtered_inputs, 57*60517a1eSAndroid Build Coastguard Worker )] 58*60517a1eSAndroid Build Coastguard Worker 59*60517a1eSAndroid Build Coastguard Workerpy_package_lib = struct( 60*60517a1eSAndroid Build Coastguard Worker implementation = _py_package_impl, 61*60517a1eSAndroid Build Coastguard Worker attrs = { 62*60517a1eSAndroid Build Coastguard Worker "deps": attr.label_list( 63*60517a1eSAndroid Build Coastguard Worker doc = "", 64*60517a1eSAndroid Build Coastguard Worker ), 65*60517a1eSAndroid Build Coastguard Worker "packages": attr.string_list( 66*60517a1eSAndroid Build Coastguard Worker mandatory = False, 67*60517a1eSAndroid Build Coastguard Worker allow_empty = True, 68*60517a1eSAndroid Build Coastguard Worker doc = """\ 69*60517a1eSAndroid Build Coastguard WorkerList of Python packages to include in the distribution. 70*60517a1eSAndroid Build Coastguard WorkerSub-packages are automatically included. 71*60517a1eSAndroid Build Coastguard Worker""", 72*60517a1eSAndroid Build Coastguard Worker ), 73*60517a1eSAndroid Build Coastguard Worker }, 74*60517a1eSAndroid Build Coastguard Worker path_inside_wheel = _path_inside_wheel, 75*60517a1eSAndroid Build Coastguard Worker) 76