Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uv with pytest and filterwarnings triggers a host of SyntaxWarnings as errors; pip-tools does not #1559

Closed
dycw opened this issue Feb 17, 2024 · 5 comments · Fixed by #2086
Closed

Comments

@dycw
Copy link

dycw commented Feb 17, 2024

I've made a repo to demonstrate this, as it tests a few setups.

From the README:

This repo demonstrates some difference with `pip-tools` and `uv` with respect to
`pytest`, `SyntaxWarning`s and/or docstrings containing _invalid escape strings_. 
Here we run 4 tests:

- (`pip-tools` or `uv`) and (no `filterwarnings` or with `filterwarnings`)

In the last case, `uv` with `filterwarnings`, we trigger a `SyntaxError` upon
reading the module docstring in https://github.com/Zulko/moviepy/blob/v1.0.3/moviepy/config_defaults.py#L47
with the text
`IMAGEMAGICK_BINARY = r"C:\Program Files\ImageMagick-6.8.8-Q16\magick.exe"`.
Needlesstosay, this blocks testing.

Unfortunately, right after writing this up, I can no longer trigger the bug!

I'll continue to do so but I felt I've done enough testing to warrant writing an issue. Maybe the Astral team can already see what's going on.

uv version 0.1.2.

@dycw dycw changed the title uv with pytest and filterwarnings is triggering a host of SyntaxWarnings as errors uv with pytest and filterwarnings triggers a host of SyntaxWarnings as errors; pip-tools does not Feb 17, 2024
@charliermarsh
Copy link
Member

One thing I notice is that in Test 4, you're using a different Python version (Python 3.11.7, while the rest use Python 3.10.13). That might be why it's an error, and not a warning?

@dycw
Copy link
Author

dycw commented Feb 17, 2024

I've gone and cleaned up my tests. It is reproducible now.

Please see v2 of the repo:

But for full disclosure, here is my full run starting with git clone:

└ ❯ git clone git@github.com:dycw/test-pip-tools-vs-uv.git
Cloning into 'test-pip-tools-vs-uv'...
remote: Enumerating objects: 84, done.
remote: Counting objects: 100% (84/84), done.
remote: Compressing objects: 100% (48/48), done.
remote: Total 84 (delta 43), reused 67 (delta 33), pack-reused 0
Receiving objects: 100% (84/84), 18.28 KiB | 1.08 MiB/s, done.
Resolving deltas: 100% (43/43), done.

└ ❯ cd test-pip-tools-vs-uv

└ ❯ cd 1-pip-tools/ && source ../run-pip-tools.sh && cd ..
cd 2-pip-tools-with-filterwarnings/ && source ../run-pip-tools.sh && cd ..
cd 3-uv/ && source ../run-uv.sh && cd ..
cd 4-uv-with-filterwarnings/ && source ../run-uv.sh && cd ..
>>> Removing .direnv / .venv...
>>> Creating venv...
>>> Installing pip-tools...
Collecting pip-tools
  Using cached pip_tools-7.4.0-py3-none-any.whl (61 kB)
Requirement already satisfied: setuptools in ./.venv/lib/python3.10/site-packages (from pip-tools) (65.5.0)
Collecting pyproject-hooks
  Using cached pyproject_hooks-1.0.0-py3-none-any.whl (9.3 kB)
Collecting click>=8
  Using cached click-8.1.7-py3-none-any.whl (97 kB)
Collecting tomli
  Using cached tomli-2.0.1-py3-none-any.whl (12 kB)
Requirement already satisfied: pip>=22.2 in ./.venv/lib/python3.10/site-packages (from pip-tools) (23.0.1)
Collecting wheel
  Using cached wheel-0.42.0-py3-none-any.whl (65 kB)
Collecting build>=1.0.0
  Using cached build-1.0.3-py3-none-any.whl (18 kB)
Collecting packaging>=19.0
  Using cached packaging-23.2-py3-none-any.whl (53 kB)
Installing collected packages: wheel, tomli, packaging, click, pyproject-hooks, build, pip-tools
Successfully installed build-1.0.3 click-8.1.7 packaging-23.2 pip-tools-7.4.0 pyproject-hooks-1.0.0 tomli-2.0.1 wheel-0.42.0

