Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of setuptools requirements of the form "package===version"

Say I have a package with a console script such as

from setuptools import setup
setup(
    name='eg_package',
    version='0.0.1',
    description='Trivial test package',
    packages=[
       'eg_package',
    ],
    entry_points={
        'console_scripts': [
            'foo = eg_package.main:main',
        ]
   },
)

If I set and explicit build tag using egg_info -b mytag the resulting script has __requires__ = 'eg-package===0.0.1mytag', i.e. with 3 "=" signs. This occurs when the tag is not something conventional like b1 for a beta release.

At first I thought this was a bug but the setuptools documentation suggests it is a valid requirement identifier. However, it doesn't work with older versions of setuptools which is causing problems with our systems.

My question is what does "===" mean and why does modern setuptools use it?

like image 714
Stephen Pascoe Avatar asked Oct 31 '22 03:10

Stephen Pascoe


1 Answers

Requirement specifier section in pip docs links to the official docs for requirement specifiers implemented by setuptools pkg_resources. It specifies the formal syntax but says nothing on the semantics. Overview docs explain semantics but say nothing on the ~= and === stuff that were apparently added somewhere between vv.7 (installed with python 2.7.9) and 16.

When docs fail, it's time to consult the sources. Downloading the setuptools hg repo and annotating pkg_resources/__init__.py ultimately brings us to changeset 3125 with the message "Implement PEP 440 by using the packaging library".

Indeed, PEP 440, Version Specifiers section explains the syntax and semantics:

  • ~= : Compatible release clause <...>
  • === : Arbitrary equality clause.

By examining other files in the commit and the related packaging package, I came to these apparent conclusions:

  • ~= is never produced; when handled1, it acts as a filter according to the rules outlined in the PEP.
  • ===, when handled, signals to fall back to the older setuptools version syntax and comparison logic. It is produced whenever the resulting version string doesn't conform to the PEP2.

1 In pkg_resources._vendor.packaging.specifiers._compare_compatible()2pkg_resources.parse_version() produces a pkg_resources.SetuptoolsLegacyVersion rather than pkg_resources.SetuptoolsVersion

like image 166
ivan_pozdeev Avatar answered Nov 15 '22 08:11

ivan_pozdeev