pip: New resolver breaks with mmcv_full package and custom find-links

I’m not sure if this is an mmcv issue or a pip issue. I’ve posted a corresponding issue with mmcv here: https://github.com/open-mmlab/mmcv/issues/679

What did you want to do?

MMCV contains custom binaries targeted towards specific versions of pytorch and custom cuda or cpu configurations. Previously with the old resolver you specified a target version you wanted as such:

pip install mmcv_full==1.0.5+torch1.6.0+cpu -f https://openmmlab.oss-accelerate.aliyuncs.com/mmcv/dist/index.html

When working on pip 20.3 and master I get this error:

ERROR: Exception:
Traceback (most recent call last):
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_vendor/resolvelib/resolvers.py", line 171, in _merge_into_criterion
    crit = self.state.criteria[name]
KeyError: 'mmcv-full'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_internal/cli/base_command.py", line 210, in _main
    status = self.run(options, args)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_internal/cli/req_command.py", line 180, in wrapper
    return func(self, options, args)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_internal/commands/install.py", line 318, in run
    requirement_set = resolver.resolve(
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 121, in resolve
    self._result = resolver.resolve(
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_vendor/resolvelib/resolvers.py", line 445, in resolve
    state = resolution.resolve(requirements, max_rounds=max_rounds)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_vendor/resolvelib/resolvers.py", line 310, in resolve
    name, crit = self._merge_into_criterion(r, parent=None)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_vendor/resolvelib/resolvers.py", line 173, in _merge_into_criterion
    crit = Criterion.from_requirement(self._p, requirement, parent)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_vendor/resolvelib/resolvers.py", line 82, in from_requirement
    if not cands:
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_vendor/resolvelib/structs.py", line 124, in __bool__
    return bool(self._sequence)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 96, in __bool__
    return any(self)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 20, in _deduplicated_by_version
    for candidate in candidates:
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 198, in iter_index_candidates
    yield self._make_candidate_from_link(
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 144, in _make_candidate_from_link
    self._link_candidate_cache[link] = LinkCandidate(
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 290, in __init__
    wheel_version = Version(wheel.version)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/pip/_vendor/packaging/version.py", line 298, in __init__
    raise InvalidVersion("Invalid version: '{0}'".format(version))
pip._vendor.packaging.version.InvalidVersion: Invalid version: '1.0.5+torch1.6.0+cpu'

Is there a different way that the version '1.0.5+torch1.6.0+cpu' should be specified? Or is this something that the new dependency resolver should be able to handle, but it doesn’t?

Disabling the new resolver fixes the issue, but that’s a unstable workaround as the old resolver will soon be removed.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (13 by maintainers)

Most upvoted comments

I think it’s fine to mandate PEP 440, I do think we should maybe try to get a better error message for it though.

For anyone reading this who doesn’t know how to temporarily switch to old resolver behavior while using pip 20.3.x: use the flag --use-deprecated=legacy-resolver. More information at https://pip.pypa.io/en/latest/user_guide/#changes-to-the-pip-dependency-resolver-in-20-3-2020 .

Yup. I’m on board with not supporting software standards from back when I was 5. 😃

enjoys the moment, as everyone around me feels old

I’m also inclined to be stricter. Metadata 1.2 mandates that versions follow PEP 440, so we can definitely be strict with anything that claims to be 1.2 or later.

Personally, I’m also fine with saying we only support PEP 440, even for older versions, because honestly, 1.2 is 15 years old by now, I think we can afford to not carry legacy code that’s solely there to handle packages that are still using standards that are 15 years out of date.

What mmcv is trying to do isn’t exactly well supported by the tooling, so it’s going to be a bit of a square peg round hole problem. That being said, they could fix the synatical problems with their PEP 440 version by doing something like 1.0.5+torch1.6.0.cpu instead. The only characters allowed in a local version are alphanumerics, and ..

That doesn’t solve the larger problem about how to handle this case, but it would fix the problem with local versions being an invalid syntax.