[notice] A new release of pip is available: 23.0.1 -> 24.0
[notice] To update, run: pip install --upgrade pip
>>> Compiling...
WARNING: --strip-extras is becoming the default in version 8.0.0. To silence this warning, either use --strip-extras to opt into the new default or use --no-strip-extras to retain the existing behavior.
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile
#
certifi==2024.2.2
    # via requests
charset-normalizer==3.3.2
    # via requests
decorator==4.4.2
    # via moviepy
exceptiongroup==1.2.0
    # via pytest
idna==3.6
    # via requests
imageio==2.34.0
    # via moviepy
imageio-ffmpeg==0.4.9
    # via moviepy
iniconfig==2.0.0
    # via pytest
moviepy==1.0.3
    # via -r requirements.in
numpy==1.26.4
    # via
    #   imageio
    #   moviepy
packaging==23.2
    # via pytest
pillow==10.2.0
    # via imageio
pluggy==1.4.0
    # via pytest
proglog==0.1.10
    # via moviepy
pyclean==2.7.6
    # via -r requirements.in
pytest==8.0.1
    # via -r requirements.in
requests==2.31.0
    # via moviepy
tomli==2.0.1
    # via pytest
tqdm==4.66.2
    # via
    #   moviepy
    #   proglog
urllib3==2.2.0
    # via requests

# The following packages are considered to be unsafe in a requirements file:
# setuptools
>>> Synchronizing...
Collecting certifi==2024.2.2
  Using cached certifi-2024.2.2-py3-none-any.whl (163 kB)
Collecting charset-normalizer==3.3.2
  Using cached charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl (120 kB)
Collecting decorator==4.4.2
  Using cached decorator-4.4.2-py2.py3-none-any.whl (9.2 kB)
Collecting exceptiongroup==1.2.0
  Using cached exceptiongroup-1.2.0-py3-none-any.whl (16 kB)
Collecting idna==3.6
  Using cached idna-3.6-py3-none-any.whl (61 kB)
Collecting imageio==2.34.0
  Using cached imageio-2.34.0-py3-none-any.whl (313 kB)
Collecting imageio-ffmpeg==0.4.9
  Using cached imageio_ffmpeg-0.4.9-py3-none-any.whl
Collecting iniconfig==2.0.0
  Using cached iniconfig-2.0.0-py3-none-any.whl (5.9 kB)
Collecting moviepy==1.0.3
  Using cached moviepy-1.0.3-py3-none-any.whl
Collecting numpy==1.26.4
  Using cached numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl (14.0 MB)
Collecting pillow==10.2.0
  Using cached pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl (3.3 MB)
Collecting pluggy==1.4.0
  Using cached pluggy-1.4.0-py3-none-any.whl (20 kB)
Collecting proglog==0.1.10
  Using cached proglog-0.1.10-py3-none-any.whl (6.1 kB)
Collecting pyclean==2.7.6
  Using cached pyclean-2.7.6-py3-none-any.whl (40 kB)
Collecting pytest==8.0.1
  Using cached pytest-8.0.1-py3-none-any.whl (333 kB)
Collecting requests==2.31.0
  Using cached requests-2.31.0-py3-none-any.whl (62 kB)
Collecting tqdm==4.66.2
  Using cached tqdm-4.66.2-py3-none-any.whl (78 kB)
Collecting urllib3==2.2.0
  Using cached urllib3-2.2.0-py3-none-any.whl (120 kB)
