Trim verbose comments on listAssets query fields

This commit is contained in:
Matt Miller 2026-07-30 16:35:22 -07:00
parent 9bab190e6b
commit 3b21f218a3
3 changed files with 11 additions and 24 deletions

View File

@ -54,16 +54,11 @@ class ListAssetsQuery(BaseModel):
exclude_tags: list[str] = Field(default_factory=list)
name_contains: str | None = None
# Filter to assets whose content hash matches exactly. Param name is `hash`
# per the projected openapi.yaml listAssets contract (the response-body field
# is `asset_hash`; the query param is `hash`).
# Filter by exact content hash (emitted as `asset_hash` in responses)
hash: str | None = None
# Declared for cloud/core contract parity. In core, reads are owner-scoped
# (owner_id == "") and there is no separate shared/public pool for this flag
# to include or exclude, so it is inert here and intentionally not threaded
# into the query. Accepted (not rejected) so the FE needs no isCloud branch;
# cloud enforces the flag in its own service layer.
# Accepted for API compatibility; has no effect, as there is no shared
# asset pool to include or exclude
include_public: bool = True
# Accept either a JSON string (query param) or a dict
@ -101,12 +96,7 @@ class ListAssetsQuery(BaseModel):
@field_validator("hash", mode="before")
@classmethod
def _normalize_hash(cls, v):
# Normalize for an exact match against stored hashes (which are
# lowercase `blake3:<hex>`). Liberal in what we accept — no pattern
# enforcement; a non-matching value simply yields an empty page.
# An explicitly-supplied-but-empty value (`?hash=`) stays `""` so it
# is treated as an exact-match miss (empty page), not silently dropped
# to "no filter" — omit the param entirely to disable the filter.
# Stored hashes are lowercase `blake3:<hex>`; no pattern is enforced
if isinstance(v, str):
return v.strip().lower()
return v

View File

@ -294,8 +294,7 @@ def list_references_page(
escaped, esc = escape_sql_like_string(name_contains)
base = base.where(AssetReference.name.ilike(f"%{escaped}%", escape=esc))
# `is not None` (not truthiness): an explicit empty hash is an exact-match
# miss (empty page), while an omitted hash (None) disables the filter.
# Not truthiness: an empty hash matches nothing, an omitted one filters nothing
if asset_hash is not None:
base = base.where(Asset.hash == asset_hash)

View File

@ -308,7 +308,7 @@ def test_list_assets_invalid_query_rejected(http: requests.Session, api_base: st
def test_list_assets_display_name_emitted(http, api_base, asset_factory, make_asset_bytes):
"""`display_name` is emitted for every populated asset in list responses,
derived from the storage path (category prefix + hash-based stored filename)."""
derived from the storage path."""
scope = f"lf-dispname-{uuid.uuid4().hex[:6]}"
tags = ["models", "model_type:checkpoints", "unit-tests", scope]
asset_factory("dn_a.safetensors", tags, {}, make_asset_bytes("dn_a", 700))
@ -371,8 +371,7 @@ def test_list_assets_hash_filter_no_match(http, api_base, asset_factory, make_as
def test_list_assets_hash_filter_normalizes_case_and_whitespace(
http, api_base, asset_factory, make_asset_bytes
):
"""`hash` is trimmed and lowercased before matching, so an upper-cased,
space-padded value still matches the stored lowercase hash."""
"""An upper-cased, space-padded `hash` still matches the stored hash."""
scope = f"lf-hashnorm-{uuid.uuid4().hex[:6]}"
tags = ["models", "model_type:checkpoints", "unit-tests", scope]
a = asset_factory("hnorm_a.safetensors", tags, {}, make_asset_bytes("hnorm_a", 1024))
@ -396,8 +395,8 @@ def test_list_assets_hash_filter_normalizes_case_and_whitespace(
def test_list_assets_hash_filter_empty_returns_empty_page(
http, api_base, asset_factory, make_asset_bytes
):
"""An explicitly-supplied but empty `hash` (`?hash=`) is an exact-match miss
and returns an empty page, rather than silently disabling the filter."""
"""An empty `hash` matches nothing and returns an empty page, rather than
disabling the filter."""
scope = f"lf-hashempty-{uuid.uuid4().hex[:6]}"
tags = ["models", "model_type:checkpoints", "unit-tests", scope]
asset_factory("he_a.safetensors", tags, {}, make_asset_bytes("he_a", 800))
@ -414,8 +413,7 @@ def test_list_assets_hash_filter_empty_returns_empty_page(
def test_list_assets_include_public_accepted(http, api_base, asset_factory, make_asset_bytes):
"""`include_public` is accepted for contract parity; core results are always
the caller's own assets regardless of its value (the param is inert)."""
"""`include_public` is accepted and does not change which assets come back."""
scope = f"lf-incpub-{uuid.uuid4().hex[:6]}"
tags = ["models", "model_type:checkpoints", "unit-tests", scope]
a = asset_factory("ip_a.safetensors", tags, {}, make_asset_bytes("ip_a", 900))
@ -429,7 +427,7 @@ def test_list_assets_include_public_accepted(http, api_base, asset_factory, make
body = r.json()
assert r.status_code == 200, body
names = [x["name"] for x in body["assets"]]
assert a["name"] in names, f"caller's own asset must be returned (include_public={value})"
assert a["name"] in names, f"asset must be returned (include_public={value})"
def test_list_assets_name_contains_literal_underscore(