Skip to content

Commit 42a8a03

Browse files
authored
requirement: handle VCS URLs correctly in pinned mode (#395)
* requirement: handle VCS URLs correctly in pinned mode * CHANGELOG: record changes * pip_audit, test: skip URL dependencies Signed-off-by: William Woodruff <[email protected]> * CHANGELOG: update changes Signed-off-by: William Woodruff <[email protected]> Signed-off-by: William Woodruff <[email protected]>
1 parent b497915 commit 42a8a03

File tree

4 files changed

+34
-21
lines changed

4 files changed

+34
-21
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ All versions prior to 0.0.9 are untracked.
1919
were not correctly filtered by "withdrawn" status; "withdrawn" vulnerabilities
2020
are now excluded ([#386](https://github.com/pypa/pip-audit/pull/386))
2121

22+
* Fixed `pip-audit`'s handling of URL-style requirements in `--no-deps` mode
23+
(URL requirements are now treated as skipped, rather than producing
24+
an error due to a lack of pinning)
25+
([#395](https://github.com/pypa/pip-audit/pull/395/files))
26+
2227
## [2.4.4]
2328

2429
### Changed

pip_audit/_cli.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ def audit() -> None:
448448
if len(vulns) > 0:
449449
pkg_count += 1
450450
vuln_count += len(vulns)
451+
except DependencySourceError as e:
452+
_fatal(str(e))
451453
except VulnServiceConnectionError as e:
452454
# The most common source of connection errors is corporate blocking,
453455
# so we offer a bit of advice.

pip_audit/_dependency_source/requirement.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -250,26 +250,30 @@ def _collect_preresolved_deps(
250250
f"requirement {req.name} does not contain a hash {str(req)}"
251251
)
252252

253-
if not req.specifier:
254-
if req.link is None:
253+
# NOTE: URL dependencies cannot be pinned, so skipping them
254+
# makes sense (under the same principle of skipping dependencies
255+
# that can't be found on PyPI). This is also consistent with
256+
# what `pip --no-deps` does (installs the URL dependency, but
257+
# not any subdependencies).
258+
if req.is_url:
259+
yield req.req, SkippedDependency(
260+
name=req.name,
261+
skip_reason="URL requirements cannot be pinned to a specific package version",
262+
)
263+
elif not req.specifier:
264+
raise RequirementSourceError(f"requirement {req.name} is not pinned: {str(req)}")
265+
else:
266+
pinned_specifier = PINNED_SPECIFIER_RE.match(str(req.specifier))
267+
if pinned_specifier is None:
255268
raise RequirementSourceError(
256269
f"requirement {req.name} is not pinned: {str(req)}"
257270
)
258-
else:
259-
raise RequirementSourceError(
260-
f"requirement {req.name} is not pinned, URL requirements must be pinned "
261-
f"with #egg=your_package_name==your_package_version: {str(req)}"
262-
)
263271

264-
pinned_specifier = PINNED_SPECIFIER_RE.match(str(req.specifier))
265-
if pinned_specifier is None:
266-
raise RequirementSourceError(f"requirement {req.name} is not pinned: {str(req)}")
267-
268-
yield req.req, ResolvedDependency(
269-
req.name,
270-
Version(pinned_specifier.group("version")),
271-
self._build_hash_options_mapping(req.hash_options),
272-
)
272+
yield req.req, ResolvedDependency(
273+
req.name,
274+
Version(pinned_specifier.group("version")),
275+
self._build_hash_options_mapping(req.hash_options),
276+
)
273277

274278
def _build_hash_options_mapping(self, hash_options: List[str]) -> Dict[str, List[str]]:
275279
"""

test/dependency_source/test_requirement.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -451,13 +451,15 @@ def test_requirement_source_no_deps_unpinned_url(monkeypatch):
451451
monkeypatch.setattr(
452452
pip_requirements_parser,
453453
"get_file_content",
454-
lambda _: "https://github.com/pallets/flask/archive/refs/tags/2.0.1.tar.gz#egg=flask\n"
455-
"requests>=1.0",
454+
lambda _: "https://github.com/pallets/flask/archive/refs/tags/2.0.1.tar.gz#egg=flask\n",
456455
)
457456

458-
# When dependency resolution is disabled, all requirements must be pinned.
459-
with pytest.raises(DependencySourceError):
460-
list(source.collect())
457+
assert list(source.collect()) == [
458+
SkippedDependency(
459+
name="flask",
460+
skip_reason="URL requirements cannot be pinned to a specific package version",
461+
)
462+
]
461463

462464

463465
def test_requirement_source_dep_caching(monkeypatch):

0 commit comments

Comments
 (0)