Requirement already satisfied: setuptools in ./.venv/lib/python3.10/site-packages (from imageio-ffmpeg==0.4.9->-r /var/folders/vz/1xckd3_n3551rv_xctlglyl00000gn/T/tmpvw3w30tw (line 7)) (65.5.0)
Requirement already satisfied: tomli>=1.0.0 in ./.venv/lib/python3.10/site-packages (from pytest==8.0.1->-r /var/folders/vz/1xckd3_n3551rv_xctlglyl00000gn/T/tmpvw3w30tw (line 15)) (2.0.1)
Requirement already satisfied: packaging in ./.venv/lib/python3.10/site-packages (from pytest==8.0.1->-r /var/folders/vz/1xckd3_n3551rv_xctlglyl00000gn/T/tmpvw3w30tw (line 15)) (23.2)
Installing collected packages: pyclean, urllib3, tqdm, pluggy, pillow, numpy, iniconfig, imageio-ffmpeg, idna, exceptiongroup, decorator, charset-normalizer, certifi, requests, pytest, proglog, imageio, moviepy
Successfully installed certifi-2024.2.2 charset-normalizer-3.3.2 decorator-4.4.2 exceptiongroup-1.2.0 idna-3.6 imageio-2.34.0 imageio-ffmpeg-0.4.9 iniconfig-2.0.0 moviepy-1.0.3 numpy-1.26.4 pillow-10.2.0 pluggy-1.4.0 proglog-0.1.10 pyclean-2.7.6 pytest-8.0.1 requests-2.31.0 tqdm-4.66.2 urllib3-2.2.0

[notice] A new release of pip is available: 23.0.1 -> 24.0
[notice] To update, run: pip install --upgrade pip
>>> Running pyclean...
Cleaning directory .
Total 0 files, 0 directories removed.
>>> Running pytest...
================================================================================ test session starts =================================================================================
platform darwin -- Python 3.10.13, pytest-8.0.1, pluggy-1.4.0
rootdir: /Users/derek/work/test-pip-tools-vs-uv/1-pip-tools
collected 1 item

test_main.py .                                                                                                                                                                 [100%]

================================================================================= 1 passed in 5.24s ==================================================================================
>>> Deactivating...
>>> Removing .direnv / .venv...
>>> Creating venv...
>>> Installing pip-tools...
Collecting pip-tools
  Using cached pip_tools-7.4.0-py3-none-any.whl (61 kB)
Collecting pyproject-hooks
  Using cached pyproject_hooks-1.0.0-py3-none-any.whl (9.3 kB)
Requirement already satisfied: setuptools in ./.venv/lib/python3.10/site-packages (from pip-tools) (65.5.0)
Collecting build>=1.0.0
  Using cached build-1.0.3-py3-none-any.whl (18 kB)
Collecting wheel
  Using cached wheel-0.42.0-py3-none-any.whl (65 kB)
Collecting tomli
  Using cached tomli-2.0.1-py3-none-any.whl (12 kB)
Requirement already satisfied: pip>=22.2 in ./.venv/lib/python3.10/site-packages (from pip-tools) (23.0.1)
Collecting click>=8
  Using cached click-8.1.7-py3-none-any.whl (97 kB)
Collecting packaging>=19.0
  Using cached packaging-23.2-py3-none-any.whl (53 kB)
Installing collected packages: wheel, tomli, packaging, click, pyproject-hooks, build, pip-tools
Successfully installed build-1.0.3 click-8.1.7 packaging-23.2 pip-tools-7.4.0 pyproject-hooks-1.0.0 tomli-2.0.1 wheel-0.42.0

[notice] A new release of pip is available: 23.0.1 -> 24.0
[notice] To update, run: pip install --upgrade pip
>>> Compiling...
WARNING: --strip-extras is becoming the default in version 8.0.0. To silence this warning, either use --strip-extras to opt into the new default or use --no-strip-extras to retain the existing behavior.
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile
#
certifi==2024.2.2
    # via requests
charset-normalizer==3.3.2
    # via requests
decorator==4.4.2
    # via moviepy
exceptiongroup==1.2.0
    # via pytest
idna==3.6
    # via requests
imageio==2.34.0
    # via moviepy
imageio-ffmpeg==0.4.9
    # via moviepy
iniconfig==2.0.0
    # via pytest
moviepy==1.0.3
    # via -r requirements.in
numpy==1.26.4
    # via
    #   imageio
    #   moviepy
packaging==23.2
    # via pytest
pillow==10.2.0
    # via imageio
pluggy==1.4.0
    # via pytest
proglog==0.1.10
    # via moviepy
pyclean==2.7.6
    # via -r requirements.in
pytest==8.0.1
    # via -r requirements.in
requests==2.31.0
    # via moviepy
tomli==2.0.1
    # via pytest
