Conditional requirements in setup.py

主宰稳场 提交于 2021-02-11 15:34:35

问题


I'm writing a library that's dependent on file-magic, which works just fine for most platforms, but in Alpine Linux, file-magic won't work so I need to instead use the python-magic library.

Now I know how to write my own code to handle the different Python library APIs, but what I don't know how to do is to write my setup.cfg or setup.py to have a different requirements based on the system on which we're doing the installation.

I figured the best option would be to use the PEP 508 rules, but I can't figure out how to say "libmagic like Alpine" or something in that syntax, let alone if that would work in a package's setup.py. Indeed, I can't even figure out how to tell the difference between the architectures without installing file-magic and watching it die :-(

Surely, there must be a best practise for this sort of thing?

Update

After some broader understanding from Tim below, I cobbled together this hack to get it working:

def get_requirements():
    """
    Alpine is problematic in how it doesn't play nice with file-magic -- a
    module that appears to be the standard for most other Linux distros.  As a
    work-around for this, we swap out file-magic for python-magic in the Alpine
    case.
    """

    config = configparser.ConfigParser()
    config.read("setup.cfg")
    requirements = config["options"]["install_requires"].split()

    os_id = None
    try:
        with open("/etc/os-release") as f:
            os_id = [_ for _ in f.readlines() if _.startswith("ID=")][0] \
                .strip() \
                .replace("ID=", "")
    except (FileNotFoundError, OSError, IndexError):
        pass

    if os_id == "alpine":
        requirements[1] = "python-magic>=0.4.15"

    return requirements


setuptools.setup(install_requires=get_requirements())

This allows for the declarative syntax of setup.cfg, but tweaks the install_requires value if the installation target is an Alpine system.


回答1:


You probably want to use the platform module to try to identify the system details.

Best bet is to try and use a combo of platform.architecture(), platform.platform(), and platform.system() with proper error handling and consideration of all possible return info.

Example:

I am running on Win10, here are the outputs of those functions (and one more):

>>> import platform
>>> print(platform.architecture())
('32bit', 'WindowsPE')
>>> print(platform.platform())
Windows-10-10.0.17134-SP0
>>> print(platform.processor())
Intel64 Family 6 Model 142 Stepping 10, GenuineIntel
>>> print(platform.system())
Windows

Edit

The above answer does not necessarily return the info that you want (I left out mention of any deprecated functions from the platform module).

Digging a little deeper, yields this SO result which explains that the built-in platform functions for gathering distro names are deprecated.

The official docs point in the direction of a PyPi package called distro. The distro docs on PyPi acknowledge the need for this type of info and an example usage found there looks like this:

>>> import distro
>>> distro.linux_distribution(full_distribution_name=False)
('centos', '7.1.1503', 'Core')


来源:https://stackoverflow.com/questions/54636870/conditional-requirements-in-setup-py

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!