fix(pylock): two PEP 751 lockfile validation fixes#1244
Conversation
|
Because bool is a subclass of int in Python, isinstance(True, int) is true, so the _get helper accepted a boolean wherever an integer was expected. This meant a lockfile with, for example, size = true would validate and set PackageWheel.size to True. TOML distinguishes booleans from integers, so _get now rejects a boolean when the expected type is int, raising the usual PylockValidationError with the field context, following the existing str-versus-Sequence special case. Assisted-by: ClaudeCode:claude-opus-4-8
…y check The mutual-exclusivity check counted distributions using the number of wheels, so an empty wheels = [] array alongside vcs, directory, or archive incorrectly validated even though [[packages.wheels]] is mutually exclusive with those direct URL sources. The check now treats the presence of the wheels key as wheels being specified, regardless of how many entries it contains. As a result, an empty wheels array on its own is also treated as a specified distribution and validates without requiring a direct URL source. Assisted-by: ClaudeCode:claude-opus-4-8
cf170d6 to
1211ec3
Compare
|
I dropped commit 3 and shortened a comment. Claude seems convinced that |
brettcannon
left a comment
There was a problem hiding this comment.
I think the model is being unnecessarily pedantic for change 2.
| tool=_get(d, Mapping, "tool"), # type: ignore[type-abstract] | ||
| ) | ||
| distributions = bool(package.sdist) + len(package.wheels or []) | ||
| # The presence of the wheels key (even as an empty array) counts as wheels |
There was a problem hiding this comment.
This makes no sense to me. I don't see why having an empty [[packages.wheels]] array just to exclude other tables makes sense. If you don't want the other tables then don't include them.
There was a problem hiding this comment.
I'm walking this back. FWIW, I think this version would have been easier to validate with a schema; it's easier to indicate that you need one key of several than to special case an empty array key as not counting as a key (it can be done via JSON Schema, but it's more steps).
…clusivity check" This reverts commit 1211ec3.
Item 3 has been removed.
🤖 AI text below 🤖
Part of #1239.
This fixes three related PEP 751 lockfile validation bugs surfaced in the code review for #1239. Each fix is a separate commit with a regression test, and
src/packaging/pylock.pystays at 100% coverage.1. Booleans accepted where TOML integers are expected
_getusedisinstance(value, expected_type), and becauseboolis a subclass ofint, a boolean passed the integer check. TOML distinguishes the two types, so a lockfile could set an integer field to a boolean:_getnow rejects a boolean when the expected type isint, raising the usualPylockValidationErrorwith field context (following the existing str-vs-Sequencespecial case):2. Empty
wheels = []array defeated the mutual-exclusivity checkThe check counted distributions with
len(package.wheels or []), so an emptywheels = []array alongside a direct URL source validated, even though[[packages.wheels]]is mutually exclusive withvcs/directory/archive:The check now treats the presence of the key (
package.wheels is not None) as wheels being specified. An emptywheels = []on its own is likewise treated as a specified distribution and validates without requiring a direct URL source.3.
select()raisedKeyErroron partial environmentsPylock.select()indexedenvironment["python_full_version"]directly, so a partial environment dict missing that key raised a bareKeyError, even though the adjacent code (dict(environment or {})) anticipates partial environments and letsMarker.evaluatefill defaults:The lookup now falls back to
markers.default_environment()["python_full_version"]when the key is missing.🤖 Generated with Claude Code