tqdm==4.66.2
    # via
    #   moviepy
    #   proglog
urllib3==2.2.0
    # via requests

# The following packages are considered to be unsafe in a requirements file:
# setuptools
>>> Synchronizing...
Collecting certifi==2024.2.2
  Using cached certifi-2024.2.2-py3-none-any.whl (163 kB)
Collecting charset-normalizer==3.3.2
  Using cached charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl (120 kB)
Collecting decorator==4.4.2
  Using cached decorator-4.4.2-py2.py3-none-any.whl (9.2 kB)
Collecting exceptiongroup==1.2.0
  Using cached exceptiongroup-1.2.0-py3-none-any.whl (16 kB)
Collecting idna==3.6
  Using cached idna-3.6-py3-none-any.whl (61 kB)
Collecting imageio==2.34.0
  Using cached imageio-2.34.0-py3-none-any.whl (313 kB)
Collecting imageio-ffmpeg==0.4.9
  Using cached imageio_ffmpeg-0.4.9-py3-none-any.whl
Collecting iniconfig==2.0.0
  Using cached iniconfig-2.0.0-py3-none-any.whl (5.9 kB)
Collecting moviepy==1.0.3
  Using cached moviepy-1.0.3-py3-none-any.whl
Collecting numpy==1.26.4
  Using cached numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl (14.0 MB)
Collecting pillow==10.2.0
  Using cached pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl (3.3 MB)
Collecting pluggy==1.4.0
  Using cached pluggy-1.4.0-py3-none-any.whl (20 kB)
Collecting proglog==0.1.10
  Using cached proglog-0.1.10-py3-none-any.whl (6.1 kB)
Collecting pyclean==2.7.6
  Using cached pyclean-2.7.6-py3-none-any.whl (40 kB)
Collecting pytest==8.0.1
  Using cached pytest-8.0.1-py3-none-any.whl (333 kB)
Collecting requests==2.31.0
  Using cached requests-2.31.0-py3-none-any.whl (62 kB)
Collecting tqdm==4.66.2
  Using cached tqdm-4.66.2-py3-none-any.whl (78 kB)
Collecting urllib3==2.2.0
  Using cached urllib3-2.2.0-py3-none-any.whl (120 kB)
Requirement already satisfied: setuptools in ./.venv/lib/python3.10/site-packages (from imageio-ffmpeg==0.4.9->-r /var/folders/vz/1xckd3_n3551rv_xctlglyl00000gn/T/tmp9j611rzg (line 7)) (65.5.0)
Requirement already satisfied: packaging in ./.venv/lib/python3.10/site-packages (from pytest==8.0.1->-r /var/folders/vz/1xckd3_n3551rv_xctlglyl00000gn/T/tmp9j611rzg (line 15)) (23.2)
Requirement already satisfied: tomli>=1.0.0 in ./.venv/lib/python3.10/site-packages (from pytest==8.0.1->-r /var/folders/vz/1xckd3_n3551rv_xctlglyl00000gn/T/tmp9j611rzg (line 15)) (2.0.1)
Installing collected packages: pyclean, urllib3, tqdm, pluggy, pillow, numpy, iniconfig, imageio-ffmpeg, idna, exceptiongroup, decorator, charset-normalizer, certifi, requests, pytest, proglog, imageio, moviepy
Successfully installed certifi-2024.2.2 charset-normalizer-3.3.2 decorator-4.4.2 exceptiongroup-1.2.0 idna-3.6 imageio-2.34.0 imageio-ffmpeg-0.4.9 iniconfig-2.0.0 moviepy-1.0.3 numpy-1.26.4 pillow-10.2.0 pluggy-1.4.0 proglog-0.1.10 pyclean-2.7.6 pytest-8.0.1 requests-2.31.0 tqdm-4.66.2 urllib3-2.2.0

[notice] A new release of pip is available: 23.0.1 -> 24.0
[notice] To update, run: pip install --upgrade pip
>>> Running pyclean...
Cleaning directory .
Total 0 files, 0 directories removed.
>>> Running pytest...
================================================================================ test session starts =================================================================================
platform darwin -- Python 3.10.13, pytest-8.0.1, pluggy-1.4.0
rootdir: /Users/derek/work/test-pip-tools-vs-uv/2-pip-tools-with-filterwarnings
configfile: pytest.ini
collected 1 item

