Search code examples
pythonnumpydependenciespython-poetry

Why doesn't Poetry select the good version of my dependency?


I maintain a library that I want to be compatible with Python 3.8+ (because I follow SemVer and I don't want to push a major version now), but has also a transitive dependency on NumPy.

Because NumPy recently dropped support for Python 3.8, I have specified in my pyproject.toml the version of NumPy that should be used depending on Python version:

[tool.poetry.dependencies]
python = "^3.8"
numpy = [
    { version = "<1.25", python = "3.8.*" },
    { version = "^1.25", python = "^3.9" },
]

If I understand correctly Poetry documentation, this should mean:

  • if Python version is 3.8.*, then use the last version of NumPy below 1.25;
  • if Python version is 3.9+, then use the last version of NumPy between 1.25 and 2.0 (thanks to caret versions).

Now NumPy version is 1.26, but running poetry install still installs 1.25.2. I have also tried to remove the lock file (which is .gitignored anyway), delete the venv and rerun poetry install, and to replace the carets with >=, but it continues to install 1.25.2 instead of 1.26.

This also happens on my CI, so it seems it doesn't have anything to do with my local installation.

Where is my mistake?


Solution

  • NumPy has recently changed the way they handle compatibility with Python in their pyproject.toml ([1]):

    [project]
    name = "numpy"
    version = "1.26.1"
    # ...
    requires-python = ">=3.9,<3.13"
    

    In version 1.25, they only raised an error on Python < 3.9 and displayed a warning on Python 3.12+ in their setup.py ([2], [3]):

    if sys.version_info[:2] < (3, 9):
        raise RuntimeError("Python version >= 3.9 required.")
    
    # ...
    
    if sys.version_info >= (3, 12):
        fmt = "NumPy {} may not yet support Python {}.{}."
        warnings.warn(
            fmt.format(VERSION, *sys.version_info[:2]),
            RuntimeWarning)
        del fmt
    

    So, to make Poetry select the last version of NumPy on Python 3.9+, we need to tell it we don't support version 3.13 yet:

    [tool.poetry.dependencies]
    python = "^3.8"
    numpy = [
        { version = "<1.25", python = "3.8.*" },
    -   { version = "^1.25", python = "^3.9" },
    +   { version = "^1.25", python = ">=3.9,<3.13" },
    ]