4

Note: this isn't a how to package question, but rather, once the METADATA has been configured with Requires-Dist extra flags, how are they used at pip install time?

These 2 dependencies are pretty clear (but do not involve extra):

./loguru-0.3.2.dist-info/METADATA:

Requires-Dist: win32-setctime (>=1.0.0) ; sys_platform == "win32"

If you're on win32, pip install loguru will pull in win32-setctime from pypi.

./pluggy-0.13.0.dist-info/METADATA:

Requires-Dist: importlib-metadata (>=0.12) ; python_version < "3.8"

And here we need importlib-metadata if we are on Python 3.7 and earlier.

But what about Require-dist that only specify an extra?

SQLAlchemy-1.3.15.dist-info/METADATA:

Requires-Dist: cx-oracle ; extra == 'oracle'
Requires-Dist: pyodbc ; extra == 'mssql_pyodbc'

Now, I can understand the intent here as well: if you plan on using Oracle, SQLAlchemy will at some point need cx-oracle from pypi. Same reasoning with MS SQLServer and pyodbc.

However, how exactly are these installs triggered? I would be extremely unhappy if an SQLAlchemy install automatically pulled in the prereqs for SQL Server and Oracle. And in fact, I remember installing them separetely, as I should.

Ditto here:

./loguru-0.3.2.dist-info/METADATA:

Requires-Dist: black (>=19.3b0) ; (python_version >= "3.6") and extra == 'dev'

If I plan to develop and I am on 3.6 and above, pull in black too. How do I indicate intent to develop via that extra at pip install time?

How does extra work in practice?

Is there a pip install extra flag?

I see this question: Specify extras_require with pip install -e, but it doesn't really look like I what I expect. The -e flag is for editable installs, so whatever extras also end up there are probably not what I am curious about.

And searching pip install --help for extras doesn't look all that promising: is used.

  --use-pep517                Use PEP 517 for building source distributions
                              (use --no-use-pep517 to force legacy behaviour).
  --install-option <options>  Extra arguments to be supplied to the setup.py
--
                              options to setup.py install. If you are using an
                              option with a directory path, be sure to use
                              absolute path.
  --global-option <options>   Extra global options to be supplied to the
--
                              repository compliant with PEP 503 (the simple
                              repository API) or a local directory laid out in
                              the same format.
  --extra-index-url <url>     Extra URLs of package indexes to use in addition

Finally, PEP345 doesn't provide much clarity either.

Requires-Dist (multiple use)

Each entry contains a string naming some other distutils project required by this distribution.

The format of a requirement string is identical to that of a distutils project name (e.g., as found in the Name: field. optionally followed by a version declaration within parentheses.

The distutils project names should correspond to names as found on the Python Package Index [4].

Version declarations must follow the rules described in Version Specifiers

JL Peyret
  • 10,917
  • 2
  • 54
  • 73

2 Answers2

1

This is defined in the core metadata document. This feature allows to bundle extra features with a package. E.g. if a fictive package foobar offers some 3d support for rendering, it might provide the 3d extra feature:

Provides-Extra: 3d
Requires-Dist: graphics3d; extra == '3d'

The extra feature can be installed with:

pip install foobar[3d]
k_o_
  • 5,143
  • 1
  • 34
  • 43
0

Eventually found it a bit later, when I found a question coming in from the other end: What do square brackets mean in pip install?, i.e. from someone asking about a particular example of pip's command line use.

reminder: SQLAlchemy's partial extra contents:

Requires-Dist: cx-oracle ; extra == 'oracle'
Requires-Dist: pyodbc ; extra == 'mssql_pyodbc'

You put one or more comma separated extra identifiers, i.e. the oracle or mssql_pyodbc in my example above, in square brackets.

i.e. pip install <somepackage>[<extrafeature1>,<extrafeature2>]

Let's try it out using a brand new virtualenv each time.

standard: pip install sqlalchemy

pip list

Package    Version
---------- -------
pip        19.2.3
setuptools 41.2.0
SQLAlchemy 1.3.17

bring in pyodbc: pip install sqlalchemy[mssql_pyodbc]

pip list

Package    Version
---------- -------
pip        19.2.3
pyodbc     4.0.30
setuptools 41.2.0
SQLAlchemy 1.3.17

The packaging viewpoint of this is documented in setuptools.

JL Peyret
  • 10,917
  • 2
  • 54
  • 73