I would add that even if this is perfectly legal:
from setuptools import setup
extras_require = {
'': ["numpy"]
}
setup(
name='test_pkg',
version='1.0.0',
extras_require=extras_require,
)
We obtain a METADATA file which is not what it should be:
Metadata-Version: 2.1
Name: test-pkg
Version: 1.0.0
Summary: UNKNOWN
Home-page: UNKNOWN
Author: UNKNOWN
Author-email: UNKNOWN
License: UNKNOWN
Platform: UNKNOWN
Requires-Dist: numpy
And it should be:
Metadata-Version: 2.1
Name: test-pkg
Version: 1.0.0
Summary: UNKNOWN
Home-page: UNKNOWN
License: UNKNOWN
Platform: UNKNOWN
Provides-Extra:
Requires-Dist: numpy ; extra == ''
UNKNOWN
This behavior makes the way extras_require
inconsistent and hardly predictable.
If you manually modifies the METADATA file and try:
$ pip install -U "dist/test_pkg-1.0.0-py3-none-any.whl"
Processing ./dist/test_pkg-1.0.0-py3-none-any.whl
Installing collected packages: test-pkg
Attempting uninstall: test-pkg
Found existing installation: test-pkg 1.0.0
Uninstalling test-pkg-1.0.0:
Successfully uninstalled test-pkg-1.0.0
Successfully installed test-pkg-1.0.0
No crash or error, just numpy is not installed as we would like it to be.
The following could also have been possible:
Metadata-Version: 2.1
Name: test-pkg
Version: 1.0.0
Summary: UNKNOWN
Home-page: UNKNOWN
License: UNKNOWN
Platform: UNKNOWN
Requires-Dist: numpy ; extra != ''
UNKNOWN
It was clooose to be working but crash:
$ pip install -U "dist/test_pkg-1.0.0-py3-none-any.whl[foo]"
Processing ./dist/test_pkg-1.0.0-py3-none-any.whl
WARNING: test-pkg 1.0.0 does not provide the extra 'foo'
Ignoring numpy: markers 'extra != ""' don't match your environment
ERROR: Error while checking for conflicts. Please file an issue on pip's issue tracker: https://github.com/pypa/pip/issues/new
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/pip/_internal/commands/install.py", line 535, in _determine_conflicts
return check_install_conflicts(to_install)
File "/usr/local/lib/python3.6/site-packages/pip/_internal/operations/check.py", line 118, in check_install_conflicts
package_set, should_ignore=lambda name: name not in whitelist
File "/usr/local/lib/python3.6/site-packages/pip/_internal/operations/check.py", line 84, in check_package_set
missed = req.marker.evaluate()
File "/usr/local/lib/python3.6/site-packages/pip/_vendor/packaging/markers.py", line 328, in evaluate
return _evaluate_markers(self._markers, current_environment)
File "/usr/local/lib/python3.6/site-packages/pip/_vendor/packaging/markers.py", line 244, in _evaluate_markers
lhs_value = _get_env(environment, lhs.value)
File "/usr/local/lib/python3.6/site-packages/pip/_vendor/packaging/markers.py", line 225, in _get_env
"{0!r} does not exist in evaluation environment.".format(name)
pip._vendor.packaging.markers.UndefinedEnvironmentName: 'extra' does not exist in evaluation environment.
Installing collected packages: test-pkg
Attempting uninstall: test-pkg
Found existing installation: test-pkg 1.0.0
Uninstalling test-pkg-1.0.0:
Successfully uninstalled test-pkg-1.0.0
Successfully installed test-pkg-1.0.0
See the message: Ignoring numpy: markers 'extra != ""' don't match your environment
=> It’s good.
But the rest ends up in a crash.
However, it’s important to note that if instead of doing 'extra != ""
we want to do: 'extra != "foo"
, now it works as we expect !
Metadata-Version: 2.1
Name: test-pkg
Version: 1.0.0
Summary: UNKNOWN
Home-page: UNKNOWN
License: UNKNOWN
Platform: UNKNOWN
Provides-Extra: foo
Requires-Dist: numpy ; extra != 'foo'
UNKNOWN
With the scripts:
$ pip install -U "dist/test_pkg-1.0.0-py3-none-any.whl[foo]"
Processing ./dist/test_pkg-1.0.0-py3-none-any.whl
Ignoring numpy: markers 'extra != "foo"' don't match your environment
Installing collected packages: test-pkg
Attempting uninstall: test-pkg
Found existing installation: test-pkg 1.0.0
Uninstalling test-pkg-1.0.0:
Successfully uninstalled test-pkg-1.0.0
Successfully installed test-pkg-1.0.0
$ pip install -U "dist/test_pkg-1.0.0-py3-none-any.whl"
Processing ./dist/test_pkg-1.0.0-py3-none-any.whl
Collecting numpy; extra != "foo"
Using cached numpy-1.19.1-cp36-cp36m-manylinux2010_x86_64.whl (14.5 MB)
Installing collected packages: numpy, test-pkg
Attempting uninstall: test-pkg
Found existing installation: test-pkg 1.0.0
Uninstalling test-pkg-1.0.0:
Successfully uninstalled test-pkg-1.0.0
Successfully installed numpy-1.19.1 test-pkg-1.0.0
Yeah ! Successfully installed numpy-1.19.1
So far this is the only possible solution to make it work. However, as shown in my issue: https://github.com/pypa/pip/issues/8686. This only work if you want to reject only one “extra”, if you need to reject many extra != "foo" and extra != "bar"
this is not working.
With None
value it’s a bit more tricky:
Metadata-Version: 2.1
Name: test-pkg
Version: 1.0.0
Summary: UNKNOWN
Home-page: UNKNOWN
License: UNKNOWN
Platform: UNKNOWN
Provides-Extra: None
Requires-Dist: numpy ; extra == "None"
UNKNOWN
No crash from the point of view of METADATA (if modified by hand), however numpy is completely ignored:
$ pip install -U "dist/test_pkg-1.0.0-py3-none-any.whl"
Processing ./dist/test_pkg-1.0.0-py3-none-any.whl
Installing collected packages: test-pkg
Attempting uninstall: test-pkg
Found existing installation: test-pkg 1.0.0
Uninstalling test-pkg-1.0.0:
Successfully uninstalled test-pkg-1.0.0
Successfully installed test-pkg-1.0.0
$ pip install -U "dist/test_pkg-1.0.0-py3-none-any.whl[None]"
Processing ./dist/test_pkg-1.0.0-py3-none-any.whl
Ignoring numpy: markers 'extra == "None"' don't match your environment
Installing collected packages: test-pkg
Attempting uninstall: test-pkg
Found existing installation: test-pkg 1.0.0
Uninstalling test-pkg-1.0.0:
Successfully uninstalled test-pkg-1.0.0
Successfully installed test-pkg-1.0.0
My hypothesis for Ignoring numpy: markers 'extra == "None"' don't match your environment
, it’s that python normalize None
to none
, and therefore not matching.