Skip to content

Commit

Permalink
Deduplicate import dirs in mypy path, minor cleanups (#42)
Browse files Browse the repository at this point in the history
imports in Bazel contain the transitive closure of all imports of all
dependencies, which creates a significant number of duplicates and blows
up MYPYPATH. This PR maintains a unique set of these imports instead.
  • Loading branch information
mark-thm authored Nov 15, 2024
1 parent 638a3bc commit 0001418
Showing 1 changed file with 16 additions and 8 deletions.
24 changes: 16 additions & 8 deletions mypy/private/mypy.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ MypyCacheInfo = provider(
},
)

def _extract_import_dir(import_):
# _main/path/to/package -> path/to/package
return import_.split("/", 1)[-1]

def _mypy_impl(target, ctx):
# skip non-root targets
if target.label.workspace_root != "":
Expand All @@ -38,7 +42,7 @@ def _mypy_impl(target, ctx):

# we need to help mypy map the location of first party deps with custom
# 'imports' by setting MYPYPATH.
custom_imports = []
imports_dirs = {}

# generated dirs
generated_dirs = {}
Expand All @@ -57,24 +61,27 @@ def _mypy_impl(target, ctx):
]

if PyInfo in target:
custom_imports.extend([x.split("/", 1)[-1] for x in target[PyInfo].imports.to_list()])
for import_ in target[PyInfo].imports.to_list():
imports_dirs[_extract_import_dir(import_)] = 1

for dep in (ctx.rule.attr.deps + additional_types):
depsets.append(dep.default_runfiles.files)

if PyTypeLibraryInfo in dep:
types.append(dep[PyTypeLibraryInfo].directory.path + "/site-packages")
elif dep.label.workspace_root.startswith("external/"):
# TODO: do we need this, still?
external_deps.append(dep.label.workspace_root + "/site-packages")

external_deps.extend([
"external/{}".format(x)
for x in dep[PyInfo].imports.to_list()
if "mypy_extensions" not in x and
"typing_extensions" not in x
])
elif PyInfo in dep and dep.label.workspace_name == "":
# _main/path/to/package -> path/to/package
custom_imports.extend([x.split("/", 1)[-1] for x in dep[PyInfo].imports.to_list()])
for import_ in dep[PyInfo].imports.to_list():
imports_dirs[_extract_import_dir(import_)] = 1

if MypyCacheInfo in dep:
upstream_caches.append(dep[MypyCacheInfo].directory)
Expand All @@ -87,15 +94,16 @@ def _mypy_impl(target, ctx):
# and as a way to skip iterating over depset contents to find generated
# file roots?

unique_imports_dirs = imports_dirs.keys()
unique_generated_dirs = generated_dirs.keys()
generated_custom_imports = []
generated_imports_dirs = []
for generated_dir in unique_generated_dirs:
for custom_import in custom_imports:
generated_custom_imports.append("{}/{}".format(generated_dir, custom_import))
for import_ in unique_imports_dirs:
generated_imports_dirs.append("{}/{}".format(generated_dir, import_))

# types need to appear first in the mypy path since the module directories
# are the same and mypy resolves the first ones, first.
mypy_path = ":".join(types + external_deps + custom_imports + unique_generated_dirs + generated_custom_imports)
mypy_path = ":".join(types + external_deps + unique_imports_dirs + unique_generated_dirs + generated_imports_dirs)

output_file = ctx.actions.declare_file(ctx.rule.attr.name + ".mypy_stdout")

Expand Down

0 comments on commit 0001418

Please sign in to comment.