test_main.py .                                                                                                                                                                 [100%]

================================================================================= 1 passed in 7.44s ==================================================================================
>>> Deactivating...
>>> Removing .direnv / .venv...
>>> Creating venv...
Using Python 3.10.13 interpreter at /Users/derek/.pyenv/versions/3.10.13/bin/python3.10
Creating virtualenv at: .venv
>>> Compiling...
Resolved 21 packages in 427ms
>>> Synchronizing...
Installed 21 packages in 170ms
 + certifi==2024.2.2
 + charset-normalizer==3.3.2
 + decorator==4.4.2
 + exceptiongroup==1.2.0
 + idna==3.6
 + imageio==2.34.0
 + imageio-ffmpeg==0.4.9
 + iniconfig==2.0.0
 + moviepy==1.0.3
 + numpy==1.26.4
 + packaging==23.2
 + pillow==10.2.0
 + pluggy==1.4.0
 + proglog==0.1.10
 + pyclean==2.7.6
 + pytest==8.0.1
 + requests==2.31.0
 + setuptools==69.1.0
 + tomli==2.0.1
 + tqdm==4.66.2
 + urllib3==2.2.0
>>> Running pyclean...
Cleaning directory .
Total 0 files, 0 directories removed.
>>> Running pytest...
================================================================================ test session starts =================================================================================
platform darwin -- Python 3.10.13, pytest-8.0.1, pluggy-1.4.0
rootdir: /Users/derek/work/test-pip-tools-vs-uv/3-uv
collected 1 item

test_main.py .                                                                                                                                                                 [100%]

================================================================================== warnings summary ==================================================================================
test_main.py::test_main
  /Users/derek/work/test-pip-tools-vs-uv/3-uv/.venv/lib/python3.10/site-packages/moviepy/config_defaults.py:1: DeprecationWarning: invalid escape sequence '\P'
    """

test_main.py::test_main
  /Users/derek/work/test-pip-tools-vs-uv/3-uv/.venv/lib/python3.10/site-packages/imageio_ffmpeg/_utils.py:7: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
    from pkg_resources import resource_filename

test_main.py::test_main
  /Users/derek/work/test-pip-tools-vs-uv/3-uv/.venv/lib/python3.10/site-packages/moviepy/video/io/ffmpeg_reader.py:294: DeprecationWarning: invalid escape sequence '\d'
    lines_video = [l for l in lines if ' Video: ' in l and re.search('\d+x\d+', l)]

test_main.py::test_main
  /Users/derek/work/test-pip-tools-vs-uv/3-uv/.venv/lib/python3.10/site-packages/moviepy/video/io/ffmpeg_reader.py:367: DeprecationWarning: invalid escape sequence '\d'
    rotation_lines = [l for l in lines if 'rotate          :' in l and re.search('\d+$', l)]

test_main.py::test_main
  /Users/derek/work/test-pip-tools-vs-uv/3-uv/.venv/lib/python3.10/site-packages/moviepy/video/io/ffmpeg_reader.py:370: DeprecationWarning: invalid escape sequence '\d'
    match = re.search('\d+$', rotation_line)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================================================================== 1 passed, 5 warnings in 7.36s ============================================================================
>>> Deactivating...
>>> Removing .direnv / .venv...
>>> Creating venv...
Using Python 3.10.13 interpreter at /Users/derek/.pyenv/versions/3.10.13/bin/python3.10
Creating virtualenv at: .venv
>>> Compiling...
Resolved 21 packages in 9ms
>>> Synchronizing...
Installed 21 packages in 36ms
 + certifi==2024.2.2
 + charset-normalizer==3.3.2
 + decorator==4.4.2
 + exceptiongroup==1.2.0
 + idna==3.6
 + imageio==2.34.0
 + imageio-ffmpeg==0.4.9
 + iniconfig==2.0.0
 + moviepy==1.0.3
 + numpy==1.26.4
 + packaging==23.2
 + pillow==10.2.0
 + pluggy==1.4.0
 + proglog==0.1.10
 + pyclean==2.7.6
 + pytest==8.0.1
 + requests==2.31.0
 + setuptools==69.1.0
 + tomli==2.0.1
 + tqdm==4.66.2
 + urllib3==2.2.0
>>> Running pyclean...
Cleaning directory .
Total 0 files, 0 directories removed.
>>> Running pytest...
================================================================================ test session starts =================================================================================
platform darwin -- Python 3.10.13, pytest-8.0.1, pluggy-1.4.0
rootdir: /Users/derek/work/test-pip-tools-vs-uv/4-uv-with-filterwarnings
configfile: pytest.ini
collected 1 item

test_main.py F                                                                                                                                                                 [100%]

====================================================================================== FAILURES ======================================================================================
_____________________________________________________________________________________ test_main ______________________________________________________________________________________

    def test_main():
>       from moviepy.editor import AudioFileClip, ColorClip, CompositeVideoClip, ImageClip

test_main.py:2:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv/lib/python3.10/site-packages/moviepy/editor.py:36: in <module>
    from .video.io.VideoFileClip import VideoFileClip
.venv/lib/python3.10/site-packages/moviepy/video/io/VideoFileClip.py:3: in <module>
    from moviepy.audio.io.AudioFileClip import AudioFileClip
.venv/lib/python3.10/site-packages/moviepy/audio/io/AudioFileClip.py:3: in <module>
    from moviepy.audio.AudioClip import AudioClip
.venv/lib/python3.10/site-packages/moviepy/audio/AudioClip.py:7: in <module>
    from moviepy.audio.io.ffmpeg_audiowriter import ffmpeg_audiowrite
.venv/lib/python3.10/site-packages/moviepy/audio/io/ffmpeg_audiowriter.py:7: in <module>
    from moviepy.config import get_setting
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    import os
    import subprocess as sp

    from .compat import DEVNULL
>   from .config_defaults import FFMPEG_BINARY, IMAGEMAGICK_BINARY
E     File "/Users/derek/work/test-pip-tools-vs-uv/4-uv-with-filterwarnings/.venv/lib/python3.10/site-packages/moviepy/config_defaults.py", line 1
E       """
E       ^^^
E   SyntaxError: invalid escape sequence '\P'

