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
sanrishi commented on Dec 18, 2025
Is there any issue in this approach
Happy to contribute.
scottshambaugh commented on 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 commented on 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 commented on 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 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.
sanrishi commented on 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 commented on Dec 18, 2025
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?
sanrishi commented on 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 commented on 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 commented on Dec 29, 2025
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.
timhoffm commented on Dec 30, 2025
We test conda here:
matplotlib/.appveyor.yml
Line 60 in 7bbe3b7
I think everything else is pip.
timhoffm commented on Dec 30, 2025
@simranjeet-kaur-5 Thanks for your interest. We're still figuring out what exactly we want to do.
scottshambaugh commented on 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 commented on 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 commented on Mar 23, 2026
There are quite a few issues on a Mac install:
I had to remove anything to do with test-extra or it tried to install win32 components.
#30480 (comment) still applies
I had to run add:
After those steps the dev build worked.
QuLogic commented on Mar 23, 2026
What win32 components? The only one directly listed is pywin32 and it is platform specific.
jklymak commented on Mar 23, 2026
@QuLogic yes, it's rather frustrating.
The crash was:
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:
jklymak commented on Mar 23, 2026
BTW< happy to try new edits to the pyproject.toml to get this working.
QuLogic commented on Mar 24, 2026
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.
TST: Replace pywin32 with ctypes wrapper
QuLogic commented on Mar 24, 2026
Assuming it works on Windows (I didn't test it locally), #31358 should remove the pywin32 dependency entirely.
jklymak commented on Mar 24, 2026
Can we add meson-python ninja meson to the pyproject.toml? I think it is ninja in particular that is missing, but I didn't test
QuLogic commented on Mar 24, 2026
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.
jklymak commented on Mar 25, 2026
OK< here is what I got to work on MacOS:
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.
jklymak commented on Mar 26, 2026
See #31384 where I suggest this toml be added to tools/pixi.toml and the documentation expanded...
TST: Replace pywin32 with ctypes wrapper