pipsetuptoolssetup.pypython-packagingpep517

Why isn't `site.main()` called by setuptools?


My code can use any Qt binding. I try to reduce the number of packages to install. For that, I'd like to check whether a package has already been installed and report it as the sole requirement. If nothing's installed, I pick the first item on the list.

# cat setup.py

from typing import NamedTuple

from setuptools import setup

class PackageRequirement(NamedTuple):
    package_name: str
    import_name: str

def is_package_importable(package_requirement: PackageRequirement) -> bool:
    try:
        __import__(package_requirement.import_name)
    except ModuleNotFoundError:
        return False
    else:
        return True

def required_package() -> str:
    qt_list = [
        PackageRequirement(package_name='PySide6', import_name='PySide6.QtCore'),
        PackageRequirement(package_name='PyQt6', import_name='PyQt6.QtCore'),
        PackageRequirement(package_name='PyQt5', import_name='PyQt5.QtCore'),
        PackageRequirement(package_name='PySide2', import_name='PySide2.QtCore'),
    ]
    for p in qt_list:
        if is_package_importable(p):
            return p.package_name
    return qt_list[0].package_name

setup(install_requires=[required_package()])

The code resembles this answer. However, despite pip freeze reports that I have PyQt5 installed in the venv, and I can import it manually, the code reports the opposite and installs PySide6.

I run the code in a venv virtual environment as

pip install package_name.tar.gz

I've tried

from importlib.metadata import version, PackageNotFoundError

try:
    version(package_requirement.package_name)
except PackageNotFoundError:
    return False
else:
    return True

instead of

try:
    __import__(package_requirement.import_name)
except ModuleNotFoundError:
    return False
else:
    return True

with the same result. It looks like either the code ignores site-packages, or the access to them is somehow blocked.

Indeed, as soon as I prepend the code with

import site

site.main()  # the line might be redundant

the packages are tested correctly.


By the way, are there any tricks to achieve the package selection more gracefully and in a wheel package?


Solution

  • As far as I know, in order to install a dependency from source code or from sdist, pip first builds this dependency into a wheel, and this build step is made in an ephemeral isolated build environment. So this isolated build environment has its own site-packages, and the other dependencies can not be imported.

    What you could try is to deactivate the "build isolation" when installing that dependency. Try to take some time to understand the possible side effects, also maybe try to use this option only for that dependency and not for its dependencies.

    python -m pip install --no-build-isolation --no-deps package_name.tar.gz