nexB / python-inspector

Inspect Python code and PyPI package manifests. Resolve Python dependencies.
20 stars 17 forks source link

Resolution fails due to encoding issue with version strings containing a `+` #143

Closed fviernau closed 9 months ago

fviernau commented 10 months ago

The following requirements.txt can be resolved with pip, but not with python-inspector.

--extra-index-url https://download.pytorch.org/whl/cpu
torch==2.0.0+cpu

Outcome:

python-inspector -p 3.10  --operating-system linux --json-pdt x.json --analyze-setup-py-insecurely --requirement requirements.txt --verbose
Resolving dependencies...
direct_dependencies:
 DependentPackage(purl='pkg:pypi/torch@2.0.0%2Bcpu', extracted_requirement='torch==2.0.0+cpu', scope='install')
environment: Environment(python_version='310', operating_system='linux')
repos:
 PypiSimpleRepository(index_url='https://pypi.org/simple', credentials=None)
Traceback (most recent call last):
  File "/home/frank/.local/lib/python3.10/site-packages/resolvelib/resolvers.py", line 397, in resolve
    self._add_to_criteria(self.state.criteria, r, parent=None)
  File "/home/frank/.local/lib/python3.10/site-packages/resolvelib/resolvers.py", line 174, in _add_to_criteria
    raise RequirementsConflicted(criterion)
resolvelib.resolvers.RequirementsConflicted: Requirements conflict: <Requirement('torch==2.0.0+cpu')>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/frank/.local/lib/python3.10/site-packages/python_inspector/resolve_cli.py", line 247, in resolve_dependencies
    resolution_result: Dict = resolver_api(
  File "/home/frank/.local/lib/python3.10/site-packages/python_inspector/api.py", line 263, in resolve_dependencies
    resolution, purls = resolve(
  File "/home/frank/.local/lib/python3.10/site-packages/python_inspector/api.py", line 322, in resolve
    resolved_dependencies, packages = get_resolved_dependencies(
  File "/home/frank/.local/lib/python3.10/site-packages/python_inspector/api.py", line 360, in get_resolved_dependencies
    resolver_results = resolver.resolve(requirements=requirements, max_rounds=max_rounds)
  File "/home/frank/.local/lib/python3.10/site-packages/resolvelib/resolvers.py", line 546, in resolve
    state = resolution.resolve(requirements, max_rounds=max_rounds)
  File "/home/frank/.local/lib/python3.10/site-packages/resolvelib/resolvers.py", line 399, in resolve
    raise ResolutionImpossible(e.criterion.information)
resolvelib.resolvers.ResolutionImpossible: [RequirementInformation(requirement=<Requirement('torch==2.0.0+cpu')>, parent=None)]

Observation:

After some debugging, I found that packages_from_links() in utils_pypi.py operates on packages which have the version encoded. In particular, the + is encoded as %2B. My guess is that the matching somehow then compares + with %2B and fails. I tried the following (workaround) requirements.txt, which can be successfully analyzed. I guess this proofs that it's an encoding bug:

--extra-index-url https://download.pytorch.org/whl/cpu
torch==2.0.0%2Bcpu
pombredanne commented 10 months ago

For reference, not sure if you have read this before, the + is for "local version identifiers" as explained here https://peps.python.org/pep-0440/#local-version-identifiers and here https://peps.python.org/pep-0440/#adding-local-version-identifiers

pombredanne commented 9 months ago

@fviernau I have a fewthings to push to our branch shortly