Skip to content

[mypyc] Import setuptools lazily in mypyc.build on Python 3.12+ - #22084

Merged
JukkaL merged 2 commits into
masterfrom
mypyc-lazy-setuptools
Oct 2, 2026
Merged

JukkaL merged 2 commits into
masterfrom
mypyc-lazy-setuptools

Conversation

@JukkaL

@JukkaL JukkaL commented Oct 2, 2026

Copy link
Copy Markdown
Collaborator

Importing mypyc.build used to always import setuptools, distutils and
mypyc.build_setup, but mypyc_build (type checking and C generation) needs
none of them. They are only needed for building extensions, e.g. in
mypycify. Importing them is slow, which adds significant fixed overhead
to tools that call mypyc_build directly for many small builds, such as
Bazel integrations.

Move these imports into a helper function, called by the functions that
need them. On Python versions before 3.12, distutils is still in the
stdlib and setuptools must be imported before it to override it, so keep
the eager imports there to preserve backward compatibility.

In an interpreted microbenchmark this saved ~34 ms of a ~190 ms run (17%).

JukkaL added 2 commits October 2, 2026 12:35
Importing mypyc.build used to always import setuptools, distutils and
mypyc.build_setup, but mypyc_build (type checking and C generation) needs
none of them. They are only needed for building extensions, e.g. in
mypycify. Importing them is slow, which adds significant fixed overhead
to tools that call mypyc_build directly for many small builds, such as
Bazel integrations.

Move these imports into import_distutils(), called by the functions that
need them. On Python versions before 3.12, distutils is still in the
stdlib and setuptools must be imported before it to override it, so keep
importing everything eagerly there to preserve backward compatibility.

In a quick local simulation (interpreted mypy, Python 3.14, warm caches,
tiny module, calling mypyc_build like a Bazel driver), this saved about
31-37 ms of a ~190 ms run (16-19%). The number of setuptools-related
modules imported went from 102 to 3.
- The module docstring overstated the distutils fallback: mypycify
  already requires setuptools (via the copy_extensions_to_source patch).
- librt_cache relied on importing mypyc.build to set up distutils, which
  is no longer true on 3.12+. Use import_distutils() explicitly.
- Add a subprocess test checking that C generation via mypyc_build
  doesn't import setuptools, distutils or mypyc.build_setup.
@JukkaL
JukkaL merged commit c614451 into master Oct 2, 2026
18 checks passed
@JukkaL
JukkaL deleted the mypyc-lazy-setuptools branch October 2, 2026 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants