Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-modelscope-hub for
openSUSE:Factory checked in at 2026-10-09 21:46:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-modelscope-hub (Old)
and /work/SRC/openSUSE:Factory/.python-modelscope-hub.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-modelscope-hub"
Fri Oct 9 21:46:49 2026 rev:8 rq:1383819 version:0.4.6
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-modelscope-hub/python-modelscope-hub.changes
2026-09-21 12:24:45.681158672 +0200
+++
/work/SRC/openSUSE:Factory/.python-modelscope-hub.new.3698736/python-modelscope-hub.changes
2026-10-09 21:48:04.780117996 +0200
@@ -1,0 +2,6 @@
+Fri Oct 9 13:12:44 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 0.4.6:
+ * Fix cross-region download
+
+-------------------------------------------------------------------
Old:
----
modelscope_hub-0.4.5.tar.gz
New:
----
modelscope_hub-0.4.6.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-modelscope-hub.spec ++++++
--- /var/tmp/diff_new_pack.i8JUww/_old 2026-10-09 21:48:05.432145341 +0200
+++ /var/tmp/diff_new_pack.i8JUww/_new 2026-10-09 21:48:05.434145424 +0200
@@ -19,7 +19,7 @@
%bcond_without libalternatives
%{?sle15_python_module_pythons}
Name: python-modelscope-hub
-Version: 0.4.5
+Version: 0.4.6
Release: 0
Summary: Official Python client for ModelScope Hub
License: Apache-2.0
++++++ modelscope_hub-0.4.5.tar.gz -> modelscope_hub-0.4.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/modelscope_hub-0.4.5/PKG-INFO
new/modelscope_hub-0.4.6/PKG-INFO
--- old/modelscope_hub-0.4.5/PKG-INFO 2026-09-21 10:26:39.113045700 +0200
+++ new/modelscope_hub-0.4.6/PKG-INFO 2026-10-09 10:08:17.160966200 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: modelscope-hub
-Version: 0.4.5
+Version: 0.4.6
Summary: The official Python client to connect with ModelScope Hub.
License: Apache-2.0
Keywords: modelscope,hub,sdk,openapi,machine-learning
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/modelscope_hub-0.4.5/src/modelscope_hub/_download.py
new/modelscope_hub-0.4.6/src/modelscope_hub/_download.py
--- old/modelscope_hub-0.4.5/src/modelscope_hub/_download.py 2026-09-21
10:26:29.791361300 +0200
+++ new/modelscope_hub-0.4.6/src/modelscope_hub/_download.py 2026-10-09
10:08:08.336837300 +0200
@@ -335,10 +335,15 @@
self._client = legacy_client
self._config = config
self._cached_region: str | None = None
- # Cache resolved inter-region probe results to avoid redundant HEAD
probes
- # when downloading multiple files from the same repo in parallel.
- self._inter_region_cache: dict[tuple[str, str], tuple[str | None,
str]] = {}
+ # Cache only confirmed OSS-internal resolutions. A repository can
contain
+ # Git metadata and LFS objects behind different download routes, so
cache
+ # entries are scoped to repo/type/revision plus the redirect endpoint.
+ self._inter_region_cache: dict[tuple[str, str, str, str], tuple[str |
None, str]] = {}
+ # Guard the cache and the per-route in-flight probes. The probe itself
is
+ # deliberately performed outside this lock so distinct storage routes
can
+ # resolve in parallel.
self._inter_region_lock = threading.Lock()
+ self._inter_region_inflight: dict[tuple[str, str, str, str],
threading.Event] = {}
# ------------------------------------------------------------------
# User-agent & headers
@@ -422,6 +427,24 @@
pass
return ""
+ @staticmethod
+ def _storage_route_key(redirect_url: str) -> str | None:
+ """Return a stable identity for the storage endpoint behind a redirect.
+
+ Presigned query parameters and object paths are intentionally excluded:
+ they differ per file and request, whereas the endpoint hostname is the
+ stable route boundary that must isolate inter-region cache entries.
+ """
+ try:
+ parsed = urlparse(redirect_url)
+ host = parsed.hostname
+ if not parsed.scheme or not host:
+ return None
+ port = f":{parsed.port}" if parsed.port is not None else ""
+ return f"{parsed.scheme.lower()}://{host.lower()}{port}"
+ except (TypeError, ValueError):
+ return None
+
def _get_inter_cloud_regions(self) -> list[str]:
"""Read the inter-cloud peer region list from the environment."""
from .constants import _env
@@ -435,6 +458,7 @@
headers: dict[str, str],
cookies: dict | None = None,
peer_regions: list[str] | None = None,
+ initial_redirect_url: str | None = None,
) -> tuple[dict[str, str], str]:
"""Probe peer regions and return headers with the best region for OSS
internal download.
@@ -453,8 +477,12 @@
current_region = headers.get("x-aliyun-region-id", "").lower()
- # Step 1: Probe with current (local) region
- redirect_url = self._probe_redirect_url(url, headers, cookies)
+ # Step 1: Probe with current (local) region. Callers that already
+ # established the storage route pass the initial redirect to avoid an
+ # identical second HEAD request.
+ redirect_url = (
+ self._probe_redirect_url(url, headers, cookies) if
initial_redirect_url is None else initial_redirect_url
+ )
if self._is_oss_internal_url(redirect_url):
logger.debug("Inter-region: local region already yields OSS
internal URL, skipping.")
return headers, "local"
@@ -1127,57 +1155,83 @@
download_headers = self._build_download_headers(user_agent)
- # Inter-region acceleration: probe peer regions for OSS internal URL.
- # Cache per (repo_id, repo_type) — all files in the same repo share one
- # OSS bucket so one probe is sufficient for the entire download
session.
+ # Inter-region acceleration: first discover the file's storage route,
+ # then cache only a confirmed internal resolution for that exact route.
+ # Git metadata may return 200 without a redirect while LFS objects use
+ # OSS; a metadata miss must therefore never suppress an LFS probe.
# Progress bar prefix: "⚡ " = local OSS, "⇄ " = peer OSS, " " = CDN,
"" = not configured
source_prefix = ""
peer_regions = self._get_inter_cloud_regions()
if peer_regions:
- cache_key = (repo_id, repo_type)
- with self._inter_region_lock:
- cached = self._inter_region_cache.get(cache_key)
- if cached is None:
- # First thread for this repo — do the probe under lock so
- # other threads wait instead of issuing redundant HEAD
reqs.
- try:
- probe_url = self._client.get_download_url(
- repo_id,
- repo_type,
- file_path,
- revision,
- )
- cookies = None
- if self._client.token:
- cookies = {"m_session_id": self._client.token}
- download_headers, source =
self._resolve_inter_region_headers(
- probe_url,
- download_headers,
- cookies,
- peer_regions=peer_regions,
- )
- resolved_region =
download_headers.get("x-aliyun-region-id")
- self._inter_region_cache[cache_key] =
(resolved_region, source)
- except Exception as exc:
- logger.warning(
- "Failed to resolve inter-region acceleration: %s.
Falling back to default.",
- exc,
- )
- self._inter_region_cache[cache_key] = (None, "default")
- cached = (None, "default")
-
- if cached is None:
- cached = self._inter_region_cache.get(cache_key)
+ source = "default"
+ cached: tuple[str | None, str] | None = None
+ probe_event: threading.Event | None = None
+ try:
+ probe_url = self._client.get_download_url(repo_id, repo_type,
file_path, revision)
+ cookies = {"m_session_id": self._client.token} if
self._client.token else None
+ initial_redirect_url = self._probe_redirect_url(probe_url,
download_headers, cookies)
+ route_key = self._storage_route_key(initial_redirect_url)
+
+ if route_key is not None:
+ cache_key = (repo_id, repo_type, revision, route_key)
+ while cached is None:
+ is_probe_owner = False
+ with self._inter_region_lock:
+ cached = self._inter_region_cache.get(cache_key)
+ if cached is not None:
+ break
+ probe_event =
self._inter_region_inflight.get(cache_key)
+ if probe_event is None:
+ probe_event = threading.Event()
+ self._inter_region_inflight[cache_key] =
probe_event
+ is_probe_owner = True
+
+ if not is_probe_owner:
+ assert probe_event is not None
+ probe_event.wait()
+ continue
+
+ try:
+ download_headers, source =
self._resolve_inter_region_headers(
+ probe_url,
+ download_headers,
+ cookies,
+ peer_regions=peer_regions,
+ initial_redirect_url=initial_redirect_url,
+ )
+ resolved_region =
download_headers.get("x-aliyun-region-id")
+ if source != "default":
+ with self._inter_region_lock:
+ self._inter_region_cache[cache_key] =
(resolved_region, source)
+ cached = (resolved_region, source)
+ finally:
+ with self._inter_region_lock:
+ self._inter_region_inflight.pop(cache_key,
None)
+ assert probe_event is not None
+ probe_event.set()
+
+ # A non-internal result is intentionally not cached.
The
+ # current file falls back now; a waiting file retries
as
+ # the next single-flight owner instead of inheriting
it.
+ if cached is None:
+ break
+
+ if cached is not None:
+ resolved_region, source = cached
+ if resolved_region is not None:
+ download_headers["x-aliyun-region-id"] =
resolved_region
+ except Exception as exc:
+ logger.warning(
+ "Failed to resolve inter-region acceleration: %s. Falling
back to default.",
+ exc,
+ )
+ source = "default"
- if cached is not None:
- resolved_region, source = cached
- if resolved_region is not None:
- download_headers["x-aliyun-region-id"] = resolved_region
- source_prefix = {
- "local": "\u26a1 ",
- "peer": "\u21c4 ",
- "default": " ",
- }[source]
+ source_prefix = {
+ "local": "\u26a1 ",
+ "peer": "\u21c4 ",
+ "default": " ",
+ }[source]
if use_parallel:
assert file_size is not None # guaranteed by use_parallel above
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/modelscope_hub-0.4.5/src/modelscope_hub/version.py
new/modelscope_hub-0.4.6/src/modelscope_hub/version.py
--- old/modelscope_hub-0.4.5/src/modelscope_hub/version.py 2026-09-21
10:26:29.797361400 +0200
+++ new/modelscope_hub-0.4.6/src/modelscope_hub/version.py 2026-10-09
10:08:08.339837300 +0200
@@ -1,3 +1,3 @@
"""Version information for modelscope_hub."""
-__version__ = "0.4.5"
+__version__ = "0.4.6"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/modelscope_hub-0.4.5/src/modelscope_hub.egg-info/PKG-INFO
new/modelscope_hub-0.4.6/src/modelscope_hub.egg-info/PKG-INFO
--- old/modelscope_hub-0.4.5/src/modelscope_hub.egg-info/PKG-INFO
2026-09-21 10:26:39.083045700 +0200
+++ new/modelscope_hub-0.4.6/src/modelscope_hub.egg-info/PKG-INFO
2026-10-09 10:08:17.138965400 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: modelscope-hub
-Version: 0.4.5
+Version: 0.4.6
Summary: The official Python client to connect with ModelScope Hub.
License: Apache-2.0
Keywords: modelscope,hub,sdk,openapi,machine-learning