feat: hf.revision property for HuggingFace Hub locations - #3890
Open
kszucs wants to merge 1 commit into
Open
Conversation
huggingface_hub.HfFileSystem resolves the revision per call rather than as a filesystem-wide default, so hf.revision is threaded through as a keyword argument on the fsspec input/output file and delete calls. Matching iceberg-rust, the property is the default revision for locations that don't pin one themselves: a revision embedded in the location (hf://datasets/user/repo@revision/path) wins, since huggingface_hub raises when both are given and differ. FsspecInputFile.exists() went through lexists(), which doesn't forward **kwargs; call exists() directly when there are kwargs to forward, as it forwards them to info() with the same broad exception handling. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new hf.revision table/catalog property to make hf:// (HuggingFace Hub) file locations reproducible by forwarding a default revision argument to fsspec HfFileSystem operations when the location itself does not already pin a revision.
Changes:
- Introduce
HF_REVISION = "hf.revision"and thread it throughFsspecFileIOintoFsspecInputFile/FsspecOutputFilecalls via per-operationfs_kwargs. - Ensure revision precedence rules: an
@revisionembedded in thehf://...location suppresses forwarding therevision=kwarg. - Add unit + HF_TOKEN-gated integration tests and document the new configuration property.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| tests/io/test_fsspec.py | Adds unit/integration coverage for hf.revision forwarding, precedence, and scheme isolation. |
| pyiceberg/io/fsspec.py | Implements hf.revision forwarding via fs_kwargs, including existence checks that preserve kwargs. |
| pyiceberg/io/init.py | Defines the HF_REVISION property key constant. |
| mkdocs/docs/configuration.md | Documents the new hf.revision configuration option. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
Supersedes #3609, which the stale bot closed and GitHub won't let me reopen. Rebased on current
main, with the review feedback from that round folded in (see below).Rationale for this change
HuggingFace Hub (
hf://) storage already works via fsspec'sHfFileSystem, but there's no way to select a revision (branch/tag/commit) the way iceberg-rust'shf.revisiondoes.HfFileSystemresolvesrevisionper call rather than as a filesystem-wide default (its constructor only takesendpoint/token/block_size/expand_info), sohf.revisionis threaded through as a keyword argument on the fsspec input file, output file and delete calls.Semantics match iceberg-rust's
HF_REVISION("default git revision for all paths that don't specify one"): the property applies to reads, writes and deletes, and a revision embedded in the location —hf://datasets/user/repo@revision/path— takes precedence. That precedence isn't cosmetic:huggingface_hubraisesValueError: Revision specified in path (...) and in 'revision' argument (...) are not the samewhen both are present and differ, so passing the kwarg unconditionally would break any table whose locations pin a revision themselves.Two smaller things fall out of this:
FsspecInputFile.exists()went throughlexists(), which doesn't forward**kwargs(fsspec'sAbstractFileSystem.lexistscallsself.exists(path), dropping them). It now callsexists()directly when there are kwargs to forward — that path forwards toinfo()with the same broad exception handlinglexists()would have provided, andLocalFileSystem's symlink-awarelexists()override is still used when there is nothing to forward.FsspecOutputFile.to_input_file()carries the kwargs over, so a read-back after a write stays on the same revision.Are these changes tested?
Yes: unit tests covering revision forwarding on reads (
len(),.exists(),.open()), on writes and deletes, path-embedded revisions taking precedence, the no-revision-set default, and non-hfschemes being unaffected. Plus anHF_TOKEN-gated integration test against a real temporary dataset repo that demonstrates the concrete problem: withouthf.revision, reads follow the moving default branch, so a file read at one commit silently returns different content once someone pushes to the same path.Are there any user-facing changes?
Yes: a new
hf.revisioncatalog/table property, documented inconfiguration.md.