Skip to content

feat: sync models from UCP and update sdk version to 0.3#24

Closed
cusell-google wants to merge 6 commits intoUniversal-Commerce-Protocol:mainfrom
cusell-google:update-sdk-0.3
Closed

feat: sync models from UCP and update sdk version to 0.3#24
cusell-google wants to merge 6 commits intoUniversal-Commerce-Protocol:mainfrom
cusell-google:update-sdk-0.3

Conversation

@cusell-google
Copy link
Copy Markdown
Collaborator

sync python-sdk from ucp and update version to 0.3. This version update is larger than the previous one which was 0.1.0.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request significantly expands the UCP Python SDK by introducing comprehensive shopping models, including cart management, catalog search/lookup, and identity linking. It refactors existing schemas to support hierarchical extensions, adds detailed types for pricing, fulfillment, and product metadata, and moves extension-specific checkout models to a dedicated namespace. Feedback focuses on ensuring model consistency with documentation, specifically regarding required fields for currency and amounts, enforcing structural constraints via validators, and consolidating redundant generated types.

model_config = ConfigDict(
extra="allow",
)
amount: signed_amount.SignedAmount | None = None
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The amount field is marked as optional with a default of None, but the docstring states that platforms MUST render all entries using the amount. Additionally, the sum of line amounts must equal this parent amount. Making it optional contradicts these requirements and could lead to inconsistencies. Since this is a core part of the pricing breakdown, it should be a required field.

Suggested change
amount: signed_amount.SignedAmount | None = None
amount: signed_amount.SignedAmount

"""


class Totals(RootModel[list[Total]]):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The Totals model docstring specifies that it MUST contain exactly one subtotal and one total entry. This constraint is currently not enforced by the code. Consider adding a Pydantic validator to ensure compliance with the UCP specification and prevent invalid pricing breakdowns from being processed.

"""
Content format, default = plain.
"""
presentation: str | None = "notice"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The presentation field has a specific set of well-known values ('notice', 'disclosure') described in the docstring. Using a Literal type would provide better validation and IDE support for SDK users.

Suggested change
presentation: str | None = "notice"
presentation: Literal["notice", "disclosure"] | None = "notice"

Comment on lines +36 to +141
class Extends(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends1Item(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")


class Extends1(RootModel[list[Extends1Item]]):
model_config = ConfigDict(
frozen=True,
)
root: list[Extends1Item] = Field(..., min_length=1)
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends2(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends3Item(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")


class Extends3(RootModel[list[Extends3Item]]):
model_config = ConfigDict(
frozen=True,
)
root: list[Extends3Item] = Field(..., min_length=1)
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends4(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends5Item(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")


class Extends5(RootModel[list[Extends5Item]]):
model_config = ConfigDict(
frozen=True,
)
root: list[Extends5Item] = Field(..., min_length=1)
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends6(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends7Item(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")


class Extends7(RootModel[list[Extends7Item]]):
model_config = ConfigDict(
frozen=True,
)
root: list[Extends7Item] = Field(..., min_length=1)
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

There is significant duplication of Extends types (e.g., Extends, Extends2, Extends4, Extends6 are identical RootModel[str] definitions). This appears to be an artifact of the code generation process. Consolidating these into a single reusable type would improve the maintainability and readability of the SDK models.

Append-only event log of money movements (refunds, returns, credits, disputes, cancellations, etc.) that exist independently of fulfillment.
"""
totals: list[total.Total]
currency: str | None = None
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The currency field is marked as optional, but the docstring states it MUST match the currency from the originating checkout session. If this is a mandatory requirement for the order representation, it should be a required field in the model to ensure data completeness.

@cusell-google cusell-google marked this pull request as draft March 31, 2026 09:09
@cusell-google cusell-google deleted the update-sdk-0.3 branch March 31, 2026 09:09
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