You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[DOC] [BLD] Building / developing matplotlib with uv & pixi #30877
I've been slowly converting all my personal repos to use uv for dependency management, and gave it a shot on matplotlib to see if it'd work. The below works right out of the box for me:
# Create a virtual environment with uv
uv venv .venv
# Activate the environment (optional, uv commands will automatically use the venv)source .venv/bin/activate # Linux/macOS# or: .venv\Scripts\activate # Windows# Install dev dependencies
uv pip install -r requirements/dev/dev-requirements.txt
# Install matplotlib in editable mode
uv pip install --no-build-isolation --editable ".[dev]"# Verify installation
uv run python -c "import matplotlib; print(matplotlib.__file__)"
Then I just point my VSCode python interpreter to the one in the .venv and everything works well. Note that a uv sync workflow does not work, given our somewhat custom build setup.
I'm ambivalent about adding this as an option to the development setup instructions, since the pip commands throughout would need a toggle. I'm also unclear what sort of CI we use to ensure build instructions work as-written. But figured it was worth sharing here in case people want to use this approach.
@sanchit122006 to clarify, this was meant more as a “sharing experience” / discussion post rather than a request to change docs or supported workflows.
Something like a new development workflow would need maintainer consensus before working on it. If there’s interest in going that direction, this thread would be the place for people to weigh in.
@scottshambaugh I’ve tried a similar setup with uv on my side and it worked pretty smoothly for me as well.
The steps you outlined match what I ended up with, including the editable install with --no-build-isolation, which I’ve found is often needed anyway when working on Matplotlib locally. Using uv run to sanity-check the install is also nice since it avoids depending on whether the environment is activated or not.
I agree that the bigger questions are more around long-term support than whether this works in practice — documenting an alternative workflow and making sure CI covers it would be the heavier lift. As a personal dev setup though, this seems totally reasonable, and it’s useful to have the experience written down here for others who are already using uv.
Would it work to just add uv there? AFAICS, the only difference is that you must use uv pip instead of pip in the following. One could either state this once and hope that the user remembers, or we would have to tabs to all such calls.
Do you think a tab in "Create a dedictated environment with a warning admonition that in the following pip has to replaced by uv pip would do the trick?
@timhoffm Yes, that seems so good a separate tab with a clear upfront note about replacing pip with uv pip should make the distinction clear without adding too much duplication to the docs
Do we currently test the pip and conda install methods through CI? I think it's fine to add the uv tab and add a note to change the later commands to uv pip, but we should test the methods we recommend.
changed the title [-][DOC] [BLD] Building / developing matplotlib with uv[/-][+][DOC] [BLD] Building / developing matplotlib with uv & pixi[/+]on Mar 23, 2026
pixi install
WARN Using local manifest /Users/jklymak/matplotlib/pyproject.toml rather than /Users/jklymak/matplotlib/pixi.toml from environment variable `PIXI_PROJECT_MANIFEST`
Error: × failed to solve the pypi requirements of environment 'default' for platform 'osx-arm64'
├─▶ failed to resolve pypi dependencies
╰─▶ Because only the following versions of pywin32 are available:
pywin32==222
pywin32==223
pywin32==224
pywin32==225
pywin32==226
pywin32==227
pywin32==228
pywin32==300
pywin32==301
pywin32==302
pywin32==303
pywin32==304
pywin32==305
pywin32==306
pywin32==307
pywin32==308
pywin32==309
pywin32==310
pywin32==311
and pywin32<=302 has no wheels with a matching Python ABI tag (e.g., `cp311`), we can conclude that pywin32<=302 cannot be used.
And because pywin32>=303 has no wheels with a matching platform tag (e.g., `macosx_13_0_arm64`) and you require pywin32, we can conclude
that your requirements are unsatisfiable.
hint: You require CPython 3.11 (`cp311`), but we only found wheels for `pywin32` (v302) with the following Python ABI tags: `cp36m`,
`cp37m`, `cp38`, `cp39`, `cp310`
hint: Wheels are available for `pywin32` (v311) on the following platforms: `win32`, `win_amd64`, `win_arm64`
I don't understand the tooling very well. Here is what gemini thought the problem was:
The Platform Mismatch
pywin32 is a library that provides a bridge to the Windows API. It contains Windows-specific C code that cannot be compiled or installed on macOS.
The Error: Pixi searched for a version of pywin32 compatible with osx-arm64.
The Result: Since no such version exists, the solver concluded that your requirements were "unsatisfiable" and stopped the entire installation.
Solve Group Strictness
In your original config, you had solve-group = "default" for all environments.
A Solve Group tells Pixi: "I want one single pixi.lock file where the versions of Numpy, Pytest, etc., are identical across my dev, test, and doc environments."
Because test-extras was part of that group, Pixi felt obligated to resolve the Windows-only pywin32 as part of the "master plan" for your Mac environment.
Solver "Eagerness"
Modern Python solvers (like uv, which Pixi uses under the hood) are very thorough. Even if a dependency has a marker like ; sys_platform == 'win32', the solver often tries to fetch the metadata for that package to ensure that if you were on Windows, a valid version exists.
Because pywin32 doesn't even have a "placeholder" for Mac, the search returned 0 results, triggering the crash.
pywin32 doesn't have wheels or an sdist to download on macOS, but I don't understand this split:
and pywin32<=302 has no wheels with a matching Python ABI tag (e.g., `cp311`), we can conclude that pywin32<=302 cannot be used.
And because pywin32>=303 has no wheels with a matching platform tag (e.g., `macosx_13_0_arm64`) and you require pywin32, we can conclude
that your requirements are unsatisfiable.
because there were never any macosx_13_0_arm64 tagged wheels.
Unfortunately, this is a bug in pixi; it doesn't affect uv on Linux, for example.
Those are in build requirements already; you can also ask to install those with --group build if you are fine doing a separate pre-install step. But I don't think the problem is missing requirements directly; it's that uv/pixi copied the nonsensical idea from pip to keep build isolation enabled even for editable installs, so it doesn't install build dependencies in the main environment and when meson tries to rebuild, ninja from the isolated environment is gone.
Anyway, I don't feel like fighting against tools that are trying to be too smart that I don't use, so someone that does use uv/pixi will have to continue this investigation on their own.
do pixi run rebuild if you need to clear out old libraries, or just pixi run dev-install
optionally, do pixi run install-test and pixi run install-doc
Note this does the freetype zconf copy for osx-arm64 but not other OSes. clean-build only works for linux-like OSs so I haven't tried to make this useful for win64.
It seems it would be nice to include this in some way for other devs, but not sure if it should be at the top-level.
Activity
[-][DOC] [BLD] Building matplotlib with uv[/-][+][DOC] [BLD] Building / developing matplotlib with uv[/+]sanrishi commentedon Dec 18, 2025
Is there any issue in this approach
Happy to contribute.
scottshambaugh commentedon Dec 18, 2025
@sanchit122006 to clarify, this was meant more as a “sharing experience” / discussion post rather than a request to change docs or supported workflows.
Something like a new development workflow would need maintainer consensus before working on it. If there’s interest in going that direction, this thread would be the place for people to weigh in.
sanrishi commentedon Dec 18, 2025
@scottshambaugh I’ve tried a similar setup with uv on my side and it worked pretty smoothly for me as well.
The steps you outlined match what I ended up with, including the editable install with --no-build-isolation, which I’ve found is often needed anyway when working on Matplotlib locally. Using uv run to sanity-check the install is also nice since it avoids depending on whether the environment is activated or not.
I agree that the bigger questions are more around long-term support than whether this works in practice — documenting an alternative workflow and making sure CI covers it would be the heavier lift. As a personal dev setup though, this seems totally reasonable, and it’s useful to have the experience written down here for others who are already using uv.
timhoffm commentedon Dec 18, 2025
https://matplotlib.org/devdocs/devel/development_setup.html currently has the high-level structure:
When applicable, we distguish different tooling, e.g. in https://matplotlib.org/devdocs/devel/development_setup.html#create-a-dedicated-environment
Would it work to just add
uvthere? AFAICS, the only difference is that you must useuv pipinstead ofpipin the following. One could either state this once and hope that the user remembers, or we would have to tabs to all such calls.sanrishi commentedon Dec 18, 2025
Yes i seen it too, In practice it mostly comes down to a pip to uv pip substitution once the environment is created.
I agree that the main challenge is how to incorporate this into the docs cleanly without introducing duplication or extra maintenance.
timhoffm commentedon Dec 18, 2025
Do you think a tab in "Create a dedictated environment with a warning admonition that in the following
piphas to replaced byuv pipwould do the trick?sanrishi commentedon Dec 18, 2025
@timhoffm Yes, that seems so good a separate tab with a clear upfront note about replacing pip with uv pip should make the distinction clear without adding too much duplication to the docs
simranjeet-kaur-5 commentedon Dec 29, 2025
Hi, I’m new to Matplotlib and would like to work on this issue if it’s still available. Please let me know if that’s okay.
scottshambaugh commentedon Dec 29, 2025
Do we currently test the pip and conda install methods through CI? I think it's fine to add the
uvtab and add a note to change the later commands touv pip, but we should test the methods we recommend.timhoffm commentedon Dec 30, 2025
We test conda here:
matplotlib/.appveyor.yml
Line 60 in 7bbe3b7
I think everything else is pip.
timhoffm commentedon Dec 30, 2025
@simranjeet-kaur-5 Thanks for your interest. We're still figuring out what exactly we want to do.
scottshambaugh commentedon Dec 30, 2025
A dedicated github workflow for this could look like the below. I'm not clear on when we use that versus the other CI hosts.
or I think it would be fine to skip the env matrix and treat it as a smoke test:
6 remaining items
scottshambaugh commentedon Mar 23, 2026
uv and pixi installs are working now with the merge of #29281
The documentation and CI to close out this issue is ready to be worked, see my comments here and here for installation commands.
jklymak commentedon Mar 23, 2026
There are quite a few issues on a Mac install:
I had to remove anything to do with
test-extraor it tried to install win32 components.#30480 (comment) still applies
I had to run add:
After those steps the dev build worked.
QuLogic commentedon Mar 23, 2026
What win32 components? The only one directly listed is
pywin32and it is platform specific.[-][DOC] [BLD] Building / developing matplotlib with uv[/-][+][DOC] [BLD] Building / developing matplotlib with uv & pixi[/+]jklymak commentedon Mar 23, 2026
@QuLogic yes, it's rather frustrating.
The crash was:
I don't understand the tooling very well. Here is what gemini thought the problem was:
jklymak commentedon Mar 23, 2026
BTW< happy to try new edits to the pyproject.toml to get this working.
QuLogic commentedon Mar 24, 2026
pywin32doesn't have wheels or an sdist to download on macOS, but I don't understand this split:because there were never any
macosx_13_0_arm64tagged wheels.Unfortunately, this is a bug in
pixi; it doesn't affectuvon Linux, for example.TST: Replace pywin32 with ctypes wrapper
QuLogic commentedon Mar 24, 2026
Assuming it works on Windows (I didn't test it locally), #31358 should remove the
pywin32dependency entirely.jklymak commentedon Mar 24, 2026
Can we add
meson-python ninja mesonto the pyproject.toml? I think it is ninja in particular that is missing, but I didn't testQuLogic commentedon Mar 24, 2026
Those are in build requirements already; you can also ask to install those with
--group buildif you are fine doing a separate pre-install step. But I don't think the problem is missing requirements directly; it's thatuv/pixicopied the nonsensical idea frompipto keep build isolation enabled even for editable installs, so it doesn't install build dependencies in the main environment and when meson tries to rebuild, ninja from the isolated environment is gone.Anyway, I don't feel like fighting against tools that are trying to be too smart that I don't use, so someone that does use
uv/pixiwill have to continue this investigation on their own.jklymak commentedon Mar 25, 2026
OK< here is what I got to work on MacOS:
pixi.toml:pixi run rebuildif you need to clear out old libraries, or justpixi run dev-installpixi run install-testandpixi run install-docNote this does the freetype zconf copy for
osx-arm64but not other OSes.clean-buildonly works for linux-like OSs so I haven't tried to make this useful for win64.It seems it would be nice to include this in some way for other devs, but not sure if it should be at the top-level.
jklymak commentedon Mar 26, 2026
See #31384 where I suggest this toml be added to
tools/pixi.tomland the documentation expanded...TST: Replace pywin32 with ctypes wrapper