-
-
Notifications
You must be signed in to change notification settings - Fork 681
Expand file tree
/
Copy pathuv_external_deps.bzl
More file actions
152 lines (131 loc) · 4.62 KB
/
uv_external_deps.bzl
File metadata and controls
152 lines (131 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""A module extension for uv external dependencies.
This extension allows users to define external dependencies using uv.
"""
load("//python/private:repo_utils.bzl", "REPO_DEBUG_ENV_VAR", "repo_utils")
load("//python/private:text_util.bzl", "render")
def _wheel_repo_impl(rctx):
rctx.download(rctx.attr.urls, output = "output.zip")
rctx.file("BUILD.bazel", "exports_files(glob(['**']))")
wheel_repo = repository_rule(
implementation = _wheel_repo_impl,
attrs = {
"urls": attr.string_list(),
},
)
_PACKAGE_BUILD_TEMPLATE = """
load("@rules_python//python/private/pypi:uv_lock_targets.bzl", "define_targets")
package(
default_visibility = ["//visibility:public"]
)
exports_files(glob(["**"]))
define_targets(
name = "{package}",
selectors = {selectors}
)
"""
def _hub_package_build_file(rctx, package, selectors):
rctx.file(
"{}/BUILD.bazel".format(package),
_PACKAGE_BUILD_TEMPLATE.format(
package = package,
selectors = render.list(selectors),
),
)
def _hub_repo_impl(rctx):
hub_selectors = json.decode(rctx.attr.selectors)
for package, selectors in hub_selectors.items():
_hub_package_build_file(rctx, package, selectors)
rctx.file("BUILD.bazel", "")
hub_repo = repository_rule(
implementation = _hub_repo_impl,
attrs = {
"selectors": attr.string(),
},
)
def wheel_tags_from_wheel_url(url):
_, _, basename = url.rpartition("/")
basename = basename.removesuffix(".whl")
distro, _, tail = basename.partition("-")
version, _, tail = tail.partition("-")
py_tag, _, tail = tail.partition("-")
abi, _, tail = tail.partition("-")
platform, _, tail = tail.partition("-")
return {
"python_tag": py_tag,
"abi_tag": abi,
"platform_tag": platform,
}
#charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl",
def _uv_external_deps_extension_impl(mctx):
logger = repo_utils.logger(mctx, "uvextdeps")
# sources[distro][version][type][url] = any_of_conditions
# url -> info
sources = {}
hub_name = None
for mod in mctx.modules:
for hub in mod.tags.hub:
out = _convert_uv_lock_to_json(mctx, hub, logger)
lock_info = json.decode(out)
break
# Basically what we're doing is:
# URLs are given name R (repo name). Thus, we never duplicate a download.
# Repo R is used if conditions C are met (wheel tags, marker, and
# custom config settings for that lock file).
url_to_repo = {}
hub_selectors = {}
packages = lock_info["package"]
for distro in packages:
# todo: handle source{virtual = "."}
if "wheels" not in distro:
continue
for i, wheel in enumerate(distro["wheels"]):
url = wheel["url"]
if url not in url_to_repo:
# todo: normalize dash to underscore etc
name = "{distro}_{version}_{i}".format(
distro = distro["name"],
version = distro["version"],
i = i,
)
wheel_repo(
name = name,
urls = [url],
)
else:
name = url_to_repo[url]
hub_selectors.setdefault(distro["name"], [])
wheel_tags = wheel_tags_from_wheel_url(url)
resolution_markers = distro.get("resolution-markers")
if resolution_markers:
for marker in resolution_markers:
hub_selectors[distro["name"]].append(struct(
wheel_tags = wheel_tags,
config_settings = hub.config_settings,
marker = marker,
actual_repo = name,
))
else:
hub_selectors[distro["name"]].append(struct(
wheel_tags = wheel_tags,
config_settings = hub.config_settings,
marker = None,
actual_repo = name,
))
hub_repo(
name = hub.name,
selectors = json.encode(hub_selectors),
)
uv_external_deps = module_extension(
implementation = _uv_external_deps_extension_impl,
tag_classes = {
"hub": tag_class(attrs = {
"name": attr.string(),
"srcs": attr.label_list(),
"config_settings": attr.label_list(),
"_toml2json": attr.label(default = "//tools/toml2json:toml2json.py"),
"_python_interpreter_target": attr.label(
default = "@python_3_14_host//:python",
),
}),
},
)