Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-huggingface-hub for
openSUSE:Factory checked in at 2026-08-09 21:37:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-huggingface-hub (Old)
and /work/SRC/openSUSE:Factory/.python-huggingface-hub.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-huggingface-hub"
Sun Aug 9 21:37:53 2026 rev:11 rq:1370303 version:1.27.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-huggingface-hub/python-huggingface-hub.changes
2026-08-01 18:35:47.441174726 +0200
+++
/work/SRC/openSUSE:Factory/.python-huggingface-hub.new.16738/python-huggingface-hub.changes
2026-08-09 21:40:03.823918259 +0200
@@ -1,0 +2,19 @@
+Sat Aug 8 04:49:15 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 1.27.0:
+ * Install and refresh the hf-cli agent skill from the standalone
+ installers and from hf update; --exclude-skill opts out
+ * Allow --container-command and --container-args on Inference
+ Endpoints without --custom-image, and allow changing them after
+ deploy
+ * Add Baseten as an inference provider for conversational tasks
+ * Accept and type region on space_info and list_spaces
+ * Raise the hf-xet floor to 1.5.2
+
+-------------------------------------------------------------------
+Fri Aug 7 05:05:22 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 1.26.1:
+ * Add Baseten as an inference provider
+
+-------------------------------------------------------------------
Old:
----
huggingface_hub-1.26.0.tar.gz
New:
----
huggingface_hub-1.27.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-huggingface-hub.spec ++++++
--- /var/tmp/diff_new_pack.7pzF3h/_old 2026-08-09 21:40:04.403938065 +0200
+++ /var/tmp/diff_new_pack.7pzF3h/_new 2026-08-09 21:40:04.407938202 +0200
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-huggingface-hub
-Version: 1.26.0
+Version: 1.27.0
Release: 0
Summary: Client library for interaction with the huggingface hub
License: Apache-2.0
++++++ huggingface_hub-1.26.0.tar.gz -> huggingface_hub-1.27.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/huggingface_hub-1.26.0/PKG-INFO
new/huggingface_hub-1.27.0/PKG-INFO
--- old/huggingface_hub-1.26.0/PKG-INFO 2026-07-30 16:11:46.509542200 +0200
+++ new/huggingface_hub-1.27.0/PKG-INFO 2026-08-07 14:47:40.748998600 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: huggingface_hub
-Version: 1.26.0
+Version: 1.27.0
Summary: Client library to download and publish models, datasets and other
repos on the huggingface.co hub
Home-page: https://github.com/huggingface/huggingface_hub
Author: Hugging Face, Inc.
@@ -26,7 +26,7 @@
Requires-Dist: click<9.0.0,>=8.4.2
Requires-Dist: filelock>=3.10.0
Requires-Dist: fsspec>=2023.5.0
-Requires-Dist: hf-xet<2.0.0,>=1.5.1; platform_machine == "x86_64" or
platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine
== "arm64" or platform_machine == "aarch64"
+Requires-Dist: hf-xet<2.0.0,>=1.5.2; platform_machine == "x86_64" or
platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine
== "arm64" or platform_machine == "aarch64"
Requires-Dist: httpx<1,>=0.23.0
Requires-Dist: packaging>=20.9
Requires-Dist: pyyaml>=5.1
@@ -45,7 +45,7 @@
Requires-Dist: fastai>=2.4; extra == "fastai"
Requires-Dist: fastcore>=1.3.27; extra == "fastai"
Provides-Extra: hf-xet
-Requires-Dist: hf-xet<2.0.0,>=1.5.1; extra == "hf-xet"
+Requires-Dist: hf-xet<2.0.0,>=1.5.2; extra == "hf-xet"
Provides-Extra: mcp
Requires-Dist: mcp>=1.8.0; extra == "mcp"
Provides-Extra: testing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/huggingface_hub-1.26.0/setup.py
new/huggingface_hub-1.27.0/setup.py
--- old/huggingface_hub-1.26.0/setup.py 2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/setup.py 2026-08-07 14:47:34.000000000 +0200
@@ -12,7 +12,7 @@
# hf-xet version used in both install_requires and extras["hf_xet"]
-HF_XET_VERSION = "hf-xet>=1.5.1,<2.0.0"
+HF_XET_VERSION = "hf-xet>=1.5.2,<2.0.0"
install_requires = [
"click>=8.4.2,<9.0.0", # 8.4.0/8.4.1 shipped a broken fish completion
script
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/__init__.py
new/huggingface_hub-1.27.0/src/huggingface_hub/__init__.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/__init__.py 2026-07-30
16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/__init__.py 2026-08-07
14:47:34.000000000 +0200
@@ -46,7 +46,7 @@
from typing import TYPE_CHECKING
-__version__ = "1.26.0"
+__version__ = "1.27.0"
# Alphabetical order of definitions is ensured in tests
# WARNING: any comment added in this dictionary definition will be lost when
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/_inference_endpoints.py
new/huggingface_hub-1.27.0/src/huggingface_hub/_inference_endpoints.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/_inference_endpoints.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/_inference_endpoints.py
2026-08-07 14:47:34.000000000 +0200
@@ -267,6 +267,8 @@
revision: str | None = None,
task: str | None = None,
custom_image: dict | None = None,
+ container_command: list[str] | None = None,
+ container_args: list[str] | None = None,
secrets: dict[str, str] | None = None,
) -> "InferenceEndpoint":
"""Update the Inference Endpoint.
@@ -302,6 +304,12 @@
custom_image (`dict`, *optional*):
A custom Docker image to use for the Inference Endpoint. This
is useful if you want to deploy an
Inference Endpoint running on the `text-generation-inference`
(TGI) framework (see examples).
+ container_command (`list[str]`, *optional*):
+ Override the container entrypoint command (maps to
`model.command` in the API payload). Works with
+ both managed engine images (e.g. vLLM, SGLang) and custom
images.
+ container_args (`list[str]`, *optional*):
+ Arguments appended to the container entrypoint (maps to
`model.args` in the API payload). Works with
+ both managed engine images (e.g. vLLM, SGLang) and custom
images.
secrets (`dict[str, str]`, *optional*):
Secret values to inject in the container environment.
Returns:
@@ -322,6 +330,8 @@
revision=revision,
task=task,
custom_image=custom_image,
+ container_command=container_command,
+ container_args=container_args,
secrets=secrets,
token=self._token, # type: ignore [arg-type]
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/cli/_cli_utils.py
new/huggingface_hub-1.27.0/src/huggingface_hub/cli/_cli_utils.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/cli/_cli_utils.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/cli/_cli_utils.py
2026-08-07 14:47:34.000000000 +0200
@@ -1022,13 +1022,15 @@
return None
-def run_update() -> int:
+def run_update(*, exclude_skill: bool = False) -> int:
"""Run the install-method-appropriate update command for the `hf` CLI.
+ Set `exclude_skill` to tell the standalone installer not to (re)install
the `hf-cli` skill.
+
Raises CLIError if the installation method can't be determined.
Returns the subprocess exit code on success/failure of the update itself.
"""
- cmd = _get_huggingface_hub_update_command()
+ cmd = _get_huggingface_hub_update_command(exclude_skill=exclude_skill)
if cmd is None:
raise CLIError(
"Cannot determine how to update huggingface_hub (unknown
installation method). Please update manually."
@@ -1036,15 +1038,19 @@
return subprocess.call(cmd)
-def _get_huggingface_hub_update_command() -> list[str] | None:
+def _get_huggingface_hub_update_command(*, exclude_skill: bool = False) ->
list[str] | None:
"""Return the command to update huggingface_hub as an argv list, or None
if the installation method is unknown."""
match installation_method():
case "brew":
return ["brew", "upgrade", "hf"]
case "hf_installer" if os.name == "nt":
- return ["powershell", "-NoProfile", "-Command", "iwr -useb
https://hf.co/cli/install.ps1 | iex"]
+ # `iwr ... | iex` cannot take parameters: create a scriptblock so
flags reach the installer.
+ flags = " -ExcludeSkill" if exclude_skill else ""
+ script = f"& ([scriptblock]::Create((iwr -useb
https://hf.co/cli/install.ps1))){flags}"
+ return ["powershell", "-NoProfile", "-Command", script]
case "hf_installer":
- return ["bash", "-c", "curl -LsSf https://hf.co/cli/install.sh |
bash -"]
+ flags = " -s -- --exclude-skill" if exclude_skill else " -"
+ return ["bash", "-c", f"curl -LsSf https://hf.co/cli/install.sh |
bash{flags}"]
case "pip":
return [sys.executable, "-m", "pip", "install", "-U",
"huggingface_hub"]
case _:
@@ -1059,7 +1065,7 @@
"powershell",
"-NoProfile",
"-Command",
- "iwr -useb https://hf.co/cli/install.ps1 | iex
-WithTransformers",
+ "& ([scriptblock]::Create((iwr -useb
https://hf.co/cli/install.ps1))) -WithTransformers",
]
case "hf_installer":
return ["bash", "-c", "curl -LsSf https://hf.co/cli/install.sh |
bash -s -- --with-transformers"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/cli/_skills.py
new/huggingface_hub-1.27.0/src/huggingface_hub/cli/_skills.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/cli/_skills.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/cli/_skills.py
2026-08-07 14:47:34.000000000 +0200
@@ -4,18 +4,23 @@
import re
import shutil
import tempfile
+import time
from collections.abc import Callable
from dataclasses import dataclass, replace
from pathlib import Path, PurePosixPath
from typing import Any, Literal
+from huggingface_hub import __version__, constants
from huggingface_hub._buckets import BucketFile
from huggingface_hub.errors import CLIError
-from ..utils import disable_progress_bars
+from ..utils import disable_progress_bars, logging
from ._cli_utils import get_hf_api
+from ._output import out
+logger = logging.get_logger(__name__)
+
DEFAULT_SKILL_ID = "hf-cli"
DEFAULT_SKILLS_BUCKET_ID = "huggingface/skills"
MARKETPLACE_PATH = "marketplace.json"
@@ -309,3 +314,76 @@
return replace(base, status="source_unreachable", detail=str(exc))
return replace(base, status="up_to_date")
+
+
+### `hf-cli` SKILL CHECKER
+
+
+# Version stamp written in the generated SKILL.md (see `build_skill_md`).
+_GENERATED_VERSION_RE = re.compile(r"Generated with `huggingface_hub
v([^`]+)`")
+
+
+def check_skill_update() -> None:
+ """Hint at installing or updating the `hf-cli` skill, at most once every
24 hours.
+
+ Only prints a hint: installing or updating stays an explicit user action.
+
+ Skipped entirely if `HF_HUB_DISABLE_UPDATE_CHECK` is set. Called at the
entry point of
+ the CLI, so any error is caught and logged to avoid breaking the CLI.
+ """
+ try:
+ _check_skill_update()
+ except Exception:
+ logger.debug("Error while checking for hf-cli skill update.",
exc_info=True)
+
+
+def _check_skill_update() -> None:
+ if constants.HF_HUB_DISABLE_UPDATE_CHECK:
+ return
+
+ # Skip if already checked in the last 24 hours
+ stamp_path = Path(constants.CHECK_FOR_SKILL_UPDATE_DONE_PATH)
+ if stamp_path.exists() and (time.time() - stamp_path.stat().st_mtime) < 24
* 3600:
+ return
+ stamp_path.parent.mkdir(parents=True, exist_ok=True)
+ stamp_path.touch()
+
+ global_dirs = _installed_hf_cli_dirs(constants.AGENTS_SKILLS_GLOBAL_PATH,
constants.CLAUDE_SKILLS_GLOBAL_PATH)
+ local_dirs = _installed_hf_cli_dirs(constants.AGENTS_SKILLS_LOCAL_PATH,
constants.CLAUDE_SKILLS_LOCAL_PATH)
+
+ if not global_dirs and not local_dirs:
+ # Don't push the skill on pre-release / dev versions (same rule as the
PyPI update check).
+ if any(tag in __version__ for tag in ["rc", "dev"]):
+ return
+ out.hint(
+ f"The `{DEFAULT_SKILL_ID}` skill is not installed. Run `hf skills
add -g --claude`"
+ " to teach your AI agents how to use the `hf` CLI."
+ )
+ return
+
+ # Suggest the command matching where the outdated skill is installed
(global takes precedence).
+ if any(_is_skill_outdated(skill_dir) for skill_dir in global_dirs):
+ scope = "-g --claude"
+ elif any(_is_skill_outdated(skill_dir) for skill_dir in local_dirs):
+ scope = "--claude"
+ else:
+ return
+ out.hint(
+ f"The installed `{DEFAULT_SKILL_ID}` skill was generated by another
`hf` version."
+ f" Run `hf skills update {DEFAULT_SKILL_ID} {scope}` to refresh it."
+ )
+
+
+def _installed_hf_cli_dirs(*roots: Path) -> list[Path]:
+ dirs = [(root.expanduser() / DEFAULT_SKILL_ID).resolve() for root in roots]
+ return [skill_dir for skill_dir in dict.fromkeys(dirs) if
skill_dir.is_dir()]
+
+
+def _is_skill_outdated(skill_dir: Path) -> bool:
+ """Whether the installed `hf-cli` SKILL.md was generated by another `hf`
version."""
+ try:
+ content = (skill_dir / "SKILL.md").read_text(encoding="utf-8")
+ except OSError:
+ return False
+ match = _GENERATED_VERSION_RE.search(content)
+ return match is None or match.group(1) != __version__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/huggingface_hub-1.26.0/src/huggingface_hub/cli/hf.py
new/huggingface_hub-1.27.0/src/huggingface_hub/cli/hf.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/cli/hf.py 2026-07-30
16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/cli/hf.py 2026-08-07
14:47:34.000000000 +0200
@@ -24,6 +24,7 @@
from huggingface_hub.cli._cp import CP_EXAMPLES, make_cp
from huggingface_hub.cli._errors import format_known_exception
from huggingface_hub.cli._output import out
+from huggingface_hub.cli._skills import check_skill_update
from huggingface_hub.cli.auth import auth_cli
from huggingface_hub.cli.buckets import buckets_cli, sync
from huggingface_hub.cli.cache import cache_cli
@@ -123,6 +124,10 @@
if not constants.HF_DEBUG:
logging.set_verbosity_info()
check_cli_update("huggingface_hub")
+ # Don't nag while the user is already managing skills, nor on `hf
update` which handles the
+ # skill itself (it would print a redundant or contradictory hint
before doing so).
+ if sys.argv[1:2] not in (["skills"], ["update"]):
+ check_skill_update()
try:
app()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/cli/inference_endpoints.py
new/huggingface_hub-1.27.0/src/huggingface_hub/cli/inference_endpoints.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/cli/inference_endpoints.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/cli/inference_endpoints.py
2026-08-07 14:47:34.000000000 +0200
@@ -191,7 +191,7 @@
"--container-command",
help=(
"Override the container entrypoint, as a quoted string split
into tokens "
- '(e.g. "python -m sglang.launch_server"). Requires
--custom-image.'
+ '(e.g. "python -m sglang.launch_server").'
),
),
] = None,
@@ -201,7 +201,7 @@
"--container-args",
help=(
"Arguments appended to the container entrypoint, as a quoted
string split into tokens "
- '(e.g. "--tp 8 --reasoning-parser qwen3"). Requires
--custom-image.'
+ '(e.g. "--tp 8 --reasoning-parser qwen3").'
),
),
] = None,
@@ -219,9 +219,11 @@
] = None,
) -> None:
"""Deploy an Inference Endpoint from a Hub repository."""
- # Custom-container knobs only make sense alongside a custom image.
- if custom_image is None and (health_route is not None or port is not None
or container_command or container_args):
- raise CLIError("--health-route, --port, --container-command and
--container-args require --custom-image.")
+ # --health-route and --port are container-level fields, and the only
container payload this
+ # command can build is the custom one, so they need --custom-image.
Container command/args are
+ # top-level model fields and apply to managed engine images too, so they
are not gated.
+ if custom_image is None and (health_route is not None or port is not None):
+ raise CLIError("--health-route and --port require --custom-image.")
custom_image_dict: dict | None = None
if custom_image is not None:
custom_image_dict = {"url": custom_image}
@@ -346,7 +348,12 @@
out.dict(endpoint.raw)
-@ie_cli.command(examples=["hf endpoints update my-endpoint --min-replica 2"])
+@ie_cli.command(
+ examples=[
+ "hf endpoints update my-endpoint --min-replica 2",
+ 'hf endpoints update my-endpoint --container-args
"--enable-auto-tool-choice --tool-call-parser lfm2"',
+ ]
+)
def update(
name: NameArg,
namespace: NamespaceOpt = None,
@@ -392,6 +399,29 @@
help="The task on which to deploy the model (e.g.
'text-classification').",
),
] = None,
+ container_command: Annotated[
+ str | None,
+ Option(
+ "--container-command",
+ help=(
+ "Override the container entrypoint, as a quoted string split
into tokens "
+ '(e.g. "python -m sglang.launch_server"). Replaces the current
value; '
+ "pass an empty string to clear it."
+ ),
+ ),
+ ] = None,
+ container_args: Annotated[
+ str | None,
+ Option(
+ "--container-args",
+ help=(
+ "Arguments appended to the container entrypoint, as a quoted
string split into tokens "
+ '(e.g. "--enable-auto-tool-choice --tool-call-parser lfm2").
Replaces the arguments currently '
+ "set on the endpoint rather than adding to them, so include
the ones you want to keep, run "
+ "'hf endpoints describe NAME' first to see them. Pass an empty
string to clear them."
+ ),
+ ),
+ ] = None,
min_replica: Annotated[
int | None,
Option(
@@ -434,6 +464,8 @@
framework=framework,
revision=revision,
task=task,
+ container_command=shlex.split(container_command) if
container_command is not None else None,
+ container_args=shlex.split(container_args) if container_args is
not None else None,
accelerator=accelerator,
instance_size=instance_size,
instance_type=instance_type,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/cli/skills.py
new/huggingface_hub-1.27.0/src/huggingface_hub/cli/skills.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/cli/skills.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/cli/skills.py
2026-08-07 14:47:34.000000000 +0200
@@ -20,6 +20,7 @@
from click import Command, Context, Group
+from huggingface_hub import constants
from huggingface_hub.errors import CLIError
from ..utils import disable_progress_bars
@@ -86,10 +87,6 @@
- Update the CLI with `hf update` (uses the correct command for the detected
install method)
"""
-CENTRAL_LOCAL = Path(".agents/skills")
-CENTRAL_GLOBAL = Path("~/.agents/skills")
-CLAUDE_LOCAL = Path(".claude/skills")
-CLAUDE_GLOBAL = Path("~/.claude/skills")
# Flags worth explaining in the common-options glossary. Self-explanatory flags
# (--namespace, --yes, --private, …) are omitted even if they appear
frequently.
_COMMON_FLAG_ALLOWLIST = {"--token", "--quiet", "--type", "--format",
"--revision"}
@@ -334,7 +331,12 @@
link_path = agent_skills_dir / skill_name
_remove_existing(link_path, force)
- link_path.symlink_to(os.path.relpath(central_skill_path, agent_skills_dir))
+ try:
+ link_path.symlink_to(os.path.relpath(central_skill_path,
agent_skills_dir))
+ except OSError:
+ # Windows needs Developer Mode or admin rights for symlinks.
+ # Fall back to a copy: `hf skills update` walks both roots, so the
copy stays in sync.
+ shutil.copytree(central_skill_path, link_path)
return link_path
@@ -350,9 +352,9 @@
raise CLIError("--dest cannot be combined with --claude or
--global.")
return [dest.expanduser().resolve()]
- roots: list[Path] = [CENTRAL_GLOBAL if global_ else CENTRAL_LOCAL]
+ roots: list[Path] = [constants.AGENTS_SKILLS_GLOBAL_PATH if global_ else
constants.AGENTS_SKILLS_LOCAL_PATH]
if claude:
- roots.append(CLAUDE_GLOBAL if global_ else CLAUDE_LOCAL)
+ roots.append(constants.CLAUDE_SKILLS_GLOBAL_PATH if global_ else
constants.CLAUDE_SKILLS_LOCAL_PATH)
return [root.expanduser().resolve() for root in roots]
@@ -374,10 +376,10 @@
) -> None:
"""List available skills from the Hugging Face marketplace."""
install_locations: list[tuple[str, Path]] = [
- ("project", CENTRAL_LOCAL),
- ("project (claude)", CLAUDE_LOCAL),
- ("global", CENTRAL_GLOBAL),
- ("global (claude)", CLAUDE_GLOBAL),
+ ("project", constants.AGENTS_SKILLS_LOCAL_PATH),
+ ("project (claude)", constants.CLAUDE_SKILLS_LOCAL_PATH),
+ ("global", constants.AGENTS_SKILLS_GLOBAL_PATH),
+ ("global (claude)", constants.CLAUDE_SKILLS_GLOBAL_PATH),
]
installed: dict[str, set[str]] = {}
for label, root in install_locations:
@@ -458,14 +460,14 @@
return
# Install to central location
- central_path = CENTRAL_GLOBAL if global_ else CENTRAL_LOCAL
+ central_path = constants.AGENTS_SKILLS_GLOBAL_PATH if global_ else
constants.AGENTS_SKILLS_LOCAL_PATH
central_skill_path = _install_to(central_path, name, force)
print(f"Installed '{name}' to central location: {central_skill_path}")
if claude:
- agent_target = CLAUDE_GLOBAL if global_ else CLAUDE_LOCAL
+ agent_target = constants.CLAUDE_SKILLS_GLOBAL_PATH if global_ else
constants.CLAUDE_SKILLS_LOCAL_PATH
link_path = _create_symlink(agent_target, name, central_skill_path,
force)
- print(f"Created symlink: {link_path}")
+ print(f"Created symlink: {link_path}" if link_path.is_symlink() else
f"Copied '{name}' to {link_path}")
@skills_cli.command(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/cli/system.py
new/huggingface_hub-1.27.0/src/huggingface_hub/cli/system.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/cli/system.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/cli/system.py
2026-08-07 14:47:34.000000000 +0200
@@ -13,13 +13,18 @@
# limitations under the License.
"""Contains commands to print information about the environment and version."""
+import shutil
+import subprocess
+import sys
+
import click
-from huggingface_hub import __version__
+from huggingface_hub import __version__, constants
-from ..utils import dump_environment_info
+from ..utils import dump_environment_info, installation_method
from ._cli_utils import _fetch_latest_pypi_version, run_update
from ._output import out
+from ._skills import DEFAULT_SKILL_ID, _installed_hf_cli_dirs
def env() -> None:
@@ -41,10 +46,33 @@
out.text(f"hf is up to date ({__version__})")
return
- returncode = run_update()
+ # The standalone installer installs the `hf-cli` skill by default. If it's
not installed at this
+ # point, the user opted out (or removed it): tell the installer to leave
it alone instead of
+ # silently undoing that choice.
+ skill_installed = bool(
+ _installed_hf_cli_dirs(constants.AGENTS_SKILLS_GLOBAL_PATH,
constants.CLAUDE_SKILLS_GLOBAL_PATH)
+ )
+
+ returncode = run_update(exclude_skill=not skill_installed)
if returncode != 0:
raise click.exceptions.Exit(code=returncode)
- out.hint(
- "You may also want to run `hf skills update` to refresh any installed
skills "
- "so your AI agent sees the latest command surface."
- )
+
+ if not skill_installed:
+ out.hint("Run `hf skills add -g --claude` to teach your AI agents how
to use the `hf` CLI.")
+ return
+
+ # Refresh the globally installed skill so agents see the new command
surface. Runs in a
+ # subprocess: the skill is generated from the CLI code, which has just
been replaced on disk
+ # while this process still runs the previous version.
+ out.text(f"Updating the `{DEFAULT_SKILL_ID}` skill...")
+ subprocess.call([*_hf_argv(), "skills", "update", DEFAULT_SKILL_ID, "-g",
"--claude"])
+
+
+def _hf_argv() -> list[str]:
+ """argv prefix to invoke the freshly updated `hf` CLI."""
+ if installation_method() == "brew":
+ # Homebrew installs the new version in a new prefix: the current
interpreter is the old one.
+ hf_bin = shutil.which("hf")
+ if hf_bin is not None:
+ return [hf_bin]
+ return [sys.executable, "-m", "huggingface_hub.cli.hf"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/constants.py
new/huggingface_hub-1.27.0/src/huggingface_hub/constants.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/constants.py 2026-07-30
16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/constants.py 2026-08-07
14:47:34.000000000 +0200
@@ -1,6 +1,7 @@
import os
import re
import typing
+from pathlib import Path
from typing import Literal
from urllib.parse import urlsplit
@@ -225,10 +226,21 @@
# Check is performed once per 24 hours at most.
CHECK_FOR_UPDATE_DONE_PATH = os.path.join(HF_HOME, ".check_for_update_done")
+# File created to mark that the `hf-cli` skill check has been done.
+# Check is performed once per 24 hours at most.
+CHECK_FOR_SKILL_UPDATE_DONE_PATH = os.path.join(HF_HOME,
".check_for_skill_update_done")
+
# File caching the AI agent harnesses registry fetched from
`{ENDPOINT}/api/agent-harnesses`.
# Refreshed once per 24 hours at most (see `utils/_detect_agent.py`).
AGENT_HARNESSES_PATH = os.path.join(HF_HOME, ".agent_harnesses.json")
+# Skills directories for AI agents: `.agents/skills` is read by most agents,
`.claude/skills` by Claude Code.
+# Local = current project, global = user-level (see `hf skills add`).
+AGENTS_SKILLS_LOCAL_PATH = Path(".agents/skills")
+AGENTS_SKILLS_GLOBAL_PATH = Path("~/.agents/skills")
+CLAUDE_SKILLS_LOCAL_PATH = Path(".claude/skills")
+CLAUDE_SKILLS_GLOBAL_PATH = Path("~/.claude/skills")
+
# Set to skip the CLI update check (PyPI query + "new version available"
warning at startup).
HF_HUB_DISABLE_UPDATE_CHECK =
_is_true(os.environ.get("HF_HUB_DISABLE_UPDATE_CHECK"))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/file_download.py
new/huggingface_hub-1.27.0/src/huggingface_hub/file_download.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/file_download.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/file_download.py
2026-08-07 14:47:34.000000000 +0200
@@ -1799,9 +1799,37 @@
if not (local_files_only or etag is not None or head_error_call is not
None):
raise RuntimeError("etag is empty due to uncovered problems")
+ if head_error_call is not None:
+ _detach_tracebacks(head_error_call)
+
return (url_to_download, etag, commit_hash, expected_size, xet_file_data,
head_error_call) # type: ignore
+def _detach_tracebacks(error: BaseException) -> None:
+ """Detach the tracebacks of an exception and of its whole
`__cause__`/`__context__` chain.
+
+ Returning an exception instead of raising it means keeping its traceback
alive. A traceback references the frames
+ it was raised from, and each frame references its caller (up to the user
code calling `hf_hub_download`) and its
+ own local variables - including the returned exception itself. This
creates a reference cycle that only the cyclic
+ garbage collector can break, so callers falling back to a cached file
(i.e. discarding the error) keep their own
+ stack - and everything it references - alive until the next `gc.collect()`.
+
+ Only the frames are dropped: exception types, messages and the
cause/context chain are preserved, so re-raising a
+ detached error still reports what went wrong.
+
+ See https://github.com/vllm-project/vllm/pull/50341 for a real-world
report of this retention.
+ """
+ seen: set[int] = set()
+ pending = [error]
+ while pending:
+ current = pending.pop()
+ if id(current) in seen: # defensive: exception chains can be cyclic
+ continue
+ seen.add(id(current))
+ current.__traceback__ = None
+ pending.extend(exc for exc in (current.__cause__, current.__context__)
if exc is not None)
+
+
def _xet_file_metadata_from_tree_cache(
*,
tree_cache_folder: str,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/huggingface_hub-1.26.0/src/huggingface_hub/hf_api.py
new/huggingface_hub-1.27.0/src/huggingface_hub/hf_api.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/hf_api.py 2026-07-30
16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/hf_api.py 2026-08-07
14:47:34.000000000 +0200
@@ -239,6 +239,7 @@
"likes",
"models",
"private",
+ "region",
"resourceGroup",
"runtime",
"sdk",
@@ -1289,6 +1290,8 @@
List of models used by the Space.
private (`bool`):
Is the repo private.
+ region (`Literal["us", "eu"]`, *optional*):
+ Cloud region in which the Space is stored.
resource_group (`dict`, *optional*):
Resource group information for the Space.
runtime (`SpaceRuntime`, *optional*):
@@ -1321,6 +1324,7 @@
likes: int | None
models: list[str] | None
private: bool | None
+ region: REPO_REGIONS | None
resource_group: dict | None
runtime: SpaceRuntime | None
sdk: str | None
@@ -1379,6 +1383,7 @@
self.runtime = SpaceRuntime(runtime) if runtime else None
self.models = kwargs.pop("models", None)
self.datasets = kwargs.pop("datasets", None)
+ self.region = kwargs.pop("region", None)
self.resource_group = kwargs.pop("resourceGroup", None)
# backwards compatibility
self.lastModified = self.last_modified
@@ -2925,7 +2930,7 @@
expand (`list[ExpandSpaceProperty_T]`, *optional*):
List properties to return in the response. When used, only the
properties in the list will be returned.
This parameter cannot be used if `full` is passed.
- Possible values are `"author"`, `"cardData"`, `"datasets"`,
`"disabled"`, `"lastModified"`, `"createdAt"`, `"likes"`, `"models"`,
`"private"`, `"runtime"`, `"sdk"`, `"siblings"`, `"sha"`, `"subdomain"`,
`"tags"`, `"trendingScore"`, `"usedStorage"`, and `"resourceGroup"`.
+ Possible values are `"author"`, `"cardData"`, `"datasets"`,
`"disabled"`, `"lastModified"`, `"createdAt"`, `"likes"`, `"models"`,
`"private"`, `"region"`, `"runtime"`, `"sdk"`, `"siblings"`, `"sha"`,
`"subdomain"`, `"tags"`, `"trendingScore"`, `"usedStorage"`, and
`"resourceGroup"`.
full (`bool`, *optional*):
Whether to fetch all Spaces data, including the
`last_modified`, `siblings`
and `card_data` fields.
@@ -3495,7 +3500,7 @@
expand (`list[ExpandSpaceProperty_T]`, *optional*):
List properties to return in the response. When used, only the
properties in the list will be returned.
This parameter cannot be used if `full` is passed.
- Possible values are `"author"`, `"cardData"`, `"createdAt"`,
`"datasets"`, `"disabled"`, `"lastModified"`, `"likes"`, `"models"`,
`"private"`, `"runtime"`, `"sdk"`, `"siblings"`, `"sha"`, `"subdomain"`,
`"tags"`, `"trendingScore"`, `"usedStorage"`, and `"resourceGroup"`.
+ Possible values are `"author"`, `"cardData"`, `"createdAt"`,
`"datasets"`, `"disabled"`, `"lastModified"`, `"likes"`, `"models"`,
`"private"`, `"region"`, `"runtime"`, `"sdk"`, `"siblings"`, `"sha"`,
`"subdomain"`, `"tags"`, `"trendingScore"`, `"usedStorage"`, and
`"resourceGroup"`.
token (`bool` or `str`, *optional*):
A valid user access token (string). Defaults to the locally
saved
token, which is the recommended method for authentication (see
@@ -9411,11 +9416,11 @@
Inference Endpoint running on the `text-generation-inference`
(TGI) framework or a custom container
(see examples).
container_command (`list[str]`, *optional*):
- Override the container entrypoint command (maps to
`model.command` in the API payload). Typically
- used together with `custom_image`.
+ Override the container entrypoint command (maps to
`model.command` in the API payload). Works with
+ both managed engine images (e.g. vLLM, SGLang) and custom
images.
container_args (`list[str]`, *optional*):
- Arguments appended to the container entrypoint (maps to
`model.args` in the API payload). Typically
- used together with `custom_image` to pass runtime flags to the
container.
+ Arguments appended to the container entrypoint (maps to
`model.args` in the API payload). Works with
+ both managed engine images (e.g. vLLM, SGLang) and custom
images.
env (`dict[str, str]`, *optional*):
Non-secret environment variables to inject in the container
environment.
secrets (`dict[str, str]`, *optional*):
@@ -9755,6 +9760,8 @@
revision: str | None = None,
task: str | None = None,
custom_image: dict | None = None,
+ container_command: list[str] | None = None,
+ container_args: list[str] | None = None,
env: dict[str, str] | None = None,
secrets: dict[str, str] | None = None,
# Route update
@@ -9806,6 +9813,12 @@
custom_image (`dict`, *optional*):
A custom Docker image to use for the Inference Endpoint. This
is useful if you want to deploy an
Inference Endpoint running on the `text-generation-inference`
(TGI) framework (see examples).
+ container_command (`list[str]`, *optional*):
+ Override the container entrypoint command (maps to
`model.command` in the API payload). Works with
+ both managed engine images (e.g. vLLM, SGLang) and custom
images.
+ container_args (`list[str]`, *optional*):
+ Arguments appended to the container entrypoint (maps to
`model.args` in the API payload). Works with
+ both managed engine images (e.g. vLLM, SGLang) and custom
images.
env (`dict[str, str]`, *optional*):
Non-secret environment variables to inject in the container
environment
secrets (`dict[str, str]`, *optional*):
@@ -9860,6 +9873,10 @@
payload["model"]["task"] = task
if custom_image is not None:
payload["model"]["image"] = {"custom": custom_image}
+ if container_command is not None:
+ payload["model"]["command"] = container_command
+ if container_args is not None:
+ payload["model"]["args"] = container_args
if env is not None:
payload["model"]["env"] = env
if secrets is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/hf_file_system.py
new/huggingface_hub-1.27.0/src/huggingface_hub/hf_file_system.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/hf_file_system.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/hf_file_system.py
2026-08-07 14:47:34.000000000 +0200
@@ -663,6 +663,11 @@
out: list[BucketFile | BucketFolder] = []
for bucket_entry in bucket_files:
+ # The server matches `prefix` lexically, so listing "logs" also
returns "logs_existing/...".
+ # Filesystem semantics require path components => drop entries
that aren't `prefix` itself
+ # or below it.
+ if prefix and bucket_entry.path != prefix and not
bucket_entry.path.startswith(f"{prefix}/"):
+ continue
out.append(bucket_entry)
# If recursive=False, both files and folders are returned by the
server => nothing to do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_client.py
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_client.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_client.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_client.py
2026-08-07 14:47:34.000000000 +0200
@@ -135,7 +135,7 @@
Note: for better compatibility with OpenAI's client, `model` has
been aliased as `base_url`. Those 2
arguments are mutually exclusive. If a URL is passed as `model` or
`base_url` for chat completion, the `(/v1)/chat/completions` suffix path will
be appended to the URL.
provider (`str`, *optional*):
- Name of the provider to use for inference. Can be `"cerebras"`,
`"cohere"`, `"deepinfra"`, `"fal-ai"`, `"featherless-ai"`, `"fireworks-ai"`,
`"groq"`, `"hf-inference"`, `"novita"`, `"nscale"`, `"openai"`, `"ovhcloud"`,
`"publicai"`, `"replicate"`, `"scaleway"`, `"together"`, `"wavespeed"` or
`"zai-org"`.
+ Name of the provider to use for inference. Can be `"baseten"`,
`"cerebras"`, `"cohere"`, `"deepinfra"`, `"fal-ai"`, `"featherless-ai"`,
`"fireworks-ai"`, `"groq"`, `"hf-inference"`, `"novita"`, `"nscale"`,
`"openai"`, `"ovhcloud"`, `"publicai"`, `"replicate"`, `"scaleway"`,
`"together"`, `"wavespeed"` or `"zai-org"`.
Defaults to "auto": automatic routing, which defaults to "fastest"
provider; you can
switch to "cheapest" or "preferred" provider order at
https://hf.co/settings/inference-providers.
If model is a URL or `base_url` is passed, then `provider` is not
used.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_generated/_async_client.py
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_generated/_async_client.py
---
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_generated/_async_client.py
2026-07-30 16:11:39.000000000 +0200
+++
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_generated/_async_client.py
2026-08-07 14:47:34.000000000 +0200
@@ -125,7 +125,7 @@
Note: for better compatibility with OpenAI's client, `model` has
been aliased as `base_url`. Those 2
arguments are mutually exclusive. If a URL is passed as `model` or
`base_url` for chat completion, the `(/v1)/chat/completions` suffix path will
be appended to the URL.
provider (`str`, *optional*):
- Name of the provider to use for inference. Can be `"cerebras"`,
`"cohere"`, `"deepinfra"`, `"fal-ai"`, `"featherless-ai"`, `"fireworks-ai"`,
`"groq"`, `"hf-inference"`, `"novita"`, `"nscale"`, `"openai"`, `"ovhcloud"`,
`"publicai"`, `"replicate"`, `"scaleway"`, `"together"`, `"wavespeed"` or
`"zai-org"`.
+ Name of the provider to use for inference. Can be `"baseten"`,
`"cerebras"`, `"cohere"`, `"deepinfra"`, `"fal-ai"`, `"featherless-ai"`,
`"fireworks-ai"`, `"groq"`, `"hf-inference"`, `"novita"`, `"nscale"`,
`"openai"`, `"ovhcloud"`, `"publicai"`, `"replicate"`, `"scaleway"`,
`"together"`, `"wavespeed"` or `"zai-org"`.
Defaults to "auto": automatic routing, which defaults to "fastest"
provider; you can
switch to "cheapest" or "preferred" provider order at
https://hf.co/settings/inference-providers.
If model is a URL or `base_url` is passed, then `provider` is not
used.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_providers/__init__.py
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_providers/__init__.py
---
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_providers/__init__.py
2026-07-30 16:11:39.000000000 +0200
+++
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_providers/__init__.py
2026-08-07 14:47:34.000000000 +0200
@@ -7,6 +7,7 @@
from huggingface_hub.utils import logging
from ._common import AutoRouterConversationalTask, TaskProviderHelper,
_fetch_inference_provider_mapping
+from .baseten import BasetenConversationalTask
from .cerebras import CerebrasConversationalTask
from .cohere import CohereConversationalTask
from .deepinfra import (
@@ -67,6 +68,7 @@
PROVIDER_T = Literal[
+ "baseten",
"cerebras",
"cohere",
"deepinfra",
@@ -92,6 +94,9 @@
CONVERSATIONAL_AUTO_ROUTER = AutoRouterConversationalTask()
PROVIDERS: dict[PROVIDER_T, dict[str, TaskProviderHelper]] = {
+ "baseten": {
+ "conversational": BasetenConversationalTask(),
+ },
"cerebras": {
"conversational": CerebrasConversationalTask(),
},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_providers/_common.py
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_providers/_common.py
---
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_providers/_common.py
2026-07-30 16:11:39.000000000 +0200
+++
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_providers/_common.py
2026-08-07 14:47:34.000000000 +0200
@@ -275,7 +275,18 @@
parameters: dict,
provider_mapping_info: InferenceProviderMapping,
) -> dict | None:
- return filter_none({"messages": inputs, **parameters, "model":
provider_mapping_info.provider_id})
+ # `model` is serialized first so that a router/proxy can resolve the
target provider from a
+ # small prefix of the request body instead of buffering the whole
payload — `messages` can
+ # hold megabytes of base64-encoded images.
+ # `parameters` also carries a caller-supplied "model" (see
`InferenceClient.chat_completion`),
+ # which must not take precedence over the provider-mapped id: drop it
from the spread.
+ return filter_none(
+ {
+ "model": provider_mapping_info.provider_id,
+ "messages": inputs,
+ **{key: value for key, value in parameters.items() if key !=
"model"},
+ }
+ )
class AutoRouterConversationalTask(BaseConversationalTask):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_providers/baseten.py
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_providers/baseten.py
---
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_providers/baseten.py
1970-01-01 01:00:00.000000000 +0100
+++
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_providers/baseten.py
2026-08-07 14:47:34.000000000 +0200
@@ -0,0 +1,6 @@
+from ._common import BaseConversationalTask
+
+
+class BasetenConversationalTask(BaseConversationalTask):
+ def __init__(self):
+ super().__init__(provider="baseten",
base_url="https://inference.baseten.co")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_providers/hf_inference.py
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_providers/hf_inference.py
---
old/huggingface_hub-1.26.0/src/huggingface_hub/inference/_providers/hf_inference.py
2026-07-30 16:11:39.000000000 +0200
+++
new/huggingface_hub-1.27.0/src/huggingface_hub/inference/_providers/hf_inference.py
2026-08-07 14:47:34.000000000 +0200
@@ -121,7 +121,14 @@
"type": "json_object",
"value": response_format["json_schema"]["schema"],
}
- return {**payload, "model": payload_model, "messages": inputs}
+ # Same ordering rationale as `BaseConversationalTask`: `model` first
so it can be read from a
+ # small prefix of the body, and dropped from the `payload` spread so
the already-resolved
+ # `payload_model` wins.
+ return {
+ "model": payload_model,
+ "messages": inputs,
+ **{key: value for key, value in payload.items() if key != "model"},
+ }
def _prepare_url(self, api_key: str, mapped_model: str) -> str:
base_url = (
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/utils/_cache_manager.py
new/huggingface_hub-1.27.0/src/huggingface_hub/utils/_cache_manager.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/utils/_cache_manager.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/utils/_cache_manager.py
2026-08-07 14:47:34.000000000 +0200
@@ -466,6 +466,15 @@
# Blobs dir
for file in revision_to_delete.files:
+ # Some files are not symlinks to the blobs dir: files
copied instead of symlinked
+ # (Windows, filesystems without symlink support) or files
created by the user
+ # inside the snapshot dir (e.g. build artifacts from a
`pip install`). They are
+ # already removed when deleting the snapshot dir -> count
them but don't delete
+ # them a second time.
+ if revision_to_delete.snapshot_path in
file.blob_path.parents:
+ delete_strategy_expected_freed_size +=
file.size_on_disk
+ continue
+
if file.blob_path not in delete_strategy_blobs:
is_file_alone = True
for revision in other_revisions:
@@ -878,13 +887,15 @@
path_type (`str`)
What path are we deleting ? Only for logging purposes. Example:
"snapshot".
"""
- logger.info(f"Delete {path_type}: {path}")
+ logger.debug(f"Delete {path_type}: {path}")
try:
if path.is_file():
os.remove(path)
else:
shutil.rmtree(path)
except FileNotFoundError:
- logger.warning(f"Couldn't delete {path_type}: file not found
({path})", exc_info=True)
+ # Nothing to delete: the path is already gone. Log without traceback
to avoid flooding the
+ # terminal when deleting many paths at once.
+ logger.warning(f"Couldn't delete {path_type}: file not found ({path})")
except PermissionError:
logger.warning(f"Couldn't delete {path_type}: permission denied
({path})", exc_info=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub/utils/_http.py
new/huggingface_hub-1.27.0/src/huggingface_hub/utils/_http.py
--- old/huggingface_hub-1.26.0/src/huggingface_hub/utils/_http.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub/utils/_http.py
2026-08-07 14:47:34.000000000 +0200
@@ -458,10 +458,12 @@
if "data" in kwargs and isinstance(kwargs["data"], (io.IOBase,
SliceFileObj)):
io_obj_initial_pos = kwargs["data"].tell()
- client = get_session()
while True:
nb_tries += 1
ratelimit_reset = None
+ # Fetched on each attempt: a previous attempt may have closed the
shared client (see `close_session` below),
+ # and closed `httpx.Client` objects cannot be reused.
+ client = get_session()
try:
# If `data` is used and is a file object (or any IO), set back
cursor to
# initial position.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub.egg-info/PKG-INFO
new/huggingface_hub-1.27.0/src/huggingface_hub.egg-info/PKG-INFO
--- old/huggingface_hub-1.26.0/src/huggingface_hub.egg-info/PKG-INFO
2026-07-30 16:11:46.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub.egg-info/PKG-INFO
2026-08-07 14:47:40.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: huggingface_hub
-Version: 1.26.0
+Version: 1.27.0
Summary: Client library to download and publish models, datasets and other
repos on the huggingface.co hub
Home-page: https://github.com/huggingface/huggingface_hub
Author: Hugging Face, Inc.
@@ -26,7 +26,7 @@
Requires-Dist: click<9.0.0,>=8.4.2
Requires-Dist: filelock>=3.10.0
Requires-Dist: fsspec>=2023.5.0
-Requires-Dist: hf-xet<2.0.0,>=1.5.1; platform_machine == "x86_64" or
platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine
== "arm64" or platform_machine == "aarch64"
+Requires-Dist: hf-xet<2.0.0,>=1.5.2; platform_machine == "x86_64" or
platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine
== "arm64" or platform_machine == "aarch64"
Requires-Dist: httpx<1,>=0.23.0
Requires-Dist: packaging>=20.9
Requires-Dist: pyyaml>=5.1
@@ -45,7 +45,7 @@
Requires-Dist: fastai>=2.4; extra == "fastai"
Requires-Dist: fastcore>=1.3.27; extra == "fastai"
Provides-Extra: hf-xet
-Requires-Dist: hf-xet<2.0.0,>=1.5.1; extra == "hf-xet"
+Requires-Dist: hf-xet<2.0.0,>=1.5.2; extra == "hf-xet"
Provides-Extra: mcp
Requires-Dist: mcp>=1.8.0; extra == "mcp"
Provides-Extra: testing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub.egg-info/SOURCES.txt
new/huggingface_hub-1.27.0/src/huggingface_hub.egg-info/SOURCES.txt
--- old/huggingface_hub-1.26.0/src/huggingface_hub.egg-info/SOURCES.txt
2026-07-30 16:11:46.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub.egg-info/SOURCES.txt
2026-08-07 14:47:40.000000000 +0200
@@ -135,6 +135,7 @@
src/huggingface_hub/inference/_mcp/utils.py
src/huggingface_hub/inference/_providers/__init__.py
src/huggingface_hub/inference/_providers/_common.py
+src/huggingface_hub/inference/_providers/baseten.py
src/huggingface_hub/inference/_providers/cerebras.py
src/huggingface_hub/inference/_providers/cohere.py
src/huggingface_hub/inference/_providers/deepinfra.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/src/huggingface_hub.egg-info/requires.txt
new/huggingface_hub-1.27.0/src/huggingface_hub.egg-info/requires.txt
--- old/huggingface_hub-1.26.0/src/huggingface_hub.egg-info/requires.txt
2026-07-30 16:11:46.000000000 +0200
+++ new/huggingface_hub-1.27.0/src/huggingface_hub.egg-info/requires.txt
2026-08-07 14:47:40.000000000 +0200
@@ -8,7 +8,7 @@
typing-extensions>=4.1.0
[:platform_machine == "x86_64" or platform_machine == "amd64" or
platform_machine == "AMD64" or platform_machine == "arm64" or platform_machine
== "aarch64"]
-hf-xet<2.0.0,>=1.5.1
+hf-xet<2.0.0,>=1.5.2
[all]
authlib>=1.3.2
@@ -82,7 +82,7 @@
requests
[hf_xet]
-hf-xet<2.0.0,>=1.5.1
+hf-xet<2.0.0,>=1.5.2
[mcp]
mcp>=1.8.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/tests/test_buckets_hf_file_system.py
new/huggingface_hub-1.27.0/tests/test_buckets_hf_file_system.py
--- old/huggingface_hub-1.26.0/tests/test_buckets_hf_file_system.py
2026-07-30 16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/tests/test_buckets_hf_file_system.py
2026-08-07 14:47:34.000000000 +0200
@@ -45,6 +45,14 @@
def _new_hffs(self):
self.hffs = HfFileSystem(endpoint=ENDPOINT_STAGING, token=TOKEN,
skip_instance_cache=True)
+ def test_prefix_collision(self):
+ colliding_path = f"{self.hf_path}/dat"
+
+ assert not self.hffs.exists(f"{colliding_path}/new.txt")
+ assert self.hffs.glob(f"{colliding_path}/*") == []
+ with pytest.raises(FileNotFoundError):
+ self.hffs.ls(colliding_path)
+
class TestHfFileSystemBucketRW(_HfFileSystemBucketChecks,
_HfFileSystemBaseRWTests):
__test__ = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/tests/test_cache_no_symlinks.py
new/huggingface_hub-1.27.0/tests/test_cache_no_symlinks.py
--- old/huggingface_hub-1.26.0/tests/test_cache_no_symlinks.py 2026-07-30
16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/tests/test_cache_no_symlinks.py 2026-08-07
14:47:34.000000000 +0200
@@ -189,8 +189,16 @@
# Test delete older revision strategy
strategy_delete_revision = report.delete_revisions(OLDER_REVISION)
- assert strategy_delete_revision.blobs == {file.blob_path for file in
older_revision.files}
+ # Only the file in the blobs dir is deleted explicitly. The one in the
snapshot dir is
+ # removed along with the snapshot dir itself (but its size is still
counted).
+ assert strategy_delete_revision.blobs == {
+ file.blob_path
+ for file in older_revision.files
+ if older_revision.snapshot_path not in file.blob_path.parents
+ }
+ assert strategy_delete_revision.expected_freed_size ==
older_revision.size_on_disk
assert strategy_delete_revision.snapshots ==
{older_revision.snapshot_path}
assert len(strategy_delete_revision.refs) == 0
assert len(strategy_delete_revision.repos) == 0
strategy_delete_revision.execute() # Execute without error
+ assert not older_revision.snapshot_path.exists()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/huggingface_hub-1.26.0/tests/test_cli.py
new/huggingface_hub-1.27.0/tests/test_cli.py
--- old/huggingface_hub-1.26.0/tests/test_cli.py 2026-07-30
16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/tests/test_cli.py 2026-08-07
14:47:34.000000000 +0200
@@ -1,5 +1,6 @@
import json
import os
+import sys
import warnings
from contextlib import contextmanager
from pathlib import Path
@@ -11,15 +12,17 @@
import pytest
from click.testing import CliRunner
-from huggingface_hub import HfApi
+from huggingface_hub import HfApi, constants
from huggingface_hub._dataset_viewer import DatasetParquetEntry
from huggingface_hub._jobs_api import JobInfo, JobOwner, _create_job_spec,
_derive_job_volume_name
from huggingface_hub._space_api import Volume
-from huggingface_hub.cli._cli_utils import RepoType, parse_volumes
+from huggingface_hub.cli import _skills, system
+from huggingface_hub.cli._cli_utils import RepoType,
_get_huggingface_hub_update_command, parse_volumes
from huggingface_hub.cli._output import OutputFormat, out
from huggingface_hub.cli.cache import CacheDeletionCounts
from huggingface_hub.cli.download import download
from huggingface_hub.cli.hf import app
+from huggingface_hub.cli.hf import main as hf_main
from huggingface_hub.cli.jobs import _parse_and_sync_job_volumes,
_parse_namespace_from_job_id
from huggingface_hub.cli.skills import build_skill_md
from huggingface_hub.cli.upload import _resolve_upload_paths, upload
@@ -2629,8 +2632,11 @@
assert kwargs["env"] == {"MODEL_ID": "/repository"}
assert kwargs["type"] == "authenticated"
- def test_deploy_custom_args_require_image(self, runner: CliRunner) -> None:
+ def test_deploy_container_args_without_custom_image(self, runner:
CliRunner) -> None:
+ endpoint = Mock(raw={"name": "hub-args"})
with patch("huggingface_hub.cli.inference_endpoints.get_hf_api") as
api_cls:
+ api = api_cls.return_value
+ api.create_inference_endpoint.return_value = endpoint
result = runner.invoke(
app,
[
@@ -2640,7 +2646,7 @@
"--repo",
"my-repo",
"--framework",
- "custom",
+ "pytorch",
"--accelerator",
"gpu",
"--instance-size",
@@ -2652,7 +2658,38 @@
"--vendor",
"aws",
"--container-args",
- "--tp 8",
+ "--enable-auto-tool-choice --tool-call-parser lfm2",
+ ],
+ )
+ assert result.exit_code == 0, result.stdout
+ _, kwargs = api.create_inference_endpoint.call_args
+ assert kwargs["container_args"] == ["--enable-auto-tool-choice",
"--tool-call-parser", "lfm2"]
+ assert "custom_image" not in kwargs
+
+ def test_deploy_port_and_health_route_require_image(self, runner:
CliRunner) -> None:
+ with patch("huggingface_hub.cli.inference_endpoints.get_hf_api") as
api_cls:
+ result = runner.invoke(
+ app,
+ [
+ "endpoints",
+ "deploy",
+ "my-endpoint",
+ "--repo",
+ "my-repo",
+ "--framework",
+ "custom",
+ "--accelerator",
+ "gpu",
+ "--instance-size",
+ "x8",
+ "--instance-type",
+ "nvidia-h200",
+ "--region",
+ "us-east-1",
+ "--vendor",
+ "aws",
+ "--port",
+ "8000",
],
)
assert result.exit_code != 0
@@ -2724,6 +2761,8 @@
framework=None,
revision=None,
task=None,
+ container_command=None,
+ container_args=None,
accelerator="gpu",
instance_size="x4",
instance_type=None,
@@ -2736,6 +2775,47 @@
)
assert '"name": "updated"' in result.stdout
+ def test_update_container_args(self, runner: CliRunner) -> None:
+ endpoint = Mock(raw={"name": "updated"})
+ with patch("huggingface_hub.cli.inference_endpoints.get_hf_api") as
api_cls:
+ api = api_cls.return_value
+ api.update_inference_endpoint.return_value = endpoint
+ result = runner.invoke(
+ app,
+ [
+ "endpoints",
+ "update",
+ "my-endpoint",
+ "--container-args",
+ "--enable-auto-tool-choice --tool-call-parser lfm2",
+ ],
+ )
+ assert result.exit_code == 0, result.stdout
+ _, kwargs = api.update_inference_endpoint.call_args
+ assert kwargs["container_args"] == ["--enable-auto-tool-choice",
"--tool-call-parser", "lfm2"]
+ assert kwargs["container_command"] is None
+ assert '"name": "updated"' in result.stdout
+
+ def test_update_container_args_empty_string_resets(self, runner:
CliRunner) -> None:
+ endpoint = Mock(raw={"name": "updated"})
+ with patch("huggingface_hub.cli.inference_endpoints.get_hf_api") as
api_cls:
+ api = api_cls.return_value
+ api.update_inference_endpoint.return_value = endpoint
+ result = runner.invoke(
+ app,
+ [
+ "endpoints",
+ "update",
+ "my-endpoint",
+ "--container-args",
+ "",
+ ],
+ )
+ assert result.exit_code == 0, result.stdout
+ _, kwargs = api.update_inference_endpoint.call_args
+ assert kwargs["container_args"] == []
+ assert kwargs["container_command"] is None
+
def test_delete(self, runner: CliRunner) -> None:
with patch("huggingface_hub.cli.inference_endpoints.get_hf_api") as
api_cls:
api = api_cls.return_value
@@ -4542,6 +4622,104 @@
assert skill_file.read_text(encoding="utf-8") == build_skill_md()
+class TestSkillUpdateCheck:
+ """The daily `hf-cli` skill check only prints hints, it never installs nor
updates."""
+
+ @pytest.fixture(autouse=True)
+ def isolated_skills_dirs(self, tmp_path: Path, monkeypatch:
pytest.MonkeyPatch) -> None:
+ monkeypatch.setattr(constants, "AGENTS_SKILLS_GLOBAL_PATH", tmp_path /
"global/.agents/skills")
+ monkeypatch.setattr(constants, "CLAUDE_SKILLS_GLOBAL_PATH", tmp_path /
"global/.claude/skills")
+ monkeypatch.setattr(constants, "AGENTS_SKILLS_LOCAL_PATH", tmp_path /
"local/.agents/skills")
+ monkeypatch.setattr(constants, "CLAUDE_SKILLS_LOCAL_PATH", tmp_path /
"local/.claude/skills")
+ monkeypatch.setattr(constants, "CHECK_FOR_SKILL_UPDATE_DONE_PATH",
str(tmp_path / ".check_done"))
+ monkeypatch.setattr(constants, "HF_HUB_DISABLE_UPDATE_CHECK", False)
+
+ def _write_global_skill(self, tmp_path: Path, content: str) -> Path:
+ skill_dir = tmp_path / "global/.agents/skills/hf-cli"
+ skill_dir.mkdir(parents=True)
+ skill_file = skill_dir / "SKILL.md"
+ skill_file.write_text(content, encoding="utf-8")
+ return skill_file
+
+ def test_hints_to_add_when_not_installed(self, capsys:
pytest.CaptureFixture) -> None:
+ with patch.object(_skills, "__version__", "1.0.0"):
+ _skills.check_skill_update()
+ assert "hf skills add -g --claude" in capsys.readouterr().err
+
+ def test_hints_to_update_when_generated_by_another_version(
+ self, tmp_path: Path, capsys: pytest.CaptureFixture
+ ) -> None:
+ self._write_global_skill(tmp_path, "Generated with `huggingface_hub
v0.0.1`.")
+ _skills.check_skill_update()
+ assert "hf skills update hf-cli -g --claude" in capsys.readouterr().err
+
+ def test_silent_when_up_to_date_and_throttled_afterwards(
+ self, tmp_path: Path, capsys: pytest.CaptureFixture
+ ) -> None:
+ skill_file = self._write_global_skill(tmp_path, build_skill_md())
+ _skills.check_skill_update()
+ assert capsys.readouterr().err == ""
+
+ # Checked less than 24 hours ago: stays silent even though the skill
is now outdated.
+ skill_file.write_text("Generated with `huggingface_hub v0.0.1`.",
encoding="utf-8")
+ _skills.check_skill_update()
+ assert capsys.readouterr().err == ""
+
+ @pytest.mark.parametrize(
+ "argv, expected_call_count",
+ [
+ (["hf", "version"], 1),
+ (["hf", "skills", "add"], 0), # the user is already managing
skills
+ (["hf", "update"], 0), # `hf update` handles the skill itself
+ ],
+ )
+ def test_skipped_for_skills_and_update_commands(self, argv: list[str],
expected_call_count: int) -> None:
+ with (
+ patch.object(sys, "argv", argv),
+ patch("huggingface_hub.cli.hf.logging"),
+ patch("huggingface_hub.cli.hf.check_cli_update"),
+ patch("huggingface_hub.cli.hf.app"),
+ patch("huggingface_hub.cli.hf.check_skill_update") as mock_check,
+ ):
+ hf_main()
+ assert mock_check.call_count == expected_call_count
+
+
+class TestUpdateSkillOptOut:
+ """`hf update` must not silently reinstall the `hf-cli` skill for users
who opted out."""
+
+ @pytest.fixture(autouse=True)
+ def isolated_skills_dirs(self, tmp_path: Path, monkeypatch:
pytest.MonkeyPatch) -> None:
+ monkeypatch.setattr(constants, "AGENTS_SKILLS_GLOBAL_PATH", tmp_path /
".agents/skills")
+ monkeypatch.setattr(constants, "CLAUDE_SKILLS_GLOBAL_PATH", tmp_path /
".claude/skills")
+
+ @contextmanager
+ def _mocked_update(self) -> Generator[Mock, None, None]:
+ with (
+ patch("huggingface_hub.cli.system._fetch_latest_pypi_version",
return_value="99.0.0"),
+ patch("huggingface_hub.cli.system.subprocess.call",
return_value=0),
+ patch("huggingface_hub.cli.system.run_update", return_value=0) as
mock_run_update,
+ ):
+ yield mock_run_update
+
+ def test_excludes_skill_when_not_installed(self) -> None:
+ with self._mocked_update() as mock_run_update:
+ system.update()
+ mock_run_update.assert_called_once_with(exclude_skill=True)
+
+ def test_keeps_skill_when_installed(self, tmp_path: Path) -> None:
+ (tmp_path / ".agents/skills/hf-cli").mkdir(parents=True)
+ with self._mocked_update() as mock_run_update:
+ system.update()
+ mock_run_update.assert_called_once_with(exclude_skill=False)
+
+ def test_installer_command_passes_the_flag(self) -> None:
+ flag = "-ExcludeSkill" if os.name == "nt" else "--exclude-skill"
+ with patch("huggingface_hub.cli._cli_utils.installation_method",
return_value="hf_installer"):
+ assert flag in
_get_huggingface_hub_update_command(exclude_skill=True)[-1]
+ assert flag not in
_get_huggingface_hub_update_command(exclude_skill=False)[-1]
+
+
@pytest.mark.xet
class TestSkillsMarketplaceCLI:
@pytest.mark.production
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/huggingface_hub-1.26.0/tests/test_hf_api.py
new/huggingface_hub-1.27.0/tests/test_hf_api.py
--- old/huggingface_hub-1.26.0/tests/test_hf_api.py 2026-07-30
16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/tests/test_hf_api.py 2026-08-07
14:47:34.000000000 +0200
@@ -4853,6 +4853,65 @@
}
+def test_update_inference_endpoint_container_command_and_args_payload(mocker):
+ mock_get_session = mocker.patch("huggingface_hub.hf_api.get_session")
+ mock_session = mock_get_session.return_value
+ mock_response = Mock()
+ mock_response.raise_for_status.return_value = None
+ mock_response.json.return_value = {
+ "name": "lfm2-endpoint",
+ "model": {"repository": "LiquidAI/LFM2-8B-A1B", "framework": "vllm",
"revision": None, "task": None},
+ "status": {
+ "state": "pending",
+ "createdAt": "2025-03-07T15:30:13.949Z",
+ "updatedAt": "2025-03-07T15:30:13.949Z",
+ },
+ "healthRoute": "/health",
+ "type": "authenticated",
+ }
+ mock_session.put.return_value = mock_response
+
+ api = HfApi(endpoint=ENDPOINT_STAGING, token=TOKEN)
+ api.update_inference_endpoint(
+ name="lfm2-endpoint",
+ namespace="Wauplin",
+ container_command=["python", "-m",
"vllm.entrypoints.openai.api_server"],
+ container_args=["--enable-auto-tool-choice", "--tool-call-parser",
"lfm2"],
+ )
+
+ _, call_kwargs = mock_session.put.call_args
+ payload = call_kwargs.get("json", {})
+ assert payload["model"]["command"] == ["python", "-m",
"vllm.entrypoints.openai.api_server"]
+ assert payload["model"]["args"] == ["--enable-auto-tool-choice",
"--tool-call-parser", "lfm2"]
+ assert "image" not in payload["model"]
+
+
+def
test_update_inference_endpoint_container_command_and_args_empty_payload(mocker):
+ """An empty list must reach the payload: it is how the CLI clears the
current value."""
+ mock_session =
mocker.patch("huggingface_hub.hf_api.get_session").return_value
+ mock_response = Mock()
+ mock_response.raise_for_status.return_value = None
+ mock_response.json.return_value = {
+ "name": "lfm2-endpoint",
+ "model": {"repository": "LiquidAI/LFM2-8B-A1B", "framework":
"pytorch", "revision": None, "task": None},
+ "status": {
+ "state": "pending",
+ "createdAt": "2025-03-07T15:30:13.949Z",
+ "updatedAt": "2025-03-07T15:30:13.949Z",
+ },
+ "healthRoute": "/health",
+ "type": "authenticated",
+ }
+ mock_session.put.return_value = mock_response
+
+ api = HfApi(endpoint=ENDPOINT_STAGING, token=TOKEN)
+ api.update_inference_endpoint(name="lfm2-endpoint", namespace="Wauplin",
container_command=[], container_args=[])
+
+ payload = mock_session.put.call_args[1]["json"]
+ assert payload["model"]["command"] == []
+ assert payload["model"]["args"] == []
+
+
class TestHfApiVerifyChecksums:
def test_verify_repo_checksums_with_local_cache(self, api: HfApi) -> None:
repo_id = api.create_repo(repo_name()).repo_id
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/huggingface_hub-1.26.0/tests/test_hf_file_system.py
new/huggingface_hub-1.27.0/tests/test_hf_file_system.py
--- old/huggingface_hub-1.26.0/tests/test_hf_file_system.py 2026-07-30
16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/tests/test_hf_file_system.py 2026-08-07
14:47:34.000000000 +0200
@@ -337,7 +337,7 @@
def test_get_file_with_temporary_folder(self):
# Test passing a file path works
- with tempfile.TemporaryDirectory() as temp_dir:
+ with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as
temp_dir:
temp_file = os.path.join(temp_dir, "temp_file.txt")
self.hffs.get_file(self.text_file, temp_file)
with open(temp_file, "rb") as f:
@@ -346,19 +346,19 @@
def test_get_file_with_kwargs(self):
# If custom kwargs are passed, the function should still work but
defaults to base implementation
with patch.object(hf_file_system, "http_get") as mock:
- with tempfile.TemporaryDirectory() as temp_dir:
+ with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as
temp_dir:
temp_file = os.path.join(temp_dir, "temp_file.txt")
self.hffs.get_file(self.text_file, temp_file, custom_kwarg=123)
mock.assert_not_called()
- with tempfile.TemporaryDirectory() as temp_dir:
+ with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as
temp_dir:
temp_file = os.path.join(temp_dir, "temp_file.txt")
self.hffs.get_file(self.text_file, temp_file)
mock.assert_called_once()
def test_get_file_on_folder(self):
# Test it works with custom kwargs
- with tempfile.TemporaryDirectory() as temp_dir:
+ with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as
temp_dir:
assert not (Path(temp_dir) / "data").exists()
self.hffs.get_file(self.hf_path + "/data", temp_dir + "/data")
assert (Path(temp_dir) / "data").exists()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/tests/test_inference_client.py
new/huggingface_hub-1.27.0/tests/test_inference_client.py
--- old/huggingface_hub-1.26.0/tests/test_inference_client.py 2026-07-30
16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/tests/test_inference_client.py 2026-08-07
14:47:34.000000000 +0200
@@ -63,6 +63,9 @@
# Avoid calling APIs in VCRed tests
_RECOMMENDED_MODELS_FOR_VCR = {
+ "baseten": {
+ "conversational": "moonshotai/Kimi-K3",
+ },
"cerebras": {
"conversational": "meta-llama/Llama-3.3-70B-Instruct",
},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/huggingface_hub-1.26.0/tests/test_snapshot_download.py
new/huggingface_hub-1.27.0/tests/test_snapshot_download.py
--- old/huggingface_hub-1.26.0/tests/test_snapshot_download.py 2026-07-30
16:11:39.000000000 +0200
+++ new/huggingface_hub-1.27.0/tests/test_snapshot_download.py 2026-08-07
14:47:34.000000000 +0200
@@ -413,5 +413,5 @@
# Everything is cached at this point => works offline as well
with offline():
assert hf_hub_download(self.repo_id, "dummy_file.txt",
revision=revision, cache_dir=tmp_path).endswith(
- f"{self.commit_hash}/dummy_file.txt"
+ os.path.join(self.commit_hash, "dummy_file.txt")
)