.venv/lib/python3.10/site-packages/moviepy/config.py:5: SyntaxError
============================================================================== short test summary info ===============================================================================
FAILED test_main.py::test_main -   File "/Users/derek/work/test-pip-tools-vs-uv/4-uv-with-filterwarnings/.venv/lib/python3.10/site-packages/moviepy/config_defaults.py", line 1
================================================================================= 1 failed in 3.85s ==================================================================================
>>> Deactivating...

@konstin
Copy link
Member

konstin commented Feb 29, 2024

Is this a duplicate of #1928?

@zanieb
Copy link
Member

zanieb commented Feb 29, 2024

It looks like the same thing to me

konstin added a commit that referenced this issue Feb 29, 2024
Add a `--compile` option to `pip install` and `pip sync`.

I chose to implement this as a separate over the entire venv. If we wanted to compile during installation, we'd have to make sure that writing is exclusive, to avoid concurrent processes writing broken `.pyc` files. Additionally, this ensures that the entire site-packages are bytecode compiled, even if there are packages that aren't from this `uv` invocation. The disadvantage is that we do not update RECORD and rely on this comment from [PEP 491](https://peps.python.org/pep-0491/):

> Uninstallers should be smart enough to remove .pyc even if it is not mentioned in RECORD.

If this is a problem we can change it to run during installation and write RECORD entries.

Internally, this is implemented as an async work-stealing subprocess worker pool. The producer is a directory traversal over site-packages, sending each `.py` file to a bounded async FIFO queue/channel. Each worker has a long-running python process. It pops the queue to get a single path (or exists if the channel is closed), then sends it to stdin, waits until it's informed that the compilation is done through a line on stdout, and repeat. This is fast, e.g. installing `jupyter plotly` on Python 3.12 it processes 15876 files in 319ms with 32 threads (vs. 3.8s with a single core). The python processes internally calls `compileall.compile_file`, the same as pip.

Like pip, we ignore and silence all compilation errors (#1559). There are 10s and 1s timeouts to ensure we don't get stuck when the python subprocess doesn't work properly or there was a panic breaking tokio. For the reviewers, please check if i missed any spots where we could deadlock, this is the hardest part of this PR.

I still have to check that windows works.

I don't think we want an option to compile the seed packages in ihe `venv` subcommand, do we?

Fixes #1788
Closes #1559
Closes #1928
konstin added a commit that referenced this issue Mar 1, 2024
Add a `--compile` option to `pip install` and `pip sync`.

I chose to implement this as a separate over the entire venv. If we wanted to compile during installation, we'd have to make sure that writing is exclusive, to avoid concurrent processes writing broken `.pyc` files. Additionally, this ensures that the entire site-packages are bytecode compiled, even if there are packages that aren't from this `uv` invocation. The disadvantage is that we do not update RECORD and rely on this comment from [PEP 491](https://peps.python.org/pep-0491/):

> Uninstallers should be smart enough to remove .pyc even if it is not mentioned in RECORD.

If this is a problem we can change it to run during installation and write RECORD entries.

Internally, this is implemented as an async work-stealing subprocess worker pool. The producer is a directory traversal over site-packages, sending each `.py` file to a bounded async FIFO queue/channel. Each worker has a long-running python process. It pops the queue to get a single path (or exists if the channel is closed), then sends it to stdin, waits until it's informed that the compilation is done through a line on stdout, and repeat. This is fast, e.g. installing `jupyter plotly` on Python 3.12 it processes 15876 files in 319ms with 32 threads (vs. 3.8s with a single core). The python processes internally calls `compileall.compile_file`, the same as pip.

Like pip, we ignore and silence all compilation errors (#1559). There are 10s and 1s timeouts to ensure we don't get stuck when the python subprocess doesn't work properly or there was a panic breaking tokio. For the reviewers, please check if i missed any spots where we could deadlock, this is the hardest part of this PR.

I still have to check that windows works.

I don't think we want an option to compile the seed packages in ihe `venv` subcommand, do we?

Fixes #1788
Closes #1559
Closes #1928
@charliermarsh
Copy link
Member

Gonna merge into that issue.

@charliermarsh charliermarsh closed this as not planned Won't fix, can't repro, duplicate, stale Mar 1, 2024
charliermarsh pushed a commit that referenced this issue Mar 5, 2024
Add a `--compile` option to `pip install` and `pip sync`.

I chose to implement this as a separate pass over the entire venv. If we
wanted to compile during installation, we'd have to make sure that
writing is exclusive, to avoid concurrent processes writing broken
`.pyc` files. Additionally, this ensures that the entire site-packages
are bytecode compiled, even if there are packages that aren't from this
`uv` invocation. The disadvantage is that we do not update RECORD and
rely on this comment from [PEP 491](https://peps.python.org/pep-0491/):

> Uninstallers should be smart enough to remove .pyc even if it is not
mentioned in RECORD.

If this is a problem we can change it to run during installation and
write RECORD entries.

Internally, this is implemented as an async work-stealing subprocess
worker pool. The producer is a directory traversal over site-packages,
sending each `.py` file to a bounded async FIFO queue/channel. Each
worker has a long-running python process. It pops the queue to get a
single path (or exists if the channel is closed), then sends it to
stdin, waits until it's informed that the compilation is done through a
line on stdout, and repeat. This is fast, e.g. installing `jupyter
plotly` on Python 3.12 it processes 15876 files in 319ms with 32 threads
(vs. 3.8s with a single core). The python processes internally calls
`compileall.compile_file`, the same as pip.

Like pip, we ignore and silence all compilation errors
(#1559). There is a 10s timeout to
handle the case when the workers got stuck. For the reviewers, please
check if i missed any spots where we could deadlock, this is the hardest
part of this PR.

I've added `uv-dev compile <dir>` and `uv-dev clear-compile <dir>`
commands, mainly for my own benchmarking. I don't want to expose them in
`uv`, they almost certainly not the correct workflow and we don't want
to support them.

Fixes #1788
Closes #1559
Closes #1928
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 a pull request may close this issue.

4 participants