@@ -109,8 +109,8 @@ def _mypy_impl(target, ctx):
109
109
110
110
depsets = []
111
111
112
- type_mapping = dict (zip ([k .label for k in ctx .attr ._types_keys ], ctx .attr ._types_values ))
113
- dep_with_stubs = [_ .label .workspace_root + "/site-packages" for _ in ctx .attr ._types_keys ]
112
+ type_mapping = dict (zip ([k .label for k in ctx .attr ._stubs_keys ], ctx .attr ._stubs_values ))
113
+ dep_with_stubs = [_ .label .workspace_root + "/site-packages" for _ in ctx .attr ._stubs_keys ]
114
114
additional_types = [
115
115
type_mapping [dep .label ]
116
116
for dep in ctx .rule .attr .deps
@@ -230,7 +230,7 @@ def _mypy_impl(target, ctx):
230
230
def mypy (
231
231
mypy_cli = None ,
232
232
mypy_ini = None ,
233
- types = None ,
233
+ stubs = None ,
234
234
cache = True ,
235
235
color = True ,
236
236
suppression_tags = None ,
@@ -242,15 +242,7 @@ def mypy(
242
242
mypy_cli: (optional) a replacement mypy_cli to use (recommended to produce
243
243
with mypy_cli macro)
244
244
mypy_ini: (optional) mypy_ini file to use
245
- types: (optional) a dict of dependency label to types dependency label
246
- example:
247
- ```
248
- {
249
- requirement("cachetools"): requirement("types-cachetools"),
250
- }
251
- ```
252
- Use the types extension to create this map for a requirements.in
253
- or requirements.txt file.
245
+ stubs: (optional) result from load_stubs()
254
246
cache: (optional, default True) propagate the mypy cache
255
247
color: (optional, default True) use color in mypy output
256
248
suppression_tags: (optional, default ["no-mypy"]) tags that suppress running
@@ -262,8 +254,6 @@ def mypy(
262
254
Returns:
263
255
a mypy aspect.
264
256
"""
265
- types = types or {}
266
-
267
257
additional_attrs = {}
268
258
269
259
return aspect (
@@ -284,15 +274,61 @@ def mypy(
284
274
),
285
275
# pass the dict[Label, Label] in parts because Bazel doesn't have
286
276
# this kind of attr to pass naturally
287
- "_types_keys " : attr .label_list (default = types . keys ()),
288
- "_types_values " : attr .label_list (default = types . values ()),
277
+ "_stubs_keys " : attr .label_list (default = stubs . mapping . keys () if stubs else [] ),
278
+ "_stubs_values " : attr .label_list (default = stubs . mapping . values () if stubs else [] ),
289
279
"_suppression_tags" : attr .string_list (default = suppression_tags or ["no-mypy" ]),
290
280
"_opt_in_tags" : attr .string_list (default = opt_in_tags or []),
291
281
"cache" : attr .bool (default = cache ),
292
282
"color" : attr .bool (default = color ),
293
283
} | additional_attrs ,
294
284
)
295
285
286
+ def _load_stubs_from_requirements (requirements ):
287
+ # for a package "foo-bar", maps "foo_bar" to "@pip//foo_bar:pkg"
288
+ parsed_reqs = {}
289
+ for req in requirements :
290
+ parsed_reqs [Label (req ).package ] = req
291
+
292
+ stubs = {}
293
+ for req in requirements :
294
+ req_name = Label (req ).package
295
+
296
+ if req_name .endswith ("_stubs" ):
297
+ base_req_name = req_name .removesuffix ("_stubs" )
298
+ elif req_name .startswith ("types_" ):
299
+ base_req_name = req_name .removeprefix ("types_" )
300
+ else :
301
+ continue
302
+
303
+ if base_req_name in parsed_reqs :
304
+ base_req = parsed_reqs [base_req_name ]
305
+ stubs [base_req ] = req
306
+
307
+ return stubs
308
+
309
+ def load_stubs (requirements = [], overrides = {}):
310
+ """
311
+ Generate a mapping of labels to their stubs label. For example:
312
+
313
+ ```
314
+ {
315
+ requirement("cachetools"): requirement("types-cachetools"),
316
+ }
317
+ ```
318
+
319
+ This can be detected automatically via `requirements`, manually via `overrides`,
320
+ or a combination of both.
321
+
322
+ Args:
323
+ requirements: (optional) the full list of requirements from "@pip//:requirements.bzl"
324
+ to automatically detect stubs from.
325
+ overrides: (optional) explicitly specified stubs mapping
326
+ """
327
+ stubs = _load_stubs_from_requirements (requirements )
328
+ return struct (
329
+ mapping = stubs | overrides ,
330
+ )
331
+
296
332
def mypy_cli (name , deps = None , mypy_requirement = None , python_version = "3.12" , tags = None ):
297
333
"""
298
334
Produce a custom mypy executable for use with the mypy build rule.
0 commit comments