Skip to content

feat(core): add HubContent.get_all and keep OriginalCreationTime on listed hub content - #6529

Closed
evakravi wants to merge 1 commit into
aws:masterfrom
evakravi:feat/hub-content-get-all
Closed

evakravi wants to merge 1 commit into
aws:masterfrom
evakravi:feat/hub-content-get-all

Conversation

@evakravi

Copy link
Copy Markdown
Member

Problem

HubContent has no get_all. The resource generator skips a List API when the list summary lacks a member that the Describe input requires, and HubContentInfo omits HubName, the name the list call was made with. As a result, every caller pages list_hub_contents on the boto3 client by hand: jumpstart/search.py, jumpstart/hub/hub.py, recipe_utils.py, ai_registry/air_hub.py, training_session/_utils.py, and model_aliases.py in this repo, and three scripts in the SageMaker agent skills.

Two more defects follow from the same gap. HubContentInfo carries OriginalCreationTime, the date a model first entered the catalog, which DescribeHubContent does not return, and the HubContent class had no field for it, so ResourceIterator dropped it (the class forbids extra fields). And HubContent.get_all_versions() built each version from a summary with no hub_name, so the first refresh() failed:

botocore.exceptions.ParamValidationError: Missing required parameter in input: "HubName"

Solution

The generator learns two per-resource tables. GET_ALL_INPUT_ATTRIBUTES names list-input members to copy onto every listed resource (HubName to hub_name), and LIST_SUMMARY_EXTRA_ATTRIBUTES names summary-only members to keep as optional attributes (OriginalCreationTime). ResourceIterator takes the copied members as extra_init_data and applies them only where the summary has no value. resources.py is the regenerated output: HubContent.get_all(hub_name, hub_content_type, name_contains, max_schema_version, creation_time_before, creation_time_after, sort_by, sort_order, session, region), the original_creation_time attribute, and the hub_name binding on get_all_versions(). No other resource class changes.

Tests

New sagemaker-core/tests/unit/test_hub_content_get_all.py, 7 tests: paging with NextToken and hub_name bound on each resource, the list filters forwarded, original_creation_time kept from the summary, each per-item refresh sent with HubName, the session and region bound to each resource, get_all_versions() refreshing with the parent's hub_name, and extra_init_data not overriding a summary value.

cd sagemaker-core && python -m pytest tests/unit/test_hub_content_get_all.py -q
7 passed

On origin/master the same file reports 7 failed (AttributeError: type object 'HubContent' has no attribute 'get_all', and the HubName parameter error on get_all_versions).

Existing suites on this branch: tests/unit/tools, tests/unit/test_resource_client_context.py, tests/unit/generated/test_utils.py, tests/unit/generated/test_resources.py, tests/unit/jumpstart/hub, tests/unit/jumpstart/test_search_unit.py: 196 passed, 1 skipped. python src/sagemaker/core/tools/codegen.py regenerates resources.py to the committed content.

black --line-length 100, flake8, and pydocstyle pass on the changed hand-written files.

Merge Checklist

  • I read the contribution guide.
  • The change is backward compatible.
  • The commits use the repository commit-message format.
  • The change creates no S3 or STS client.
  • The change has regression coverage and adds no dependency.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

…isted hub content

`HubContent` had no `get_all`. The resource generator skips a List API when
the list summary lacks a member the Describe input requires, and
`HubContentInfo` omits `HubName`, the name the list call was made with. So
every caller paged `list_hub_contents` on the boto3 client by hand: six places
in the SDK and three scripts in the SageMaker agent skills repeat the same
loop. `HubContentInfo` also carries `OriginalCreationTime`, the model-level
catalog date, which `DescribeHubContent` does not return, and the `HubContent`
class had no field for it, so `ResourceIterator` dropped it. The same gap made
`HubContent.get_all_versions()` build each version without `hub_name`, so the
first `refresh()` failed with `Missing required parameter in input: "HubName"`.

Teach the generator two per-resource tables: list-input members to copy onto
every listed resource (`HubName` -> `hub_name`), and summary-only members to
keep as optional attributes (`OriginalCreationTime`). `ResourceIterator` takes
the copied members as `extra_init_data`. `resources.py` is the regenerated
output: `HubContent.get_all(hub_name, hub_content_type, name_contains,
max_schema_version, creation_time_before, creation_time_after, sort_by,
sort_order, session, region)`, the `original_creation_time` attribute, and the
`hub_name` binding on `get_all_versions()`.

---
X-AI-Prompt: Why does sagemaker-core have no HubContent.get_all, and why does get_all_versions() fail on refresh with a missing HubName?
X-AI-Tool: claude-code
@evakravi
evakravi deployed to auto-approve October 23, 2026 17:42 — with GitHub Actions Active
@evakravi
evakravi deployed to auto-approve October 23, 2026 17:42 — with GitHub Actions Active
@evakravi
evakravi deployed to auto-approve October 23, 2026 17:46 — with GitHub Actions Active
@evakravi

Copy link
Copy Markdown
Member Author

Superseded by #6533, which combines the four changes into one PR and moves the hub-model metadata accessors onto HubContent itself (a HubContentMixin in sagemaker.core.hub_content) instead of a separate class.

@evakravi evakravi closed this Oct 23, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI code review

This PR adds HubContent.get_all, keeps OriginalCreationTime on listed hub content, and binds hub_name onto resources produced by get_all/get_all_versions so their first refresh() succeeds. It does this by teaching the codegen two per-resource tables (GET_ALL_INPUT_ATTRIBUTES, LIST_SUMMARY_EXTRA_ATTRIBUTES) plus an extra_init_data path in ResourceIterator, and regenerating resources.py. The logic is sound: the Describe-required-but-summary-missing HubName is now excluded from the "skip get_all" check and copied onto each resource via setdefault (so summary values win), and the extra original_creation_time field is added to the class so it is no longer dropped. Tests are thorough and cover paging, filter forwarding, the retained attribute, per-item refresh, session/region binding, and the setdefault precedence. Overall it looks correct and well-tested; only one low-severity latent limitation noted.

Reviewed commit d5068d5. Automated review; verify before acting.

class_attributes_string = (
class_attributes_string + "hub_name: Optional[str] = Unassigned()"
class_attributes_string + "hub_name: Optional[str] = Unassigned()\n"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Low: The LIST_SUMMARY_EXTRA_ATTRIBUTES loop is added only to the get-method branch of _get_class_attributes. Since the following branch is elif "get_all" in class_methods: (mutually exclusive), a resource that has get_all but no get would be generated without the extra summary-only attribute, so ResourceIterator would again silently drop it. This is harmless today because the only entry (HubContent) also has a get method, but if the table is extended to a get_all-only resource the attribute would be lost without an obvious failure. Consider applying the same loop in the elif "get_all" branch (or factoring it out) to avoid the trap.

This branch was successfully deployed

1 active deployment
auto-approve — d5068d5a Deployed Oct 23, 2026 by evakravi via wait-for-approval #738
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant