Repository navigation
Conversation
…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
|
Superseded by #6533, which combines the four changes into one PR and moves the hub-model metadata accessors onto |
There was a problem hiding this comment.
🤖 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" | ||
| ) |
There was a problem hiding this comment.
🟡 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.
Problem
HubContenthas noget_all. The resource generator skips a List API when the list summary lacks a member that the Describe input requires, andHubContentInfoomitsHubName, the name the list call was made with. As a result, every caller pageslist_hub_contentson the boto3 client by hand:jumpstart/search.py,jumpstart/hub/hub.py,recipe_utils.py,ai_registry/air_hub.py,training_session/_utils.py, andmodel_aliases.pyin this repo, and three scripts in the SageMaker agent skills.Two more defects follow from the same gap.
HubContentInfocarriesOriginalCreationTime, the date a model first entered the catalog, whichDescribeHubContentdoes not return, and theHubContentclass had no field for it, soResourceIteratordropped it (the class forbids extra fields). AndHubContent.get_all_versions()built each version from a summary with nohub_name, so the firstrefresh()failed:Solution
The generator learns two per-resource tables.
GET_ALL_INPUT_ATTRIBUTESnames list-input members to copy onto every listed resource (HubNametohub_name), andLIST_SUMMARY_EXTRA_ATTRIBUTESnames summary-only members to keep as optional attributes (OriginalCreationTime).ResourceIteratortakes the copied members asextra_init_dataand applies them only where the summary has no value.resources.pyis 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), theoriginal_creation_timeattribute, and thehub_namebinding onget_all_versions(). No other resource class changes.Tests
New
sagemaker-core/tests/unit/test_hub_content_get_all.py, 7 tests: paging withNextTokenandhub_namebound on each resource, the list filters forwarded,original_creation_timekept from the summary, each per-item refresh sent withHubName, the session and region bound to each resource,get_all_versions()refreshing with the parent'shub_name, andextra_init_datanot overriding a summary value.On
origin/masterthe same file reports7 failed(AttributeError: type object 'HubContent' has no attribute 'get_all', and theHubNameparameter error onget_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.pyregeneratesresources.pyto the committed content.black --line-length 100,flake8, andpydocstylepass on the changed hand-written files.Merge Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.