Use the new XetSession API - #4116
Conversation
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #4116 +/- ##
==========================================
+ Coverage 75.00% 76.40% +1.39%
==========================================
Files 145 173 +28
Lines 13978 20349 +6371
==========================================
+ Hits 10484 15547 +5063
- Misses 3494 4802 +1308 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Wauplin
left a comment
There was a problem hiding this comment.
This looks very solid now! Extensively tested it locally (mainly the CLI) and works as smoothly as before 👍
|
I've asked Claude code to review the PR and it commented a few things. Nothing critical IMO
Suggestion: Delete My opinion (Wauplin): fine to remove them and mention the breaking change in the PR description (it's a breaking change but I don't expect downstream users to have actually raised from it)
My opinion (Wauplin): quick and easy to test so let's do it (even if not introduced in this PR)
My opinion (Wauplin): let's keep it as-is except if you really care about it^^
My opinion (Wauplin): why not but low prio |
| "repo_type": "bucket", | ||
| "revision": "some-rev", | ||
| }, | ||
| "/api/buckets/user/mybucket/xet-write-token/some-rev", |
There was a problem hiding this comment.
Is this expected? The xet_connection_info_refresh_url function logic was entirely extracted from the previous fetch_xet_connection_info_from_repo_info function, and the logic implies this. But the comment # On "bucket" repo type, the revision never needed => don't use it suggests otherwise. @Wauplin
hanouticelina
left a comment
There was a problem hiding this comment.
thanks a lot @seanses for working on this! and very sorry for the delay. I left a couple of comments and tested the PR as well (with with hf_xet==1.5.0),
let me know if I'm missing something.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 910d691. Configure here.
hanouticelina
left a comment
There was a problem hiding this comment.
Looks good to me, I tested the PR against a locally built wheel from xet-core PR huggingface/xet-core#856 and all good on my side, thanks a lot @seanses for working on this!
I'll let @Wauplin take a look and give the green light
Wauplin
left a comment
There was a problem hiding this comment.
Made another pass on the PR. I think we are very close to getting this merged (once hf_xet==1.5.1 gets released).
About the progress bars I like the idea of reporting both the "download" and "reconstruction" progress for better UX. Left 2 comments about it but I think it can be addressed in a separate PR. Let me know what you think
Wauplin
left a comment
There was a problem hiding this comment.
Pre-approving, only remaining item is bumping hf_xet version in setup.py 🎉
|
🎉 |
|
This PR has been shipped as part of the v1.19.0 release. |

Summary
Migrates all xet upload/download code from the old function-based
hf_xetAPI (upload_files,download_files, globalMULTITHREADED_RUNTIME) to the new session-basedXetSessionAPI introduced inhf-xet >= 1.5.0.Upload:
Download:
Architecture:
utils/_xet.py—XetSessionHolderis a lightweight wrapper aroundXetSessionwith three safety guarantees:sigint_abort()cancels the active session and clears the reference so the nextget()creates a fresh one (notebook-friendly — subsequent cells still work after Ctrl-C)get()checksos.getpid()against the PID that created the session; on mismatch the inherited session is discarded and a fresh one is created for the child process (prevents deadlock when multiprocessing workers inherit a dead Tokio runtime)threading.Lockguards all state mutations, important for free-threaded Python (3.14t) where multiple threads can race onget()orsigint_abort()without the GIL serialising them_GLOBAL_XET_HOLDER = XetSessionHolder()is a module-level singleton (analogous toget_session()for HTTP). All upload/download call sites share the same session viaget_xet_session()— repo commits,hf_hub_download, bucket uploads/downloads, andsnapshot_downloadall reuse the same underlying Tokio runtimeexcept KeyboardInterrupt: _GLOBAL_XET_HOLDER.sigint_abort(); raiseto abort the in-flight Rust operation and allow clean re-use of xet in the same processxet_connection_info_refresh_url()centralises token-refresh URL construction: handles thebucketrepo-type (revision omitted) and the/Nonerevision for PR write-token requests (where the final revision is not yet known)_xet_progress_reporting.py— progress callback receives(group_report, item_reports)matching the new API contractsetup.py— minimumhf-xetversion bumped to>= 1.5.0hf_xet.XetSession; fork-safety unit and integration tests added totest_xet_utils.pyNote on
upload_large_folderand Ctrl-C: xet work there runs inside background worker threads. Python only deliversKeyboardInterruptto the main thread, andPyErr_CheckSignals()is a no-op in non-main threads — so Ctrl-C responsiveness forupload_large_folderrequires a separate fix (shared stop event + worker cooperation) and is out of scope for this PR.TODO
upload_large_folderto use theXetSessionAPI directly: register each file to the upload commit object immediately after SHA-256 computation (no batching needed — xet handles concurrency internally), then callcommit()once at the end. This removes the artificial batch size tuning (UPLOAD_BATCH_SIZE_XET) and makes the xet path inupload_large_folderconsistent with the rest of the codebase.Note
Medium Risk
Touches the primary large-file transfer path across commits, hub downloads, and buckets with a dependency floor bump; behavior changes around token refresh, KeyboardInterrupt, and forked workers warrant careful regression testing.
Overview
Migrates all Hub Xet uploads and downloads from the legacy
hf_xethelpers (upload_files,upload_bytes,download_files) to theXetSessionAPI (new_upload_commit,new_file_download_group), withhf-xetbumped to>=1.5.1.A shared
get_xet_session()singleton inutils/_xet.py(fork-safe, thread-safe,abort_xet_session()on Ctrl-C) backs repo commits (_upload_xet_files),xet_get/hf_hub_download, and bucket batch upload/download. Auth is nowtoken_refresh_url+token_refresh_headersinstead of pre-fetching endpoints/tokens and passingtoken_refreshercallbacks;xet_connection_info_refresh_url()centralizes refresh URL building.XetProgressReporterfollows the new(group_report, item_reports)progress contract;XetAuthorizationError/XetRefreshTokenErrorare removed. Tests mockXetSessionand add fork-safety coverage forXetSessionHolder.Reviewed by Cursor Bugbot for commit 44aec7a. Bugbot is set up for automated code reviews on this repo. Configure here.