pipx icon indicating copy to clipboard operation
pipx copied to clipboard

pipx doesn't respect manually selected point releases on `upgrade`

Open tobwen opened this issue 3 years ago • 11 comments

Describe the bug

In the following example, the system's headers and library of gdal are in v3.2.2. Latest gdal is on v3.3.2, so is pygdal looking for this version, can't find it and breaks. Even when installed with pygdal==3.2.2.*, pipx upgrade doesn't respect this limitation and the upgrade fails, since the installer can't find latest gdal:

_main__.GDALConfigError: Version mismatch 3.2.2 != 3.3.2

How to reproduce

$ apt-install libgdal-dev gdal-bin gdal-data # should be 3.2.2 on Debian
$ pipx install --include-deps pygdal==3.2.2.* # works
$ pipx upgrade pygdal # fails

It gets worse when pygdal has been injected into another package. This completely fails then:

$ pipx upgrade --include-injected --force mapproxy

Expected behavior

Read package_or_url from pipx_metadata.json and limit it to the version stated in there.

Workarounds

pipx upgrade --pip-args 'install pygdal==3.2.2.*' pygdal
pipx upgrade --include-injected --pip-args 'install pygdal==3.2.2.*' mapproxy

~/.local/pipx/venvs/pygdal/pipx_metadata.json

{
    "injected_packages": {},
    "main_package": {
        "app_paths": [],
        "app_paths_of_dependencies": {
            "numpy": [
                {
                    "__Path__": "/home/tobwen/.local/pipx/venvs/pygdal/bin/f2py",
                    "__type__": "Path"
                },
                {
                    "__Path__": "/home/tobwen/.local/pipx/venvs/pygdal/bin/f2py3",
                    "__type__": "Path"
                },
                {
                    "__Path__": "/home/tobwen/.local/pipx/venvs/pygdal/bin/f2py3.9",
                    "__type__": "Path"
                }
            ]
        },
        "apps": [],
        "apps_of_dependencies": [
            "f2py",
            "f2py3",
            "f2py3.9"
        ],
        "include_apps": true,
        "include_dependencies": true,
        "package": "pygdal",
        "package_or_url": "pygdal==3.2.2.*",
        "package_version": "3.2.2.10",
        "pip_args": [],
        "suffix": ""
    },
    "pipx_metadata_version": "0.2",
    "python_version": "Python 3.9.2",
    "venv_args": []
}

tobwen avatar Jan 24 '22 12:01 tobwen

Currently pipx upgrade will ignore any version specifiers and upgrade the package to the newest version.

Maybe we can introduce a new option (probably --include-version-spec?) for users to upgrade their packages with version specifiers? i.e. pip install -U package==20.0.* instead of pip install -U package.

dukecat0 avatar Aug 09 '22 14:08 dukecat0

Do we save the original user request in metadata? (I don’t quite remember) If we do, we should make pipx upgrade respect that original input, and introduce a new flag (say pip upgrade --spec) to ignore existing constraints.

uranusjr avatar Aug 10 '22 08:08 uranusjr

Do we save the original user request in metadata?

package_or_url is the original user request, and pipx upgrade actually respects it. However, packages specifiers and markers are removed by this function: https://github.com/pypa/pipx/blob/71fe102014393061fcb953609a5b5b2a763f4c0a/src/pipx/package_specifier.py#L176-L188

and introduce a new flag (say pip upgrade --spec) to ignore existing constraints.

EDIT: Or we should simply introduce --include-version-spec? Since pipx upgrade also has --include-injected option, and it won't work if injected packages contain version specifiers like package==1.0.0. Probably we can allow --include-version-spec if * exists in the version specifier?

dukecat0 avatar Aug 10 '22 11:08 dukecat0

I would really love to have any solution for that issue - I used to run pipx upgrade-all automatically, but recently I wanted to maintain two Poetry versions: 1.1.x and 1.2.x. I've installed the previous one with pipx install "poetry<1.2" --suffix 1.1, but unfortunately when I run the upgrade comment - the constraint is not respected and it's being updated to 1.2.x, so each time I have to reinstall it.

jaklan avatar Sep 29 '22 16:09 jaklan

Hah, it seems I can help myself here - there's some workaround: pipx install poetry --pip-args 'install poetry<1.2' --suffix 1.1 This way the constraint is preserved (so actually that's almost the same like the workaround from the first comment).

Anyway, I believe pipx install "poetry<1.2" --suffix 1.1 workflow is much more intuitive.

jaklan avatar Sep 29 '22 16:09 jaklan

Maybe #891 can help with this case. Run pipx pin poetry1.1 and then pipx upgrade-all will not upgrade it.

(But I am still implementing pipx pin and pipx unpin, so I guess it will be available in the next release.)

dukecat0 avatar Sep 29 '22 16:09 dukecat0

(But I am still implementing pipx pin and pipx unpin, so I guess it will be available in the next release.)

@dukecat0 what's the status of that? 😉

jaklan avatar Nov 03 '23 12:11 jaklan

Hi @jaklan, I've implemented the logic of it before, but seems like the changes were dismissed accidentally, so I will try to work on it again.

dukecat0 avatar Nov 03 '23 13:11 dukecat0

Great to hear, that would be a huge improvement! Btw, for pipx upgrade-all I believe the logic is quite simple - upgrade all apps except the pinned ones, but what is the plan for pipx upgrade behaviour? Would it fail and suggest to use pipx upgrade --force, fail and suggest pipx unpin && pipx upgrade, or some other approach?

jaklan avatar Nov 03 '23 14:11 jaklan

fail and suggest pipx unpin && pipx upgrade

IIRC I used this approach in my previous implementation.

dukecat0 avatar Nov 03 '23 14:11 dukecat0

PR weclome.

gaborbernat avatar Dec 02 '23 17:12 gaborbernat