Repository navigation
feat(wheelname): add ParseTags, which does not require a parseable version - #56
Merged
Merged
Conversation
…rsion Parse rejects a whole filename when only the version fails PEP 440, and the version contributes nothing to a PEP 425 tag. PEP 427 escapes non-alphanumeric runs to "_", so a legal 1.0+cpu reaches disk as 1.0_cpu and does not parse. Over a sweep of 14.3M mirrored PyPI wheels, 221 of 299 rejected filenames failed on the version alone with readable tags, understating real platform compatibility. Un-escaping inside Parse was rejected: the escaping is not losslessly invertible. Both 2.5.0+post1_cpu and 2.5.0_post1+cpu parse from the escaped 2.5.0_post1_cpu and only the second is right, so it would return a wrong version with no error. Both entry points share parseExceptVersion so they cannot disagree about what a wheel filename is. WheelTags is a separate type rather than a WheelFilename with an empty Version, so no caller can read a zero version as a real one. Fixes #55 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jonyoder
added a commit
that referenced
this pull request
Sep 18, 2026
Releases wheelname.ParseTags (#56) so the PyPI manifest producer can consume it; rstudio/package-manager#20776 is blocked on this tag existing. Additive only; Parse's behaviour is unchanged. Minor bump while major is 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
wheelname.ParseTags, which reads a wheel's compatibility tags without requiring its version to parse.Parseis unchanged.Fixes #55.
Why additive rather than un-escaping inside
ParseThe issue proposed un-escaping
_back to+before PEP 440 parsing. I probed this library's ownversion.Parsefirst, and the inverse is ambiguous silently:2.5.0_post1_cpu2.5.0+post1_cpu2.5.0+post1.cpu2.5.0_post1+cpu2.5.0.post1+cpuBoth parse, and only the second is right for
torch-2.5.0.post1+cpu. Any candidate-ordering heuristic therefore returns a plausible wrong version with no error on some inputs. Also worth noting:_and-are already accepted as pre/post/dev separators (1.0_rc1parses today), so the only genuinely broken case is the local-version+— and the tag component of those filenames parses standalone.So the version was never needed to answer the tag question.
ParseTagsrecovers all 221 affected filenames rather than the ~137 unambiguous ones, and cannot ever return a wrong version.Shape
WheelTags{Name, Build, Tags}is a distinct type, not aWheelFilenamewith an emptyVersion— a caller cannot read a zero version and mistake it for a real one.parseExceptVersion, so they cannot drift on what a wheel filename is. A test asserts they agree on name, build and tags for a valid filename.Dropping version validation also drops the only signal that rejected some malformed names.
too-few-py3-none-any.whlsplits into five fields withfewwhere a version belongs, soParseTagsaccepts it whereParsedoes not. Re-validating the version would defeat the function's purpose, so there is a test documenting this rather than hiding it.Separately, I noticed
tags.ParseTagaccepts a platform containing!(e.g.py3-none-not!a!platform), so bothParseandParseTagsaccept it. Pre-existing and left alone — flagging it in case it is worth its own issue.Verification
go build,go vet,gofmtclean;go test ./...green across all 12 packagesParseTagsto delegate toParse: exactly the two behaviour-carrying tests failed while the drift and rejection guards kept passinggolangci-lintnot yet run locally (another process held its lock); CI covers it🤖 Generated with Claude Code