Skip to content

New resolver breaks with mmcv_full package and custom find-links #9183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Erotemic opened this issue Nov 30, 2020 · 15 comments
Closed

New resolver breaks with mmcv_full package and custom find-links #9183

Erotemic opened this issue Nov 30, 2020 · 15 comments
Labels
C: error messages Improving error messages

Comments

@Erotemic
Copy link

I'm not sure if this is an mmcv issue or a pip issue. I've posted a corresponding issue with mmcv here: open-mmlab/mmcv#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.

@dstufft
Copy link
Member

dstufft commented Nov 30, 2020

FWIW, that version number looks invalid, I suspect the new resolver only works with PEP 440 compliant versions.

@dstufft
Copy link
Member

dstufft commented Nov 30, 2020

(Maybe it should support non compliant versions as the old resolver does, but just looking at the code there, it's using internal APIs that only work on PEP 440 valid versions)

@uranusjr
Copy link
Member

The invalid version in question came from a wheel. Wheel only allows PEP 440 versions.

@dstufft
Copy link
Member

dstufft commented Nov 30, 2020

The invalid version in question came from a wheel. Wheel only allows PEP 440 versions.

I don't think that's historically true, the Wheel PEP predates PEP 440.

@dstufft
Copy link
Member

dstufft commented Nov 30, 2020

To be clear, I'm perfectly OK with the idea that the new resolver mandates PEP 440 versions, since they're the only versions we actually know how to interpret correctly, and as a general case of ratcheting to be stricter in what sort of malformed, or non standards based data we accept.

@Erotemic
Copy link
Author

So, I suppose my question is how should mmcv change such that it is possible to specify which wheel you need depending on your torch and cuda (or lack there of) versions? Is this possible with PEP 440 version, a quick look seems like it might not be? In that case what can mmcv do?

@dstufft
Copy link
Member

dstufft commented Nov 30, 2020

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.

@uranusjr
Copy link
Member

I don't think that's historically true, the Wheel PEP predates PEP 440.

You’re correct, the PEP 440 is not added until Metadata 1.2, and wheels are allowed to use 1.1. I think it’s the easiest way out to just allow legacy versions here. (It would only result in a build failure later in this case, however, since mmcv wheels are actually using Metadata 2.1, making them invalid).

@pradyunsg
Copy link
Member

If we do decide to allow legacy versions (I'm in the "let's be strict and make people fix their metadata" camp, so if I'm making the call -- no changes beyond a better error message needed here), I'd like to gate allowing legacy versions to only wheels that declare to be under metadata versions < 1.2.

Everything over that, should still get the exact same failure because PEP 440 is a thing and what pip saw is an invalid wheel.

@pfmoore
Copy link
Member

pfmoore commented Nov 30, 2020

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.

@pradyunsg
Copy link
Member

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

@dstufft
Copy link
Member

dstufft commented Nov 30, 2020

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.

@pradyunsg pradyunsg added the C: error messages Improving error messages label Nov 30, 2020
@pradyunsg
Copy link
Member

"let's be strict and make people fix their metadata" [snip] no changes beyond a better error message needed here

Looks like we are all tending toward this! :)

@Erotemic
Copy link
Author

That's good enough for me. I'm happy to accept the answer mmcv should fix this on their end.

@brainwane
Copy link
Contributor

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 .

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
C: error messages Improving error messages
Projects
None yet
Development

No branches or pull requests

6 participants