From 452d10987bfe2ce15b3020b0e79494cf38c81895 Mon Sep 17 00:00:00 2001 From: damaz91 Date: Fri, 6 Feb 2026 10:10:34 +0000 Subject: [PATCH 01/22] update SDK to 2026-01-23 --- generate_models.sh | 41 +++- preprocess_schemas.py | 192 +++++++++++++++ pyproject.toml | 21 +- src/ucp_sdk/__init__.py | 19 -- src/ucp_sdk/models/_internal.py | 227 ------------------ .../models/discovery/profile_schema.py | 114 +++++---- .../models/handlers/tokenization/openapi.py | 3 +- src/ucp_sdk/models/ruff.toml | 16 ++ src/ucp_sdk/models/schemas/capability.py | 36 ++- src/ucp_sdk/models/schemas/payment_handler.py | 55 +++++ src/ucp_sdk/models/schemas/service.py | 197 +++++++++++++++ .../models/schemas/shopping/ap2_mandate.py | 126 ++++------ ...buyer_consent_resp.py => buyer_consent.py} | 59 ++--- .../shopping/buyer_consent_create_req.py | 79 ------ .../shopping/buyer_consent_update_req.py | 79 ------ src/ucp_sdk/models/schemas/shopping/cart.py | 128 ++++++++++ .../models/schemas/shopping/checkout.py | 190 +++++++++++++++ .../schemas/shopping/checkout_create_req.py | 44 ---- .../models/schemas/shopping/checkout_resp.py | 93 ------- .../schemas/shopping/checkout_update_req.py | 48 ---- .../{discount_resp.py => discount.py} | 91 ++++--- .../schemas/shopping/discount_create_req.py | 107 --------- .../schemas/shopping/discount_update_req.py | 107 --------- .../schemas/shopping/fulfillment/__init__.py | 58 +++++ .../shopping/fulfillment/dev}/__init__.py | 0 .../shopping/fulfillment/dev/ucp/__init__.py} | 5 - .../shopping/fulfillment/dev/ucp/shopping.py} | 5 +- .../shopping/fulfillment_create_req.py | 77 ------ .../schemas/shopping/fulfillment_resp.py | 79 ------ .../shopping/fulfillment_update_req.py | 77 ------ src/ucp_sdk/models/schemas/shopping/order.py | 85 +++---- .../{payment_update_req.py => payment.py} | 19 +- .../schemas/shopping/payment_create_req.py | 38 --- .../models/schemas/shopping/payment_data.py | 31 --- .../models/schemas/shopping/payment_resp.py | 42 ---- .../schemas/shopping/types/account_info.py | 14 +- .../schemas/shopping/types/adjustment.py | 55 +++-- .../models/schemas/shopping/types/binding.py | 19 +- .../types/business_fulfillment_config.py | 59 +++++ .../models/schemas/shopping/types/buyer.py | 24 +- .../schemas/shopping/types/card_credential.py | 53 ++-- .../shopping/types/card_payment_instrument.py | 62 +++-- .../models/schemas/shopping/types/context.py | 47 ++++ .../schemas/shopping/types/expectation.py | 52 ++-- .../{fulfillment_resp.py => fulfillment.py} | 26 +- ...esp.py => fulfillment_available_method.py} | 29 ++- .../types/fulfillment_available_method_req.py | 29 --- ...tion_req.py => fulfillment_destination.py} | 19 +- .../types/fulfillment_destination_resp.py | 37 --- .../shopping/types/fulfillment_event.py | 56 ++--- ...ent_group_resp.py => fulfillment_group.py} | 31 +-- .../types/fulfillment_group_create_req.py | 33 --- ...t_method_resp.py => fulfillment_method.py} | 42 ++-- .../types/fulfillment_method_create_req.py | 55 ----- .../types/fulfillment_method_update_req.py | 54 ----- ...t_option_resp.py => fulfillment_option.py} | 43 ++-- .../shopping/types/fulfillment_option_req.py | 29 --- .../schemas/shopping/types/fulfillment_req.py | 36 --- .../shopping/types/{item_resp.py => item.py} | 28 +-- .../schemas/shopping/types/item_create_req.py | 31 --- .../schemas/shopping/types/item_update_req.py | 31 --- .../types/{line_item_resp.py => line_item.py} | 32 +-- .../shopping/types/line_item_create_req.py | 35 --- .../shopping/types/line_item_update_req.py | 40 --- .../models/schemas/shopping/types/link.py | 18 +- .../types/merchant_fulfillment_config.py | 41 ++-- .../models/schemas/shopping/types/message.py | 19 +- .../schemas/shopping/types/message_error.py | 33 ++- .../schemas/shopping/types/message_info.py | 27 ++- .../schemas/shopping/types/message_warning.py | 27 ++- .../shopping/types/order_confirmation.py | 18 +- .../schemas/shopping/types/order_line_item.py | 55 +++-- .../shopping/types/payment_credential.py | 26 +- .../types/payment_handler_create_req.py | 27 --- .../shopping/types/payment_handler_resp.py | 54 ----- .../types/payment_handler_update_req.py | 27 --- .../shopping/types/payment_identity.py | 14 +- .../shopping/types/payment_instrument.py | 51 +++- .../shopping/types/payment_instrument_base.py | 47 ---- .../types/platform_fulfillment_config.py | 14 +- .../schemas/shopping/types/postal_address.py | 44 ++-- ...il_location_resp.py => retail_location.py} | 25 +- ...ination_req.py => shipping_destination.py} | 17 +- .../types/shipping_destination_resp.py | 34 --- ...tial_create_req.py => token_credential.py} | 24 +- .../shopping/types/token_credential_resp.py | 33 --- .../types/token_credential_update_req.py | 37 --- .../types/{total_resp.py => total.py} | 29 +-- .../shopping/types/total_create_req.py | 27 --- .../shopping/types/total_update_req.py | 27 --- .../models/schemas/transports/__init__.py | 18 ++ .../embedded_config.py} | 20 +- src/ucp_sdk/models/schemas/ucp.py | 174 ++++++++++++-- .../shopping/embedded.py} | 18 +- .../{embedded_openrpc.py => openapi.py} | 3 +- .../shopping/{mcp_openrpc.py => openrpc.py} | 3 +- src/ucp_sdk/py.typed | 0 97 files changed, 2020 insertions(+), 2700 deletions(-) create mode 100644 preprocess_schemas.py delete mode 100644 src/ucp_sdk/__init__.py delete mode 100644 src/ucp_sdk/models/_internal.py create mode 100644 src/ucp_sdk/models/ruff.toml create mode 100644 src/ucp_sdk/models/schemas/payment_handler.py create mode 100644 src/ucp_sdk/models/schemas/service.py rename src/ucp_sdk/models/schemas/shopping/{buyer_consent_resp.py => buyer_consent.py} (56%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/buyer_consent_create_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/buyer_consent_update_req.py create mode 100644 src/ucp_sdk/models/schemas/shopping/cart.py create mode 100644 src/ucp_sdk/models/schemas/shopping/checkout.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/checkout_create_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/checkout_resp.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/checkout_update_req.py rename src/ucp_sdk/models/schemas/shopping/{discount_resp.py => discount.py} (63%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/discount_create_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/discount_update_req.py create mode 100644 src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py rename src/ucp_sdk/models/{ => schemas/shopping/fulfillment/dev}/__init__.py (100%) rename src/ucp_sdk/models/{services/service_schema.py => schemas/shopping/fulfillment/dev/ucp/__init__.py} (80%) rename src/ucp_sdk/models/{services/shopping/rest_openapi.py => schemas/shopping/fulfillment/dev/ucp/shopping.py} (93%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/fulfillment_create_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/fulfillment_resp.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/fulfillment_update_req.py rename src/ucp_sdk/models/schemas/shopping/{payment_update_req.py => payment.py} (69%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/payment_create_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/payment_data.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/payment_resp.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/context.py rename src/ucp_sdk/models/schemas/shopping/types/{fulfillment_resp.py => fulfillment.py} (65%) rename src/ucp_sdk/models/schemas/shopping/types/{fulfillment_available_method_resp.py => fulfillment_available_method.py} (75%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_req.py rename src/ucp_sdk/models/schemas/shopping/types/{fulfillment_destination_req.py => fulfillment_destination.py} (65%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination_resp.py rename src/ucp_sdk/models/schemas/shopping/types/{fulfillment_group_resp.py => fulfillment_group.py} (70%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_req.py rename src/ucp_sdk/models/schemas/shopping/types/{fulfillment_method_resp.py => fulfillment_method.py} (66%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_req.py rename src/ucp_sdk/models/schemas/shopping/types/{fulfillment_option_resp.py => fulfillment_option.py} (68%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_req.py rename src/ucp_sdk/models/schemas/shopping/types/{item_resp.py => item.py} (69%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/item_create_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/item_update_req.py rename src/ucp_sdk/models/schemas/shopping/types/{line_item_resp.py => line_item.py} (70%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/line_item_create_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/line_item_update_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/payment_handler_create_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/payment_handler_resp.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/payment_handler_update_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/payment_instrument_base.py rename src/ucp_sdk/models/schemas/shopping/types/{retail_location_resp.py => retail_location.py} (76%) rename src/ucp_sdk/models/schemas/shopping/types/{shipping_destination_req.py => shipping_destination.py} (83%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/shipping_destination_resp.py rename src/ucp_sdk/models/schemas/shopping/types/{token_credential_create_req.py => token_credential.py} (67%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/token_credential_resp.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/token_credential_update_req.py rename src/ucp_sdk/models/schemas/shopping/types/{total_resp.py => total.py} (78%) delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/total_create_req.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/total_update_req.py create mode 100644 src/ucp_sdk/models/schemas/transports/__init__.py rename src/ucp_sdk/models/schemas/{shopping/types/fulfillment_group_update_req.py => transports/embedded_config.py} (60%) rename src/ucp_sdk/models/{schemas/shopping/types/retail_location_req.py => services/shopping/embedded.py} (62%) rename src/ucp_sdk/models/services/shopping/{embedded_openrpc.py => openapi.py} (98%) rename src/ucp_sdk/models/services/shopping/{mcp_openrpc.py => openrpc.py} (98%) delete mode 100644 src/ucp_sdk/py.typed diff --git a/generate_models.sh b/generate_models.sh index 7cebf5a..7826da2 100755 --- a/generate_models.sh +++ b/generate_models.sh @@ -8,9 +8,13 @@ cd "$(dirname "$0")" OUTPUT_DIR="src/ucp_sdk/models" # Schema directory (relative to this script) -SCHEMA_DIR="../../spec/" +SCHEMA_DIR="ucp/source" +TEMP_SCHEMA_DIR="temp_schemas" -echo "Generating Pydantic models from $SCHEMA_DIR..." +echo "Preprocessing schemas..." +python3 preprocess_schemas.py + +echo "Generating Pydantic models from preprocessed schemas..." # Check if uv is installed if ! command -v uv &> /dev/null; then @@ -23,14 +27,35 @@ fi rm -r -f "$OUTPUT_DIR" mkdir -p "$OUTPUT_DIR" +# Create ruff configuration for generated code +cat > "$OUTPUT_DIR/ruff.toml" << 'EOF' +# Ruff configuration for generated models +# These are auto-generated files, so we're more lenient with style rules + +line-length = 120 +target-version = "py311" + +[lint] +select = ["E", "F", "I"] +ignore = ["E501"] + +[lint.pydocstyle] +convention = "google" + +[lint.per-file-ignores] +"__init__.py" = ["D104"] +"*.py" = ["D100", "D101", "D102", "D103", "D200", "D205", "D212"] +EOF + # Run generation using uv # We use --use-schema-description to use descriptions from JSON schema as docstrings # We use --field-constraints to include validation constraints (regex, min/max, etc.) +# Note: Formatters removed as they can hang on large schemas uv run \ --link-mode=copy \ --extra-index-url https://pypi.org/simple python \ -m datamodel_code_generator \ - --input "$SCHEMA_DIR" \ + --input "$TEMP_SCHEMA_DIR" \ --input-file-type jsonschema \ --output "$OUTPUT_DIR" \ --output-model-type pydantic_v2.BaseModel \ @@ -41,7 +66,13 @@ uv run \ --disable-timestamp \ --use-double-quotes \ --no-use-annotated \ - --allow-extra-fields \ - --formatters ruff-format ruff-check + --allow-extra-fields + +echo "Formatting generated models..." +uv run ruff format "$OUTPUT_DIR" +uv run ruff check --fix --config "$OUTPUT_DIR/ruff.toml" "$OUTPUT_DIR" 2>&1 | grep -E "^(All checks passed|Fixed|Found)" || echo "Formatting complete" + +# Clean up temp schemas +rm -rf "$TEMP_SCHEMA_DIR" echo "Done. Models generated in $OUTPUT_DIR" diff --git a/preprocess_schemas.py b/preprocess_schemas.py new file mode 100644 index 0000000..a83004f --- /dev/null +++ b/preprocess_schemas.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 + +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Preprocess JSON schemas for datamodel-code-generator compatibility. +""" +import json +import shutil +import copy +from pathlib import Path +from typing import Any, Dict + + +def remove_extension_defs(schema: Dict[str, Any]) -> Dict[str, Any]: + """ + Remove $defs that extend EXTERNAL schemas using allOf. + These cause circular dependency issues. + """ + if "$defs" not in schema: + return schema + + defs_to_remove = [] + + for def_name, def_schema in schema["$defs"].items(): + if isinstance(def_schema, dict) and "allOf" in def_schema: + # Check if this extends an external schema + all_of = def_schema["allOf"] + has_external_ref = False + for item in all_of: + if isinstance(item, dict) and "$ref" in item: + ref = item["$ref"] + # If referencing another top-level schema (not within same file's $defs) + if not ref.startswith("#/"): + has_external_ref = True + break + + if has_external_ref: + print(f" -> Removing extension def: {def_name}") + defs_to_remove.append(def_name) + + # Remove extension defs + for def_name in defs_to_remove: + del schema["$defs"][def_name] + + # Remove empty $defs + if "$defs" in schema and not schema["$defs"]: + del schema["$defs"] + + return schema + + +def inline_internal_refs(obj: Any, defs: Dict[str, Any], processed: set = None) -> Any: + """ + Recursively inline $ref references that point to #/$defs/... + This resolves internal references to avoid cross-file confusion. + """ + if processed is None: + processed = set() + + if isinstance(obj, dict): + # Check for $ref + if "$ref" in obj and len(obj) == 1: + ref = obj["$ref"] + if ref.startswith("#/$defs/"): + def_name = ref.split("/")[-1] + # Avoid infinite recursion + if def_name not in processed and def_name in defs: + processed.add(def_name) + # Inline the definition + inlined = copy.deepcopy(defs[def_name]) + result = inline_internal_refs(inlined, defs, processed) + processed.remove(def_name) + return result + return obj + + # Recursively process all properties + result = {} + for key, value in obj.items(): + result[key] = inline_internal_refs(value, defs, processed) + return result + elif isinstance(obj, list): + return [inline_internal_refs(item, defs, processed) for item in obj] + return obj + + +def flatten_allof_in_defs(schema: Dict[str, Any]) -> Dict[str, Any]: + """ + Flatten allOf patterns within $defs that only use internal references. + """ + if "$defs" not in schema: + return schema + + defs = schema["$defs"] + + for def_name, def_schema in list(defs.items()): + if isinstance(def_schema, dict) and "allOf" in def_schema: + all_of = def_schema["allOf"] + + # Check if all refs are internal + all_internal = True + for item in all_of: + if isinstance(item, dict) and "$ref" in item: + ref = item["$ref"] + if not ref.startswith("#/"): + all_internal = False + break + + if all_internal: + # Flatten the allOf by inlining refs + merged = {} + for item in all_of: + resolved = inline_internal_refs(item, defs, set()) + # Merge properties + for k, v in resolved.items(): + if k == "properties" and k in merged: + merged[k].update(v) + elif k == "required" and k in merged: + merged[k] = list(set(merged[k] + v)) + elif k not in ["title", "description", "allOf"]: + merged[k] = v + + # Keep original title and description + if "title" in def_schema: + merged["title"] = def_schema["title"] + if "description" in def_schema: + merged["description"] = def_schema["description"] + + defs[def_name] = merged + + return schema + + +def preprocess_schema_file(input_path: Path, output_path: Path) -> None: + """Preprocess a single schema file.""" + with open(input_path, 'r', encoding='utf-8') as f: + schema = json.load(f) + + # Remove extension definitions that reference external schemas + schema = remove_extension_defs(schema) + + # Flatten allOf patterns within $defs that only use internal refs + schema = flatten_allof_in_defs(schema) + + # Ensure output directory exists + output_path.parent.mkdir(parents=True, exist_ok=True) + + # Write preprocessed schema + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(schema, f, indent=2) + + +def preprocess_schemas(input_dir: Path, output_dir: Path) -> None: + """Preprocess all schema files in the directory tree.""" + # Clean output directory + if output_dir.exists(): + shutil.rmtree(output_dir) + output_dir.mkdir(parents=True) + + # Find all JSON files + json_files = list(input_dir.rglob("*.json")) + + print(f"Preprocessing {len(json_files)} schema files...") + + for json_file in json_files: + # Calculate relative path + rel_path = json_file.relative_to(input_dir) + output_path = output_dir / rel_path + + print(f" Processing: {rel_path}") + preprocess_schema_file(json_file, output_path) + + print(f"Preprocessing complete. Output in {output_dir}") + + +if __name__ == "__main__": + script_dir = Path(__file__).parent + input_schemas = script_dir / "ucp" / "source" + output_schemas = script_dir / "temp_schemas" + + preprocess_schemas(input_schemas, output_schemas) diff --git a/pyproject.toml b/pyproject.toml index d4d858a..78695e0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,23 +43,4 @@ custom-file-header = """ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable -""" - -[tool.ruff] -line-length = 80 -indent-width = 2 - -[tool.ruff.format] -quote-style = "double" -indent-style = "space" -skip-magic-trailing-comma = false -line-ending = "auto" -docstring-code-format = true - -[tool.ruff.lint] -select = ["E", "F", "W", "B", "C4", "SIM", "N", "UP", "D", "PTH", "T20"] - -[tool.ruff.lint.isort] -combine-as-imports = true -force-sort-within-sections = true -case-sensitive = true +""" \ No newline at end of file diff --git a/src/ucp_sdk/__init__.py b/src/ucp_sdk/__init__.py deleted file mode 100644 index 6762e09..0000000 --- a/src/ucp_sdk/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""UCP Python SDK.""" - - -def hello() -> str: - return "Hello from ucp-python-sdk!" diff --git a/src/ucp_sdk/models/_internal.py b/src/ucp_sdk/models/_internal.py deleted file mode 100644 index edad471..0000000 --- a/src/ucp_sdk/models/_internal.py +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Any -from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel - - -class UcpCapability(RootModel[Any]): - root: Any = Field(..., title="UCP Capability") - """ - Schema for UCP capabilities and extensions. Extensions are capabilities with an 'extends' field. Uses reverse-domain naming for governance. - """ - - -class Base(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - name: str | None = Field( - None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$" - ) - """ - Stable capability identifier in reverse-domain notation (e.g., dev.ucp.shopping.checkout). Used in capability negotiation. - """ - version: Version | None = None - """ - Capability version in YYYY-MM-DD format. - """ - spec: AnyUrl | None = None - """ - URL to human-readable specification document. - """ - schema_: AnyUrl | None = Field(None, alias="schema") - """ - URL to JSON Schema for this capability's payload. - """ - extends: str | None = Field( - None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$" - ) - """ - Parent capability this extends. Present for extensions, absent for root capabilities. - """ - config: dict[str, Any] | None = None - """ - Capability-specific configuration (structure defined by each capability). - """ - - -class Discovery(Base): - """Full capability declaration for discovery profiles. Includes spec/schema URLs for agent fetching.""" - - model_config = ConfigDict( - extra="allow", - ) - - -class Response(Base): - """Capability reference in responses. Only name/version required to confirm active capabilities.""" - - model_config = ConfigDict( - extra="allow", - ) - - -class UcpMetadata(RootModel[Any]): - root: Any = Field(..., title="UCP Metadata") - """ - Protocol metadata for discovery profiles and responses. Uses slim schema pattern with context-specific required fields. - """ - - -class Version(RootModel[str]): - root: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") - """ - UCP protocol version in YYYY-MM-DD format. - """ - - -class Services(RootModel[dict[str, "UcpService"]]): - """Service definitions keyed by reverse-domain service name.""" - - root: dict[str, UcpService] - - -class DiscoveryProfile(BaseModel): - """Full UCP metadata for /.well-known/ucp discovery.""" - - model_config = ConfigDict( - extra="allow", - ) - version: Version - services: Services - capabilities: list[Discovery] - """ - Supported capabilities and extensions. - """ - - -class ResponseCheckout(BaseModel): - """UCP metadata for checkout responses.""" - - model_config = ConfigDict( - extra="allow", - ) - version: Version - capabilities: list[Response] - """ - Active capabilities for this response. - """ - - -class ResponseOrder(BaseModel): - """UCP metadata for order responses. No payment handlers needed post-purchase.""" - - model_config = ConfigDict( - extra="allow", - ) - version: Version - capabilities: list[Response] - """ - Active capabilities for this response. - """ - - -class Rest(BaseModel): - """REST transport binding.""" - - model_config = ConfigDict( - extra="allow", - ) - schema_: AnyUrl = Field(..., alias="schema") - """ - URL to OpenAPI 3.x specification (JSON format) - """ - endpoint: AnyUrl - """ - Merchant's REST API endpoint - """ - - -class Mcp(BaseModel): - """MCP transport binding.""" - - model_config = ConfigDict( - extra="allow", - ) - schema_: AnyUrl = Field(..., alias="schema") - """ - URL to OpenRPC specification (JSON format) - """ - endpoint: AnyUrl - """ - Merchant's MCP endpoint - """ - - -class A2a(BaseModel): - """A2A transport binding.""" - - model_config = ConfigDict( - extra="allow", - ) - endpoint: AnyUrl - """ - Merchant's Agent Card endpoint - """ - - -class Embedded(BaseModel): - """Embedded transport binding (JSON-RPC 2.0 over postMessage). Unlike REST/MCP, the endpoint is per-capability (i.e. per-checkout via continue_url), not per-service.""" - - model_config = ConfigDict( - extra="allow", - ) - schema_: AnyUrl = Field(..., alias="schema") - """ - URL to OpenRPC specification (JSON format) defining the embedded protocol - """ - - -class UcpService(BaseModel): - """Schema for UCP service definitions. A service defines the API surface for a vertical (shopping, common, etc.) with transport bindings.""" - - model_config = ConfigDict( - extra="allow", - ) - version: Version - """ - Service version in YYYY-MM-DD format. - """ - spec: AnyUrl - """ - URL to service documentation. Origin MUST match namespace authority. - """ - rest: Rest | None = None - """ - REST transport binding - """ - mcp: Mcp | None = None - """ - MCP transport binding - """ - a2a: A2a | None = None - """ - A2A transport binding - """ - embedded: Embedded | None = None - """ - Embedded transport binding (JSON-RPC 2.0 over postMessage). Unlike REST/MCP, the endpoint is per-capability (i.e. per-checkout via continue_url), not per-service. - """ diff --git a/src/ucp_sdk/models/discovery/profile_schema.py b/src/ucp_sdk/models/discovery/profile_schema.py index bef9040..68ec227 100644 --- a/src/ucp_sdk/models/discovery/profile_schema.py +++ b/src/ucp_sdk/models/discovery/profile_schema.py @@ -19,77 +19,105 @@ from __future__ import annotations from typing import Literal -from pydantic import BaseModel, ConfigDict -from ..schemas.shopping.types import payment_handler_resp -from .._internal import DiscoveryProfile + +from pydantic import BaseModel, ConfigDict, Field, RootModel + +from ..schemas import ucp as ucp_1 class SigningKey(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - kid: str - """ + """ + Public key for signature verification in JWK format. + """ + + model_config = ConfigDict( + extra="allow", + ) + kid: str + """ Key ID. Referenced in signature headers to identify which key to use for verification. """ - kty: str - """ + kty: str + """ Key type (e.g., 'EC', 'RSA'). """ - crv: str | None = None - """ + crv: str | None = None + """ Curve name for EC keys (e.g., 'P-256'). """ - x: str | None = None - """ + x: str | None = None + """ X coordinate for EC public keys (base64url encoded). """ - y: str | None = None - """ + y: str | None = None + """ Y coordinate for EC public keys (base64url encoded). """ - n: str | None = None - """ + n: str | None = None + """ Modulus for RSA public keys (base64url encoded). """ - e: str | None = None - """ + e: str | None = None + """ Exponent for RSA public keys (base64url encoded). """ - use: Literal["sig", "enc"] | None = None - """ + use: Literal["sig", "enc"] | None = None + """ Key usage. Should be 'sig' for signing keys. """ - alg: str | None = None - """ + alg: str | None = None + """ Algorithm (e.g., 'ES256', 'RS256'). """ -class Payment(BaseModel): - """Payment configuration containing handlers.""" +class PlatformProfile(BaseModel): + """ + Full discovery profile for platforms. Exposes complete service, capability, and payment handler registries. + """ + + model_config = ConfigDict( + extra="allow", + ) + ucp: ucp_1.PlatformSchema + signing_keys: list[SigningKey] | None = None + """ + Public keys for signature verification (JWK format). Used to verify signed responses, webhooks, and other authenticated messages from this party. + """ + + +class BusinessProfile(BaseModel): + """ + Discovery profile for businesses/merchants. Subset of platform profile with business-specific configuration. + """ + + model_config = ConfigDict( + extra="allow", + ) + ucp: ucp_1.BusinessSchema + signing_keys: list[SigningKey] | None = None + """ + Public keys for signature verification (JWK format). Used to verify signed responses, webhooks, and other authenticated messages from this party. + """ + - model_config = ConfigDict( - extra="allow", - ) - handlers: list[payment_handler_resp.PaymentHandlerResponse] | None = None - """ - Payment handler definitions that describe how instruments can be collected +class UcpDiscoveryProfile(RootModel[PlatformProfile | BusinessProfile]): + root: PlatformProfile | BusinessProfile = Field(..., title="UCP Discovery Profile") + """ + Schema for UCP discovery profiles. Business profiles are hosted at /.well-known/ucp; platform profiles are hosted at URIs advertised in request headers. """ -class UcpDiscoveryProfile(BaseModel): - """Schema for UCP discovery profile returned from /.well-known/ucp.""" +class Base(BaseModel): + """ + Base discovery profile with shared properties for all profile types. + """ - model_config = ConfigDict( - extra="allow", - ) - ucp: DiscoveryProfile - payment: Payment | None = None - """ - Payment configuration containing handlers + model_config = ConfigDict( + extra="allow", + ) + ucp: ucp_1.Base + signing_keys: list[SigningKey] | None = None """ - signing_keys: list[SigningKey] | None = None - """ Public keys for signature verification (JWK format). Used to verify signed responses, webhooks, and other authenticated messages from this party. """ diff --git a/src/ucp_sdk/models/handlers/tokenization/openapi.py b/src/ucp_sdk/models/handlers/tokenization/openapi.py index e8b3b8c..66b2502 100644 --- a/src/ucp_sdk/models/handlers/tokenization/openapi.py +++ b/src/ucp_sdk/models/handlers/tokenization/openapi.py @@ -19,8 +19,9 @@ from __future__ import annotations from typing import Any + from pydantic import RootModel class Model(RootModel[Any]): - root: Any + root: Any diff --git a/src/ucp_sdk/models/ruff.toml b/src/ucp_sdk/models/ruff.toml new file mode 100644 index 0000000..9473cff --- /dev/null +++ b/src/ucp_sdk/models/ruff.toml @@ -0,0 +1,16 @@ +# Ruff configuration for generated models +# These are auto-generated files, so we're more lenient with style rules + +line-length = 120 +target-version = "py311" + +[lint] +select = ["E", "F", "I"] +ignore = ["E501"] + +[lint.pydocstyle] +convention = "google" + +[lint.per-file-ignores] +"__init__.py" = ["D104"] +"*.py" = ["D100", "D101", "D102", "D103", "D200", "D205", "D212"] diff --git a/src/ucp_sdk/models/schemas/capability.py b/src/ucp_sdk/models/schemas/capability.py index 26dc3d7..5145d47 100644 --- a/src/ucp_sdk/models/schemas/capability.py +++ b/src/ucp_sdk/models/schemas/capability.py @@ -18,6 +18,38 @@ from __future__ import annotations -from .._internal import Base, Discovery, Response, UcpCapability +from typing import Any -__all__ = ["Base", "Discovery", "Response", "UcpCapability"] +from pydantic import Field, RootModel + + +class UcpCapability(RootModel[Any]): + root: Any = Field(..., title="UCP Capability") + """ + Schema for UCP capabilities and extensions. Extensions are capabilities with an 'extends' field. Uses reverse-domain naming for governance. + """ + + +class PlatformSchema(RootModel[Any]): + root: Any = Field(..., title="Capability (Platform Schema)") + """ + Full capability declaration for platform-level discovery. Includes spec/schema URLs for agent fetching. + """ + + +class Base(RootModel[Any]): + root: Any + + +class BusinessSchema(RootModel[Base]): + root: Base = Field(..., title="Capability (Business Schema)") + """ + Capability configuration for business/merchant level. May include business-specific config overrides. + """ + + +class ResponseSchema(RootModel[Base]): + root: Base = Field(..., title="Capability (Response Schema)") + """ + Capability reference in responses. Only name/version required to confirm active capabilities. + """ diff --git a/src/ucp_sdk/models/schemas/payment_handler.py b/src/ucp_sdk/models/schemas/payment_handler.py new file mode 100644 index 0000000..5ddf666 --- /dev/null +++ b/src/ucp_sdk/models/schemas/payment_handler.py @@ -0,0 +1,55 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from typing import Any + +from pydantic import Field, RootModel + + +class PaymentHandler(RootModel[Any]): + root: Any = Field(..., title="Payment Handler") + """ + Schema for UCP payment handlers. Handlers define how payment instruments are processed. + """ + + +class PlatformSchema(RootModel[Any]): + root: Any = Field(..., title="Payment Handler (Platform Schema)") + """ + Platform declaration for discovery profiles. May include partial config state required for discovery. + """ + + +class Base(RootModel[Any]): + root: Any + + +class BusinessSchema(RootModel[Base]): + root: Base = Field(..., title="Payment Handler (Business Schema)") + """ + Business declaration for discovery profiles. May include partial config state required for discovery. + """ + + +class ResponseSchema(RootModel[Base]): + root: Base = Field(..., title="Payment Handler (Response Schema)") + """ + Handler reference in responses. May include full config state for runtime usage of the handler. + """ diff --git a/src/ucp_sdk/models/schemas/service.py b/src/ucp_sdk/models/schemas/service.py new file mode 100644 index 0000000..227ca16 --- /dev/null +++ b/src/ucp_sdk/models/schemas/service.py @@ -0,0 +1,197 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from typing import Any, Literal + +from pydantic import BaseModel, ConfigDict, Field, RootModel + +from .transports import embedded_config + + +class UcpService(RootModel[Any]): + root: Any = Field(..., title="UCP Service") + """ + Service binding for a specific transport. Each transport binding is a separate entry in the service array. + """ + + +class PlatformSchema(BaseModel): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" + + +class PlatformSchema5(BaseModel): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" + + +class PlatformSchema6(BaseModel): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" + + +class PlatformSchema7(BaseModel): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + + +class PlatformSchema3(RootModel[PlatformSchema | PlatformSchema5 | PlatformSchema6 | PlatformSchema7]): + root: PlatformSchema | PlatformSchema5 | PlatformSchema6 | PlatformSchema7 = Field( + ..., title="Service (Platform Schema)" + ) + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + +class BusinessSchema(BaseModel): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" + + +class BusinessSchema4(BaseModel): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" + + +class BusinessSchema5(BaseModel): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" + + +class BusinessSchema6(BaseModel): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + config: embedded_config.EmbeddedTransportConfig | None = None + + +class BusinessSchema2(RootModel[BusinessSchema | BusinessSchema4 | BusinessSchema5 | BusinessSchema6]): + root: BusinessSchema | BusinessSchema4 | BusinessSchema5 | BusinessSchema6 = Field( + ..., title="Service (Business Schema)" + ) + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + +class ResponseSchema(BaseModel): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" + + +class ResponseSchema4(BaseModel): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" + + +class ResponseSchema5(BaseModel): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" + + +class ResponseSchema6(BaseModel): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + config: embedded_config.EmbeddedTransportConfig | None = None + + +class ResponseSchema2(RootModel[ResponseSchema | ResponseSchema4 | ResponseSchema5 | ResponseSchema6]): + root: ResponseSchema | ResponseSchema4 | ResponseSchema5 | ResponseSchema6 = Field( + ..., title="Service (Response Schema)" + ) + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + +class Base(RootModel[Any]): + root: Any diff --git a/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py b/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py index a41ef4c..cecaa1c 100644 --- a/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py +++ b/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py @@ -19,109 +19,89 @@ from __future__ import annotations from typing import Any, Literal + from pydantic import BaseModel, ConfigDict, Field, RootModel -from .checkout_resp import CheckoutResponse class Ap2MandateExtension(RootModel[Any]): - root: Any = Field(..., title="AP2 Mandate Extension") - """ + root: Any = Field(..., title="AP2 Mandate Extension") + """ Extends Checkout with cryptographic mandate support for non-repudiable authorization per the AP2 protocol. Uses embedded signature model with ap2 namespace. """ class MerchantAuthorization(RootModel[str]): - root: str = Field( - ..., - pattern="^[A-Za-z0-9_-]+\\.\\.[A-Za-z0-9_-]+$", - title="Merchant Authorization", - ) - """ + root: str = Field( + ..., + pattern="^[A-Za-z0-9_-]+\\.\\.[A-Za-z0-9_-]+$", + title="Merchant Authorization", + ) + """ JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: `..`. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload. """ class CheckoutMandate(RootModel[str]): - root: str = Field( - ..., - pattern="^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]+(~[A-Za-z0-9_-]+)*$", - title="Checkout Mandate", - ) - """ + root: str = Field( + ..., + pattern="^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]+(~[A-Za-z0-9_-]+)*$", + title="Checkout Mandate", + ) + """ SD-JWT+kb credential in `ap2.checkout_mandate`. Proving user authorization for the checkout. Contains the full checkout including `ap2.merchant_authorization`. """ -class Ap2CheckoutResponse(BaseModel): - """The ap2 object included in checkout responses when AP2 is negotiated.""" +class Ap2WithMerchantAuthorization(BaseModel): + """ + AP2 extension data including merchant authorization. + """ - model_config = ConfigDict( - extra="allow", - ) - merchant_authorization: MerchantAuthorization - """ + model_config = ConfigDict( + extra="allow", + ) + merchant_authorization: str | None = None + """ Merchant's signature proving checkout terms are authentic. """ -class Ap2CompleteRequest(BaseModel): - """The ap2 object included in complete_checkout requests when AP2 is negotiated.""" +class Ap2WithCheckoutMandate(BaseModel): + """ + AP2 extension data including checkout mandate. + """ - model_config = ConfigDict( - extra="allow", - ) - checkout_mandate: CheckoutMandate - """ + model_config = ConfigDict( + extra="allow", + ) + checkout_mandate: str | None = None + """ SD-JWT+kb proving user authorized this checkout. """ class ErrorCode( - RootModel[ - Literal[ - "mandate_required", - "agent_missing_key", - "mandate_invalid_signature", - "mandate_expired", - "mandate_scope_mismatch", - "merchant_authorization_invalid", - "merchant_authorization_missing", + RootModel[ + Literal[ + "mandate_required", + "agent_missing_key", + "mandate_invalid_signature", + "mandate_expired", + "mandate_scope_mismatch", + "merchant_authorization_invalid", + "merchant_authorization_missing", + ] ] - ] ): - root: Literal[ - "mandate_required", - "agent_missing_key", - "mandate_invalid_signature", - "mandate_expired", - "mandate_scope_mismatch", - "merchant_authorization_invalid", - "merchant_authorization_missing", - ] = Field(..., title="AP2 Error Code") - """ - Error codes specific to AP2 mandate verification. - """ - - -class CompleteRequestWithAp2(BaseModel): - """Extension fields for complete_checkout when AP2 is negotiated.""" - - model_config = ConfigDict( - extra="allow", - ) - ap2: Ap2CompleteRequest | None = None - """ - AP2 extension data including checkout mandate. + root: Literal[ + "mandate_required", + "agent_missing_key", + "mandate_invalid_signature", + "mandate_expired", + "mandate_scope_mismatch", + "merchant_authorization_invalid", + "merchant_authorization_missing", + ] = Field(..., title="AP2 Error Code") """ - - -class CheckoutResponseWithAp2(CheckoutResponse): - """Checkout extended with AP2 embedded signature support.""" - - model_config = ConfigDict( - extra="allow", - ) - ap2: Ap2CheckoutResponse | None = None - """ - AP2 extension data including merchant authorization. + Error codes specific to AP2 mandate verification. """ diff --git a/src/ucp_sdk/models/schemas/shopping/buyer_consent_resp.py b/src/ucp_sdk/models/schemas/shopping/buyer_consent.py similarity index 56% rename from src/ucp_sdk/models/schemas/shopping/buyer_consent_resp.py rename to src/ucp_sdk/models/schemas/shopping/buyer_consent.py index f2117fb..d7b3c74 100644 --- a/src/ucp_sdk/models/schemas/shopping/buyer_consent_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/buyer_consent.py @@ -19,61 +19,38 @@ from __future__ import annotations from typing import Any + from pydantic import BaseModel, ConfigDict, Field, RootModel -from .types.buyer import Buyer as Buyer_1 -from .checkout_resp import CheckoutResponse -class BuyerConsentExtensionResponse(RootModel[Any]): - root: Any = Field(..., title="Buyer Consent Extension Response") - """ +class BuyerConsentExtension(RootModel[Any]): + root: Any = Field(..., title="Buyer Consent Extension") + """ Extends Checkout with buyer consent tracking for privacy compliance via the buyer object. """ class Consent(BaseModel): - """User consent states for data processing.""" + """ + User consent states for data processing + """ - model_config = ConfigDict( - extra="allow", - ) - analytics: bool | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + analytics: bool | None = None + """ Consent for analytics and performance tracking. """ - preferences: bool | None = None - """ + preferences: bool | None = None + """ Consent for storing user preferences. """ - marketing: bool | None = None - """ - Consent for marketing communications. + marketing: bool | None = None """ - sale_of_data: bool | None = None - """ - Consent for selling data to third parties (CCPA). + Consent for marketing communications. """ - - -class Buyer(Buyer_1): - """Buyer object extended with consent tracking.""" - - model_config = ConfigDict( - extra="allow", - ) - consent: Consent | None = None - """ - Consent tracking fields. + sale_of_data: bool | None = None """ - - -class Checkout(CheckoutResponse): - """Checkout extended with consent tracking via buyer object.""" - - model_config = ConfigDict( - extra="allow", - ) - buyer: Buyer | None = None - """ - Buyer with consent tracking. + Consent for selling data to third parties (CCPA). """ diff --git a/src/ucp_sdk/models/schemas/shopping/buyer_consent_create_req.py b/src/ucp_sdk/models/schemas/shopping/buyer_consent_create_req.py deleted file mode 100644 index f1d2dae..0000000 --- a/src/ucp_sdk/models/schemas/shopping/buyer_consent_create_req.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Any -from pydantic import BaseModel, ConfigDict, Field, RootModel -from .types.buyer import Buyer as Buyer_1 -from .checkout_create_req import CheckoutCreateRequest - - -class BuyerConsentExtensionCreateRequest(RootModel[Any]): - root: Any = Field(..., title="Buyer Consent Extension Create Request") - """ - Extends Checkout with buyer consent tracking for privacy compliance via the buyer object. - """ - - -class Consent(BaseModel): - """User consent states for data processing.""" - - model_config = ConfigDict( - extra="allow", - ) - analytics: bool | None = None - """ - Consent for analytics and performance tracking. - """ - preferences: bool | None = None - """ - Consent for storing user preferences. - """ - marketing: bool | None = None - """ - Consent for marketing communications. - """ - sale_of_data: bool | None = None - """ - Consent for selling data to third parties (CCPA). - """ - - -class Buyer(Buyer_1): - """Buyer object extended with consent tracking.""" - - model_config = ConfigDict( - extra="allow", - ) - consent: Consent | None = None - """ - Consent tracking fields. - """ - - -class Checkout(CheckoutCreateRequest): - """Checkout extended with consent tracking via buyer object.""" - - model_config = ConfigDict( - extra="allow", - ) - buyer: Buyer | None = None - """ - Buyer with consent tracking. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/buyer_consent_update_req.py b/src/ucp_sdk/models/schemas/shopping/buyer_consent_update_req.py deleted file mode 100644 index 33d4e84..0000000 --- a/src/ucp_sdk/models/schemas/shopping/buyer_consent_update_req.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Any -from pydantic import BaseModel, ConfigDict, Field, RootModel -from .types.buyer import Buyer as Buyer_1 -from .checkout_update_req import CheckoutUpdateRequest - - -class BuyerConsentExtensionUpdateRequest(RootModel[Any]): - root: Any = Field(..., title="Buyer Consent Extension Update Request") - """ - Extends Checkout with buyer consent tracking for privacy compliance via the buyer object. - """ - - -class Consent(BaseModel): - """User consent states for data processing.""" - - model_config = ConfigDict( - extra="allow", - ) - analytics: bool | None = None - """ - Consent for analytics and performance tracking. - """ - preferences: bool | None = None - """ - Consent for storing user preferences. - """ - marketing: bool | None = None - """ - Consent for marketing communications. - """ - sale_of_data: bool | None = None - """ - Consent for selling data to third parties (CCPA). - """ - - -class Buyer(Buyer_1): - """Buyer object extended with consent tracking.""" - - model_config = ConfigDict( - extra="allow", - ) - consent: Consent | None = None - """ - Consent tracking fields. - """ - - -class Checkout(CheckoutUpdateRequest): - """Checkout extended with consent tracking via buyer object.""" - - model_config = ConfigDict( - extra="allow", - ) - buyer: Buyer | None = None - """ - Buyer with consent tracking. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/cart.py b/src/ucp_sdk/models/schemas/shopping/cart.py new file mode 100644 index 0000000..d66c2c7 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/cart.py @@ -0,0 +1,128 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from typing import Any + +from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict + +from .types import line_item, link, message, total + + +class Context(BaseModel): + """ + Buyer signals for localization (country, region, postal_code). Merchant uses for pricing, availability, currency. Falls back to geo-IP if omitted. + """ + + model_config = ConfigDict( + extra="allow", + ) + address_country: str | None = None + """ + The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. + """ + address_region: str | None = None + """ + The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. + """ + postal_code: str | None = None + """ + The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. + """ + intent: str | None = None + """ + Background context describing buyer's intent (e.g., 'looking for a gift under $50', 'need something durable for outdoor use'). Informs relevance, recommendations, and personalization. + """ + + +class Buyer(BaseModel): + """ + Optional buyer information for personalized estimates. + """ + + model_config = ConfigDict( + extra="allow", + ) + first_name: str | None = None + """ + First name of the buyer. + """ + last_name: str | None = None + """ + Last name of the buyer. + """ + email: str | None = None + """ + Email of the buyer. + """ + phone_number: str | None = None + """ + E.164 standard. + """ + + +class Cart(BaseModel): + """ + Shopping cart with estimated pricing before checkout. Lightweight pre-purchase exploration with no payment info or complex status states. Cart exists (200) or doesn't (404). + """ + + model_config = ConfigDict( + extra="allow", + ) + ucp: Any + id: str + """ + Unique cart identifier. + """ + line_items: list[line_item.LineItem] + """ + Cart line items. Same structure as checkout. Full replacement on update. + """ + context: Context | None = None + """ + Buyer signals for localization (country, region, postal_code). Merchant uses for pricing, availability, currency. Falls back to geo-IP if omitted. + """ + buyer: Buyer | None = None + """ + Optional buyer information for personalized estimates. + """ + currency: str + """ + ISO 4217 currency code. Determined by merchant based on context or geo-IP. + """ + totals: list[total.Total] + """ + Estimated cost breakdown. May be partial if shipping/tax not yet calculable. + """ + messages: list[message.Message] | None = None + """ + Validation messages, warnings, or informational notices. + """ + links: list[link.Link] | None = None + """ + Optional merchant links (policies, FAQs). + """ + continue_url: AnyUrl | None = None + """ + URL for cart handoff and session recovery. Enables sharing and human-in-the-loop flows. + """ + expires_at: AwareDatetime | None = None + """ + Cart expiry timestamp (RFC 3339). Optional. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/checkout.py b/src/ucp_sdk/models/schemas/shopping/checkout.py new file mode 100644 index 0000000..62a0d69 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/checkout.py @@ -0,0 +1,190 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from typing import Any, Literal + +from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict, Field + +from .types import line_item, link, message, payment_instrument, total + + +class Ucp(BaseModel): + """ + UCP metadata for checkout responses. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") + """ + UCP version in YYYY-MM-DD format. + """ + services: Any | None = None + capabilities: Any | None = None + payment_handlers: Any + + +class Buyer(BaseModel): + """ + Representation of the buyer. + """ + + model_config = ConfigDict( + extra="allow", + ) + first_name: str | None = None + """ + First name of the buyer. + """ + last_name: str | None = None + """ + Last name of the buyer. + """ + email: str | None = None + """ + Email of the buyer. + """ + phone_number: str | None = None + """ + E.164 standard. + """ + + +class Context(BaseModel): + """ + Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context SHOULD be non-identifying and can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. + """ + + model_config = ConfigDict( + extra="allow", + ) + address_country: str | None = None + """ + The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. + """ + address_region: str | None = None + """ + The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. + """ + postal_code: str | None = None + """ + The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. + """ + intent: str | None = None + """ + Background context describing buyer's intent (e.g., 'looking for a gift under $50', 'need something durable for outdoor use'). Informs relevance, recommendations, and personalization. + """ + + +class Order(BaseModel): + """ + Details about an order created for this checkout session. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + Unique order identifier. + """ + permalink_url: AnyUrl + """ + Permalink to access the order on merchant site. + """ + + +class Payment(BaseModel): + """ + Payment configuration containing handlers. + """ + + model_config = ConfigDict( + extra="allow", + ) + instruments: list[payment_instrument.SelectedPaymentInstrument] | None = None + """ + The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. + """ + + +class Checkout(BaseModel): + """ + Base checkout schema. Extensions compose onto this using allOf. + """ + + model_config = ConfigDict( + extra="allow", + ) + ucp: Ucp + id: str + """ + Unique identifier of the checkout session. + """ + line_items: list[line_item.LineItem] + """ + List of line items being checked out. + """ + buyer: Buyer | None = None + """ + Representation of the buyer. + """ + context: Context | None = None + status: Literal[ + "incomplete", + "requires_escalation", + "ready_for_complete", + "complete_in_progress", + "completed", + "canceled", + ] + """ + Checkout state indicating the current phase and required action. See Checkout Status lifecycle documentation for state transition details. + """ + currency: str + """ + ISO 4217 currency code reflecting the merchant's market determination. Derived from address, context, and geo IP—buyers provide signals, merchants determine currency. + """ + totals: list[total.Total] + """ + Different cart totals. + """ + messages: list[message.Message] | None = None + """ + List of messages with error and info about the checkout session state. + """ + links: list[link.Link] + """ + Links to be displayed by the platform (Privacy Policy, TOS). Mandatory for legal compliance. + """ + expires_at: AwareDatetime | None = None + """ + RFC 3339 expiry timestamp. Default TTL is 6 hours from creation if not sent. + """ + continue_url: AnyUrl | None = None + """ + URL for checkout handoff and session recovery. MUST be provided when status is requires_escalation. See specification for format and availability requirements. + """ + payment: Payment | None = None + order: Order | None = None + """ + Details about an order created for this checkout session. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_create_req.py b/src/ucp_sdk/models/schemas/shopping/checkout_create_req.py deleted file mode 100644 index ad53d1f..0000000 --- a/src/ucp_sdk/models/schemas/shopping/checkout_create_req.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict -from .types import buyer as buyer_1, line_item_create_req -from . import payment_create_req - - -class CheckoutCreateRequest(BaseModel): - """Base checkout schema. Extensions compose onto this using allOf.""" - - model_config = ConfigDict( - extra="allow", - ) - line_items: list[line_item_create_req.LineItemCreateRequest] - """ - List of line items being checked out. - """ - buyer: buyer_1.Buyer | None = None - """ - Representation of the buyer. - """ - currency: str - """ - ISO 4217 currency code. - """ - payment: payment_create_req.PaymentCreateRequest diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_resp.py b/src/ucp_sdk/models/schemas/shopping/checkout_resp.py deleted file mode 100644 index 46085e3..0000000 --- a/src/ucp_sdk/models/schemas/shopping/checkout_resp.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Literal -from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict -from ..._internal import ResponseCheckout -from .types import ( - buyer as buyer_1, - line_item_resp, - link, - message, - order_confirmation, - total_resp, -) -from . import payment_resp - - -class CheckoutResponse(BaseModel): - """Base checkout schema. Extensions compose onto this using allOf.""" - - model_config = ConfigDict( - extra="allow", - ) - ucp: ResponseCheckout - id: str - """ - Unique identifier of the checkout session. - """ - line_items: list[line_item_resp.LineItemResponse] - """ - List of line items being checked out. - """ - buyer: buyer_1.Buyer | None = None - """ - Representation of the buyer. - """ - status: Literal[ - "incomplete", - "requires_escalation", - "ready_for_complete", - "complete_in_progress", - "completed", - "canceled", - ] - """ - Checkout state indicating the current phase and required action. See Checkout Status lifecycle documentation for state transition details. - """ - currency: str - """ - ISO 4217 currency code. - """ - totals: list[total_resp.TotalResponse] - """ - Different cart totals. - """ - messages: list[message.Message] | None = None - """ - List of messages with error and info about the checkout session state. - """ - links: list[link.Link] - """ - Links to be displayed by the platform (Privacy Policy, TOS). Mandatory for legal compliance. - """ - expires_at: AwareDatetime | None = None - """ - RFC 3339 expiry timestamp. Default TTL is 6 hours from creation if not sent. - """ - continue_url: AnyUrl | None = None - """ - URL for checkout handoff and session recovery. MUST be provided when status is requires_escalation. See specification for format and availability requirements. - """ - payment: payment_resp.PaymentResponse - order: order_confirmation.OrderConfirmation | None = None - """ - Details about an order created for this checkout session. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_update_req.py b/src/ucp_sdk/models/schemas/shopping/checkout_update_req.py deleted file mode 100644 index 6234448..0000000 --- a/src/ucp_sdk/models/schemas/shopping/checkout_update_req.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict -from .types import buyer as buyer_1, line_item_update_req -from . import payment_update_req - - -class CheckoutUpdateRequest(BaseModel): - """Base checkout schema. Extensions compose onto this using allOf.""" - - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Unique identifier of the checkout session. - """ - line_items: list[line_item_update_req.LineItemUpdateRequest] - """ - List of line items being checked out. - """ - buyer: buyer_1.Buyer | None = None - """ - Representation of the buyer. - """ - currency: str - """ - ISO 4217 currency code. - """ - payment: payment_update_req.PaymentUpdateRequest diff --git a/src/ucp_sdk/models/schemas/shopping/discount_resp.py b/src/ucp_sdk/models/schemas/shopping/discount.py similarity index 63% rename from src/ucp_sdk/models/schemas/shopping/discount_resp.py rename to src/ucp_sdk/models/schemas/shopping/discount.py index 86fd012..952ded6 100644 --- a/src/ucp_sdk/models/schemas/shopping/discount_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/discount.py @@ -19,89 +19,86 @@ from __future__ import annotations from typing import Any, Literal + from pydantic import BaseModel, ConfigDict, Field, RootModel -from .checkout_resp import CheckoutResponse -class DiscountExtensionResponse(RootModel[Any]): - root: Any = Field(..., title="Discount Extension Response") - """ +class DiscountExtension(RootModel[Any]): + root: Any = Field(..., title="Discount Extension") + """ Extends Checkout with discount code support, enabling agents to apply promotional, loyalty, referral, and other discount codes. """ class Allocation(BaseModel): - """Breakdown of how a discount amount was allocated to a specific target.""" + """ + Breakdown of how a discount amount was allocated to a specific target. + """ - model_config = ConfigDict( - extra="allow", - ) - path: str - """ + model_config = ConfigDict( + extra="allow", + ) + path: str + """ JSONPath to the allocation target (e.g., '$.line_items[0]', '$.totals.shipping'). """ - amount: int = Field(..., ge=0) - """ + amount: int = Field(..., ge=0) + """ Amount allocated to this target in minor (cents) currency units. """ class AppliedDiscount(BaseModel): - """A discount that was successfully applied.""" + """ + A discount that was successfully applied. + """ - model_config = ConfigDict( - extra="allow", - ) - code: str | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + code: str | None = None + """ The discount code. Omitted for automatic discounts. """ - title: str - """ + title: str + """ Human-readable discount name (e.g., 'Summer Sale 20% Off'). """ - amount: int = Field(..., ge=0) - """ + amount: int = Field(..., ge=0) + """ Total discount amount in minor (cents) currency units. """ - automatic: bool | None = False - """ + automatic: bool | None = False + """ True if applied automatically by merchant rules (no code required). """ - method: Literal["each", "across"] | None = None - """ + method: Literal["each", "across"] | None = None + """ Allocation method. 'each' = applied independently per item. 'across' = split proportionally by value. """ - priority: int | None = Field(None, ge=1) - """ + priority: int | None = Field(None, ge=1) + """ Stacking order for discount calculation. Lower numbers applied first (1 = first). """ - allocations: list[Allocation] | None = None - """ + allocations: list[Allocation] | None = None + """ Breakdown of where this discount was allocated. Sum of allocation amounts equals total amount. """ class DiscountsObject(BaseModel): - """Discount codes input and applied discounts output.""" + """ + Discount codes input and applied discounts output. + """ - model_config = ConfigDict( - extra="allow", - ) - codes: list[str] | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + codes: list[str] | None = None + """ Discount codes to apply. Case-insensitive. Replaces previously submitted codes. Send empty array to clear. """ - applied: list[AppliedDiscount] | None = None - """ + applied: list[AppliedDiscount] | None = None + """ Discounts successfully applied (code-based and automatic). """ - - -class Checkout(CheckoutResponse): - """Checkout extended with discount capability.""" - - model_config = ConfigDict( - extra="allow", - ) - discounts: DiscountsObject | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/discount_create_req.py b/src/ucp_sdk/models/schemas/shopping/discount_create_req.py deleted file mode 100644 index 7595bb1..0000000 --- a/src/ucp_sdk/models/schemas/shopping/discount_create_req.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Any, Literal -from pydantic import BaseModel, ConfigDict, Field, RootModel -from .checkout_create_req import CheckoutCreateRequest - - -class DiscountExtensionCreateRequest(RootModel[Any]): - root: Any = Field(..., title="Discount Extension Create Request") - """ - Extends Checkout with discount code support, enabling agents to apply promotional, loyalty, referral, and other discount codes. - """ - - -class Allocation(BaseModel): - """Breakdown of how a discount amount was allocated to a specific target.""" - - model_config = ConfigDict( - extra="allow", - ) - path: str - """ - JSONPath to the allocation target (e.g., '$.line_items[0]', '$.totals.shipping'). - """ - amount: int = Field(..., ge=0) - """ - Amount allocated to this target in minor (cents) currency units. - """ - - -class AppliedDiscount(BaseModel): - """A discount that was successfully applied.""" - - model_config = ConfigDict( - extra="allow", - ) - code: str | None = None - """ - The discount code. Omitted for automatic discounts. - """ - title: str - """ - Human-readable discount name (e.g., 'Summer Sale 20% Off'). - """ - amount: int = Field(..., ge=0) - """ - Total discount amount in minor (cents) currency units. - """ - automatic: bool | None = False - """ - True if applied automatically by merchant rules (no code required). - """ - method: Literal["each", "across"] | None = None - """ - Allocation method. 'each' = applied independently per item. 'across' = split proportionally by value. - """ - priority: int | None = Field(None, ge=1) - """ - Stacking order for discount calculation. Lower numbers applied first (1 = first). - """ - allocations: list[Allocation] | None = None - """ - Breakdown of where this discount was allocated. Sum of allocation amounts equals total amount. - """ - - -class DiscountsObject(BaseModel): - """Discount codes input and applied discounts output.""" - - model_config = ConfigDict( - extra="allow", - ) - codes: list[str] | None = None - """ - Discount codes to apply. Case-insensitive. Replaces previously submitted codes. Send empty array to clear. - """ - applied: list[AppliedDiscount] | None = None - """ - Discounts successfully applied (code-based and automatic). - """ - - -class Checkout(CheckoutCreateRequest): - """Checkout extended with discount capability.""" - - model_config = ConfigDict( - extra="allow", - ) - discounts: DiscountsObject | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/discount_update_req.py b/src/ucp_sdk/models/schemas/shopping/discount_update_req.py deleted file mode 100644 index a724dc2..0000000 --- a/src/ucp_sdk/models/schemas/shopping/discount_update_req.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Any, Literal -from pydantic import BaseModel, ConfigDict, Field, RootModel -from .checkout_update_req import CheckoutUpdateRequest - - -class DiscountExtensionUpdateRequest(RootModel[Any]): - root: Any = Field(..., title="Discount Extension Update Request") - """ - Extends Checkout with discount code support, enabling agents to apply promotional, loyalty, referral, and other discount codes. - """ - - -class Allocation(BaseModel): - """Breakdown of how a discount amount was allocated to a specific target.""" - - model_config = ConfigDict( - extra="allow", - ) - path: str - """ - JSONPath to the allocation target (e.g., '$.line_items[0]', '$.totals.shipping'). - """ - amount: int = Field(..., ge=0) - """ - Amount allocated to this target in minor (cents) currency units. - """ - - -class AppliedDiscount(BaseModel): - """A discount that was successfully applied.""" - - model_config = ConfigDict( - extra="allow", - ) - code: str | None = None - """ - The discount code. Omitted for automatic discounts. - """ - title: str - """ - Human-readable discount name (e.g., 'Summer Sale 20% Off'). - """ - amount: int = Field(..., ge=0) - """ - Total discount amount in minor (cents) currency units. - """ - automatic: bool | None = False - """ - True if applied automatically by merchant rules (no code required). - """ - method: Literal["each", "across"] | None = None - """ - Allocation method. 'each' = applied independently per item. 'across' = split proportionally by value. - """ - priority: int | None = Field(None, ge=1) - """ - Stacking order for discount calculation. Lower numbers applied first (1 = first). - """ - allocations: list[Allocation] | None = None - """ - Breakdown of where this discount was allocated. Sum of allocation amounts equals total amount. - """ - - -class DiscountsObject(BaseModel): - """Discount codes input and applied discounts output.""" - - model_config = ConfigDict( - extra="allow", - ) - codes: list[str] | None = None - """ - Discount codes to apply. Case-insensitive. Replaces previously submitted codes. Send empty array to clear. - """ - applied: list[AppliedDiscount] | None = None - """ - Discounts successfully applied (code-based and automatic). - """ - - -class Checkout(CheckoutUpdateRequest): - """Checkout extended with discount capability.""" - - model_config = ConfigDict( - extra="allow", - ) - discounts: DiscountsObject | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py b/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py new file mode 100644 index 0000000..3390b86 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py @@ -0,0 +1,58 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from typing import Any + +from pydantic import Field, RootModel + +from ..types import ( + fulfillment, + fulfillment_available_method, + fulfillment_group, + fulfillment_method, + fulfillment_option, +) + + +class FulfillmentExtension(RootModel[Any]): + root: Any = Field(..., title="Fulfillment Extension") + """ + Extends Checkout with fulfillment support using methods, destinations, and groups. + """ + + +class FulfillmentAvailableMethod(RootModel[fulfillment_available_method.FulfillmentAvailableMethod]): + root: fulfillment_available_method.FulfillmentAvailableMethod + + +class FulfillmentOption(RootModel[fulfillment_option.FulfillmentOption]): + root: fulfillment_option.FulfillmentOption + + +class FulfillmentGroup(RootModel[fulfillment_group.FulfillmentGroup]): + root: fulfillment_group.FulfillmentGroup + + +class FulfillmentMethod(RootModel[fulfillment_method.FulfillmentMethod]): + root: fulfillment_method.FulfillmentMethod + + +class Fulfillment(RootModel[fulfillment.Fulfillment]): + root: fulfillment.Fulfillment diff --git a/src/ucp_sdk/models/__init__.py b/src/ucp_sdk/models/schemas/shopping/fulfillment/dev/__init__.py similarity index 100% rename from src/ucp_sdk/models/__init__.py rename to src/ucp_sdk/models/schemas/shopping/fulfillment/dev/__init__.py diff --git a/src/ucp_sdk/models/services/service_schema.py b/src/ucp_sdk/models/schemas/shopping/fulfillment/dev/ucp/__init__.py similarity index 80% rename from src/ucp_sdk/models/services/service_schema.py rename to src/ucp_sdk/models/schemas/shopping/fulfillment/dev/ucp/__init__.py index 3272570..421dc21 100644 --- a/src/ucp_sdk/models/services/service_schema.py +++ b/src/ucp_sdk/models/schemas/shopping/fulfillment/dev/ucp/__init__.py @@ -16,8 +16,3 @@ # pylint: disable=all # pyformat: disable -from __future__ import annotations - -from .._internal import A2a, Embedded, Mcp, Rest, UcpService - -__all__ = ["A2a", "Embedded", "Mcp", "Rest", "UcpService"] diff --git a/src/ucp_sdk/models/services/shopping/rest_openapi.py b/src/ucp_sdk/models/schemas/shopping/fulfillment/dev/ucp/shopping.py similarity index 93% rename from src/ucp_sdk/models/services/shopping/rest_openapi.py rename to src/ucp_sdk/models/schemas/shopping/fulfillment/dev/ucp/shopping.py index e8b3b8c..cc3e02d 100644 --- a/src/ucp_sdk/models/services/shopping/rest_openapi.py +++ b/src/ucp_sdk/models/schemas/shopping/fulfillment/dev/ucp/shopping.py @@ -19,8 +19,9 @@ from __future__ import annotations from typing import Any + from pydantic import RootModel -class Model(RootModel[Any]): - root: Any +class Fulfillment(RootModel[Any]): + root: Any diff --git a/src/ucp_sdk/models/schemas/shopping/fulfillment_create_req.py b/src/ucp_sdk/models/schemas/shopping/fulfillment_create_req.py deleted file mode 100644 index 3e1abf8..0000000 --- a/src/ucp_sdk/models/schemas/shopping/fulfillment_create_req.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Any -from pydantic import ConfigDict, Field, RootModel -from .types import ( - fulfillment_available_method_req, - fulfillment_group_create_req, - fulfillment_method_create_req, - fulfillment_option_req, - fulfillment_req, -) -from .checkout_create_req import CheckoutCreateRequest - - -class FulfillmentExtensionCreateRequest(RootModel[Any]): - root: Any = Field(..., title="Fulfillment Extension Create Request") - """ - Extends Checkout with fulfillment support using methods, destinations, and groups. - """ - - -class FulfillmentOption( - RootModel[fulfillment_option_req.FulfillmentOptionRequest] -): - root: fulfillment_option_req.FulfillmentOptionRequest - - -class FulfillmentGroup( - RootModel[fulfillment_group_create_req.FulfillmentGroupCreateRequest] -): - root: fulfillment_group_create_req.FulfillmentGroupCreateRequest - - -class FulfillmentAvailableMethod( - RootModel[fulfillment_available_method_req.FulfillmentAvailableMethodRequest] -): - root: fulfillment_available_method_req.FulfillmentAvailableMethodRequest - - -class FulfillmentMethod( - RootModel[fulfillment_method_create_req.FulfillmentMethodCreateRequest] -): - root: fulfillment_method_create_req.FulfillmentMethodCreateRequest - - -class Fulfillment(RootModel[fulfillment_req.FulfillmentRequest]): - root: fulfillment_req.FulfillmentRequest - - -class Checkout(CheckoutCreateRequest): - """Checkout extended with hierarchical fulfillment.""" - - model_config = ConfigDict( - extra="allow", - ) - fulfillment: Fulfillment | None = None - """ - Fulfillment details. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/fulfillment_resp.py b/src/ucp_sdk/models/schemas/shopping/fulfillment_resp.py deleted file mode 100644 index ff445dc..0000000 --- a/src/ucp_sdk/models/schemas/shopping/fulfillment_resp.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Any -from pydantic import ConfigDict, Field, RootModel -from .types import ( - fulfillment_available_method_resp, - fulfillment_group_resp, - fulfillment_method_resp, - fulfillment_option_resp, - fulfillment_resp, -) -from .checkout_resp import CheckoutResponse - - -class FulfillmentExtensionResponse(RootModel[Any]): - root: Any = Field(..., title="Fulfillment Extension Response") - """ - Extends Checkout with fulfillment support using methods, destinations, and groups. - """ - - -class FulfillmentAvailableMethod( - RootModel[ - fulfillment_available_method_resp.FulfillmentAvailableMethodResponse - ] -): - root: fulfillment_available_method_resp.FulfillmentAvailableMethodResponse - - -class FulfillmentOption( - RootModel[fulfillment_option_resp.FulfillmentOptionResponse] -): - root: fulfillment_option_resp.FulfillmentOptionResponse - - -class FulfillmentGroup( - RootModel[fulfillment_group_resp.FulfillmentGroupResponse] -): - root: fulfillment_group_resp.FulfillmentGroupResponse - - -class FulfillmentMethod( - RootModel[fulfillment_method_resp.FulfillmentMethodResponse] -): - root: fulfillment_method_resp.FulfillmentMethodResponse - - -class Fulfillment(RootModel[fulfillment_resp.FulfillmentResponse]): - root: fulfillment_resp.FulfillmentResponse - - -class Checkout(CheckoutResponse): - """Checkout extended with hierarchical fulfillment.""" - - model_config = ConfigDict( - extra="allow", - ) - fulfillment: Fulfillment | None = None - """ - Fulfillment details. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/fulfillment_update_req.py b/src/ucp_sdk/models/schemas/shopping/fulfillment_update_req.py deleted file mode 100644 index 01d1608..0000000 --- a/src/ucp_sdk/models/schemas/shopping/fulfillment_update_req.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Any -from pydantic import ConfigDict, Field, RootModel -from .types import ( - fulfillment_available_method_req, - fulfillment_group_update_req, - fulfillment_method_update_req, - fulfillment_option_req, - fulfillment_req, -) -from .checkout_update_req import CheckoutUpdateRequest - - -class FulfillmentExtensionUpdateRequest(RootModel[Any]): - root: Any = Field(..., title="Fulfillment Extension Update Request") - """ - Extends Checkout with fulfillment support using methods, destinations, and groups. - """ - - -class FulfillmentOption( - RootModel[fulfillment_option_req.FulfillmentOptionRequest] -): - root: fulfillment_option_req.FulfillmentOptionRequest - - -class FulfillmentGroup( - RootModel[fulfillment_group_update_req.FulfillmentGroupUpdateRequest] -): - root: fulfillment_group_update_req.FulfillmentGroupUpdateRequest - - -class FulfillmentAvailableMethod( - RootModel[fulfillment_available_method_req.FulfillmentAvailableMethodRequest] -): - root: fulfillment_available_method_req.FulfillmentAvailableMethodRequest - - -class FulfillmentMethod( - RootModel[fulfillment_method_update_req.FulfillmentMethodUpdateRequest] -): - root: fulfillment_method_update_req.FulfillmentMethodUpdateRequest - - -class Fulfillment(RootModel[fulfillment_req.FulfillmentRequest]): - root: fulfillment_req.FulfillmentRequest - - -class Checkout(CheckoutUpdateRequest): - """Checkout extended with hierarchical fulfillment.""" - - model_config = ConfigDict( - extra="allow", - ) - fulfillment: Fulfillment | None = None - """ - Fulfillment details. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/order.py b/src/ucp_sdk/models/schemas/shopping/order.py index eeed457..645cd05 100644 --- a/src/ucp_sdk/models/schemas/shopping/order.py +++ b/src/ucp_sdk/models/schemas/shopping/order.py @@ -19,76 +19,77 @@ from __future__ import annotations from pydantic import AnyUrl, BaseModel, ConfigDict -from .types import ( - adjustment, - expectation, - fulfillment_event, - order_line_item, - total_resp, -) -from ..._internal import ResponseOrder +from .. import ucp as ucp_1 +from .types import adjustment, expectation, fulfillment_event, order_line_item, total -class PlatformConfig(BaseModel): - """Platform's order capability configuration.""" - model_config = ConfigDict( - extra="allow", - ) - webhook_url: AnyUrl - """ +class PlatformSchema(BaseModel): + """ + Platform's order capability configuration. + """ + + model_config = ConfigDict( + extra="allow", + ) + webhook_url: AnyUrl + """ URL where merchant sends order lifecycle events (webhooks). """ class Fulfillment(BaseModel): - """Fulfillment data: buyer expectations and what actually happened.""" + """ + Fulfillment data: buyer expectations and what actually happened. + """ - model_config = ConfigDict( - extra="allow", - ) - expectations: list[expectation.Expectation] | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + expectations: list[expectation.Expectation] | None = None + """ Buyer-facing groups representing when/how items will be delivered. Can be split, merged, or adjusted post-order. """ - events: list[fulfillment_event.FulfillmentEvent] | None = None - """ + events: list[fulfillment_event.FulfillmentEvent] | None = None + """ Append-only event log of actual shipments. Each event references line items by ID. """ class Order(BaseModel): - """Order schema with immutable line items, buyer-facing fulfillment expectations, and append-only event logs.""" + """ + Order schema with immutable line items, buyer-facing fulfillment expectations, and append-only event logs. + """ - model_config = ConfigDict( - extra="allow", - ) - ucp: ResponseOrder - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + ucp: ucp_1.ResponseOrderSchema + id: str + """ Unique order identifier. """ - checkout_id: str - """ + checkout_id: str + """ Associated checkout ID for reconciliation. """ - permalink_url: AnyUrl - """ + permalink_url: AnyUrl + """ Permalink to access the order on merchant site. """ - line_items: list[order_line_item.OrderLineItem] - """ + line_items: list[order_line_item.OrderLineItem] + """ Immutable line items — source of truth for what was ordered. """ - fulfillment: Fulfillment - """ + fulfillment: Fulfillment + """ Fulfillment data: buyer expectations and what actually happened. """ - adjustments: list[adjustment.Adjustment] | None = None - """ + adjustments: list[adjustment.Adjustment] | None = None + """ Append-only event log of money movements (refunds, returns, credits, disputes, cancellations, etc.) that exist independently of fulfillment. """ - totals: list[total_resp.TotalResponse] - """ + totals: list[total.Total] + """ Different totals for the order. """ diff --git a/src/ucp_sdk/models/schemas/shopping/payment_update_req.py b/src/ucp_sdk/models/schemas/shopping/payment.py similarity index 69% rename from src/ucp_sdk/models/schemas/shopping/payment_update_req.py rename to src/ucp_sdk/models/schemas/shopping/payment.py index 083d0a7..a4f5d78 100644 --- a/src/ucp_sdk/models/schemas/shopping/payment_update_req.py +++ b/src/ucp_sdk/models/schemas/shopping/payment.py @@ -19,20 +19,19 @@ from __future__ import annotations from pydantic import BaseModel, ConfigDict + from .types import payment_instrument -class PaymentUpdateRequest(BaseModel): - """Payment configuration containing handlers.""" +class Payment(BaseModel): + """ + Payment configuration containing handlers. + """ - model_config = ConfigDict( - extra="allow", - ) - selected_instrument_id: str | None = None - """ - The id of the currently selected payment instrument from the instruments array. Set by the agent when submitting payment, and echoed back by the merchant in finalized state. + model_config = ConfigDict( + extra="allow", + ) + instruments: list[payment_instrument.SelectedPaymentInstrument] | None = None """ - instruments: list[payment_instrument.PaymentInstrument] | None = None - """ The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. """ diff --git a/src/ucp_sdk/models/schemas/shopping/payment_create_req.py b/src/ucp_sdk/models/schemas/shopping/payment_create_req.py deleted file mode 100644 index 1b5359d..0000000 --- a/src/ucp_sdk/models/schemas/shopping/payment_create_req.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict -from .types import payment_instrument - - -class PaymentCreateRequest(BaseModel): - """Payment configuration containing handlers.""" - - model_config = ConfigDict( - extra="allow", - ) - selected_instrument_id: str | None = None - """ - The id of the currently selected payment instrument from the instruments array. Set by the agent when submitting payment, and echoed back by the merchant in finalized state. - """ - instruments: list[payment_instrument.PaymentInstrument] | None = None - """ - The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/payment_data.py b/src/ucp_sdk/models/schemas/shopping/payment_data.py deleted file mode 100644 index 5a8a03d..0000000 --- a/src/ucp_sdk/models/schemas/shopping/payment_data.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict -from .types import payment_instrument - - -class PaymentData(BaseModel): - """The data that will used to submit payment to the merchant.""" - - model_config = ConfigDict( - extra="allow", - ) - payment_data: payment_instrument.PaymentInstrument diff --git a/src/ucp_sdk/models/schemas/shopping/payment_resp.py b/src/ucp_sdk/models/schemas/shopping/payment_resp.py deleted file mode 100644 index e8dda1d..0000000 --- a/src/ucp_sdk/models/schemas/shopping/payment_resp.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict -from .types import payment_handler_resp, payment_instrument - - -class PaymentResponse(BaseModel): - """Payment configuration containing handlers.""" - - model_config = ConfigDict( - extra="allow", - ) - handlers: list[payment_handler_resp.PaymentHandlerResponse] - """ - Processing configurations that define how payment instruments can be collected. Each handler specifies a tokenization or payment collection strategy. - """ - selected_instrument_id: str | None = None - """ - The id of the currently selected payment instrument from the instruments array. Set by the agent when submitting payment, and echoed back by the merchant in finalized state. - """ - instruments: list[payment_instrument.PaymentInstrument] | None = None - """ - The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/account_info.py b/src/ucp_sdk/models/schemas/shopping/types/account_info.py index f06f00f..aeb2665 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/account_info.py +++ b/src/ucp_sdk/models/schemas/shopping/types/account_info.py @@ -22,12 +22,14 @@ class PaymentAccountInfo(BaseModel): - """Non-sensitive backend identifiers for linking.""" + """ + Non-sensitive backend identifiers for linking. + """ - model_config = ConfigDict( - extra="allow", - ) - payment_account_reference: str | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + payment_account_reference: str | None = None + """ EMVCo PAR. A unique identifier linking a payment card to a specific account, enabling tracking across tokens (Apple Pay, physical card, etc). """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/adjustment.py b/src/ucp_sdk/models/schemas/shopping/types/adjustment.py index 17719e6..f28c0ea 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/adjustment.py +++ b/src/ucp_sdk/models/schemas/shopping/types/adjustment.py @@ -18,55 +18,58 @@ from __future__ import annotations -from pydantic import AwareDatetime, BaseModel, ConfigDict, Field from typing import Literal +from pydantic import AwareDatetime, BaseModel, ConfigDict, Field + class LineItem(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Line item ID reference. """ - quantity: int = Field(..., ge=1) - """ + quantity: int = Field(..., ge=1) + """ Quantity affected by this adjustment. """ class Adjustment(BaseModel): - """Append-only event that exists independently of fulfillment. Typically represents money movements but can be any post-order change. Polymorphic type that can optionally reference line items.""" + """ + Append-only event that exists independently of fulfillment. Typically represents money movements but can be any post-order change. Polymorphic type that can optionally reference line items. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Adjustment event identifier. """ - type: str - """ + type: str + """ Type of adjustment (open string). Typically money-related like: refund, return, credit, price_adjustment, dispute, cancellation. Can be any value that makes sense for the merchant's business. """ - occurred_at: AwareDatetime - """ + occurred_at: AwareDatetime + """ RFC 3339 timestamp when this adjustment occurred. """ - status: Literal["pending", "completed", "failed"] - """ + status: Literal["pending", "completed", "failed"] + """ Adjustment status. """ - line_items: list[LineItem] | None = None - """ + line_items: list[LineItem] | None = None + """ Which line items and quantities are affected (optional). """ - amount: int | None = None - """ + amount: int | None = None + """ Amount in minor units (cents) for refunds, credits, price adjustments (optional). """ - description: str | None = None - """ + description: str | None = None + """ Human-readable reason or description (e.g., 'Defective item', 'Customer requested'). """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/binding.py b/src/ucp_sdk/models/schemas/shopping/types/binding.py index c4971ca..16f6961 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/binding.py +++ b/src/ucp_sdk/models/schemas/shopping/types/binding.py @@ -19,20 +19,23 @@ from __future__ import annotations from pydantic import BaseModel, ConfigDict + from . import payment_identity class Binding(BaseModel): - """Binds a token to a specific checkout session and participant. Prevents token reuse across different checkouts or participants.""" + """ + Binds a token to a specific checkout session and participant. Prevents token reuse across different checkouts or participants. + """ - model_config = ConfigDict( - extra="allow", - ) - checkout_id: str - """ + model_config = ConfigDict( + extra="allow", + ) + checkout_id: str + """ The checkout session identifier this token is bound to. """ - identity: payment_identity.PaymentIdentity | None = None - """ + identity: payment_identity.PaymentIdentity | None = None + """ The participant this token is bound to. Required when acting on behalf of another participant (e.g., agent tokenizing for merchant). Omit when the authenticated caller is the binding target. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py b/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py new file mode 100644 index 0000000..2786056 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py @@ -0,0 +1,59 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from typing import Literal + +from pydantic import BaseModel, ConfigDict + + +class AllowsMultiDestination(BaseModel): + """ + Permits multiple destinations per method type. + """ + + model_config = ConfigDict( + extra="allow", + ) + shipping: bool | None = None + """ + Multiple shipping destinations allowed. + """ + pickup: bool | None = None + """ + Multiple pickup locations allowed. + """ + + +class BusinessFulfillmentConfig(BaseModel): + """ + Business's fulfillment configuration. + """ + + model_config = ConfigDict( + extra="allow", + ) + allows_multi_destination: AllowsMultiDestination | None = None + """ + Permits multiple destinations per method type. + """ + allows_method_combinations: list[list[Literal["shipping", "pickup"]]] | None = None + """ + Allowed method type combinations. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/buyer.py b/src/ucp_sdk/models/schemas/shopping/types/buyer.py index c93c729..ff8ef6a 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/buyer.py +++ b/src/ucp_sdk/models/schemas/shopping/types/buyer.py @@ -22,26 +22,22 @@ class Buyer(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - first_name: str | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + first_name: str | None = None + """ First name of the buyer. """ - last_name: str | None = None - """ + last_name: str | None = None + """ Last name of the buyer. """ - full_name: str | None = None - """ - Optional, buyer's full name (if first_name or last_name fields are present they take precedence). + email: str | None = None """ - email: str | None = None - """ Email of the buyer. """ - phone_number: str | None = None - """ + phone_number: str | None = None + """ E.164 standard. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/card_credential.py b/src/ucp_sdk/models/schemas/shopping/types/card_credential.py index 40854dc..43b231a 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/card_credential.py +++ b/src/ucp_sdk/models/schemas/shopping/types/card_credential.py @@ -19,48 +19,53 @@ from __future__ import annotations from typing import Literal -from pydantic import BaseModel, ConfigDict, Field +from pydantic import ConfigDict, Field -class CardCredential(BaseModel): - """A card credential containing sensitive payment card details including raw Primary Account Numbers (PANs). This credential type MUST NOT be used for checkout, only with payment handlers that tokenize or encrypt credentials. CRITICAL: Both parties handling CardCredential (sender and receiver) MUST be PCI DSS compliant. Transmission MUST use HTTPS/TLS with strong cipher suites.""" +from .payment_credential import PaymentCredential - model_config = ConfigDict( - extra="allow", - ) - type: Literal["card"] - """ + +class CardCredential(PaymentCredential): + """ + A card credential containing sensitive payment card details including raw Primary Account Numbers (PANs). This credential type MUST NOT be used for checkout, only with payment handlers that tokenize or encrypt credentials. CRITICAL: Both parties handling CardCredential (sender and receiver) MUST be PCI DSS compliant. Transmission MUST use HTTPS/TLS with strong cipher suites. + """ + + model_config = ConfigDict( + extra="allow", + ) + type: Literal["card"] + """ The credential type identifier for card credentials. """ - card_number_type: Literal["fpan", "network_token", "dpan"] - """ + card_number_type: Literal["fpan", "network_token", "dpan"] + """ The type of card number. Network tokens are preferred with fallback to FPAN. See PCI Scope for more details. """ - number: str | None = Field(None, examples=["4242424242424242"]) - """ + number: str | None = Field(None, examples=["4242424242424242"]) + """ Card number. """ - expiry_month: int | None = None - """ + expiry_month: int | None = None + """ The month of the card's expiration date (1-12). """ - expiry_year: int | None = None - """ + expiry_year: int | None = None + """ The year of the card's expiration date. """ - name: str | None = Field(None, examples=["Jane Doe"]) - """ + name: str | None = Field(None, examples=["Jane Doe"]) + """ Cardholder name. """ - cvc: str | None = Field(None, examples=["223"], max_length=4) - """ + cvc: str | None = Field(None, examples=["223"], max_length=4) + """ Card CVC number. """ - cryptogram: str | None = Field(None, examples=["gXc5UCLnM6ckD7pjM1TdPA=="]) - """ + cryptogram: str | None = Field(None, examples=["gXc5UCLnM6ckD7pjM1TdPA=="]) + """ Cryptogram provided with network tokens. """ - eci_value: str | None = Field(None, examples=["07"]) - """ + eci_value: str | None = Field(None, examples=["07"]) + """ Electronic Commerce Indicator / Security Level Indicator provided with network tokens. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/card_payment_instrument.py b/src/ucp_sdk/models/schemas/shopping/types/card_payment_instrument.py index f57d38e..e5cffa1 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/card_payment_instrument.py +++ b/src/ucp_sdk/models/schemas/shopping/types/card_payment_instrument.py @@ -19,41 +19,59 @@ from __future__ import annotations from typing import Literal -from pydantic import AnyUrl, ConfigDict -from .payment_instrument_base import PaymentInstrumentBase +from pydantic import AnyUrl, BaseModel, ConfigDict -class CardPaymentInstrument(PaymentInstrumentBase): - """A basic card payment instrument with visible card details. Can be inherited by a handler's instrument schema to define handler-specific display details or more complex credential structures.""" +from .payment_instrument import PaymentInstrument - model_config = ConfigDict( - extra="allow", - ) - type: Literal["card"] - """ - Indicates this is a card payment instrument. + +class Display(BaseModel): + """ + Display information for this card payment instrument. + """ + + model_config = ConfigDict( + extra="allow", + ) + brand: str | None = None """ - brand: str - """ The card brand/network (e.g., visa, mastercard, amex). """ - last_digits: str - """ + last_digits: str | None = None + """ Last 4 digits of the card number. """ - expiry_month: int | None = None - """ + expiry_month: int | None = None + """ The month of the card's expiration date (1-12). """ - expiry_year: int | None = None - """ + expiry_year: int | None = None + """ The year of the card's expiration date. """ - rich_text_description: str | None = None - """ + description: str | None = None + """ An optional rich text description of the card to display to the user (e.g., 'Visa ending in 1234, expires 12/2025'). """ - rich_card_art: AnyUrl | None = None - """ + card_art: AnyUrl | None = None + """ An optional URI to a rich image representing the card (e.g., card art provided by the issuer). """ + + +class CardPaymentInstrument(PaymentInstrument): + """ + A basic card payment instrument with visible card details. Can be inherited by a handler's instrument schema to define handler-specific display details or more complex credential structures. + """ + + model_config = ConfigDict( + extra="allow", + ) + type: Literal["card"] + """ + Indicates this is a card payment instrument. + """ + display: Display | None = None + """ + Display information for this card payment instrument. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/context.py b/src/ucp_sdk/models/schemas/shopping/types/context.py new file mode 100644 index 0000000..cf73cf1 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/context.py @@ -0,0 +1,47 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class Context(BaseModel): + """ + Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context SHOULD be non-identifying and can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. + """ + + model_config = ConfigDict( + extra="allow", + ) + address_country: str | None = None + """ + The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. + """ + address_region: str | None = None + """ + The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. + """ + postal_code: str | None = None + """ + The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. + """ + intent: str | None = None + """ + Background context describing buyer's intent (e.g., 'looking for a gift under $50', 'need something durable for outdoor use'). Informs relevance, recommendations, and personalization. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/expectation.py b/src/ucp_sdk/models/schemas/shopping/types/expectation.py index 28b85a5..03e8182 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/expectation.py +++ b/src/ucp_sdk/models/schemas/shopping/types/expectation.py @@ -18,52 +18,56 @@ from __future__ import annotations -from pydantic import BaseModel, ConfigDict, Field from typing import Literal + +from pydantic import BaseModel, ConfigDict, Field + from . import postal_address class LineItem(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Line item ID reference. """ - quantity: int = Field(..., ge=1) - """ + quantity: int = Field(..., ge=1) + """ Quantity of this item in this expectation. """ class Expectation(BaseModel): - """Buyer-facing fulfillment expectation representing logical groupings of items (e.g., 'package'). Can be split, merged, or adjusted post-order to set buyer expectations for when/how items arrive.""" + """ + Buyer-facing fulfillment expectation representing logical groupings of items (e.g., 'package'). Can be split, merged, or adjusted post-order to set buyer expectations for when/how items arrive. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Expectation identifier. """ - line_items: list[LineItem] - """ + line_items: list[LineItem] + """ Which line items and quantities are in this expectation. """ - method_type: Literal["shipping", "pickup", "digital"] - """ + method_type: Literal["shipping", "pickup", "digital"] + """ Delivery method type (shipping, pickup, digital). """ - destination: postal_address.PostalAddress - """ + destination: postal_address.PostalAddress + """ Delivery destination address. """ - description: str | None = None - """ + description: str | None = None + """ Human-readable delivery description (e.g., 'Arrives in 5-8 business days'). """ - fulfillable_on: str | None = None - """ + fulfillable_on: str | None = None + """ When this expectation can be fulfilled: 'now' or ISO 8601 timestamp for future date (backorder, pre-order). """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_resp.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment.py similarity index 65% rename from src/ucp_sdk/models/schemas/shopping/types/fulfillment_resp.py rename to src/ucp_sdk/models/schemas/shopping/types/fulfillment.py index 2c23ea1..5603b07 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment.py @@ -19,23 +19,23 @@ from __future__ import annotations from pydantic import BaseModel, ConfigDict -from . import fulfillment_available_method_resp, fulfillment_method_resp +from . import fulfillment_available_method, fulfillment_method -class FulfillmentResponse(BaseModel): - """Container for fulfillment methods and availability.""" - model_config = ConfigDict( - extra="allow", - ) - methods: list[fulfillment_method_resp.FulfillmentMethodResponse] | None = None - """ +class Fulfillment(BaseModel): + """ + Container for fulfillment methods and availability. + """ + + model_config = ConfigDict( + extra="allow", + ) + methods: list[fulfillment_method.FulfillmentMethod] | None = None + """ Fulfillment methods for cart items. """ - available_methods: ( - list[fulfillment_available_method_resp.FulfillmentAvailableMethodResponse] - | None - ) = None - """ + available_methods: list[fulfillment_available_method.FulfillmentAvailableMethod] | None = None + """ Inventory availability hints. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_resp.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method.py similarity index 75% rename from src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_resp.py rename to src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method.py index 9181950..4c9a1bb 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method.py @@ -19,28 +19,31 @@ from __future__ import annotations from typing import Literal + from pydantic import BaseModel, ConfigDict -class FulfillmentAvailableMethodResponse(BaseModel): - """Inventory availability hint for a fulfillment method type.""" +class FulfillmentAvailableMethod(BaseModel): + """ + Inventory availability hint for a fulfillment method type. + """ - model_config = ConfigDict( - extra="allow", - ) - type: Literal["shipping", "pickup"] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal["shipping", "pickup"] + """ Fulfillment method type this availability applies to. """ - line_item_ids: list[str] - """ + line_item_ids: list[str] + """ Line items available for this fulfillment method. """ - fulfillable_on: str | None = None - """ + fulfillable_on: str | None = None + """ 'now' for immediate availability, or ISO 8601 date for future (preorders, transfers). """ - description: str | None = None - """ + description: str | None = None + """ Human-readable availability info (e.g., 'Available for pickup at Downtown Store today'). """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_req.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_req.py deleted file mode 100644 index 6bb4ef5..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_req.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class FulfillmentAvailableMethodRequest(BaseModel): - """Inventory availability hint for a fulfillment method type.""" - - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination_req.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py similarity index 65% rename from src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination_req.py rename to src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py index e8d45eb..3f4351a 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination_req.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py @@ -19,19 +19,14 @@ from __future__ import annotations from pydantic import Field, RootModel -from . import retail_location_req, shipping_destination_req +from . import retail_location, shipping_destination -class FulfillmentDestinationRequest( - RootModel[ - shipping_destination_req.ShippingDestinationRequest - | retail_location_req.RetailLocationRequest - ] -): - root: ( - shipping_destination_req.ShippingDestinationRequest - | retail_location_req.RetailLocationRequest - ) = Field(..., title="Fulfillment Destination Request") - """ + +class FulfillmentDestination(RootModel[shipping_destination.ShippingDestination | retail_location.RetailLocation]): + root: shipping_destination.ShippingDestination | retail_location.RetailLocation = Field( + ..., title="Fulfillment Destination" + ) + """ A destination for fulfillment. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination_resp.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination_resp.py deleted file mode 100644 index 91ae5fb..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination_resp.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import Field, RootModel -from . import retail_location_resp, shipping_destination_resp - - -class FulfillmentDestinationResponse( - RootModel[ - shipping_destination_resp.ShippingDestinationResponse - | retail_location_resp.RetailLocationResponse - ] -): - root: ( - shipping_destination_resp.ShippingDestinationResponse - | retail_location_resp.RetailLocationResponse - ) = Field(..., title="Fulfillment Destination Response") - """ - A destination for fulfillment. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_event.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_event.py index 5711111..68e09c6 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_event.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_event.py @@ -22,54 +22,56 @@ class LineItem(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Line item ID reference. """ - quantity: int = Field(..., ge=1) - """ + quantity: int = Field(..., ge=1) + """ Quantity fulfilled in this event. """ class FulfillmentEvent(BaseModel): - """Append-only fulfillment event representing an actual shipment. References line items by ID.""" + """ + Append-only fulfillment event representing an actual shipment. References line items by ID. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Fulfillment event identifier. """ - occurred_at: AwareDatetime - """ + occurred_at: AwareDatetime + """ RFC 3339 timestamp when this fulfillment event occurred. """ - type: str - """ + type: str + """ Fulfillment event type. Common values include: processing (preparing to ship), shipped (handed to carrier), in_transit (in delivery network), delivered (received by buyer), failed_attempt (delivery attempt failed), canceled (fulfillment canceled), undeliverable (cannot be delivered), returned_to_sender (returned to merchant). """ - line_items: list[LineItem] - """ + line_items: list[LineItem] + """ Which line items and quantities are fulfilled in this event. """ - tracking_number: str | None = None - """ + tracking_number: str | None = None + """ Carrier tracking number (required if type != processing). """ - tracking_url: AnyUrl | None = None - """ + tracking_url: AnyUrl | None = None + """ URL to track this shipment (required if type != processing). """ - carrier: str | None = None - """ + carrier: str | None = None + """ Carrier name (e.g., 'FedEx', 'USPS'). """ - description: str | None = None - """ + description: str | None = None + """ Human-readable description of the shipment status or delivery information (e.g., 'Delivered to front door', 'Out for delivery'). """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_resp.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group.py similarity index 70% rename from src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_resp.py rename to src/ucp_sdk/models/schemas/shopping/types/fulfillment_group.py index cf00987..b3646b8 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group.py @@ -19,28 +19,31 @@ from __future__ import annotations from pydantic import BaseModel, ConfigDict -from . import fulfillment_option_resp +from . import fulfillment_option -class FulfillmentGroupResponse(BaseModel): - """A merchant-generated package/group of line items with fulfillment options.""" - model_config = ConfigDict( - extra="allow", - ) - id: str - """ +class FulfillmentGroup(BaseModel): + """ + A merchant-generated package/group of line items with fulfillment options. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Group identifier for referencing merchant-generated groups in updates. """ - line_item_ids: list[str] - """ + line_item_ids: list[str] + """ Line item IDs included in this group/package. """ - options: list[fulfillment_option_resp.FulfillmentOptionResponse] | None = None - """ + options: list[fulfillment_option.FulfillmentOption] | None = None + """ Available fulfillment options for this group. """ - selected_option_id: str | None = None - """ + selected_option_id: str | None = None + """ ID of the selected fulfillment option for this group. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_req.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_req.py deleted file mode 100644 index 171cf2b..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_req.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class FulfillmentGroupCreateRequest(BaseModel): - """A merchant-generated package/group of line items with fulfillment options.""" - - model_config = ConfigDict( - extra="allow", - ) - selected_option_id: str | None = None - """ - ID of the selected fulfillment option for this group. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_resp.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py similarity index 66% rename from src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_resp.py rename to src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py index a593d84..f6608d0 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py @@ -19,39 +19,41 @@ from __future__ import annotations from typing import Literal + from pydantic import BaseModel, ConfigDict -from . import fulfillment_destination_resp, fulfillment_group_resp +from . import fulfillment_destination, fulfillment_group -class FulfillmentMethodResponse(BaseModel): - """A fulfillment method (shipping or pickup) with destinations and groups.""" - model_config = ConfigDict( - extra="allow", - ) - id: str - """ +class FulfillmentMethod(BaseModel): + """ + A fulfillment method (shipping or pickup) with destinations and groups. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Unique fulfillment method identifier. """ - type: Literal["shipping", "pickup"] - """ + type: Literal["shipping", "pickup"] + """ Fulfillment method type. """ - line_item_ids: list[str] - """ + line_item_ids: list[str] + """ Line item IDs fulfilled via this method. """ - destinations: ( - list[fulfillment_destination_resp.FulfillmentDestinationResponse] | None - ) = None - """ + destinations: list[fulfillment_destination.FulfillmentDestination] | None = None + """ Available destinations. For shipping: addresses. For pickup: retail locations. """ - selected_destination_id: str | None = None - """ + selected_destination_id: str | None = None + """ ID of the selected destination. """ - groups: list[fulfillment_group_resp.FulfillmentGroupResponse] | None = None - """ + groups: list[fulfillment_group.FulfillmentGroup] | None = None + """ Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_req.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_req.py deleted file mode 100644 index 3c2e61d..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_req.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Literal -from pydantic import BaseModel, ConfigDict -from . import fulfillment_destination_req, fulfillment_group_create_req - - -class FulfillmentMethodCreateRequest(BaseModel): - """A fulfillment method (shipping or pickup) with destinations and groups.""" - - model_config = ConfigDict( - extra="allow", - ) - type: Literal["shipping", "pickup"] - """ - Fulfillment method type. - """ - line_item_ids: list[str] | None = None - """ - Line item IDs fulfilled via this method. - """ - destinations: ( - list[fulfillment_destination_req.FulfillmentDestinationRequest] | None - ) = None - """ - Available destinations. For shipping: addresses. For pickup: retail locations. - """ - selected_destination_id: str | None = None - """ - ID of the selected destination. - """ - groups: ( - list[fulfillment_group_create_req.FulfillmentGroupCreateRequest] | None - ) = None - """ - Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_req.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_req.py deleted file mode 100644 index 253f03f..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_req.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict -from . import fulfillment_destination_req, fulfillment_group_update_req - - -class FulfillmentMethodUpdateRequest(BaseModel): - """A fulfillment method (shipping or pickup) with destinations and groups.""" - - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Unique fulfillment method identifier. - """ - line_item_ids: list[str] - """ - Line item IDs fulfilled via this method. - """ - destinations: ( - list[fulfillment_destination_req.FulfillmentDestinationRequest] | None - ) = None - """ - Available destinations. For shipping: addresses. For pickup: retail locations. - """ - selected_destination_id: str | None = None - """ - ID of the selected destination. - """ - groups: ( - list[fulfillment_group_update_req.FulfillmentGroupUpdateRequest] | None - ) = None - """ - Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_resp.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option.py similarity index 68% rename from src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_resp.py rename to src/ucp_sdk/models/schemas/shopping/types/fulfillment_option.py index 3ba75eb..93b3bf8 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option.py @@ -19,40 +19,43 @@ from __future__ import annotations from pydantic import AwareDatetime, BaseModel, ConfigDict -from . import total_resp +from . import total -class FulfillmentOptionResponse(BaseModel): - """A fulfillment option within a group (e.g., Standard Shipping $5, Express $15).""" - model_config = ConfigDict( - extra="allow", - ) - id: str - """ +class FulfillmentOption(BaseModel): + """ + A fulfillment option within a group (e.g., Standard Shipping $5, Express $15). + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Unique fulfillment option identifier. """ - title: str - """ + title: str + """ Short label (e.g., 'Express Shipping', 'Curbside Pickup'). """ - description: str | None = None - """ + description: str | None = None + """ Complete context for buyer decision (e.g., 'Arrives Dec 12-15 via FedEx'). """ - carrier: str | None = None - """ + carrier: str | None = None + """ Carrier name (for shipping). """ - earliest_fulfillment_time: AwareDatetime | None = None - """ + earliest_fulfillment_time: AwareDatetime | None = None + """ Earliest fulfillment date. """ - latest_fulfillment_time: AwareDatetime | None = None - """ + latest_fulfillment_time: AwareDatetime | None = None + """ Latest fulfillment date. """ - totals: list[total_resp.TotalResponse] - """ + totals: list[total.Total] + """ Fulfillment option totals breakdown. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_req.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_req.py deleted file mode 100644 index d33445e..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_req.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class FulfillmentOptionRequest(BaseModel): - """A fulfillment option within a group (e.g., Standard Shipping $5, Express $15).""" - - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_req.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_req.py deleted file mode 100644 index 560ce75..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_req.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict -from . import fulfillment_method_create_req - - -class FulfillmentRequest(BaseModel): - """Container for fulfillment methods and availability.""" - - model_config = ConfigDict( - extra="allow", - ) - methods: ( - list[fulfillment_method_create_req.FulfillmentMethodCreateRequest] | None - ) = None - """ - Fulfillment methods for cart items. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_resp.py b/src/ucp_sdk/models/schemas/shopping/types/item.py similarity index 69% rename from src/ucp_sdk/models/schemas/shopping/types/item_resp.py rename to src/ucp_sdk/models/schemas/shopping/types/item.py index 11b7afc..d942f0b 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/item_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/types/item.py @@ -21,23 +21,23 @@ from pydantic import AnyUrl, BaseModel, ConfigDict, Field -class ItemResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. - """ - title: str - """ +class Item(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + The product identifier, often the SKU, required to resolve the product details associated with this line item. Should be recognized by both the Platform, and the Business. + """ + title: str + """ Product title. """ - price: int = Field(..., ge=0) - """ + price: int = Field(..., ge=0) + """ Unit price in minor (cents) currency units. """ - image_url: AnyUrl | None = None - """ + image_url: AnyUrl | None = None + """ Product image URI. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_create_req.py b/src/ucp_sdk/models/schemas/shopping/types/item_create_req.py deleted file mode 100644 index 19e0d07..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/item_create_req.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class ItemCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_update_req.py b/src/ucp_sdk/models/schemas/shopping/types/item_update_req.py deleted file mode 100644 index 156fe97..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/item_update_req.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class ItemUpdateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_resp.py b/src/ucp_sdk/models/schemas/shopping/types/line_item.py similarity index 70% rename from src/ucp_sdk/models/schemas/shopping/types/line_item_resp.py rename to src/ucp_sdk/models/schemas/shopping/types/line_item.py index 963d6e6..9f2befe 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/line_item_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/types/line_item.py @@ -19,26 +19,30 @@ from __future__ import annotations from pydantic import BaseModel, ConfigDict, Field -from . import item_resp, total_resp +from . import item as item_1 +from . import total -class LineItemResponse(BaseModel): - """Line item object. Expected to use the currency of the parent object.""" - model_config = ConfigDict( - extra="allow", - ) - id: str - item: item_resp.ItemResponse - quantity: int = Field(..., ge=1) - """ +class LineItem(BaseModel): + """ + Line item object. Expected to use the currency of the parent object. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + item: item_1.Item + quantity: int = Field(..., ge=1) + """ Quantity of the item being purchased. """ - totals: list[total_resp.TotalResponse] - """ + totals: list[total.Total] + """ Line item totals breakdown. """ - parent_id: str | None = None - """ + parent_id: str | None = None + """ Parent line item identifier for any nested structures. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_create_req.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_create_req.py deleted file mode 100644 index 310c501..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/line_item_create_req.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict, Field -from . import item_create_req - - -class LineItemCreateRequest(BaseModel): - """Line item object. Expected to use the currency of the parent object.""" - - model_config = ConfigDict( - extra="allow", - ) - item: item_create_req.ItemCreateRequest - quantity: int = Field(..., ge=1) - """ - Quantity of the item being purchased. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_update_req.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_update_req.py deleted file mode 100644 index 5322178..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/line_item_update_req.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict, Field -from . import item_update_req - - -class LineItemUpdateRequest(BaseModel): - """Line item object. Expected to use the currency of the parent object.""" - - model_config = ConfigDict( - extra="allow", - ) - id: str | None = None - item: item_update_req.ItemUpdateRequest - quantity: int = Field(..., ge=1) - """ - Quantity of the item being purchased. - """ - parent_id: str | None = None - """ - Parent line item identifier for any nested structures. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/link.py b/src/ucp_sdk/models/schemas/shopping/types/link.py index ada733f..c3cdd02 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/link.py +++ b/src/ucp_sdk/models/schemas/shopping/types/link.py @@ -22,18 +22,18 @@ class Link(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - type: str - """ + model_config = ConfigDict( + extra="allow", + ) + type: str + """ Type of link. Well-known values: `privacy_policy`, `terms_of_service`, `refund_policy`, `shipping_policy`, `faq`. Consumers SHOULD handle unknown values gracefully by displaying them using the `title` field or omitting the link. """ - url: AnyUrl - """ + url: AnyUrl + """ The actual URL pointing to the content to be displayed. """ - title: str | None = None - """ + title: str | None = None + """ Optional display text for the link. When provided, use this instead of generating from type. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py b/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py index 29456f5..48919c5 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py +++ b/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py @@ -18,39 +18,42 @@ from __future__ import annotations -from pydantic import BaseModel, ConfigDict from typing import Literal +from pydantic import BaseModel, ConfigDict + class AllowsMultiDestination(BaseModel): - """Permits multiple destinations per method type.""" + """ + Permits multiple destinations per method type. + """ - model_config = ConfigDict( - extra="allow", - ) - shipping: bool | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + shipping: bool | None = None + """ Multiple shipping destinations allowed. """ - pickup: bool | None = None - """ + pickup: bool | None = None + """ Multiple pickup locations allowed. """ class MerchantFulfillmentConfig(BaseModel): - """Merchant's fulfillment configuration.""" + """ + Merchant's fulfillment configuration. + """ - model_config = ConfigDict( - extra="allow", - ) - allows_multi_destination: AllowsMultiDestination | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + allows_multi_destination: AllowsMultiDestination | None = None + """ Permits multiple destinations per method type. """ - allows_method_combinations: ( - list[list[Literal["shipping", "pickup"]]] | None - ) = None - """ + allows_method_combinations: list[list[Literal["shipping", "pickup"]]] | None = None + """ Allowed method type combinations. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/message.py b/src/ucp_sdk/models/schemas/shopping/types/message.py index 452fdb7..cbf3c5f 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/message.py +++ b/src/ucp_sdk/models/schemas/shopping/types/message.py @@ -19,21 +19,14 @@ from __future__ import annotations from pydantic import Field, RootModel + from . import message_error, message_info, message_warning -class Message( - RootModel[ - message_error.MessageError - | message_warning.MessageWarning - | message_info.MessageInfo - ] -): - root: ( - message_error.MessageError - | message_warning.MessageWarning - | message_info.MessageInfo - ) = Field(..., title="Message") - """ +class Message(RootModel[message_error.MessageError | message_warning.MessageWarning | message_info.MessageInfo]): + root: message_error.MessageError | message_warning.MessageWarning | message_info.MessageInfo = Field( + ..., title="Message" + ) + """ Container for error, warning, or info messages. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/message_error.py b/src/ucp_sdk/models/schemas/shopping/types/message_error.py index 2a1dffd..1dd3500 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/message_error.py +++ b/src/ucp_sdk/models/schemas/shopping/types/message_error.py @@ -19,36 +19,35 @@ from __future__ import annotations from typing import Literal + from pydantic import BaseModel, ConfigDict class MessageError(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - type: Literal["error"] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal["error"] + """ Message type discriminator. """ - code: str - """ + code: str + """ Error code. Possible values include: missing, invalid, out_of_stock, payment_declined, requires_sign_in, requires_3ds, requires_identity_linking. Freeform codes also allowed. """ - path: str | None = None - """ + path: str | None = None + """ RFC 9535 JSONPath to the component the message refers to (e.g., $.items[1]). """ - content_type: Literal["plain", "markdown"] | None = "plain" - """ + content_type: Literal["plain", "markdown"] | None = "plain" + """ Content format, default = plain. """ - content: str - """ + content: str + """ Human-readable message. """ - severity: Literal[ - "recoverable", "requires_buyer_input", "requires_buyer_review" - ] - """ + severity: Literal["recoverable", "requires_buyer_input", "requires_buyer_review"] + """ Declares who resolves this error. 'recoverable': agent can fix via API. 'requires_buyer_input': merchant requires information their API doesn't support collecting programmatically (checkout incomplete). 'requires_buyer_review': buyer must authorize before order placement due to policy, regulatory, or entitlement rules (checkout complete). Errors with 'requires_*' severity contribute to 'status: requires_escalation'. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/message_info.py b/src/ucp_sdk/models/schemas/shopping/types/message_info.py index 69f70f8..e0bcb31 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/message_info.py +++ b/src/ucp_sdk/models/schemas/shopping/types/message_info.py @@ -19,30 +19,31 @@ from __future__ import annotations from typing import Literal + from pydantic import BaseModel, ConfigDict class MessageInfo(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - type: Literal["info"] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal["info"] + """ Message type discriminator. """ - path: str | None = None - """ + path: str | None = None + """ RFC 9535 JSONPath to the component the message refers to. """ - code: str | None = None - """ + code: str | None = None + """ Info code for programmatic handling. """ - content_type: Literal["plain", "markdown"] | None = "plain" - """ + content_type: Literal["plain", "markdown"] | None = "plain" + """ Content format, default = plain. """ - content: str - """ + content: str + """ Human-readable message. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/message_warning.py b/src/ucp_sdk/models/schemas/shopping/types/message_warning.py index 564f391..f5eee46 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/message_warning.py +++ b/src/ucp_sdk/models/schemas/shopping/types/message_warning.py @@ -19,30 +19,31 @@ from __future__ import annotations from typing import Literal + from pydantic import BaseModel, ConfigDict class MessageWarning(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - type: Literal["warning"] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal["warning"] + """ Message type discriminator. """ - path: str | None = None - """ + path: str | None = None + """ JSONPath (RFC 9535) to related field (e.g., $.line_items[0]). """ - code: str - """ + code: str + """ Warning code. Machine-readable identifier for the warning type (e.g., final_sale, prop65, fulfillment_changed, age_restricted, etc.). """ - content: str - """ + content: str + """ Human-readable warning message that MUST be displayed. """ - content_type: Literal["plain", "markdown"] | None = "plain" - """ + content_type: Literal["plain", "markdown"] | None = "plain" + """ Content format, default = plain. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/order_confirmation.py b/src/ucp_sdk/models/schemas/shopping/types/order_confirmation.py index 2ddb26f..b17864a 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/order_confirmation.py +++ b/src/ucp_sdk/models/schemas/shopping/types/order_confirmation.py @@ -22,16 +22,18 @@ class OrderConfirmation(BaseModel): - """Order details available at the time of checkout completion.""" + """ + Order details available at the time of checkout completion. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Unique order identifier. """ - permalink_url: AnyUrl - """ + permalink_url: AnyUrl + """ Permalink to access the order on merchant site. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/order_line_item.py b/src/ucp_sdk/models/schemas/shopping/types/order_line_item.py index 841b19c..8f991bc 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/order_line_item.py +++ b/src/ucp_sdk/models/schemas/shopping/types/order_line_item.py @@ -18,52 +18,57 @@ from __future__ import annotations -from pydantic import BaseModel, ConfigDict, Field from typing import Literal -from . import item_resp, total_resp + +from pydantic import BaseModel, ConfigDict, Field + +from . import item as item_1 +from . import total as total_1 class Quantity(BaseModel): - """Quantity tracking. Both total and fulfilled are derived from events.""" + """ + Quantity tracking. Both total and fulfilled are derived from events. + """ - model_config = ConfigDict( - extra="allow", - ) - total: int = Field(..., ge=0) - """ + model_config = ConfigDict( + extra="allow", + ) + total: int = Field(..., ge=0) + """ Current total quantity. """ - fulfilled: int = Field(..., ge=0) - """ + fulfilled: int = Field(..., ge=0) + """ Quantity fulfilled (sum from fulfillment events). """ class OrderLineItem(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Line item identifier. """ - item: item_resp.ItemResponse - """ + item: item_1.Item + """ Product data (id, title, price, image_url). """ - quantity: Quantity - """ + quantity: Quantity + """ Quantity tracking. Both total and fulfilled are derived from events. """ - totals: list[total_resp.TotalResponse] - """ + totals: list[total_1.Total] + """ Line item totals breakdown. """ - status: Literal["processing", "partial", "fulfilled"] - """ + status: Literal["processing", "partial", "fulfilled"] + """ Derived status: fulfilled if quantity.fulfilled == quantity.total, partial if quantity.fulfilled > 0, otherwise processing. """ - parent_id: str | None = None - """ + parent_id: str | None = None + """ Parent line item identifier for any nested structures. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_credential.py b/src/ucp_sdk/models/schemas/shopping/types/payment_credential.py index 1e5b2c4..4a4e09d 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_credential.py +++ b/src/ucp_sdk/models/schemas/shopping/types/payment_credential.py @@ -18,20 +18,18 @@ from __future__ import annotations -from pydantic import Field, RootModel -from . import card_credential, token_credential_resp +from pydantic import BaseModel, ConfigDict -class PaymentCredential( - RootModel[ - token_credential_resp.TokenCredentialResponse - | card_credential.CardCredential - ] -): - root: ( - token_credential_resp.TokenCredentialResponse - | card_credential.CardCredential - ) = Field(..., title="Payment Credential") - """ - Container for sensitive payment data. Use the specific schema matching the 'type' field. +class PaymentCredential(BaseModel): + """ + The base definition for any payment credential. Handlers define specific credential types. + """ + + model_config = ConfigDict( + extra="allow", + ) + type: str + """ + The credential type discriminator. Specific schemas will constrain this to a constant value. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_handler_create_req.py b/src/ucp_sdk/models/schemas/shopping/types/payment_handler_create_req.py deleted file mode 100644 index e8526ef..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_handler_create_req.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class PaymentHandlerCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_handler_resp.py b/src/ucp_sdk/models/schemas/shopping/types/payment_handler_resp.py deleted file mode 100644 index c254191..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_handler_resp.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import AnyUrl, BaseModel, ConfigDict -from typing import Any -from ...._internal import Version - - -class PaymentHandlerResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - The unique identifier for this handler instance within the payment.handlers. Used by payment instruments to reference which handler produced them. - """ - name: str - """ - The specification name using reverse-DNS format. For example, dev.ucp.delegate_payment. - """ - version: Version - """ - Handler version in YYYY-MM-DD format. - """ - spec: AnyUrl - """ - A URI pointing to the technical specification or schema that defines how this handler operates. - """ - config_schema: AnyUrl - """ - A URI pointing to a JSON Schema used to validate the structure of the config object. - """ - instrument_schemas: list[AnyUrl] - config: dict[str, Any] - """ - A dictionary containing provider-specific configuration details, such as merchant IDs, supported networks, or gateway credentials. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_handler_update_req.py b/src/ucp_sdk/models/schemas/shopping/types/payment_handler_update_req.py deleted file mode 100644 index ce959e0..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_handler_update_req.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class PaymentHandlerUpdateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_identity.py b/src/ucp_sdk/models/schemas/shopping/types/payment_identity.py index c61230f..b30f85d 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_identity.py +++ b/src/ucp_sdk/models/schemas/shopping/types/payment_identity.py @@ -22,12 +22,14 @@ class PaymentIdentity(BaseModel): - """Identity of a participant for token binding. The access_token uniquely identifies the participant who tokens should be bound to.""" + """ + Identity of a participant for token binding. The access_token uniquely identifies the participant who tokens should be bound to. + """ - model_config = ConfigDict( - extra="allow", - ) - access_token: str - """ + model_config = ConfigDict( + extra="allow", + ) + access_token: str + """ Unique identifier for this participant, obtained during onboarding with the tokenizer. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py b/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py index 449580f..e99d68f 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py +++ b/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py @@ -18,16 +18,43 @@ from __future__ import annotations -from pydantic import Field, RootModel -from . import card_payment_instrument - - -class PaymentInstrument( - RootModel[card_payment_instrument.CardPaymentInstrument] -): - root: card_payment_instrument.CardPaymentInstrument = Field( - ..., title="Payment Instrument" - ) - """ - Matches a specific instrument type based on validation logic. +from typing import Any + +from pydantic import BaseModel, ConfigDict, RootModel + +from . import payment_credential, postal_address + + +class SelectedPaymentInstrument(RootModel[Any]): + root: Any + + +class PaymentInstrument(BaseModel): + """ + The base definition for any payment instrument. It links the instrument to a specific payment handler. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + A unique identifier for this instrument instance, assigned by the platform. + """ + handler_id: str + """ + The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition. + """ + type: str + """ + The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value. + """ + billing_address: postal_address.PostalAddress | None = None + """ + The billing address associated with this payment method. + """ + credential: payment_credential.PaymentCredential | None = None + display: dict[str, Any] | None = None + """ + Display information for this payment instrument. Each payment instrument schema defines its specific display properties, as outlined by the payment handler. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_instrument_base.py b/src/ucp_sdk/models/schemas/shopping/types/payment_instrument_base.py deleted file mode 100644 index 1bb01da..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_instrument_base.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict -from . import payment_credential, postal_address - - -class PaymentInstrumentBase(BaseModel): - """The base definition for any payment instrument. It links the instrument to a specific Merchant configuration (handler_id) and defines common fields like billing address.""" - - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - A unique identifier for this instrument instance, assigned by the Agent. Used to reference this specific instrument in the 'payment.selected_instrument_id' field. - """ - handler_id: str - """ - The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition. - """ - type: str - """ - The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value. - """ - billing_address: postal_address.PostalAddress | None = None - """ - The billing address associated with this payment method. - """ - credential: payment_credential.PaymentCredential | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/types/platform_fulfillment_config.py b/src/ucp_sdk/models/schemas/shopping/types/platform_fulfillment_config.py index f3ce34a..5757821 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/platform_fulfillment_config.py +++ b/src/ucp_sdk/models/schemas/shopping/types/platform_fulfillment_config.py @@ -22,12 +22,14 @@ class PlatformFulfillmentConfig(BaseModel): - """Platform's fulfillment configuration.""" + """ + Platform's fulfillment configuration. + """ - model_config = ConfigDict( - extra="allow", - ) - supports_multi_group: bool | None = False - """ + model_config = ConfigDict( + extra="allow", + ) + supports_multi_group: bool | None = False + """ Enables multiple groups per method. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/postal_address.py b/src/ucp_sdk/models/schemas/shopping/types/postal_address.py index 309dfdd..7c57364 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/postal_address.py +++ b/src/ucp_sdk/models/schemas/shopping/types/postal_address.py @@ -22,46 +22,42 @@ class PostalAddress(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - extended_address: str | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + extended_address: str | None = None + """ An address extension such as an apartment number, C/O or alternative name. """ - street_address: str | None = None - """ + street_address: str | None = None + """ The street address. """ - address_locality: str | None = None - """ + address_locality: str | None = None + """ The locality in which the street address is, and which is in the region. For example, Mountain View. """ - address_region: str | None = None - """ + address_region: str | None = None + """ The region in which the locality is, and which is in the country. Required for applicable countries (i.e. state in US, province in CA). For example, California or another appropriate first-level Administrative division. """ - address_country: str | None = None - """ + address_country: str | None = None + """ The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. """ - postal_code: str | None = None - """ + postal_code: str | None = None + """ The postal code. For example, 94043. """ - first_name: str | None = None - """ + first_name: str | None = None + """ Optional. First name of the contact associated with the address. """ - last_name: str | None = None - """ + last_name: str | None = None + """ Optional. Last name of the contact associated with the address. """ - full_name: str | None = None - """ - Optional. Full name of the contact associated with the address (if first_name or last_name fields are present they take precedence). + phone_number: str | None = None """ - phone_number: str | None = None - """ Optional. Phone number of the contact associated with the address. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/retail_location_resp.py b/src/ucp_sdk/models/schemas/shopping/types/retail_location.py similarity index 76% rename from src/ucp_sdk/models/schemas/shopping/types/retail_location_resp.py rename to src/ucp_sdk/models/schemas/shopping/types/retail_location.py index 951fe59..c0353af 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/retail_location_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/types/retail_location.py @@ -19,24 +19,27 @@ from __future__ import annotations from pydantic import BaseModel, ConfigDict + from . import postal_address -class RetailLocationResponse(BaseModel): - """A pickup location (retail store, locker, etc.).""" +class RetailLocation(BaseModel): + """ + A pickup location (retail store, locker, etc.). + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Unique location identifier. """ - name: str - """ + name: str + """ Location name (e.g., store name). """ - address: postal_address.PostalAddress | None = None - """ + address: postal_address.PostalAddress | None = None + """ Physical address of the location. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/shipping_destination_req.py b/src/ucp_sdk/models/schemas/shopping/types/shipping_destination.py similarity index 83% rename from src/ucp_sdk/models/schemas/shopping/types/shipping_destination_req.py rename to src/ucp_sdk/models/schemas/shopping/types/shipping_destination.py index 1bba351..f8b929d 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/shipping_destination_req.py +++ b/src/ucp_sdk/models/schemas/shopping/types/shipping_destination.py @@ -19,16 +19,19 @@ from __future__ import annotations from pydantic import ConfigDict + from .postal_address import PostalAddress -class ShippingDestinationRequest(PostalAddress): - """Shipping destination.""" +class ShippingDestination(PostalAddress): + """ + Shipping destination. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ ID specific to this shipping destination. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/shipping_destination_resp.py b/src/ucp_sdk/models/schemas/shopping/types/shipping_destination_resp.py deleted file mode 100644 index 6ba62ae..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/shipping_destination_resp.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import ConfigDict -from .postal_address import PostalAddress - - -class ShippingDestinationResponse(PostalAddress): - """Shipping destination.""" - - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - ID specific to this shipping destination. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/token_credential_create_req.py b/src/ucp_sdk/models/schemas/shopping/types/token_credential.py similarity index 67% rename from src/ucp_sdk/models/schemas/shopping/types/token_credential_create_req.py rename to src/ucp_sdk/models/schemas/shopping/types/token_credential.py index ed52d78..596f097 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/token_credential_create_req.py +++ b/src/ucp_sdk/models/schemas/shopping/types/token_credential.py @@ -18,20 +18,24 @@ from __future__ import annotations -from pydantic import BaseModel, ConfigDict +from pydantic import ConfigDict +from .payment_credential import PaymentCredential -class TokenCredentialCreateRequest(BaseModel): - """Base token credential schema. Concrete payment handlers may extend this schema with additional fields and define their own constraints.""" - model_config = ConfigDict( - extra="allow", - ) - type: str - """ +class TokenCredential(PaymentCredential): + """ + Base token credential schema. Concrete payment handlers may extend this schema with additional fields and define their own constraints. + """ + + model_config = ConfigDict( + extra="allow", + ) + type: str + """ The specific type of token produced by the handler (e.g., 'stripe_token'). """ - token: str - """ + token: str + """ The token value. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/token_credential_resp.py b/src/ucp_sdk/models/schemas/shopping/types/token_credential_resp.py deleted file mode 100644 index 1cf6844..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/token_credential_resp.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class TokenCredentialResponse(BaseModel): - """Base token credential schema. Concrete payment handlers may extend this schema with additional fields and define their own constraints.""" - - model_config = ConfigDict( - extra="allow", - ) - type: str - """ - The specific type of token produced by the handler (e.g., 'stripe_token'). - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/token_credential_update_req.py b/src/ucp_sdk/models/schemas/shopping/types/token_credential_update_req.py deleted file mode 100644 index ff044f8..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/token_credential_update_req.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class TokenCredentialUpdateRequest(BaseModel): - """Base token credential schema. Concrete payment handlers may extend this schema with additional fields and define their own constraints.""" - - model_config = ConfigDict( - extra="allow", - ) - type: str - """ - The specific type of token produced by the handler (e.g., 'stripe_token'). - """ - token: str - """ - The token value. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/total_resp.py b/src/ucp_sdk/models/schemas/shopping/types/total.py similarity index 78% rename from src/ucp_sdk/models/schemas/shopping/types/total_resp.py rename to src/ucp_sdk/models/schemas/shopping/types/total.py index 8323cfb..320e79b 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/total_resp.py +++ b/src/ucp_sdk/models/schemas/shopping/types/total.py @@ -19,30 +19,23 @@ from __future__ import annotations from typing import Literal + from pydantic import BaseModel, ConfigDict, Field -class TotalResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - type: Literal[ - "items_discount", - "subtotal", - "discount", - "fulfillment", - "tax", - "fee", - "total", - ] - """ +class Total(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + type: Literal["items_discount", "subtotal", "discount", "fulfillment", "tax", "fee", "total"] + """ Type of total categorization. """ - display_text: str | None = None - """ + display_text: str | None = None + """ Text to display against the amount. Should reflect appropriate method (e.g., 'Shipping', 'Delivery'). """ - amount: int = Field(..., ge=0) - """ + amount: int = Field(..., ge=0) + """ If type == total, sums subtotal - discount + fulfillment + tax + fee. Should be >= 0. Amount in minor (cents) currency units. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/total_create_req.py b/src/ucp_sdk/models/schemas/shopping/types/total_create_req.py deleted file mode 100644 index ab0c7d2..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/total_create_req.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class TotalCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/total_update_req.py b/src/ucp_sdk/models/schemas/shopping/types/total_update_req.py deleted file mode 100644 index ef0dfe3..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/total_update_req.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class TotalUpdateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/transports/__init__.py b/src/ucp_sdk/models/schemas/transports/__init__.py new file mode 100644 index 0000000..421dc21 --- /dev/null +++ b/src/ucp_sdk/models/schemas/transports/__init__.py @@ -0,0 +1,18 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_req.py b/src/ucp_sdk/models/schemas/transports/embedded_config.py similarity index 60% rename from src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_req.py rename to src/ucp_sdk/models/schemas/transports/embedded_config.py index 6b6893b..8f3cba7 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_req.py +++ b/src/ucp_sdk/models/schemas/transports/embedded_config.py @@ -21,17 +21,15 @@ from pydantic import BaseModel, ConfigDict -class FulfillmentGroupUpdateRequest(BaseModel): - """A merchant-generated package/group of line items with fulfillment options.""" +class EmbeddedTransportConfig(BaseModel): + """ + Per-checkout configuration for embedded transport binding. Allows businesses to vary ECP availability and delegations based on cart contents, agent authorization, or policy. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Group identifier for referencing merchant-generated groups in updates. + model_config = ConfigDict( + extra="allow", + ) + delegate: list[str] | None = None """ - selected_option_id: str | None = None - """ - ID of the selected fulfillment option for this group. + Delegations the business allows. At service-level, declares available delegations. In checkout responses, confirms accepted delegations for this session. """ diff --git a/src/ucp_sdk/models/schemas/ucp.py b/src/ucp_sdk/models/schemas/ucp.py index d64119d..d1ce414 100644 --- a/src/ucp_sdk/models/schemas/ucp.py +++ b/src/ucp_sdk/models/schemas/ucp.py @@ -18,20 +18,160 @@ from __future__ import annotations -from .._internal import ( - DiscoveryProfile, - ResponseCheckout, - ResponseOrder, - Services, - UcpMetadata, - Version, -) - -__all__ = [ - "DiscoveryProfile", - "ResponseCheckout", - "ResponseOrder", - "Services", - "UcpMetadata", - "Version", -] +from typing import Any + +from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel + +from . import capability, payment_handler, service + + +class UcpMetadata(RootModel[Any]): + root: Any = Field(..., title="UCP Metadata") + """ + Protocol metadata for discovery profiles and responses. Uses slim schema pattern with context-specific required fields. + """ + + +class Version(RootModel[str]): + root: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") + """ + UCP version in YYYY-MM-DD format. + """ + + +class ReverseDomainName(RootModel[str]): + root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$") + """ + Reverse-domain identifier (e.g., com.google.pay, dev.ucp.shopping.checkout) + """ + + +class Entity(BaseModel): + """ + Shared foundation for all UCP entities. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: Version + """ + Entity version in YYYY-MM-DD format. + """ + spec: AnyUrl | None = None + """ + URL to human-readable specification document. + """ + schema_: AnyUrl | None = Field(None, alias="schema") + """ + URL to JSON Schema defining this entity's structure and payloads. + """ + id: str | None = None + """ + Unique identifier for this entity instance. Used to disambiguate when multiple instances exist. + """ + config: dict[str, Any] | None = None + """ + Entity-specific configuration. Structure defined by each entity's schema. + """ + + +class PlatformSchema(BaseModel): + """ + Full UCP metadata for platform-level configuration. Hosted at a URI advertised by the platform in request headers. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") + """ + UCP version in YYYY-MM-DD format. + """ + services: Any + capabilities: Any | None = None + payment_handlers: Any + + +class BusinessSchema(BaseModel): + """ + UCP metadata for business/merchant-level configuration. Subset of platform schema with business-specific settings. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") + """ + UCP version in YYYY-MM-DD format. + """ + services: Any + capabilities: Any | None = None + payment_handlers: Any + + +class ResponseCheckoutSchema(BaseModel): + """ + UCP metadata for checkout responses. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") + """ + UCP version in YYYY-MM-DD format. + """ + services: Any | None = None + capabilities: Any | None = None + payment_handlers: Any + + +class ResponseCartSchema(RootModel[Any]): + root: Any + + +class Base(BaseModel): + """ + Base UCP metadata with shared properties for all schema types. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: Version + services: dict[ReverseDomainName, list[service.Base]] | None = None + """ + Service registry keyed by reverse-domain name. + """ + capabilities: dict[ReverseDomainName, list[capability.Base]] | None = None + """ + Capability registry keyed by reverse-domain name. + """ + payment_handlers: dict[ReverseDomainName, list[payment_handler.Base]] | None = None + """ + Payment handler registry keyed by reverse-domain name. + """ + + +class ResponseOrderSchema(BaseModel): + """ + UCP metadata for order responses. No payment handlers needed post-purchase. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") + """ + UCP version in YYYY-MM-DD format. + """ + services: dict[str, list[service.Base]] | None = None + """ + Service registry keyed by reverse-domain name. + """ + capabilities: Any | None = None + payment_handlers: dict[str, list[payment_handler.Base]] | None = None + """ + Payment handler registry keyed by reverse-domain name. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/retail_location_req.py b/src/ucp_sdk/models/services/shopping/embedded.py similarity index 62% rename from src/ucp_sdk/models/schemas/shopping/types/retail_location_req.py rename to src/ucp_sdk/models/services/shopping/embedded.py index 6b1a8e2..7da4251 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/retail_location_req.py +++ b/src/ucp_sdk/models/services/shopping/embedded.py @@ -18,21 +18,13 @@ from __future__ import annotations -from pydantic import BaseModel, ConfigDict -from . import postal_address +from typing import Any +from pydantic import Field, RootModel -class RetailLocationRequest(BaseModel): - """A pickup location (retail store, locker, etc.).""" - model_config = ConfigDict( - extra="allow", - ) - name: str - """ - Location name (e.g., store name). +class EmbeddedProtocol(RootModel[Any]): + root: Any = Field(..., title="Embedded Protocol") """ - address: postal_address.PostalAddress | None = None - """ - Physical address of the location. + Embedded Protocol (EP) methods for UCP capabilities. Methods are sent from Merchant to Host via postMessage/JSON-RPC 2.0. Method prefixes indicate capability scope: ec.* (checkout). Future capabilities may define additional prefixes (e.g., eo.* for order). """ diff --git a/src/ucp_sdk/models/services/shopping/embedded_openrpc.py b/src/ucp_sdk/models/services/shopping/openapi.py similarity index 98% rename from src/ucp_sdk/models/services/shopping/embedded_openrpc.py rename to src/ucp_sdk/models/services/shopping/openapi.py index e8b3b8c..66b2502 100644 --- a/src/ucp_sdk/models/services/shopping/embedded_openrpc.py +++ b/src/ucp_sdk/models/services/shopping/openapi.py @@ -19,8 +19,9 @@ from __future__ import annotations from typing import Any + from pydantic import RootModel class Model(RootModel[Any]): - root: Any + root: Any diff --git a/src/ucp_sdk/models/services/shopping/mcp_openrpc.py b/src/ucp_sdk/models/services/shopping/openrpc.py similarity index 98% rename from src/ucp_sdk/models/services/shopping/mcp_openrpc.py rename to src/ucp_sdk/models/services/shopping/openrpc.py index e8b3b8c..66b2502 100644 --- a/src/ucp_sdk/models/services/shopping/mcp_openrpc.py +++ b/src/ucp_sdk/models/services/shopping/openrpc.py @@ -19,8 +19,9 @@ from __future__ import annotations from typing import Any + from pydantic import RootModel class Model(RootModel[Any]): - root: Any + root: Any diff --git a/src/ucp_sdk/py.typed b/src/ucp_sdk/py.typed deleted file mode 100644 index e69de29..0000000 From 6d46afbde4a4d77698fa382954059977efa09a5b Mon Sep 17 00:00:00 2001 From: damaz91 Date: Fri, 6 Feb 2026 10:13:10 +0000 Subject: [PATCH 02/22] add init at the base level --- src/ucp_sdk/__init__.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/ucp_sdk/__init__.py diff --git a/src/ucp_sdk/__init__.py b/src/ucp_sdk/__init__.py new file mode 100644 index 0000000..fd754fb --- /dev/null +++ b/src/ucp_sdk/__init__.py @@ -0,0 +1,19 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""UCP Python SDK.""" + + +def hello() -> str: + return "Hello from ucp-python-sdk!" \ No newline at end of file From 921471297941b97987f2249ce0f47a37f4bfeec7 Mon Sep 17 00:00:00 2001 From: damaz91 Date: Fri, 6 Feb 2026 10:17:24 +0000 Subject: [PATCH 03/22] update README --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 729cc17..d6da2e4 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,7 @@ For now, you can install the SDK using the following commands: mkdir sdk # Clone the repository -git clone https://github.com/Universal-Commerce-Protocol/python-sdk.git sdk/python - -# Navigate to the directory -cd sdk/python +git clone https://github.com/Universal-Commerce-Protocol/python-sdk.git # Install dependencies uv sync @@ -58,6 +55,12 @@ This project uses `uv` for dependency management. The models are automatically generated from the JSON schemas in the UCP Specification. +Clone the UCP main repository in the same folder: + +```bash +git clone https://github.com/Universal-Commerce-Protocol/ucp.git +``` + To regenerate the models: ```bash From 6b8407000260f4f60f782c1c2383598dbe141e30 Mon Sep 17 00:00:00 2001 From: damaz91 Date: Fri, 6 Feb 2026 11:14:14 +0000 Subject: [PATCH 04/22] add request specific classes --- generate_models.sh | 2 +- preprocess_schemas.py | 207 ++++++++++++- .../models/discovery/profile_schema.py | 2 +- src/ucp_sdk/models/schemas/service.py | 4 - src/ucp_sdk/models/schemas/shopping/cart.py | 28 +- .../schemas/shopping/cart_create_request.py | 47 +++ .../schemas/shopping/cart_update_request.py | 51 ++++ .../shopping/checkout_complete_request.py | 34 +++ .../shopping/checkout_create_request.py | 71 +++++ .../shopping/checkout_update_request.py | 75 +++++ .../types/fulfillment_group_create_request.py | 35 +++ .../types/fulfillment_group_update_request.py | 39 +++ .../fulfillment_method_create_request.py | 55 ++++ .../fulfillment_method_update_request.py | 53 ++++ .../types/line_item_create_request.py | 38 +++ .../types/line_item_update_request.py | 43 +++ src/ucp_sdk/models/schemas/ucp.py | 276 ++++++++++++++++-- ucp | 1 + 18 files changed, 1029 insertions(+), 32 deletions(-) create mode 100644 src/ucp_sdk/models/schemas/shopping/cart_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/cart_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/checkout_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/checkout_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py create mode 160000 ucp diff --git a/generate_models.sh b/generate_models.sh index 7826da2..297a26e 100755 --- a/generate_models.sh +++ b/generate_models.sh @@ -72,7 +72,7 @@ echo "Formatting generated models..." uv run ruff format "$OUTPUT_DIR" uv run ruff check --fix --config "$OUTPUT_DIR/ruff.toml" "$OUTPUT_DIR" 2>&1 | grep -E "^(All checks passed|Fixed|Found)" || echo "Formatting complete" -# Clean up temp schemas +# Clean up temporary schemas rm -rf "$TEMP_SCHEMA_DIR" echo "Done. Models generated in $OUTPUT_DIR" diff --git a/preprocess_schemas.py b/preprocess_schemas.py index a83004f..1dea8ac 100644 --- a/preprocess_schemas.py +++ b/preprocess_schemas.py @@ -142,23 +142,202 @@ def flatten_allof_in_defs(schema: Dict[str, Any]) -> Dict[str, Any]: return schema -def preprocess_schema_file(input_path: Path, output_path: Path) -> None: +def update_refs_for_scenario(obj: Any, scenario: str, schemas_with_scenarios: set, current_dir: str = "") -> Any: + """ + Recursively update $ref paths to point to scenario-specific schemas. + For example, changes "types/line_item.json" to "types/line_item_create_request.json" for create scenario. + Only updates references to schemas that actually have scenarios. + """ + if isinstance(obj, dict): + result = {} + for key, value in obj.items(): + if key == "$ref" and isinstance(value, str): + # Skip internal references and references with fragments (e.g., "../ucp.json#/$defs/...") + if value.startswith("#/") or "#/$defs/" in value: + result[key] = value + # Check if this is a reference to a schema file (not internal #/$defs/) + elif value.endswith(".json"): + # Resolve the relative path from current schema's directory + if current_dir: + ref_path = str(Path(current_dir) / value) + else: + ref_path = value + + # Normalize the path + ref_path = ref_path.replace("\\", "/") + + # Check if the referenced schema has scenarios + if ref_path in schemas_with_scenarios: + base_path = value[:-5] # Remove .json + # Create scenario-specific reference + result[key] = f"{base_path}_{scenario}_request.json" + else: + # Keep original reference for schemas without scenarios + result[key] = value + else: + result[key] = value + else: + result[key] = update_refs_for_scenario(value, scenario, schemas_with_scenarios, current_dir) + return result + elif isinstance(obj, list): + return [update_refs_for_scenario(item, scenario, schemas_with_scenarios, current_dir) for item in obj] + return obj + + +def process_ucp_request_scenarios(schema: Dict[str, Any], base_name: str, schemas_with_scenarios: set, schema_dir: str = "") -> Dict[str, Dict[str, Any]]: + """ + Generate separate schemas for create, update, and complete scenarios based on ucp_request annotations. + + Returns a dict mapping scenario names (e.g., 'create', 'update', 'complete') to their schemas. + """ + scenarios = {} + + # Check if this schema has properties with ucp_request annotations + if "properties" not in schema: + return {"base": schema} + + # Detect which scenarios exist + scenario_types = set() + for prop_name, prop_schema in schema["properties"].items(): + if isinstance(prop_schema, dict) and "ucp_request" in prop_schema: + ucp_req = prop_schema["ucp_request"] + if isinstance(ucp_req, dict): + scenario_types.update(ucp_req.keys()) + + # If no scenarios detected, return base schema + if not scenario_types: + return {"base": schema} + + # Generate a schema for each scenario + for scenario in scenario_types: + scenario_schema = copy.deepcopy(schema) + + # Update title and description to reflect the scenario + if "title" in scenario_schema: + scenario_schema["title"] = f"{scenario_schema['title']} ({scenario.capitalize()} Request)" + + # Process each property based on its ucp_request directive + properties_to_remove = [] + required_fields = set(scenario_schema.get("required", [])) + + for prop_name, prop_schema in scenario_schema["properties"].items(): + if isinstance(prop_schema, dict) and "ucp_request" in prop_schema: + ucp_req = prop_schema["ucp_request"] + + # Clean up the ucp_request annotation from the property + del prop_schema["ucp_request"] + + # Determine the directive for this scenario + if isinstance(ucp_req, str): + directive = ucp_req + elif isinstance(ucp_req, dict): + directive = ucp_req.get(scenario, "optional") + else: + directive = "optional" + + # Handle the directive + if directive == "omit": + properties_to_remove.append(prop_name) + required_fields.discard(prop_name) + elif directive == "required": + required_fields.add(prop_name) + elif directive == "optional": + required_fields.discard(prop_name) + + # Remove omitted properties + for prop_name in properties_to_remove: + del scenario_schema["properties"][prop_name] + + # Update required fields + if required_fields: + scenario_schema["required"] = sorted(list(required_fields)) + elif "required" in scenario_schema: + del scenario_schema["required"] + + # Update all $ref paths to point to scenario-specific schemas + scenario_schema = update_refs_for_scenario(scenario_schema, scenario, schemas_with_scenarios, schema_dir) + + scenarios[scenario] = scenario_schema + + return scenarios + + +def clean_schema_for_codegen(schema: Dict[str, Any]) -> Dict[str, Any]: + """ + Clean up schema to avoid issues with datamodel-code-generator. + - Remove $id fields that might cause URL resolution issues + - Remove $schema fields + """ + schema = copy.deepcopy(schema) + + # Remove fields that can cause URL resolution issues + if "$id" in schema: + del schema["$id"] + if "$schema" in schema: + del schema["$schema"] + + return schema + + +def preprocess_schema_file(input_path: Path, output_path: Path, schemas_with_scenarios: set) -> None: """Preprocess a single schema file.""" with open(input_path, 'r', encoding='utf-8') as f: schema = json.load(f) + # WARN: Workaround for datamodel-codegen issue with relative paths + # When ucp.json is referenced from a subdirectory (e.g. schemas/shopping/checkout.json referencing ../ucp.json), + # the subsequent reference to service.json (in ucp.json) is incorrectly resolved relative to the subdirectory. + # We force an absolute path here. + if input_path.name == "ucp.json": + # Force absolute paths for all sibling references in ucp.json + # This fixes resolution issues when ucp.json is referenced from subdirectories + schema_str = json.dumps(schema) + + input_dir_abs = output_path.parent.resolve() + for ref_file in ["service.json", "capability.json", "payment_handler.json"]: + ref_path = input_dir_abs / ref_file + schema_str = schema_str.replace(f'"{ref_file}', f'"file://{ref_path}') + + schema = json.loads(schema_str) + # Remove extension definitions that reference external schemas schema = remove_extension_defs(schema) # Flatten allOf patterns within $defs that only use internal refs schema = flatten_allof_in_defs(schema) + # Generate scenario-specific schemas + base_name = output_path.stem # filename without extension + + # Get the directory of this schema relative to the root (for resolving refs) + schema_dir = str(output_path.parent.relative_to(output_path.parent.parent.parent)) + + scenarios = process_ucp_request_scenarios(schema, base_name, schemas_with_scenarios, schema_dir) + # Ensure output directory exists output_path.parent.mkdir(parents=True, exist_ok=True) - # Write preprocessed schema - with open(output_path, 'w', encoding='utf-8') as f: - json.dump(schema, f, indent=2) + # Write preprocessed schema(s) + if len(scenarios) == 1 and "base" in scenarios: + # No scenarios, write single file + cleaned = clean_schema_for_codegen(scenarios["base"]) + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(cleaned, f, indent=2) + else: + # Write both base schema and scenario-specific files + # First, write the base schema (for non-scenario-specific references) + base_schema = copy.deepcopy(schema) + cleaned_base = clean_schema_for_codegen(base_schema) + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(cleaned_base, f, indent=2) + + # Then write separate files for each scenario + for scenario_name, scenario_schema in scenarios.items(): + scenario_path = output_path.parent / f"{base_name}_{scenario_name}_request.json" + print(f" -> Generating {scenario_name} request schema") + cleaned = clean_schema_for_codegen(scenario_schema) + with open(scenario_path, 'w', encoding='utf-8') as f: + json.dump(cleaned, f, indent=2) def preprocess_schemas(input_dir: Path, output_dir: Path) -> None: @@ -173,13 +352,31 @@ def preprocess_schemas(input_dir: Path, output_dir: Path) -> None: print(f"Preprocessing {len(json_files)} schema files...") + # First pass: track which schemas have scenarios + schemas_with_scenarios = set() + for json_file in json_files: + with open(json_file, 'r', encoding='utf-8') as f: + schema = json.load(f) + + # Check if this schema has ucp_request scenarios + if "properties" in schema: + for prop_schema in schema["properties"].values(): + if isinstance(prop_schema, dict) and "ucp_request" in prop_schema: + ucp_req = prop_schema["ucp_request"] + if isinstance(ucp_req, dict): + # This schema has scenarios + rel_path = json_file.relative_to(input_dir) + schemas_with_scenarios.add(str(rel_path)) + break + + # Second pass: preprocess and generate schemas for json_file in json_files: # Calculate relative path rel_path = json_file.relative_to(input_dir) output_path = output_dir / rel_path print(f" Processing: {rel_path}") - preprocess_schema_file(json_file, output_path) + preprocess_schema_file(json_file, output_path, schemas_with_scenarios) print(f"Preprocessing complete. Output in {output_dir}") diff --git a/src/ucp_sdk/models/discovery/profile_schema.py b/src/ucp_sdk/models/discovery/profile_schema.py index 68ec227..42e446c 100644 --- a/src/ucp_sdk/models/discovery/profile_schema.py +++ b/src/ucp_sdk/models/discovery/profile_schema.py @@ -116,7 +116,7 @@ class Base(BaseModel): model_config = ConfigDict( extra="allow", ) - ucp: ucp_1.Base + ucp: ucp_1.BaseModel1 signing_keys: list[SigningKey] | None = None """ Public keys for signature verification (JWK format). Used to verify signed responses, webhooks, and other authenticated messages from this party. diff --git a/src/ucp_sdk/models/schemas/service.py b/src/ucp_sdk/models/schemas/service.py index 227ca16..5c619d2 100644 --- a/src/ucp_sdk/models/schemas/service.py +++ b/src/ucp_sdk/models/schemas/service.py @@ -191,7 +191,3 @@ class ResponseSchema2(RootModel[ResponseSchema | ResponseSchema4 | ResponseSchem """ Service binding in API responses. Includes per-resource transport configuration via typed config. """ - - -class Base(RootModel[Any]): - root: Any diff --git a/src/ucp_sdk/models/schemas/shopping/cart.py b/src/ucp_sdk/models/schemas/shopping/cart.py index d66c2c7..7110dfc 100644 --- a/src/ucp_sdk/models/schemas/shopping/cart.py +++ b/src/ucp_sdk/models/schemas/shopping/cart.py @@ -20,8 +20,9 @@ from typing import Any -from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict +from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict, Field +from .. import ucp as ucp_1 from .types import line_item, link, message, total @@ -77,6 +78,29 @@ class Buyer(BaseModel): """ +class Ucp(BaseModel): + """ + UCP metadata for cart responses. No payment handlers needed pre-checkout. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") + """ + UCP version in YYYY-MM-DD format. + """ + services: dict[str, list[ucp_1.Base]] | None = None + """ + Service registry keyed by reverse-domain name. + """ + capabilities: Any | None = None + payment_handlers: dict[str, list[ucp_1.Base]] | None = None + """ + Payment handler registry keyed by reverse-domain name. + """ + + class Cart(BaseModel): """ Shopping cart with estimated pricing before checkout. Lightweight pre-purchase exploration with no payment info or complex status states. Cart exists (200) or doesn't (404). @@ -85,7 +109,7 @@ class Cart(BaseModel): model_config = ConfigDict( extra="allow", ) - ucp: Any + ucp: Ucp id: str """ Unique cart identifier. diff --git a/src/ucp_sdk/models/schemas/shopping/cart_create_request.py b/src/ucp_sdk/models/schemas/shopping/cart_create_request.py new file mode 100644 index 0000000..f948b9a --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/cart_create_request.py @@ -0,0 +1,47 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from .types import buyer as buyer_1 +from .types import context as context_1 +from .types import line_item_create_request + + +class CartCreateRequest(BaseModel): + """ + Shopping cart with estimated pricing before checkout. Lightweight pre-purchase exploration with no payment info or complex status states. Cart exists (200) or doesn't (404). + """ + + model_config = ConfigDict( + extra="allow", + ) + line_items: list[line_item_create_request.LineItemCreateRequest] + """ + Cart line items. Same structure as checkout. Full replacement on update. + """ + context: context_1.Context | None = None + """ + Buyer signals for localization (country, region, postal_code). Merchant uses for pricing, availability, currency. Falls back to geo-IP if omitted. + """ + buyer: buyer_1.Buyer | None = None + """ + Optional buyer information for personalized estimates. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/cart_update_request.py b/src/ucp_sdk/models/schemas/shopping/cart_update_request.py new file mode 100644 index 0000000..3815fdf --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/cart_update_request.py @@ -0,0 +1,51 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from .types import buyer as buyer_1 +from .types import context as context_1 +from .types import line_item_update_request + + +class CartUpdateRequest(BaseModel): + """ + Shopping cart with estimated pricing before checkout. Lightweight pre-purchase exploration with no payment info or complex status states. Cart exists (200) or doesn't (404). + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + Unique cart identifier. + """ + line_items: list[line_item_update_request.LineItemUpdateRequest] + """ + Cart line items. Same structure as checkout. Full replacement on update. + """ + context: context_1.Context | None = None + """ + Buyer signals for localization (country, region, postal_code). Merchant uses for pricing, availability, currency. Falls back to geo-IP if omitted. + """ + buyer: buyer_1.Buyer | None = None + """ + Optional buyer information for personalized estimates. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py new file mode 100644 index 0000000..5799fc2 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py @@ -0,0 +1,34 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import payment as payment_1 + + +class CheckoutCompleteRequest(BaseModel): + """ + Base checkout schema. Extensions compose onto this using allOf. + """ + + model_config = ConfigDict( + extra="allow", + ) + payment: payment_1.Payment diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py new file mode 100644 index 0000000..fccc424 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py @@ -0,0 +1,71 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import payment as payment_1 +from .types import buyer as buyer_1 +from .types import line_item_create_request + + +class Context(BaseModel): + """ + Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context SHOULD be non-identifying and can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. + """ + + model_config = ConfigDict( + extra="allow", + ) + address_country: str | None = None + """ + The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. + """ + address_region: str | None = None + """ + The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. + """ + postal_code: str | None = None + """ + The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. + """ + intent: str | None = None + """ + Background context describing buyer's intent (e.g., 'looking for a gift under $50', 'need something durable for outdoor use'). Informs relevance, recommendations, and personalization. + """ + + +class CheckoutCreateRequest(BaseModel): + """ + Base checkout schema. Extensions compose onto this using allOf. + """ + + model_config = ConfigDict( + extra="allow", + ) + line_items: list[line_item_create_request.LineItemCreateRequest] + """ + List of line items being checked out. + """ + buyer: buyer_1.Buyer | None = None + """ + Representation of the buyer. + """ + context: Context | None = None + payment: payment_1.Payment | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py new file mode 100644 index 0000000..8e2b1c9 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py @@ -0,0 +1,75 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import payment as payment_1 +from .types import buyer as buyer_1 +from .types import line_item_update_request + + +class Context(BaseModel): + """ + Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context SHOULD be non-identifying and can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. + """ + + model_config = ConfigDict( + extra="allow", + ) + address_country: str | None = None + """ + The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. + """ + address_region: str | None = None + """ + The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. + """ + postal_code: str | None = None + """ + The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. + """ + intent: str | None = None + """ + Background context describing buyer's intent (e.g., 'looking for a gift under $50', 'need something durable for outdoor use'). Informs relevance, recommendations, and personalization. + """ + + +class CheckoutUpdateRequest(BaseModel): + """ + Base checkout schema. Extensions compose onto this using allOf. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + Unique identifier of the checkout session. + """ + line_items: list[line_item_update_request.LineItemUpdateRequest] + """ + List of line items being checked out. + """ + buyer: buyer_1.Buyer | None = None + """ + Representation of the buyer. + """ + context: Context | None = None + payment: payment_1.Payment | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py new file mode 100644 index 0000000..99489e4 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py @@ -0,0 +1,35 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class FulfillmentGroupCreateRequest(BaseModel): + """ + A merchant-generated package/group of line items with fulfillment options. + """ + + model_config = ConfigDict( + extra="allow", + ) + selected_option_id: str | None = None + """ + ID of the selected fulfillment option for this group. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py new file mode 100644 index 0000000..c830c71 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py @@ -0,0 +1,39 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class FulfillmentGroupUpdateRequest(BaseModel): + """ + A merchant-generated package/group of line items with fulfillment options. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + Group identifier for referencing merchant-generated groups in updates. + """ + selected_option_id: str | None = None + """ + ID of the selected fulfillment option for this group. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py new file mode 100644 index 0000000..8ee2ebc --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py @@ -0,0 +1,55 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from typing import Literal + +from pydantic import BaseModel, ConfigDict + +from . import fulfillment_destination, fulfillment_group + + +class FulfillmentMethodCreateRequest(BaseModel): + """ + A fulfillment method (shipping or pickup) with destinations and groups. + """ + + model_config = ConfigDict( + extra="allow", + ) + type: Literal["shipping", "pickup"] + """ + Fulfillment method type. + """ + line_item_ids: list[str] | None = None + """ + Line item IDs fulfilled via this method. + """ + destinations: list[fulfillment_destination.FulfillmentDestination] | None = None + """ + Available destinations. For shipping: addresses. For pickup: retail locations. + """ + selected_destination_id: str | None = None + """ + ID of the selected destination. + """ + groups: list[fulfillment_group.FulfillmentGroup] | None = None + """ + Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py new file mode 100644 index 0000000..e5796c2 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py @@ -0,0 +1,53 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import fulfillment_destination, fulfillment_group + + +class FulfillmentMethodUpdateRequest(BaseModel): + """ + A fulfillment method (shipping or pickup) with destinations and groups. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + Unique fulfillment method identifier. + """ + line_item_ids: list[str] + """ + Line item IDs fulfilled via this method. + """ + destinations: list[fulfillment_destination.FulfillmentDestination] | None = None + """ + Available destinations. For shipping: addresses. For pickup: retail locations. + """ + selected_destination_id: str | None = None + """ + ID of the selected destination. + """ + groups: list[fulfillment_group.FulfillmentGroup] | None = None + """ + Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py new file mode 100644 index 0000000..e760d41 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py @@ -0,0 +1,38 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict, Field + +from . import item as item_1 + + +class LineItemCreateRequest(BaseModel): + """ + Line item object. Expected to use the currency of the parent object. + """ + + model_config = ConfigDict( + extra="allow", + ) + item: item_1.Item + quantity: int = Field(..., ge=1) + """ + Quantity of the item being purchased. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py new file mode 100644 index 0000000..c85a360 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py @@ -0,0 +1,43 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict, Field + +from . import item as item_1 + + +class LineItemUpdateRequest(BaseModel): + """ + Line item object. Expected to use the currency of the parent object. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str | None = None + item: item_1.Item + quantity: int = Field(..., ge=1) + """ + Quantity of the item being purchased. + """ + parent_id: str | None = None + """ + Parent line item identifier for any nested structures. + """ diff --git a/src/ucp_sdk/models/schemas/ucp.py b/src/ucp_sdk/models/schemas/ucp.py index d1ce414..ca18a9a 100644 --- a/src/ucp_sdk/models/schemas/ucp.py +++ b/src/ucp_sdk/models/schemas/ucp.py @@ -18,12 +18,10 @@ from __future__ import annotations -from typing import Any +from typing import Any, Literal from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel -from . import capability, payment_handler, service - class UcpMetadata(RootModel[Any]): root: Any = Field(..., title="UCP Metadata") @@ -76,6 +74,206 @@ class Entity(BaseModel): """ +class Base(RootModel[Any]): + root: Any + + +class PlatformSchema9(BaseModel): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" + + +class PlatformSchema10(BaseModel): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" + + +class PlatformSchema11(BaseModel): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" + + +class PlatformSchema12(BaseModel): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + + +class PlatformSchema8(RootModel[PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12]): + root: PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 = Field( + ..., title="Service (Platform Schema)" + ) + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + +class BusinessSchema8(BaseModel): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" + + +class BusinessSchema9(BaseModel): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" + + +class BusinessSchema10(BaseModel): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" + + +class EmbeddedConfig(BaseModel): + """ + Per-checkout configuration for embedded transport binding. Allows businesses to vary ECP availability and delegations based on cart contents, agent authorization, or policy. + """ + + model_config = ConfigDict( + extra="allow", + ) + delegate: list[str] | None = None + """ + Delegations the business allows. At service-level, declares available delegations. In checkout responses, confirms accepted delegations for this session. + """ + + +class ResponseSchema(BaseModel): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" + + +class ResponseSchema9(BaseModel): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" + + +class ResponseSchema10(BaseModel): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" + + +class ResponseSchema11(BaseModel): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + config: EmbeddedConfig | None = None + + +class ResponseSchema7(RootModel[ResponseSchema | ResponseSchema9 | ResponseSchema10 | ResponseSchema11]): + root: ResponseSchema | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 = Field( + ..., title="Service (Response Schema)" + ) + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + +class PlatformSchema13(RootModel[Any]): + root: Any = Field(..., title="Capability (Platform Schema)") + """ + Full capability declaration for platform-level discovery. Includes spec/schema URLs for agent fetching. + """ + + +class BusinessSchema12(RootModel[Base]): + root: Base = Field(..., title="Capability (Business Schema)") + """ + Capability configuration for business/merchant level. May include business-specific config overrides. + """ + + +class ResponseSchema12(RootModel[Base]): + root: Base = Field(..., title="Capability (Response Schema)") + """ + Capability reference in responses. Only name/version required to confirm active capabilities. + """ + + +class PlatformSchema14(RootModel[Any]): + root: Any = Field(..., title="Payment Handler (Platform Schema)") + """ + Platform declaration for discovery profiles. May include partial config state required for discovery. + """ + + +class BusinessSchema13(RootModel[Base]): + root: Base = Field(..., title="Payment Handler (Business Schema)") + """ + Business declaration for discovery profiles. May include partial config state required for discovery. + """ + + +class ResponseSchema13(RootModel[Base]): + root: Base = Field(..., title="Payment Handler (Response Schema)") + """ + Handler reference in responses. May include full config state for runtime usage of the handler. + """ + + class PlatformSchema(BaseModel): """ Full UCP metadata for platform-level configuration. Hosted at a URI advertised by the platform in request headers. @@ -127,36 +325,32 @@ class ResponseCheckoutSchema(BaseModel): payment_handlers: Any -class ResponseCartSchema(RootModel[Any]): - root: Any - - -class Base(BaseModel): +class ResponseOrderSchema(BaseModel): """ - Base UCP metadata with shared properties for all schema types. + UCP metadata for order responses. No payment handlers needed post-purchase. """ model_config = ConfigDict( extra="allow", ) - version: Version - services: dict[ReverseDomainName, list[service.Base]] | None = None + version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") """ - Service registry keyed by reverse-domain name. + UCP version in YYYY-MM-DD format. """ - capabilities: dict[ReverseDomainName, list[capability.Base]] | None = None + services: dict[str, list[Base]] | None = None """ - Capability registry keyed by reverse-domain name. + Service registry keyed by reverse-domain name. """ - payment_handlers: dict[ReverseDomainName, list[payment_handler.Base]] | None = None + capabilities: Any | None = None + payment_handlers: dict[str, list[Base]] | None = None """ Payment handler registry keyed by reverse-domain name. """ -class ResponseOrderSchema(BaseModel): +class ResponseCartSchema(BaseModel): """ - UCP metadata for order responses. No payment handlers needed post-purchase. + UCP metadata for cart responses. No payment handlers needed pre-checkout. """ model_config = ConfigDict( @@ -166,12 +360,56 @@ class ResponseOrderSchema(BaseModel): """ UCP version in YYYY-MM-DD format. """ - services: dict[str, list[service.Base]] | None = None + services: dict[str, list[Base]] | None = None """ Service registry keyed by reverse-domain name. """ capabilities: Any | None = None - payment_handlers: dict[str, list[payment_handler.Base]] | None = None + payment_handlers: dict[str, list[Base]] | None = None """ Payment handler registry keyed by reverse-domain name. """ + + +class BaseModel1(BaseModel): + """ + Base UCP metadata with shared properties for all schema types. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: Version + services: dict[ReverseDomainName, list[Base]] | None = None + """ + Service registry keyed by reverse-domain name. + """ + capabilities: dict[ReverseDomainName, list[Base]] | None = None + """ + Capability registry keyed by reverse-domain name. + """ + payment_handlers: dict[ReverseDomainName, list[Base]] | None = None + """ + Payment handler registry keyed by reverse-domain name. + """ + + +class BusinessSchema11(BaseModel): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + config: EmbeddedConfig | None = None + + +class BusinessSchema7(RootModel[BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11]): + root: BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 = Field( + ..., title="Service (Business Schema)" + ) + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ diff --git a/ucp b/ucp new file mode 160000 index 0000000..cc50009 --- /dev/null +++ b/ucp @@ -0,0 +1 @@ +Subproject commit cc500091eb173ef6f1578cf8904b05015f6a7e06 From d339a83544fde227e4d1a4267ae5c2ef90f8516a Mon Sep 17 00:00:00 2001 From: damaz91 Date: Fri, 6 Feb 2026 11:38:46 +0000 Subject: [PATCH 05/22] fix schema generation --- preprocess_schemas.py | 20 ++++++--- ...illment_available_method_create_request.py | 31 ++++++++++++++ ...illment_available_method_update_request.py | 31 ++++++++++++++ .../types/fulfillment_create_request.py | 37 +++++++++++++++++ .../fulfillment_option_create_request.py | 31 ++++++++++++++ .../fulfillment_option_update_request.py | 31 ++++++++++++++ .../types/fulfillment_update_request.py | 37 +++++++++++++++++ .../shopping/types/item_create_request.py | 31 ++++++++++++++ .../shopping/types/item_update_request.py | 31 ++++++++++++++ .../types/retail_location_create_request.py | 41 +++++++++++++++++++ .../types/retail_location_update_request.py | 41 +++++++++++++++++++ .../shopping/types/total_create_request.py | 27 ++++++++++++ .../shopping/types/total_update_request.py | 27 ++++++++++++ ucp | 1 - 14 files changed, 410 insertions(+), 7 deletions(-) create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/item_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/item_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/total_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/total_update_request.py delete mode 160000 ucp diff --git a/preprocess_schemas.py b/preprocess_schemas.py index 1dea8ac..fc15eb1 100644 --- a/preprocess_schemas.py +++ b/preprocess_schemas.py @@ -198,11 +198,20 @@ def process_ucp_request_scenarios(schema: Dict[str, Any], base_name: str, schema # Detect which scenarios exist scenario_types = set() + has_string_directive = False + for prop_name, prop_schema in schema["properties"].items(): if isinstance(prop_schema, dict) and "ucp_request" in prop_schema: ucp_req = prop_schema["ucp_request"] if isinstance(ucp_req, dict): scenario_types.update(ucp_req.keys()) + else: + has_string_directive = True + + # If no scenarios detected but plain strings exist, imply "create" and "update" scenarios + if not scenario_types and has_string_directive: + scenario_types.add("create") + scenario_types.add("update") # If no scenarios detected, return base schema if not scenario_types: @@ -362,12 +371,11 @@ def preprocess_schemas(input_dir: Path, output_dir: Path) -> None: if "properties" in schema: for prop_schema in schema["properties"].values(): if isinstance(prop_schema, dict) and "ucp_request" in prop_schema: - ucp_req = prop_schema["ucp_request"] - if isinstance(ucp_req, dict): - # This schema has scenarios - rel_path = json_file.relative_to(input_dir) - schemas_with_scenarios.add(str(rel_path)) - break + # If any ucp_request is present (dict or string), it has scenarios + rel_path = json_file.relative_to(input_dir) + path_str = str(rel_path).replace("\\", "/") # Normalize path separators + schemas_with_scenarios.add(path_str) + break # Second pass: preprocess and generate schemas for json_file in json_files: diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py new file mode 100644 index 0000000..54854b7 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py @@ -0,0 +1,31 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class FulfillmentAvailableMethodCreateRequest(BaseModel): + """ + Inventory availability hint for a fulfillment method type. + """ + + model_config = ConfigDict( + extra="allow", + ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py new file mode 100644 index 0000000..678c052 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py @@ -0,0 +1,31 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class FulfillmentAvailableMethodUpdateRequest(BaseModel): + """ + Inventory availability hint for a fulfillment method type. + """ + + model_config = ConfigDict( + extra="allow", + ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py new file mode 100644 index 0000000..6b3a605 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py @@ -0,0 +1,37 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import fulfillment_method + + +class FulfillmentCreateRequest(BaseModel): + """ + Container for fulfillment methods and availability. + """ + + model_config = ConfigDict( + extra="allow", + ) + methods: list[fulfillment_method.FulfillmentMethod] | None = None + """ + Fulfillment methods for cart items. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py new file mode 100644 index 0000000..d08ee75 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py @@ -0,0 +1,31 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class FulfillmentOptionCreateRequest(BaseModel): + """ + A fulfillment option within a group (e.g., Standard Shipping $5, Express $15). + """ + + model_config = ConfigDict( + extra="allow", + ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py new file mode 100644 index 0000000..363e7f3 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py @@ -0,0 +1,31 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class FulfillmentOptionUpdateRequest(BaseModel): + """ + A fulfillment option within a group (e.g., Standard Shipping $5, Express $15). + """ + + model_config = ConfigDict( + extra="allow", + ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py new file mode 100644 index 0000000..3422acb --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py @@ -0,0 +1,37 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import fulfillment_method + + +class FulfillmentUpdateRequest(BaseModel): + """ + Container for fulfillment methods and availability. + """ + + model_config = ConfigDict( + extra="allow", + ) + methods: list[fulfillment_method.FulfillmentMethod] | None = None + """ + Fulfillment methods for cart items. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py new file mode 100644 index 0000000..bbef8e8 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py @@ -0,0 +1,31 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class ItemCreateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + The product identifier, often the SKU, required to resolve the product details associated with this line item. Should be recognized by both the Platform, and the Business. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py new file mode 100644 index 0000000..c957d16 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py @@ -0,0 +1,31 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class ItemUpdateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + The product identifier, often the SKU, required to resolve the product details associated with this line item. Should be recognized by both the Platform, and the Business. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py new file mode 100644 index 0000000..9de6eb1 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py @@ -0,0 +1,41 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import postal_address + + +class RetailLocationCreateRequest(BaseModel): + """ + A pickup location (retail store, locker, etc.). + """ + + model_config = ConfigDict( + extra="allow", + ) + name: str + """ + Location name (e.g., store name). + """ + address: postal_address.PostalAddress | None = None + """ + Physical address of the location. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py new file mode 100644 index 0000000..8e83ff4 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py @@ -0,0 +1,41 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import postal_address + + +class RetailLocationUpdateRequest(BaseModel): + """ + A pickup location (retail store, locker, etc.). + """ + + model_config = ConfigDict( + extra="allow", + ) + name: str + """ + Location name (e.g., store name). + """ + address: postal_address.PostalAddress | None = None + """ + Physical address of the location. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/total_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/total_create_request.py new file mode 100644 index 0000000..6318099 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/total_create_request.py @@ -0,0 +1,27 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class TotalCreateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/total_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/total_update_request.py new file mode 100644 index 0000000..e8ca037 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/total_update_request.py @@ -0,0 +1,27 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class TotalUpdateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) diff --git a/ucp b/ucp deleted file mode 160000 index cc50009..0000000 --- a/ucp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cc500091eb173ef6f1578cf8904b05015f6a7e06 From 95e1ed53616c62df3421dbcfd2df76eec0206190 Mon Sep 17 00:00:00 2001 From: damaz91 Date: Fri, 6 Feb 2026 11:51:01 +0000 Subject: [PATCH 06/22] fix schema generation --- preprocess_schemas.py | 20 +++++++++++-------- .../types/fulfillment_create_request.py | 4 ++-- .../fulfillment_method_create_request.py | 4 ++-- .../fulfillment_method_update_request.py | 4 ++-- .../types/fulfillment_update_request.py | 4 ++-- .../types/line_item_create_request.py | 4 ++-- .../types/line_item_update_request.py | 4 ++-- ucp | 1 + 8 files changed, 25 insertions(+), 20 deletions(-) create mode 160000 ucp diff --git a/preprocess_schemas.py b/preprocess_schemas.py index fc15eb1..2d8e802 100644 --- a/preprocess_schemas.py +++ b/preprocess_schemas.py @@ -19,6 +19,7 @@ import json import shutil import copy +import os from pathlib import Path from typing import Any, Dict @@ -159,11 +160,12 @@ def update_refs_for_scenario(obj: Any, scenario: str, schemas_with_scenarios: se elif value.endswith(".json"): # Resolve the relative path from current schema's directory if current_dir: - ref_path = str(Path(current_dir) / value) + combined = os.path.join(current_dir, value) + ref_path = os.path.normpath(combined) else: - ref_path = value + ref_path = os.path.normpath(value) - # Normalize the path + # Normalize the path (force forward slashes) ref_path = ref_path.replace("\\", "/") # Check if the referenced schema has scenarios @@ -288,7 +290,7 @@ def clean_schema_for_codegen(schema: Dict[str, Any]) -> Dict[str, Any]: return schema -def preprocess_schema_file(input_path: Path, output_path: Path, schemas_with_scenarios: set) -> None: +def preprocess_schema_file(input_path: Path, output_path: Path, schemas_with_scenarios: set, schema_dir: str) -> None: """Preprocess a single schema file.""" with open(input_path, 'r', encoding='utf-8') as f: schema = json.load(f) @@ -318,9 +320,6 @@ def preprocess_schema_file(input_path: Path, output_path: Path, schemas_with_sce # Generate scenario-specific schemas base_name = output_path.stem # filename without extension - # Get the directory of this schema relative to the root (for resolving refs) - schema_dir = str(output_path.parent.relative_to(output_path.parent.parent.parent)) - scenarios = process_ucp_request_scenarios(schema, base_name, schemas_with_scenarios, schema_dir) # Ensure output directory exists @@ -383,8 +382,13 @@ def preprocess_schemas(input_dir: Path, output_dir: Path) -> None: rel_path = json_file.relative_to(input_dir) output_path = output_dir / rel_path + # Calculate directory of this file relative to valid root + file_rel_dir = str(rel_path.parent).replace("\\", "/") + if file_rel_dir == ".": + file_rel_dir = "" + print(f" Processing: {rel_path}") - preprocess_schema_file(json_file, output_path, schemas_with_scenarios) + preprocess_schema_file(json_file, output_path, schemas_with_scenarios, file_rel_dir) print(f"Preprocessing complete. Output in {output_dir}") diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py index 6b3a605..14bdc77 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py @@ -20,7 +20,7 @@ from pydantic import BaseModel, ConfigDict -from . import fulfillment_method +from . import fulfillment_method_create_request class FulfillmentCreateRequest(BaseModel): @@ -31,7 +31,7 @@ class FulfillmentCreateRequest(BaseModel): model_config = ConfigDict( extra="allow", ) - methods: list[fulfillment_method.FulfillmentMethod] | None = None + methods: list[fulfillment_method_create_request.FulfillmentMethodCreateRequest] | None = None """ Fulfillment methods for cart items. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py index 8ee2ebc..399ef6f 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py @@ -22,7 +22,7 @@ from pydantic import BaseModel, ConfigDict -from . import fulfillment_destination, fulfillment_group +from . import fulfillment_destination, fulfillment_group_create_request class FulfillmentMethodCreateRequest(BaseModel): @@ -49,7 +49,7 @@ class FulfillmentMethodCreateRequest(BaseModel): """ ID of the selected destination. """ - groups: list[fulfillment_group.FulfillmentGroup] | None = None + groups: list[fulfillment_group_create_request.FulfillmentGroupCreateRequest] | None = None """ Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py index e5796c2..4d1e810 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py @@ -20,7 +20,7 @@ from pydantic import BaseModel, ConfigDict -from . import fulfillment_destination, fulfillment_group +from . import fulfillment_destination, fulfillment_group_update_request class FulfillmentMethodUpdateRequest(BaseModel): @@ -47,7 +47,7 @@ class FulfillmentMethodUpdateRequest(BaseModel): """ ID of the selected destination. """ - groups: list[fulfillment_group.FulfillmentGroup] | None = None + groups: list[fulfillment_group_update_request.FulfillmentGroupUpdateRequest] | None = None """ Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py index 3422acb..7551337 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py @@ -20,7 +20,7 @@ from pydantic import BaseModel, ConfigDict -from . import fulfillment_method +from . import fulfillment_method_update_request class FulfillmentUpdateRequest(BaseModel): @@ -31,7 +31,7 @@ class FulfillmentUpdateRequest(BaseModel): model_config = ConfigDict( extra="allow", ) - methods: list[fulfillment_method.FulfillmentMethod] | None = None + methods: list[fulfillment_method_update_request.FulfillmentMethodUpdateRequest] | None = None """ Fulfillment methods for cart items. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py index e760d41..754e4fe 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py @@ -20,7 +20,7 @@ from pydantic import BaseModel, ConfigDict, Field -from . import item as item_1 +from . import item_create_request class LineItemCreateRequest(BaseModel): @@ -31,7 +31,7 @@ class LineItemCreateRequest(BaseModel): model_config = ConfigDict( extra="allow", ) - item: item_1.Item + item: item_create_request.ItemCreateRequest quantity: int = Field(..., ge=1) """ Quantity of the item being purchased. diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py index c85a360..fc43593 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py @@ -20,7 +20,7 @@ from pydantic import BaseModel, ConfigDict, Field -from . import item as item_1 +from . import item_update_request class LineItemUpdateRequest(BaseModel): @@ -32,7 +32,7 @@ class LineItemUpdateRequest(BaseModel): extra="allow", ) id: str | None = None - item: item_1.Item + item: item_update_request.ItemUpdateRequest quantity: int = Field(..., ge=1) """ Quantity of the item being purchased. diff --git a/ucp b/ucp new file mode 160000 index 0000000..cc50009 --- /dev/null +++ b/ucp @@ -0,0 +1 @@ +Subproject commit cc500091eb173ef6f1578cf8904b05015f6a7e06 From c487f9809d2b0ff26731ada9121b946141d3293a Mon Sep 17 00:00:00 2001 From: Federico D'Amato Date: Fri, 6 Feb 2026 19:07:17 +0100 Subject: [PATCH 07/22] Update pyproject.toml --- pyproject.toml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 78695e0..6cd8fea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,11 @@ [project] name = "ucp-sdk" -version = "0.1.0" +version = "0.2.0" description = "UCP Python SDK" readme = "README.md" authors = [ - { name = "Florin Iucha", email = "fiucha@google.com" } + { name = "Florin Iucha", email = "fiucha@google.com" }, + { name = "Federico D'Amato", email = "damaz@google.com" } ] requires-python = ">=3.10" dependencies = [ @@ -43,4 +44,4 @@ custom-file-header = """ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable -""" \ No newline at end of file +""" From 87df21ed94fcd8ec0b576c46324ad2b497974ba2 Mon Sep 17 00:00:00 2001 From: damaz91 Date: Wed, 11 Feb 2026 09:20:37 +0000 Subject: [PATCH 08/22] update pre-processing to correctly handle self-reference --- preprocess_schemas.py | 24 +++++++--- .../shopping/types/payment_instrument.py | 45 ++++++++++++++++--- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/preprocess_schemas.py b/preprocess_schemas.py index 2d8e802..b0b72da 100644 --- a/preprocess_schemas.py +++ b/preprocess_schemas.py @@ -42,8 +42,9 @@ def remove_extension_defs(schema: Dict[str, Any]) -> Dict[str, Any]: for item in all_of: if isinstance(item, dict) and "$ref" in item: ref = item["$ref"] - # If referencing another top-level schema (not within same file's $defs) - if not ref.startswith("#/"): + # If referencing another top-level schema (not within same file's $defs or root) + # Note: "#" is a reference to the root schema, which is internal + if not ref.startswith("#/") and ref != "#": has_external_ref = True break @@ -109,12 +110,17 @@ def flatten_allof_in_defs(schema: Dict[str, Any]) -> Dict[str, Any]: if isinstance(def_schema, dict) and "allOf" in def_schema: all_of = def_schema["allOf"] - # Check if all refs are internal + # Check if all refs are internal (including root schema references like "#") all_internal = True + has_root_ref = False for item in all_of: if isinstance(item, dict) and "$ref" in item: ref = item["$ref"] - if not ref.startswith("#/"): + # Check for root schema reference + if ref == "#": + has_root_ref = True + # Not internal if it's an external reference (doesn't start with #/) + elif not ref.startswith("#/"): all_internal = False break @@ -122,7 +128,15 @@ def flatten_allof_in_defs(schema: Dict[str, Any]) -> Dict[str, Any]: # Flatten the allOf by inlining refs merged = {} for item in all_of: - resolved = inline_internal_refs(item, defs, set()) + # Handle root schema reference "#" + if isinstance(item, dict) and "$ref" in item and item["$ref"] == "#": + # Inline the root schema (exclude $defs, $id, $schema, title, description) + root_copy = {k: v for k, v in schema.items() + if k not in ["$defs", "$id", "$schema", "title", "description"]} + resolved = root_copy + else: + resolved = inline_internal_refs(item, defs, set()) + # Merge properties for k, v in resolved.items(): if k == "properties" and k in merged: diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py b/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py index e99d68f..c8d897d 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py +++ b/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py @@ -20,15 +20,11 @@ from typing import Any -from pydantic import BaseModel, ConfigDict, RootModel +from pydantic import BaseModel, ConfigDict from . import payment_credential, postal_address -class SelectedPaymentInstrument(RootModel[Any]): - root: Any - - class PaymentInstrument(BaseModel): """ The base definition for any payment instrument. It links the instrument to a specific payment handler. @@ -58,3 +54,42 @@ class PaymentInstrument(BaseModel): """ Display information for this payment instrument. Each payment instrument schema defines its specific display properties, as outlined by the payment handler. """ + selected: bool | None = None + """ + Whether this instrument is selected by the user. + """ + + +class SelectedPaymentInstrument(BaseModel): + """ + A payment instrument with selection state. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + A unique identifier for this instrument instance, assigned by the platform. + """ + handler_id: str + """ + The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition. + """ + type: str + """ + The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value. + """ + billing_address: postal_address.PostalAddress | None = None + """ + The billing address associated with this payment method. + """ + credential: payment_credential.PaymentCredential | None = None + display: dict[str, Any] | None = None + """ + Display information for this payment instrument. Each payment instrument schema defines its specific display properties, as outlined by the payment handler. + """ + selected: bool | None = None + """ + Whether this instrument is selected by the user. + """ From bbad289c14143ab2a3a4bd729eb71ad421b7ec91 Mon Sep 17 00:00:00 2001 From: damaz91 Date: Wed, 11 Feb 2026 09:21:48 +0000 Subject: [PATCH 09/22] fix --- ucp | 1 - 1 file changed, 1 deletion(-) delete mode 160000 ucp diff --git a/ucp b/ucp deleted file mode 160000 index cc50009..0000000 --- a/ucp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cc500091eb173ef6f1578cf8904b05015f6a7e06 From 16e045b10db7b75dd5c78a911860e895685cc21e Mon Sep 17 00:00:00 2001 From: damaz91 Date: Wed, 11 Feb 2026 09:23:28 +0000 Subject: [PATCH 10/22] sync --- pyproject.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 78695e0..eda1f2a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,12 @@ [project] name = "ucp-sdk" -version = "0.1.0" +version = "0.2.0" description = "UCP Python SDK" readme = "README.md" authors = [ - { name = "Florin Iucha", email = "fiucha@google.com" } + { name = "Florin Iucha", email = "fiucha@google.com" }, + { name = "Federico D'Amato", email = "damaz@google.com" } + ] requires-python = ">=3.10" dependencies = [ From bea0f7fce62cd6aedde9c8da01368a490f8d5a10 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 15:08:30 +0100 Subject: [PATCH 11/22] address comments Change-Id: I7400c7bd870e3505d5b8c9a9e179d305c65bb3dc --- README.md | 14 +- generate_models.sh | 46 ++-- preprocess_schemas.py | 209 +++++++++++------- pyproject.toml | 20 +- src/ucp_sdk/__init__.py | 19 -- src/ucp_sdk/models/__init__.py | 18 ++ .../models/discovery/profile_schema.py | 4 +- src/ucp_sdk/models/ruff.toml | 16 -- src/ucp_sdk/models/schemas/service.py | 36 ++- .../models/schemas/shopping/ap2_mandate.py | 4 +- src/ucp_sdk/models/schemas/shopping/cart.py | 152 ------------- .../schemas/shopping/cart_create_request.py | 47 ---- .../schemas/shopping/cart_update_request.py | 51 ----- .../models/schemas/shopping/checkout.py | 121 +--------- .../shopping/checkout_create_request.py | 29 +-- .../shopping/checkout_update_request.py | 29 +-- .../schemas/shopping/fulfillment/__init__.py | 4 +- src/ucp_sdk/models/schemas/shopping/order.py | 8 +- .../models/schemas/shopping/payment.py | 4 +- .../types/business_fulfillment_config.py | 4 +- .../models/schemas/shopping/types/context.py | 6 +- .../schemas/shopping/types/fulfillment.py | 4 +- .../types/fulfillment_create_request.py | 5 +- .../shopping/types/fulfillment_destination.py | 14 +- .../shopping/types/fulfillment_method.py | 4 +- .../fulfillment_method_create_request.py | 9 +- .../fulfillment_method_update_request.py | 9 +- .../types/fulfillment_update_request.py | 5 +- .../models/schemas/shopping/types/item.py | 2 +- .../shopping/types/item_create_request.py | 2 +- .../shopping/types/item_update_request.py | 2 +- .../types/merchant_fulfillment_config.py | 4 +- .../models/schemas/shopping/types/message.py | 16 +- .../schemas/shopping/types/message_error.py | 4 +- .../models/schemas/shopping/types/total.py | 10 +- src/ucp_sdk/models/schemas/ucp.py | 77 +++---- 36 files changed, 368 insertions(+), 640 deletions(-) delete mode 100644 src/ucp_sdk/__init__.py create mode 100644 src/ucp_sdk/models/__init__.py delete mode 100644 src/ucp_sdk/models/ruff.toml delete mode 100644 src/ucp_sdk/models/schemas/shopping/cart.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/cart_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/cart_update_request.py diff --git a/README.md b/README.md index d6da2e4..4a3bd74 100644 --- a/README.md +++ b/README.md @@ -55,24 +55,24 @@ This project uses `uv` for dependency management. The models are automatically generated from the JSON schemas in the UCP Specification. -Clone the UCP main repository in the same folder: +To regenerate the models: ```bash -git clone https://github.com/Universal-Commerce-Protocol/ucp.git +uv sync +./generate_models.sh ``` -To regenerate the models: +By default, it uses the version `release-2026.01.23`. You can specify a different tag or branch as an argument: ```bash -uv sync -./generate_models.sh +./generate_models.sh v2026.03.01 ``` -The generated code is automatically formatted using `ruff`. +The latest version of the [UCP repo](https://github.com/Universal-Commerce-Protocol/ucp) is automatically downloaded and used to generate the models. The generated code is automatically formatted using `ruff`. ## Contributing -We welcome community contributions. See our [Contribution Guide](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/CONTRIBUTING.md) for details. +We welcome community contributions. See our [Contribution Guide](https://github.com/Universal-Commerce-Protocol/.github/blob/main/CONTRIBUTING.md) for details. ## License diff --git a/generate_models.sh b/generate_models.sh index 297a26e..59f8792 100755 --- a/generate_models.sh +++ b/generate_models.sh @@ -4,6 +4,25 @@ # Ensure we are in the script's directory cd "$(dirname "$0")" +# Check if git is installed +if ! command -v git &> /dev/null; then + echo "Error: git not found. Please install git." + exit 1 +fi + +# UCP Version to use (if provided, use release/$1 branch; otherwise, use main) +if [ -z "$1" ]; then + BRANCH="main" + echo "No version specified, cloning main branch..." +else + BRANCH="release/$1" + echo "Cloning version $1 (branch: $BRANCH)..." +fi + +# Ensure ucp directory is clean before cloning +rm -rf ucp +git clone -b "$BRANCH" --depth 1 https://github.com/Universal-Commerce-Protocol/ucp ucp + # Output directory OUTPUT_DIR="src/ucp_sdk/models" @@ -12,7 +31,7 @@ SCHEMA_DIR="ucp/source" TEMP_SCHEMA_DIR="temp_schemas" echo "Preprocessing schemas..." -python3 preprocess_schemas.py +uv run python preprocess_schemas.py echo "Generating Pydantic models from preprocessed schemas..." @@ -27,30 +46,11 @@ fi rm -r -f "$OUTPUT_DIR" mkdir -p "$OUTPUT_DIR" -# Create ruff configuration for generated code -cat > "$OUTPUT_DIR/ruff.toml" << 'EOF' -# Ruff configuration for generated models -# These are auto-generated files, so we're more lenient with style rules - -line-length = 120 -target-version = "py311" - -[lint] -select = ["E", "F", "I"] -ignore = ["E501"] - -[lint.pydocstyle] -convention = "google" - -[lint.per-file-ignores] -"__init__.py" = ["D104"] -"*.py" = ["D100", "D101", "D102", "D103", "D200", "D205", "D212"] -EOF # Run generation using uv # We use --use-schema-description to use descriptions from JSON schema as docstrings # We use --field-constraints to include validation constraints (regex, min/max, etc.) -# Note: Formatters removed as they can hang on large schemas +# Note: Formatting is done as a post-processing step. uv run \ --link-mode=copy \ --extra-index-url https://pypi.org/simple python \ @@ -69,8 +69,8 @@ uv run \ --allow-extra-fields echo "Formatting generated models..." -uv run ruff format "$OUTPUT_DIR" -uv run ruff check --fix --config "$OUTPUT_DIR/ruff.toml" "$OUTPUT_DIR" 2>&1 | grep -E "^(All checks passed|Fixed|Found)" || echo "Formatting complete" +uv run ruff format +uv run ruff check --fix "$OUTPUT_DIR" 2>&1 | grep -E "^(All checks passed|Fixed|Found)" || echo "Formatting complete" # Clean up temporary schemas rm -rf "$TEMP_SCHEMA_DIR" diff --git a/preprocess_schemas.py b/preprocess_schemas.py index b0b72da..08275f2 100644 --- a/preprocess_schemas.py +++ b/preprocess_schemas.py @@ -16,6 +16,7 @@ """ Preprocess JSON schemas for datamodel-code-generator compatibility. """ + import json import shutil import copy @@ -31,9 +32,9 @@ def remove_extension_defs(schema: Dict[str, Any]) -> Dict[str, Any]: """ if "$defs" not in schema: return schema - + defs_to_remove = [] - + for def_name, def_schema in schema["$defs"].items(): if isinstance(def_schema, dict) and "allOf" in def_schema: # Check if this extends an external schema @@ -47,30 +48,32 @@ def remove_extension_defs(schema: Dict[str, Any]) -> Dict[str, Any]: if not ref.startswith("#/") and ref != "#": has_external_ref = True break - + if has_external_ref: print(f" -> Removing extension def: {def_name}") defs_to_remove.append(def_name) - + # Remove extension defs for def_name in defs_to_remove: del schema["$defs"][def_name] - + # Remove empty $defs if "$defs" in schema and not schema["$defs"]: del schema["$defs"] - + return schema -def inline_internal_refs(obj: Any, defs: Dict[str, Any], processed: set = None) -> Any: +def inline_internal_refs( + obj: Any, defs: Dict[str, Any], processed: set = None +) -> Any: """ Recursively inline $ref references that point to #/$defs/... This resolves internal references to avoid cross-file confusion. """ if processed is None: processed = set() - + if isinstance(obj, dict): # Check for $ref if "$ref" in obj and len(obj) == 1: @@ -86,7 +89,7 @@ def inline_internal_refs(obj: Any, defs: Dict[str, Any], processed: set = None) processed.remove(def_name) return result return obj - + # Recursively process all properties result = {} for key, value in obj.items(): @@ -103,13 +106,13 @@ def flatten_allof_in_defs(schema: Dict[str, Any]) -> Dict[str, Any]: """ if "$defs" not in schema: return schema - + defs = schema["$defs"] - + for def_name, def_schema in list(defs.items()): if isinstance(def_schema, dict) and "allOf" in def_schema: all_of = def_schema["allOf"] - + # Check if all refs are internal (including root schema references like "#") all_internal = True has_root_ref = False @@ -123,20 +126,34 @@ def flatten_allof_in_defs(schema: Dict[str, Any]) -> Dict[str, Any]: elif not ref.startswith("#/"): all_internal = False break - + if all_internal: # Flatten the allOf by inlining refs merged = {} for item in all_of: # Handle root schema reference "#" - if isinstance(item, dict) and "$ref" in item and item["$ref"] == "#": + if ( + isinstance(item, dict) + and "$ref" in item + and item["$ref"] == "#" + ): # Inline the root schema (exclude $defs, $id, $schema, title, description) - root_copy = {k: v for k, v in schema.items() - if k not in ["$defs", "$id", "$schema", "title", "description"]} + root_copy = { + k: v + for k, v in schema.items() + if k + not in [ + "$defs", + "$id", + "$schema", + "title", + "description", + ] + } resolved = root_copy else: resolved = inline_internal_refs(item, defs, set()) - + # Merge properties for k, v in resolved.items(): if k == "properties" and k in merged: @@ -145,19 +162,21 @@ def flatten_allof_in_defs(schema: Dict[str, Any]) -> Dict[str, Any]: merged[k] = list(set(merged[k] + v)) elif k not in ["title", "description", "allOf"]: merged[k] = v - + # Keep original title and description if "title" in def_schema: merged["title"] = def_schema["title"] if "description" in def_schema: merged["description"] = def_schema["description"] - + defs[def_name] = merged - + return schema -def update_refs_for_scenario(obj: Any, scenario: str, schemas_with_scenarios: set, current_dir: str = "") -> Any: +def update_refs_for_scenario( + obj: Any, scenario: str, schemas_with_scenarios: set, current_dir: str = "" +) -> Any: """ Recursively update $ref paths to point to scenario-specific schemas. For example, changes "types/line_item.json" to "types/line_item_create_request.json" for create scenario. @@ -178,10 +197,10 @@ def update_refs_for_scenario(obj: Any, scenario: str, schemas_with_scenarios: se ref_path = os.path.normpath(combined) else: ref_path = os.path.normpath(value) - + # Normalize the path (force forward slashes) ref_path = ref_path.replace("\\", "/") - + # Check if the referenced schema has scenarios if ref_path in schemas_with_scenarios: base_path = value[:-5] # Remove .json @@ -193,25 +212,37 @@ def update_refs_for_scenario(obj: Any, scenario: str, schemas_with_scenarios: se else: result[key] = value else: - result[key] = update_refs_for_scenario(value, scenario, schemas_with_scenarios, current_dir) + result[key] = update_refs_for_scenario( + value, scenario, schemas_with_scenarios, current_dir + ) return result elif isinstance(obj, list): - return [update_refs_for_scenario(item, scenario, schemas_with_scenarios, current_dir) for item in obj] + return [ + update_refs_for_scenario( + item, scenario, schemas_with_scenarios, current_dir + ) + for item in obj + ] return obj -def process_ucp_request_scenarios(schema: Dict[str, Any], base_name: str, schemas_with_scenarios: set, schema_dir: str = "") -> Dict[str, Dict[str, Any]]: +def process_ucp_request_scenarios( + schema: Dict[str, Any], + base_name: str, + schemas_with_scenarios: set, + schema_dir: str = "", +) -> Dict[str, Dict[str, Any]]: """ Generate separate schemas for create, update, and complete scenarios based on ucp_request annotations. - + Returns a dict mapping scenario names (e.g., 'create', 'update', 'complete') to their schemas. """ scenarios = {} - + # Check if this schema has properties with ucp_request annotations if "properties" not in schema: return {"base": schema} - + # Detect which scenarios exist scenario_types = set() has_string_directive = False @@ -228,30 +259,32 @@ def process_ucp_request_scenarios(schema: Dict[str, Any], base_name: str, schema if not scenario_types and has_string_directive: scenario_types.add("create") scenario_types.add("update") - + # If no scenarios detected, return base schema if not scenario_types: return {"base": schema} - + # Generate a schema for each scenario for scenario in scenario_types: scenario_schema = copy.deepcopy(schema) - + # Update title and description to reflect the scenario if "title" in scenario_schema: - scenario_schema["title"] = f"{scenario_schema['title']} ({scenario.capitalize()} Request)" - + scenario_schema["title"] = ( + f"{scenario_schema['title']} ({scenario.capitalize()} Request)" + ) + # Process each property based on its ucp_request directive properties_to_remove = [] required_fields = set(scenario_schema.get("required", [])) - + for prop_name, prop_schema in scenario_schema["properties"].items(): if isinstance(prop_schema, dict) and "ucp_request" in prop_schema: ucp_req = prop_schema["ucp_request"] - + # Clean up the ucp_request annotation from the property del prop_schema["ucp_request"] - + # Determine the directive for this scenario if isinstance(ucp_req, str): directive = ucp_req @@ -259,7 +292,7 @@ def process_ucp_request_scenarios(schema: Dict[str, Any], base_name: str, schema directive = ucp_req.get(scenario, "optional") else: directive = "optional" - + # Handle the directive if directive == "omit": properties_to_remove.append(prop_name) @@ -268,22 +301,24 @@ def process_ucp_request_scenarios(schema: Dict[str, Any], base_name: str, schema required_fields.add(prop_name) elif directive == "optional": required_fields.discard(prop_name) - + # Remove omitted properties for prop_name in properties_to_remove: del scenario_schema["properties"][prop_name] - + # Update required fields if required_fields: scenario_schema["required"] = sorted(list(required_fields)) elif "required" in scenario_schema: del scenario_schema["required"] - + # Update all $ref paths to point to scenario-specific schemas - scenario_schema = update_refs_for_scenario(scenario_schema, scenario, schemas_with_scenarios, schema_dir) - + scenario_schema = update_refs_for_scenario( + scenario_schema, scenario, schemas_with_scenarios, schema_dir + ) + scenarios[scenario] = scenario_schema - + return scenarios @@ -294,21 +329,26 @@ def clean_schema_for_codegen(schema: Dict[str, Any]) -> Dict[str, Any]: - Remove $schema fields """ schema = copy.deepcopy(schema) - + # Remove fields that can cause URL resolution issues if "$id" in schema: del schema["$id"] if "$schema" in schema: del schema["$schema"] - + return schema -def preprocess_schema_file(input_path: Path, output_path: Path, schemas_with_scenarios: set, schema_dir: str) -> None: +def preprocess_schema_file( + input_path: Path, + output_path: Path, + schemas_with_scenarios: set, + schema_dir: str, +) -> None: """Preprocess a single schema file.""" - with open(input_path, 'r', encoding='utf-8') as f: + with open(input_path, "r", encoding="utf-8") as f: schema = json.load(f) - + # WARN: Workaround for datamodel-codegen issue with relative paths # When ucp.json is referenced from a subdirectory (e.g. schemas/shopping/checkout.json referencing ../ucp.json), # the subsequent reference to service.json (in ucp.json) is incorrectly resolved relative to the subdirectory. @@ -317,48 +357,58 @@ def preprocess_schema_file(input_path: Path, output_path: Path, schemas_with_sce # Force absolute paths for all sibling references in ucp.json # This fixes resolution issues when ucp.json is referenced from subdirectories schema_str = json.dumps(schema) - + input_dir_abs = output_path.parent.resolve() - for ref_file in ["service.json", "capability.json", "payment_handler.json"]: + for ref_file in [ + "service.json", + "capability.json", + "payment_handler.json", + ]: ref_path = input_dir_abs / ref_file - schema_str = schema_str.replace(f'"{ref_file}', f'"file://{ref_path}') - + schema_str = schema_str.replace( + f'"{ref_file}', f'"file://{ref_path}' + ) + schema = json.loads(schema_str) # Remove extension definitions that reference external schemas schema = remove_extension_defs(schema) - + # Flatten allOf patterns within $defs that only use internal refs schema = flatten_allof_in_defs(schema) - + # Generate scenario-specific schemas base_name = output_path.stem # filename without extension - - scenarios = process_ucp_request_scenarios(schema, base_name, schemas_with_scenarios, schema_dir) - + + scenarios = process_ucp_request_scenarios( + schema, base_name, schemas_with_scenarios, schema_dir + ) + # Ensure output directory exists output_path.parent.mkdir(parents=True, exist_ok=True) - + # Write preprocessed schema(s) if len(scenarios) == 1 and "base" in scenarios: # No scenarios, write single file cleaned = clean_schema_for_codegen(scenarios["base"]) - with open(output_path, 'w', encoding='utf-8') as f: + with open(output_path, "w", encoding="utf-8") as f: json.dump(cleaned, f, indent=2) else: # Write both base schema and scenario-specific files # First, write the base schema (for non-scenario-specific references) base_schema = copy.deepcopy(schema) cleaned_base = clean_schema_for_codegen(base_schema) - with open(output_path, 'w', encoding='utf-8') as f: + with open(output_path, "w", encoding="utf-8") as f: json.dump(cleaned_base, f, indent=2) - + # Then write separate files for each scenario for scenario_name, scenario_schema in scenarios.items(): - scenario_path = output_path.parent / f"{base_name}_{scenario_name}_request.json" + scenario_path = ( + output_path.parent / f"{base_name}_{scenario_name}_request.json" + ) print(f" -> Generating {scenario_name} request schema") cleaned = clean_schema_for_codegen(scenario_schema) - with open(scenario_path, 'w', encoding='utf-8') as f: + with open(scenario_path, "w", encoding="utf-8") as f: json.dump(cleaned, f, indent=2) @@ -368,42 +418,49 @@ def preprocess_schemas(input_dir: Path, output_dir: Path) -> None: if output_dir.exists(): shutil.rmtree(output_dir) output_dir.mkdir(parents=True) - + # Find all JSON files json_files = list(input_dir.rglob("*.json")) - + print(f"Preprocessing {len(json_files)} schema files...") - + # First pass: track which schemas have scenarios schemas_with_scenarios = set() for json_file in json_files: - with open(json_file, 'r', encoding='utf-8') as f: + with open(json_file, "r", encoding="utf-8") as f: schema = json.load(f) - + # Check if this schema has ucp_request scenarios if "properties" in schema: for prop_schema in schema["properties"].values(): - if isinstance(prop_schema, dict) and "ucp_request" in prop_schema: + if ( + isinstance(prop_schema, dict) + and "ucp_request" in prop_schema + ): # If any ucp_request is present (dict or string), it has scenarios rel_path = json_file.relative_to(input_dir) - path_str = str(rel_path).replace("\\", "/") # Normalize path separators + path_str = str(rel_path).replace( + "\\", "/" + ) # Normalize path separators schemas_with_scenarios.add(path_str) break - + # Second pass: preprocess and generate schemas for json_file in json_files: # Calculate relative path rel_path = json_file.relative_to(input_dir) output_path = output_dir / rel_path - + # Calculate directory of this file relative to valid root file_rel_dir = str(rel_path.parent).replace("\\", "/") if file_rel_dir == ".": file_rel_dir = "" print(f" Processing: {rel_path}") - preprocess_schema_file(json_file, output_path, schemas_with_scenarios, file_rel_dir) - + preprocess_schema_file( + json_file, output_path, schemas_with_scenarios, file_rel_dir + ) + print(f"Preprocessing complete. Output in {output_dir}") @@ -411,5 +468,5 @@ def preprocess_schemas(input_dir: Path, output_dir: Path) -> None: script_dir = Path(__file__).parent input_schemas = script_dir / "ucp" / "source" output_schemas = script_dir / "temp_schemas" - + preprocess_schemas(input_schemas, output_schemas) diff --git a/pyproject.toml b/pyproject.toml index 71e8eb6..632ab81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,11 @@ [project] name = "ucp-sdk" -version = "0.2.0" +version = "2026.01.23" description = "UCP Python SDK" readme = "README.md" authors = [ - { name = "Florin Iucha", email = "fiucha@google.com" } + { name = "Florin Iucha", email = "fiucha@google.com" }, + { name = "Federico D'Amato", email = "damaz@google.com" }, ] requires-python = ">=3.10" dependencies = [ @@ -24,6 +25,21 @@ build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/ucp_sdk"] +[tool.ruff] +line-length = 80 +target-version = "py311" + +[tool.ruff.lint] +select = ["E", "F", "I"] +ignore = ["E501"] + +[tool.ruff.lint.pydocstyle] +convention = "google" + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["D104"] +"*.py" = ["D100", "D101", "D102", "D103", "D200", "D205", "D212"] + [tool.datamodel-codegen] custom-file-header = """ # Copyright 2026 UCP Authors diff --git a/src/ucp_sdk/__init__.py b/src/ucp_sdk/__init__.py deleted file mode 100644 index fd754fb..0000000 --- a/src/ucp_sdk/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""UCP Python SDK.""" - - -def hello() -> str: - return "Hello from ucp-python-sdk!" \ No newline at end of file diff --git a/src/ucp_sdk/models/__init__.py b/src/ucp_sdk/models/__init__.py new file mode 100644 index 0000000..421dc21 --- /dev/null +++ b/src/ucp_sdk/models/__init__.py @@ -0,0 +1,18 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + diff --git a/src/ucp_sdk/models/discovery/profile_schema.py b/src/ucp_sdk/models/discovery/profile_schema.py index 42e446c..f0994c3 100644 --- a/src/ucp_sdk/models/discovery/profile_schema.py +++ b/src/ucp_sdk/models/discovery/profile_schema.py @@ -102,7 +102,9 @@ class BusinessProfile(BaseModel): class UcpDiscoveryProfile(RootModel[PlatformProfile | BusinessProfile]): - root: PlatformProfile | BusinessProfile = Field(..., title="UCP Discovery Profile") + root: PlatformProfile | BusinessProfile = Field( + ..., title="UCP Discovery Profile" + ) """ Schema for UCP discovery profiles. Business profiles are hosted at /.well-known/ucp; platform profiles are hosted at URIs advertised in request headers. """ diff --git a/src/ucp_sdk/models/ruff.toml b/src/ucp_sdk/models/ruff.toml deleted file mode 100644 index 9473cff..0000000 --- a/src/ucp_sdk/models/ruff.toml +++ /dev/null @@ -1,16 +0,0 @@ -# Ruff configuration for generated models -# These are auto-generated files, so we're more lenient with style rules - -line-length = 120 -target-version = "py311" - -[lint] -select = ["E", "F", "I"] -ignore = ["E501"] - -[lint.pydocstyle] -convention = "google" - -[lint.per-file-ignores] -"__init__.py" = ["D104"] -"*.py" = ["D100", "D101", "D102", "D103", "D200", "D205", "D212"] diff --git a/src/ucp_sdk/models/schemas/service.py b/src/ucp_sdk/models/schemas/service.py index 5c619d2..dd2ac08 100644 --- a/src/ucp_sdk/models/schemas/service.py +++ b/src/ucp_sdk/models/schemas/service.py @@ -76,10 +76,14 @@ class PlatformSchema7(BaseModel): transport: Literal["embedded"] = "embedded" -class PlatformSchema3(RootModel[PlatformSchema | PlatformSchema5 | PlatformSchema6 | PlatformSchema7]): - root: PlatformSchema | PlatformSchema5 | PlatformSchema6 | PlatformSchema7 = Field( - ..., title="Service (Platform Schema)" - ) +class PlatformSchema3( + RootModel[ + PlatformSchema | PlatformSchema5 | PlatformSchema6 | PlatformSchema7 + ] +): + root: ( + PlatformSchema | PlatformSchema5 | PlatformSchema6 | PlatformSchema7 + ) = Field(..., title="Service (Platform Schema)") """ Full service declaration for platform-level discovery. Different transports require different fields. """ @@ -130,10 +134,14 @@ class BusinessSchema6(BaseModel): config: embedded_config.EmbeddedTransportConfig | None = None -class BusinessSchema2(RootModel[BusinessSchema | BusinessSchema4 | BusinessSchema5 | BusinessSchema6]): - root: BusinessSchema | BusinessSchema4 | BusinessSchema5 | BusinessSchema6 = Field( - ..., title="Service (Business Schema)" - ) +class BusinessSchema2( + RootModel[ + BusinessSchema | BusinessSchema4 | BusinessSchema5 | BusinessSchema6 + ] +): + root: ( + BusinessSchema | BusinessSchema4 | BusinessSchema5 | BusinessSchema6 + ) = Field(..., title="Service (Business Schema)") """ Service binding for business/merchant configuration. May override platform endpoints. """ @@ -184,10 +192,14 @@ class ResponseSchema6(BaseModel): config: embedded_config.EmbeddedTransportConfig | None = None -class ResponseSchema2(RootModel[ResponseSchema | ResponseSchema4 | ResponseSchema5 | ResponseSchema6]): - root: ResponseSchema | ResponseSchema4 | ResponseSchema5 | ResponseSchema6 = Field( - ..., title="Service (Response Schema)" - ) +class ResponseSchema2( + RootModel[ + ResponseSchema | ResponseSchema4 | ResponseSchema5 | ResponseSchema6 + ] +): + root: ( + ResponseSchema | ResponseSchema4 | ResponseSchema5 | ResponseSchema6 + ) = Field(..., title="Service (Response Schema)") """ Service binding in API responses. Includes per-resource transport configuration via typed config. """ diff --git a/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py b/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py index cecaa1c..04db2f3 100644 --- a/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py +++ b/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py @@ -60,7 +60,7 @@ class Ap2WithMerchantAuthorization(BaseModel): model_config = ConfigDict( extra="allow", ) - merchant_authorization: str | None = None + merchant_authorization: MerchantAuthorization | None = None """ Merchant's signature proving checkout terms are authentic. """ @@ -74,7 +74,7 @@ class Ap2WithCheckoutMandate(BaseModel): model_config = ConfigDict( extra="allow", ) - checkout_mandate: str | None = None + checkout_mandate: CheckoutMandate | None = None """ SD-JWT+kb proving user authorized this checkout. """ diff --git a/src/ucp_sdk/models/schemas/shopping/cart.py b/src/ucp_sdk/models/schemas/shopping/cart.py deleted file mode 100644 index 7110dfc..0000000 --- a/src/ucp_sdk/models/schemas/shopping/cart.py +++ /dev/null @@ -1,152 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Any - -from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict, Field - -from .. import ucp as ucp_1 -from .types import line_item, link, message, total - - -class Context(BaseModel): - """ - Buyer signals for localization (country, region, postal_code). Merchant uses for pricing, availability, currency. Falls back to geo-IP if omitted. - """ - - model_config = ConfigDict( - extra="allow", - ) - address_country: str | None = None - """ - The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. - """ - address_region: str | None = None - """ - The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. - """ - postal_code: str | None = None - """ - The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. - """ - intent: str | None = None - """ - Background context describing buyer's intent (e.g., 'looking for a gift under $50', 'need something durable for outdoor use'). Informs relevance, recommendations, and personalization. - """ - - -class Buyer(BaseModel): - """ - Optional buyer information for personalized estimates. - """ - - model_config = ConfigDict( - extra="allow", - ) - first_name: str | None = None - """ - First name of the buyer. - """ - last_name: str | None = None - """ - Last name of the buyer. - """ - email: str | None = None - """ - Email of the buyer. - """ - phone_number: str | None = None - """ - E.164 standard. - """ - - -class Ucp(BaseModel): - """ - UCP metadata for cart responses. No payment handlers needed pre-checkout. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") - """ - UCP version in YYYY-MM-DD format. - """ - services: dict[str, list[ucp_1.Base]] | None = None - """ - Service registry keyed by reverse-domain name. - """ - capabilities: Any | None = None - payment_handlers: dict[str, list[ucp_1.Base]] | None = None - """ - Payment handler registry keyed by reverse-domain name. - """ - - -class Cart(BaseModel): - """ - Shopping cart with estimated pricing before checkout. Lightweight pre-purchase exploration with no payment info or complex status states. Cart exists (200) or doesn't (404). - """ - - model_config = ConfigDict( - extra="allow", - ) - ucp: Ucp - id: str - """ - Unique cart identifier. - """ - line_items: list[line_item.LineItem] - """ - Cart line items. Same structure as checkout. Full replacement on update. - """ - context: Context | None = None - """ - Buyer signals for localization (country, region, postal_code). Merchant uses for pricing, availability, currency. Falls back to geo-IP if omitted. - """ - buyer: Buyer | None = None - """ - Optional buyer information for personalized estimates. - """ - currency: str - """ - ISO 4217 currency code. Determined by merchant based on context or geo-IP. - """ - totals: list[total.Total] - """ - Estimated cost breakdown. May be partial if shipping/tax not yet calculable. - """ - messages: list[message.Message] | None = None - """ - Validation messages, warnings, or informational notices. - """ - links: list[link.Link] | None = None - """ - Optional merchant links (policies, FAQs). - """ - continue_url: AnyUrl | None = None - """ - URL for cart handoff and session recovery. Enables sharing and human-in-the-loop flows. - """ - expires_at: AwareDatetime | None = None - """ - Cart expiry timestamp (RFC 3339). Optional. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/cart_create_request.py b/src/ucp_sdk/models/schemas/shopping/cart_create_request.py deleted file mode 100644 index f948b9a..0000000 --- a/src/ucp_sdk/models/schemas/shopping/cart_create_request.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - -from .types import buyer as buyer_1 -from .types import context as context_1 -from .types import line_item_create_request - - -class CartCreateRequest(BaseModel): - """ - Shopping cart with estimated pricing before checkout. Lightweight pre-purchase exploration with no payment info or complex status states. Cart exists (200) or doesn't (404). - """ - - model_config = ConfigDict( - extra="allow", - ) - line_items: list[line_item_create_request.LineItemCreateRequest] - """ - Cart line items. Same structure as checkout. Full replacement on update. - """ - context: context_1.Context | None = None - """ - Buyer signals for localization (country, region, postal_code). Merchant uses for pricing, availability, currency. Falls back to geo-IP if omitted. - """ - buyer: buyer_1.Buyer | None = None - """ - Optional buyer information for personalized estimates. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/cart_update_request.py b/src/ucp_sdk/models/schemas/shopping/cart_update_request.py deleted file mode 100644 index 3815fdf..0000000 --- a/src/ucp_sdk/models/schemas/shopping/cart_update_request.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - -from .types import buyer as buyer_1 -from .types import context as context_1 -from .types import line_item_update_request - - -class CartUpdateRequest(BaseModel): - """ - Shopping cart with estimated pricing before checkout. Lightweight pre-purchase exploration with no payment info or complex status states. Cart exists (200) or doesn't (404). - """ - - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Unique cart identifier. - """ - line_items: list[line_item_update_request.LineItemUpdateRequest] - """ - Cart line items. Same structure as checkout. Full replacement on update. - """ - context: context_1.Context | None = None - """ - Buyer signals for localization (country, region, postal_code). Merchant uses for pricing, availability, currency. Falls back to geo-IP if omitted. - """ - buyer: buyer_1.Buyer | None = None - """ - Optional buyer information for personalized estimates. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/checkout.py b/src/ucp_sdk/models/schemas/shopping/checkout.py index 62a0d69..1356cc0 100644 --- a/src/ucp_sdk/models/schemas/shopping/checkout.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout.py @@ -18,112 +18,15 @@ from __future__ import annotations -from typing import Any, Literal +from typing import Literal -from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict, Field +from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict -from .types import line_item, link, message, payment_instrument, total - - -class Ucp(BaseModel): - """ - UCP metadata for checkout responses. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") - """ - UCP version in YYYY-MM-DD format. - """ - services: Any | None = None - capabilities: Any | None = None - payment_handlers: Any - - -class Buyer(BaseModel): - """ - Representation of the buyer. - """ - - model_config = ConfigDict( - extra="allow", - ) - first_name: str | None = None - """ - First name of the buyer. - """ - last_name: str | None = None - """ - Last name of the buyer. - """ - email: str | None = None - """ - Email of the buyer. - """ - phone_number: str | None = None - """ - E.164 standard. - """ - - -class Context(BaseModel): - """ - Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context SHOULD be non-identifying and can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. - """ - - model_config = ConfigDict( - extra="allow", - ) - address_country: str | None = None - """ - The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. - """ - address_region: str | None = None - """ - The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. - """ - postal_code: str | None = None - """ - The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. - """ - intent: str | None = None - """ - Background context describing buyer's intent (e.g., 'looking for a gift under $50', 'need something durable for outdoor use'). Informs relevance, recommendations, and personalization. - """ - - -class Order(BaseModel): - """ - Details about an order created for this checkout session. - """ - - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Unique order identifier. - """ - permalink_url: AnyUrl - """ - Permalink to access the order on merchant site. - """ - - -class Payment(BaseModel): - """ - Payment configuration containing handlers. - """ - - model_config = ConfigDict( - extra="allow", - ) - instruments: list[payment_instrument.SelectedPaymentInstrument] | None = None - """ - The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. - """ +from .. import ucp as ucp_1 +from . import payment as payment_1 +from .types import buyer as buyer_1 +from .types import context as context_1 +from .types import line_item, link, message, order_confirmation, total class Checkout(BaseModel): @@ -134,7 +37,7 @@ class Checkout(BaseModel): model_config = ConfigDict( extra="allow", ) - ucp: Ucp + ucp: ucp_1.ResponseCheckoutSchema id: str """ Unique identifier of the checkout session. @@ -143,11 +46,11 @@ class Checkout(BaseModel): """ List of line items being checked out. """ - buyer: Buyer | None = None + buyer: buyer_1.Buyer | None = None """ Representation of the buyer. """ - context: Context | None = None + context: context_1.Context | None = None status: Literal[ "incomplete", "requires_escalation", @@ -183,8 +86,8 @@ class Checkout(BaseModel): """ URL for checkout handoff and session recovery. MUST be provided when status is requires_escalation. See specification for format and availability requirements. """ - payment: Payment | None = None - order: Order | None = None + payment: payment_1.Payment | None = None + order: order_confirmation.OrderConfirmation | None = None """ Details about an order created for this checkout session. """ diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py index fccc424..0e23017 100644 --- a/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py @@ -22,35 +22,10 @@ from . import payment as payment_1 from .types import buyer as buyer_1 +from .types import context as context_1 from .types import line_item_create_request -class Context(BaseModel): - """ - Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context SHOULD be non-identifying and can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. - """ - - model_config = ConfigDict( - extra="allow", - ) - address_country: str | None = None - """ - The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. - """ - address_region: str | None = None - """ - The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. - """ - postal_code: str | None = None - """ - The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. - """ - intent: str | None = None - """ - Background context describing buyer's intent (e.g., 'looking for a gift under $50', 'need something durable for outdoor use'). Informs relevance, recommendations, and personalization. - """ - - class CheckoutCreateRequest(BaseModel): """ Base checkout schema. Extensions compose onto this using allOf. @@ -67,5 +42,5 @@ class CheckoutCreateRequest(BaseModel): """ Representation of the buyer. """ - context: Context | None = None + context: context_1.Context | None = None payment: payment_1.Payment | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py index 8e2b1c9..5390a98 100644 --- a/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py @@ -22,35 +22,10 @@ from . import payment as payment_1 from .types import buyer as buyer_1 +from .types import context as context_1 from .types import line_item_update_request -class Context(BaseModel): - """ - Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context SHOULD be non-identifying and can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. - """ - - model_config = ConfigDict( - extra="allow", - ) - address_country: str | None = None - """ - The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. - """ - address_region: str | None = None - """ - The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. - """ - postal_code: str | None = None - """ - The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. - """ - intent: str | None = None - """ - Background context describing buyer's intent (e.g., 'looking for a gift under $50', 'need something durable for outdoor use'). Informs relevance, recommendations, and personalization. - """ - - class CheckoutUpdateRequest(BaseModel): """ Base checkout schema. Extensions compose onto this using allOf. @@ -71,5 +46,5 @@ class CheckoutUpdateRequest(BaseModel): """ Representation of the buyer. """ - context: Context | None = None + context: context_1.Context | None = None payment: payment_1.Payment | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py b/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py index 3390b86..0d4c0aa 100644 --- a/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py +++ b/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py @@ -38,7 +38,9 @@ class FulfillmentExtension(RootModel[Any]): """ -class FulfillmentAvailableMethod(RootModel[fulfillment_available_method.FulfillmentAvailableMethod]): +class FulfillmentAvailableMethod( + RootModel[fulfillment_available_method.FulfillmentAvailableMethod] +): root: fulfillment_available_method.FulfillmentAvailableMethod diff --git a/src/ucp_sdk/models/schemas/shopping/order.py b/src/ucp_sdk/models/schemas/shopping/order.py index 645cd05..e747417 100644 --- a/src/ucp_sdk/models/schemas/shopping/order.py +++ b/src/ucp_sdk/models/schemas/shopping/order.py @@ -21,7 +21,13 @@ from pydantic import AnyUrl, BaseModel, ConfigDict from .. import ucp as ucp_1 -from .types import adjustment, expectation, fulfillment_event, order_line_item, total +from .types import ( + adjustment, + expectation, + fulfillment_event, + order_line_item, + total, +) class PlatformSchema(BaseModel): diff --git a/src/ucp_sdk/models/schemas/shopping/payment.py b/src/ucp_sdk/models/schemas/shopping/payment.py index a4f5d78..ba698c7 100644 --- a/src/ucp_sdk/models/schemas/shopping/payment.py +++ b/src/ucp_sdk/models/schemas/shopping/payment.py @@ -31,7 +31,9 @@ class Payment(BaseModel): model_config = ConfigDict( extra="allow", ) - instruments: list[payment_instrument.SelectedPaymentInstrument] | None = None + instruments: list[payment_instrument.SelectedPaymentInstrument] | None = ( + None + ) """ The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py b/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py index 2786056..53e3bd5 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py +++ b/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py @@ -53,7 +53,9 @@ class BusinessFulfillmentConfig(BaseModel): """ Permits multiple destinations per method type. """ - allows_method_combinations: list[list[Literal["shipping", "pickup"]]] | None = None + allows_method_combinations: ( + list[list[Literal["shipping", "pickup"]]] | None + ) = None """ Allowed method type combinations. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/context.py b/src/ucp_sdk/models/schemas/shopping/types/context.py index cf73cf1..d501c00 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/context.py +++ b/src/ucp_sdk/models/schemas/shopping/types/context.py @@ -23,7 +23,7 @@ class Context(BaseModel): """ - Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context SHOULD be non-identifying and can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. + Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. """ model_config = ConfigDict( @@ -41,7 +41,3 @@ class Context(BaseModel): """ The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. """ - intent: str | None = None - """ - Background context describing buyer's intent (e.g., 'looking for a gift under $50', 'need something durable for outdoor use'). Informs relevance, recommendations, and personalization. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment.py index 5603b07..8ff2c27 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment.py @@ -35,7 +35,9 @@ class Fulfillment(BaseModel): """ Fulfillment methods for cart items. """ - available_methods: list[fulfillment_available_method.FulfillmentAvailableMethod] | None = None + available_methods: ( + list[fulfillment_available_method.FulfillmentAvailableMethod] | None + ) = None """ Inventory availability hints. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py index 14bdc77..32accc9 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py @@ -31,7 +31,10 @@ class FulfillmentCreateRequest(BaseModel): model_config = ConfigDict( extra="allow", ) - methods: list[fulfillment_method_create_request.FulfillmentMethodCreateRequest] | None = None + methods: ( + list[fulfillment_method_create_request.FulfillmentMethodCreateRequest] + | None + ) = None """ Fulfillment methods for cart items. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py index 3f4351a..4e1ac65 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py @@ -23,10 +23,16 @@ from . import retail_location, shipping_destination -class FulfillmentDestination(RootModel[shipping_destination.ShippingDestination | retail_location.RetailLocation]): - root: shipping_destination.ShippingDestination | retail_location.RetailLocation = Field( - ..., title="Fulfillment Destination" - ) +class FulfillmentDestination( + RootModel[ + shipping_destination.ShippingDestination + | retail_location.RetailLocation + ] +): + root: ( + shipping_destination.ShippingDestination + | retail_location.RetailLocation + ) = Field(..., title="Fulfillment Destination") """ A destination for fulfillment. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py index f6608d0..e022d8d 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py @@ -45,7 +45,9 @@ class FulfillmentMethod(BaseModel): """ Line item IDs fulfilled via this method. """ - destinations: list[fulfillment_destination.FulfillmentDestination] | None = None + destinations: ( + list[fulfillment_destination.FulfillmentDestination] | None + ) = None """ Available destinations. For shipping: addresses. For pickup: retail locations. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py index 399ef6f..b268341 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py @@ -41,7 +41,9 @@ class FulfillmentMethodCreateRequest(BaseModel): """ Line item IDs fulfilled via this method. """ - destinations: list[fulfillment_destination.FulfillmentDestination] | None = None + destinations: ( + list[fulfillment_destination.FulfillmentDestination] | None + ) = None """ Available destinations. For shipping: addresses. For pickup: retail locations. """ @@ -49,7 +51,10 @@ class FulfillmentMethodCreateRequest(BaseModel): """ ID of the selected destination. """ - groups: list[fulfillment_group_create_request.FulfillmentGroupCreateRequest] | None = None + groups: ( + list[fulfillment_group_create_request.FulfillmentGroupCreateRequest] + | None + ) = None """ Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py index 4d1e810..d6062e6 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py @@ -39,7 +39,9 @@ class FulfillmentMethodUpdateRequest(BaseModel): """ Line item IDs fulfilled via this method. """ - destinations: list[fulfillment_destination.FulfillmentDestination] | None = None + destinations: ( + list[fulfillment_destination.FulfillmentDestination] | None + ) = None """ Available destinations. For shipping: addresses. For pickup: retail locations. """ @@ -47,7 +49,10 @@ class FulfillmentMethodUpdateRequest(BaseModel): """ ID of the selected destination. """ - groups: list[fulfillment_group_update_request.FulfillmentGroupUpdateRequest] | None = None + groups: ( + list[fulfillment_group_update_request.FulfillmentGroupUpdateRequest] + | None + ) = None """ Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py index 7551337..849b10a 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py @@ -31,7 +31,10 @@ class FulfillmentUpdateRequest(BaseModel): model_config = ConfigDict( extra="allow", ) - methods: list[fulfillment_method_update_request.FulfillmentMethodUpdateRequest] | None = None + methods: ( + list[fulfillment_method_update_request.FulfillmentMethodUpdateRequest] + | None + ) = None """ Fulfillment methods for cart items. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item.py b/src/ucp_sdk/models/schemas/shopping/types/item.py index d942f0b..e2b1954 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/item.py +++ b/src/ucp_sdk/models/schemas/shopping/types/item.py @@ -27,7 +27,7 @@ class Item(BaseModel): ) id: str """ - The product identifier, often the SKU, required to resolve the product details associated with this line item. Should be recognized by both the Platform, and the Business. + Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. """ title: str """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py index bbef8e8..fd3f850 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py @@ -27,5 +27,5 @@ class ItemCreateRequest(BaseModel): ) id: str """ - The product identifier, often the SKU, required to resolve the product details associated with this line item. Should be recognized by both the Platform, and the Business. + Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py index c957d16..735b984 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py @@ -27,5 +27,5 @@ class ItemUpdateRequest(BaseModel): ) id: str """ - The product identifier, often the SKU, required to resolve the product details associated with this line item. Should be recognized by both the Platform, and the Business. + Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py b/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py index 48919c5..b908e47 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py +++ b/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py @@ -53,7 +53,9 @@ class MerchantFulfillmentConfig(BaseModel): """ Permits multiple destinations per method type. """ - allows_method_combinations: list[list[Literal["shipping", "pickup"]]] | None = None + allows_method_combinations: ( + list[list[Literal["shipping", "pickup"]]] | None + ) = None """ Allowed method type combinations. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/message.py b/src/ucp_sdk/models/schemas/shopping/types/message.py index cbf3c5f..42964ae 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/message.py +++ b/src/ucp_sdk/models/schemas/shopping/types/message.py @@ -23,10 +23,18 @@ from . import message_error, message_info, message_warning -class Message(RootModel[message_error.MessageError | message_warning.MessageWarning | message_info.MessageInfo]): - root: message_error.MessageError | message_warning.MessageWarning | message_info.MessageInfo = Field( - ..., title="Message" - ) +class Message( + RootModel[ + message_error.MessageError + | message_warning.MessageWarning + | message_info.MessageInfo + ] +): + root: ( + message_error.MessageError + | message_warning.MessageWarning + | message_info.MessageInfo + ) = Field(..., title="Message") """ Container for error, warning, or info messages. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/message_error.py b/src/ucp_sdk/models/schemas/shopping/types/message_error.py index 1dd3500..d1e6adb 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/message_error.py +++ b/src/ucp_sdk/models/schemas/shopping/types/message_error.py @@ -47,7 +47,9 @@ class MessageError(BaseModel): """ Human-readable message. """ - severity: Literal["recoverable", "requires_buyer_input", "requires_buyer_review"] + severity: Literal[ + "recoverable", "requires_buyer_input", "requires_buyer_review" + ] """ Declares who resolves this error. 'recoverable': agent can fix via API. 'requires_buyer_input': merchant requires information their API doesn't support collecting programmatically (checkout incomplete). 'requires_buyer_review': buyer must authorize before order placement due to policy, regulatory, or entitlement rules (checkout complete). Errors with 'requires_*' severity contribute to 'status: requires_escalation'. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/total.py b/src/ucp_sdk/models/schemas/shopping/types/total.py index 320e79b..623c2dd 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/total.py +++ b/src/ucp_sdk/models/schemas/shopping/types/total.py @@ -27,7 +27,15 @@ class Total(BaseModel): model_config = ConfigDict( extra="allow", ) - type: Literal["items_discount", "subtotal", "discount", "fulfillment", "tax", "fee", "total"] + type: Literal[ + "items_discount", + "subtotal", + "discount", + "fulfillment", + "tax", + "fee", + "total", + ] """ Type of total categorization. """ diff --git a/src/ucp_sdk/models/schemas/ucp.py b/src/ucp_sdk/models/schemas/ucp.py index ca18a9a..f8d1fdd 100644 --- a/src/ucp_sdk/models/schemas/ucp.py +++ b/src/ucp_sdk/models/schemas/ucp.py @@ -20,7 +20,7 @@ from typing import Any, Literal -from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel +from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel, constr class UcpMetadata(RootModel[Any]): @@ -122,10 +122,14 @@ class PlatformSchema12(BaseModel): transport: Literal["embedded"] = "embedded" -class PlatformSchema8(RootModel[PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12]): - root: PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 = Field( - ..., title="Service (Platform Schema)" - ) +class PlatformSchema8( + RootModel[ + PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 + ] +): + root: ( + PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 + ) = Field(..., title="Service (Platform Schema)") """ Full service declaration for platform-level discovery. Different transports require different fields. """ @@ -223,10 +227,14 @@ class ResponseSchema11(BaseModel): config: EmbeddedConfig | None = None -class ResponseSchema7(RootModel[ResponseSchema | ResponseSchema9 | ResponseSchema10 | ResponseSchema11]): - root: ResponseSchema | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 = Field( - ..., title="Service (Response Schema)" - ) +class ResponseSchema7( + RootModel[ + ResponseSchema | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 + ] +): + root: ( + ResponseSchema | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 + ) = Field(..., title="Service (Response Schema)") """ Service binding in API responses. Includes per-resource transport configuration via typed config. """ @@ -337,35 +345,24 @@ class ResponseOrderSchema(BaseModel): """ UCP version in YYYY-MM-DD format. """ - services: dict[str, list[Base]] | None = None - """ - Service registry keyed by reverse-domain name. - """ - capabilities: Any | None = None - payment_handlers: dict[str, list[Base]] | None = None - """ - Payment handler registry keyed by reverse-domain name. - """ - - -class ResponseCartSchema(BaseModel): - """ - UCP metadata for cart responses. No payment handlers needed pre-checkout. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") - """ - UCP version in YYYY-MM-DD format. - """ - services: dict[str, list[Base]] | None = None + services: ( + dict[ + constr(pattern=r"^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9_]*)+$"), + list[Base], + ] + | None + ) = None """ Service registry keyed by reverse-domain name. """ capabilities: Any | None = None - payment_handlers: dict[str, list[Base]] | None = None + payment_handlers: ( + dict[ + constr(pattern=r"^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9_]*)+$"), + list[Base], + ] + | None + ) = None """ Payment handler registry keyed by reverse-domain name. """ @@ -406,10 +403,14 @@ class BusinessSchema11(BaseModel): config: EmbeddedConfig | None = None -class BusinessSchema7(RootModel[BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11]): - root: BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 = Field( - ..., title="Service (Business Schema)" - ) +class BusinessSchema7( + RootModel[ + BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 + ] +): + root: ( + BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 + ) = Field(..., title="Service (Business Schema)") """ Service binding for business/merchant configuration. May override platform endpoints. """ From 736c503da337d0fae8b212616515f3b185dad508 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 15:13:11 +0100 Subject: [PATCH 12/22] add win32 specific check for paths Change-Id: I4583f94619b072eb7aff0fc28f040d0b2fd30de3 --- preprocess_schemas.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/preprocess_schemas.py b/preprocess_schemas.py index 08275f2..fbb713c 100644 --- a/preprocess_schemas.py +++ b/preprocess_schemas.py @@ -368,6 +368,8 @@ def preprocess_schema_file( schema_str = schema_str.replace( f'"{ref_file}', f'"file://{ref_path}' ) + if sys.platform == "win32": + ref_path = f'/{ref_path.as_posix()}' schema = json.loads(schema_str) From 8d559b98c40425413c91a5a4eb9268cd8adfaa08 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 15:28:30 +0100 Subject: [PATCH 13/22] remove preprocessing Change-Id: Ib7d74192095677f98a79906f5ed2d69dc16e1520 --- generate_models.sh | 7 +- preprocess_schemas.py | 474 ----------- .../models/discovery/profile_schema.py | 40 +- src/ucp_sdk/models/schemas/_internal.py | 579 +++++++++++++ src/ucp_sdk/models/schemas/capability.py | 50 +- src/ucp_sdk/models/schemas/payment_handler.py | 48 +- src/ucp_sdk/models/schemas/service.py | 254 ++---- .../models/schemas/shopping/ap2_mandate.py | 19 + .../models/schemas/shopping/buyer_consent.py | 31 + .../models/schemas/shopping/checkout.py | 4 +- .../shopping/checkout_complete_request.py | 34 - .../shopping/checkout_create_request.py | 46 -- .../shopping/checkout_update_request.py | 50 -- .../models/schemas/shopping/discount.py | 13 + .../schemas/shopping/fulfillment/__init__.py | 23 +- src/ucp_sdk/models/schemas/shopping/order.py | 4 +- ...illment_available_method_create_request.py | 31 - ...illment_available_method_update_request.py | 31 - .../types/fulfillment_create_request.py | 40 - .../types/fulfillment_group_create_request.py | 35 - .../types/fulfillment_group_update_request.py | 39 - .../fulfillment_method_create_request.py | 60 -- .../fulfillment_method_update_request.py | 58 -- .../fulfillment_option_create_request.py | 31 - .../fulfillment_option_update_request.py | 31 - .../types/fulfillment_update_request.py | 40 - .../shopping/types/item_create_request.py | 31 - .../shopping/types/item_update_request.py | 31 - .../types/line_item_create_request.py | 38 - .../types/line_item_update_request.py | 43 - .../shopping/types/payment_instrument.py | 27 +- .../types/retail_location_create_request.py | 41 - .../types/retail_location_update_request.py | 41 - .../shopping/types/total_create_request.py | 27 - .../shopping/types/total_update_request.py | 27 - src/ucp_sdk/models/schemas/ucp.py | 419 +--------- ucp | 1 + uv.lock | 762 ++++++++++++++++++ 38 files changed, 1567 insertions(+), 1993 deletions(-) delete mode 100644 preprocess_schemas.py create mode 100644 src/ucp_sdk/models/schemas/_internal.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/checkout_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/checkout_update_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/item_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/item_update_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/total_create_request.py delete mode 100644 src/ucp_sdk/models/schemas/shopping/types/total_update_request.py create mode 160000 ucp create mode 100644 uv.lock diff --git a/generate_models.sh b/generate_models.sh index 400f79d..a0f78b7 100755 --- a/generate_models.sh +++ b/generate_models.sh @@ -28,10 +28,9 @@ OUTPUT_DIR="src/ucp_sdk/models" # Schema directory (relative to this script) SCHEMA_DIR="ucp/source" -TEMP_SCHEMA_DIR="temp_schemas" echo "Preprocessing schemas..." -uv run python preprocess_schemas.py +# uv run python preprocess_schemas.py echo "Generating Pydantic models from preprocessed schemas..." @@ -55,7 +54,7 @@ uv run \ --link-mode=copy \ --extra-index-url https://pypi.org/simple python \ -m datamodel_code_generator \ - --input "$TEMP_SCHEMA_DIR" \ + --input "$SCHEMA_DIR" \ --input-file-type jsonschema \ --output "$OUTPUT_DIR" \ --output-model-type pydantic_v2.BaseModel \ @@ -72,7 +71,5 @@ echo "Formatting generated models..." uv run ruff format uv run ruff check --fix "$OUTPUT_DIR" 2>&1 | grep -E "^(All checks passed|Fixed|Found)" || echo "Formatting complete" -# Clean up temporary schemas -rm -rf "$TEMP_SCHEMA_DIR" echo "Done. Models generated in $OUTPUT_DIR" diff --git a/preprocess_schemas.py b/preprocess_schemas.py deleted file mode 100644 index fbb713c..0000000 --- a/preprocess_schemas.py +++ /dev/null @@ -1,474 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Preprocess JSON schemas for datamodel-code-generator compatibility. -""" - -import json -import shutil -import copy -import os -from pathlib import Path -from typing import Any, Dict - - -def remove_extension_defs(schema: Dict[str, Any]) -> Dict[str, Any]: - """ - Remove $defs that extend EXTERNAL schemas using allOf. - These cause circular dependency issues. - """ - if "$defs" not in schema: - return schema - - defs_to_remove = [] - - for def_name, def_schema in schema["$defs"].items(): - if isinstance(def_schema, dict) and "allOf" in def_schema: - # Check if this extends an external schema - all_of = def_schema["allOf"] - has_external_ref = False - for item in all_of: - if isinstance(item, dict) and "$ref" in item: - ref = item["$ref"] - # If referencing another top-level schema (not within same file's $defs or root) - # Note: "#" is a reference to the root schema, which is internal - if not ref.startswith("#/") and ref != "#": - has_external_ref = True - break - - if has_external_ref: - print(f" -> Removing extension def: {def_name}") - defs_to_remove.append(def_name) - - # Remove extension defs - for def_name in defs_to_remove: - del schema["$defs"][def_name] - - # Remove empty $defs - if "$defs" in schema and not schema["$defs"]: - del schema["$defs"] - - return schema - - -def inline_internal_refs( - obj: Any, defs: Dict[str, Any], processed: set = None -) -> Any: - """ - Recursively inline $ref references that point to #/$defs/... - This resolves internal references to avoid cross-file confusion. - """ - if processed is None: - processed = set() - - if isinstance(obj, dict): - # Check for $ref - if "$ref" in obj and len(obj) == 1: - ref = obj["$ref"] - if ref.startswith("#/$defs/"): - def_name = ref.split("/")[-1] - # Avoid infinite recursion - if def_name not in processed and def_name in defs: - processed.add(def_name) - # Inline the definition - inlined = copy.deepcopy(defs[def_name]) - result = inline_internal_refs(inlined, defs, processed) - processed.remove(def_name) - return result - return obj - - # Recursively process all properties - result = {} - for key, value in obj.items(): - result[key] = inline_internal_refs(value, defs, processed) - return result - elif isinstance(obj, list): - return [inline_internal_refs(item, defs, processed) for item in obj] - return obj - - -def flatten_allof_in_defs(schema: Dict[str, Any]) -> Dict[str, Any]: - """ - Flatten allOf patterns within $defs that only use internal references. - """ - if "$defs" not in schema: - return schema - - defs = schema["$defs"] - - for def_name, def_schema in list(defs.items()): - if isinstance(def_schema, dict) and "allOf" in def_schema: - all_of = def_schema["allOf"] - - # Check if all refs are internal (including root schema references like "#") - all_internal = True - has_root_ref = False - for item in all_of: - if isinstance(item, dict) and "$ref" in item: - ref = item["$ref"] - # Check for root schema reference - if ref == "#": - has_root_ref = True - # Not internal if it's an external reference (doesn't start with #/) - elif not ref.startswith("#/"): - all_internal = False - break - - if all_internal: - # Flatten the allOf by inlining refs - merged = {} - for item in all_of: - # Handle root schema reference "#" - if ( - isinstance(item, dict) - and "$ref" in item - and item["$ref"] == "#" - ): - # Inline the root schema (exclude $defs, $id, $schema, title, description) - root_copy = { - k: v - for k, v in schema.items() - if k - not in [ - "$defs", - "$id", - "$schema", - "title", - "description", - ] - } - resolved = root_copy - else: - resolved = inline_internal_refs(item, defs, set()) - - # Merge properties - for k, v in resolved.items(): - if k == "properties" and k in merged: - merged[k].update(v) - elif k == "required" and k in merged: - merged[k] = list(set(merged[k] + v)) - elif k not in ["title", "description", "allOf"]: - merged[k] = v - - # Keep original title and description - if "title" in def_schema: - merged["title"] = def_schema["title"] - if "description" in def_schema: - merged["description"] = def_schema["description"] - - defs[def_name] = merged - - return schema - - -def update_refs_for_scenario( - obj: Any, scenario: str, schemas_with_scenarios: set, current_dir: str = "" -) -> Any: - """ - Recursively update $ref paths to point to scenario-specific schemas. - For example, changes "types/line_item.json" to "types/line_item_create_request.json" for create scenario. - Only updates references to schemas that actually have scenarios. - """ - if isinstance(obj, dict): - result = {} - for key, value in obj.items(): - if key == "$ref" and isinstance(value, str): - # Skip internal references and references with fragments (e.g., "../ucp.json#/$defs/...") - if value.startswith("#/") or "#/$defs/" in value: - result[key] = value - # Check if this is a reference to a schema file (not internal #/$defs/) - elif value.endswith(".json"): - # Resolve the relative path from current schema's directory - if current_dir: - combined = os.path.join(current_dir, value) - ref_path = os.path.normpath(combined) - else: - ref_path = os.path.normpath(value) - - # Normalize the path (force forward slashes) - ref_path = ref_path.replace("\\", "/") - - # Check if the referenced schema has scenarios - if ref_path in schemas_with_scenarios: - base_path = value[:-5] # Remove .json - # Create scenario-specific reference - result[key] = f"{base_path}_{scenario}_request.json" - else: - # Keep original reference for schemas without scenarios - result[key] = value - else: - result[key] = value - else: - result[key] = update_refs_for_scenario( - value, scenario, schemas_with_scenarios, current_dir - ) - return result - elif isinstance(obj, list): - return [ - update_refs_for_scenario( - item, scenario, schemas_with_scenarios, current_dir - ) - for item in obj - ] - return obj - - -def process_ucp_request_scenarios( - schema: Dict[str, Any], - base_name: str, - schemas_with_scenarios: set, - schema_dir: str = "", -) -> Dict[str, Dict[str, Any]]: - """ - Generate separate schemas for create, update, and complete scenarios based on ucp_request annotations. - - Returns a dict mapping scenario names (e.g., 'create', 'update', 'complete') to their schemas. - """ - scenarios = {} - - # Check if this schema has properties with ucp_request annotations - if "properties" not in schema: - return {"base": schema} - - # Detect which scenarios exist - scenario_types = set() - has_string_directive = False - - for prop_name, prop_schema in schema["properties"].items(): - if isinstance(prop_schema, dict) and "ucp_request" in prop_schema: - ucp_req = prop_schema["ucp_request"] - if isinstance(ucp_req, dict): - scenario_types.update(ucp_req.keys()) - else: - has_string_directive = True - - # If no scenarios detected but plain strings exist, imply "create" and "update" scenarios - if not scenario_types and has_string_directive: - scenario_types.add("create") - scenario_types.add("update") - - # If no scenarios detected, return base schema - if not scenario_types: - return {"base": schema} - - # Generate a schema for each scenario - for scenario in scenario_types: - scenario_schema = copy.deepcopy(schema) - - # Update title and description to reflect the scenario - if "title" in scenario_schema: - scenario_schema["title"] = ( - f"{scenario_schema['title']} ({scenario.capitalize()} Request)" - ) - - # Process each property based on its ucp_request directive - properties_to_remove = [] - required_fields = set(scenario_schema.get("required", [])) - - for prop_name, prop_schema in scenario_schema["properties"].items(): - if isinstance(prop_schema, dict) and "ucp_request" in prop_schema: - ucp_req = prop_schema["ucp_request"] - - # Clean up the ucp_request annotation from the property - del prop_schema["ucp_request"] - - # Determine the directive for this scenario - if isinstance(ucp_req, str): - directive = ucp_req - elif isinstance(ucp_req, dict): - directive = ucp_req.get(scenario, "optional") - else: - directive = "optional" - - # Handle the directive - if directive == "omit": - properties_to_remove.append(prop_name) - required_fields.discard(prop_name) - elif directive == "required": - required_fields.add(prop_name) - elif directive == "optional": - required_fields.discard(prop_name) - - # Remove omitted properties - for prop_name in properties_to_remove: - del scenario_schema["properties"][prop_name] - - # Update required fields - if required_fields: - scenario_schema["required"] = sorted(list(required_fields)) - elif "required" in scenario_schema: - del scenario_schema["required"] - - # Update all $ref paths to point to scenario-specific schemas - scenario_schema = update_refs_for_scenario( - scenario_schema, scenario, schemas_with_scenarios, schema_dir - ) - - scenarios[scenario] = scenario_schema - - return scenarios - - -def clean_schema_for_codegen(schema: Dict[str, Any]) -> Dict[str, Any]: - """ - Clean up schema to avoid issues with datamodel-code-generator. - - Remove $id fields that might cause URL resolution issues - - Remove $schema fields - """ - schema = copy.deepcopy(schema) - - # Remove fields that can cause URL resolution issues - if "$id" in schema: - del schema["$id"] - if "$schema" in schema: - del schema["$schema"] - - return schema - - -def preprocess_schema_file( - input_path: Path, - output_path: Path, - schemas_with_scenarios: set, - schema_dir: str, -) -> None: - """Preprocess a single schema file.""" - with open(input_path, "r", encoding="utf-8") as f: - schema = json.load(f) - - # WARN: Workaround for datamodel-codegen issue with relative paths - # When ucp.json is referenced from a subdirectory (e.g. schemas/shopping/checkout.json referencing ../ucp.json), - # the subsequent reference to service.json (in ucp.json) is incorrectly resolved relative to the subdirectory. - # We force an absolute path here. - if input_path.name == "ucp.json": - # Force absolute paths for all sibling references in ucp.json - # This fixes resolution issues when ucp.json is referenced from subdirectories - schema_str = json.dumps(schema) - - input_dir_abs = output_path.parent.resolve() - for ref_file in [ - "service.json", - "capability.json", - "payment_handler.json", - ]: - ref_path = input_dir_abs / ref_file - schema_str = schema_str.replace( - f'"{ref_file}', f'"file://{ref_path}' - ) - if sys.platform == "win32": - ref_path = f'/{ref_path.as_posix()}' - - schema = json.loads(schema_str) - - # Remove extension definitions that reference external schemas - schema = remove_extension_defs(schema) - - # Flatten allOf patterns within $defs that only use internal refs - schema = flatten_allof_in_defs(schema) - - # Generate scenario-specific schemas - base_name = output_path.stem # filename without extension - - scenarios = process_ucp_request_scenarios( - schema, base_name, schemas_with_scenarios, schema_dir - ) - - # Ensure output directory exists - output_path.parent.mkdir(parents=True, exist_ok=True) - - # Write preprocessed schema(s) - if len(scenarios) == 1 and "base" in scenarios: - # No scenarios, write single file - cleaned = clean_schema_for_codegen(scenarios["base"]) - with open(output_path, "w", encoding="utf-8") as f: - json.dump(cleaned, f, indent=2) - else: - # Write both base schema and scenario-specific files - # First, write the base schema (for non-scenario-specific references) - base_schema = copy.deepcopy(schema) - cleaned_base = clean_schema_for_codegen(base_schema) - with open(output_path, "w", encoding="utf-8") as f: - json.dump(cleaned_base, f, indent=2) - - # Then write separate files for each scenario - for scenario_name, scenario_schema in scenarios.items(): - scenario_path = ( - output_path.parent / f"{base_name}_{scenario_name}_request.json" - ) - print(f" -> Generating {scenario_name} request schema") - cleaned = clean_schema_for_codegen(scenario_schema) - with open(scenario_path, "w", encoding="utf-8") as f: - json.dump(cleaned, f, indent=2) - - -def preprocess_schemas(input_dir: Path, output_dir: Path) -> None: - """Preprocess all schema files in the directory tree.""" - # Clean output directory - if output_dir.exists(): - shutil.rmtree(output_dir) - output_dir.mkdir(parents=True) - - # Find all JSON files - json_files = list(input_dir.rglob("*.json")) - - print(f"Preprocessing {len(json_files)} schema files...") - - # First pass: track which schemas have scenarios - schemas_with_scenarios = set() - for json_file in json_files: - with open(json_file, "r", encoding="utf-8") as f: - schema = json.load(f) - - # Check if this schema has ucp_request scenarios - if "properties" in schema: - for prop_schema in schema["properties"].values(): - if ( - isinstance(prop_schema, dict) - and "ucp_request" in prop_schema - ): - # If any ucp_request is present (dict or string), it has scenarios - rel_path = json_file.relative_to(input_dir) - path_str = str(rel_path).replace( - "\\", "/" - ) # Normalize path separators - schemas_with_scenarios.add(path_str) - break - - # Second pass: preprocess and generate schemas - for json_file in json_files: - # Calculate relative path - rel_path = json_file.relative_to(input_dir) - output_path = output_dir / rel_path - - # Calculate directory of this file relative to valid root - file_rel_dir = str(rel_path.parent).replace("\\", "/") - if file_rel_dir == ".": - file_rel_dir = "" - - print(f" Processing: {rel_path}") - preprocess_schema_file( - json_file, output_path, schemas_with_scenarios, file_rel_dir - ) - - print(f"Preprocessing complete. Output in {output_dir}") - - -if __name__ == "__main__": - script_dir = Path(__file__).parent - input_schemas = script_dir / "ucp" / "source" - output_schemas = script_dir / "temp_schemas" - - preprocess_schemas(input_schemas, output_schemas) diff --git a/src/ucp_sdk/models/discovery/profile_schema.py b/src/ucp_sdk/models/discovery/profile_schema.py index f0994c3..5d3c08f 100644 --- a/src/ucp_sdk/models/discovery/profile_schema.py +++ b/src/ucp_sdk/models/discovery/profile_schema.py @@ -22,7 +22,7 @@ from pydantic import BaseModel, ConfigDict, Field, RootModel -from ..schemas import ucp as ucp_1 +from ..schemas._internal import Base_3, BusinessSchema_3, PlatformSchema_3 class SigningKey(BaseModel): @@ -71,35 +71,42 @@ class SigningKey(BaseModel): """ -class PlatformProfile(BaseModel): +class Base(BaseModel): """ - Full discovery profile for platforms. Exposes complete service, capability, and payment handler registries. + Base discovery profile with shared properties for all profile types. """ model_config = ConfigDict( extra="allow", ) - ucp: ucp_1.PlatformSchema + ucp: Base_3 signing_keys: list[SigningKey] | None = None """ Public keys for signature verification (JWK format). Used to verify signed responses, webhooks, and other authenticated messages from this party. """ -class BusinessProfile(BaseModel): +class PlatformProfile(Base): """ - Discovery profile for businesses/merchants. Subset of platform profile with business-specific configuration. + Full discovery profile for platforms. Exposes complete service, capability, and payment handler registries. """ model_config = ConfigDict( extra="allow", ) - ucp: ucp_1.BusinessSchema - signing_keys: list[SigningKey] | None = None + ucp: PlatformSchema_3 | None = None + + +class BusinessProfile(Base): """ - Public keys for signature verification (JWK format). Used to verify signed responses, webhooks, and other authenticated messages from this party. + Discovery profile for businesses/merchants. Subset of platform profile with business-specific configuration. """ + model_config = ConfigDict( + extra="allow", + ) + ucp: BusinessSchema_3 | None = None + class UcpDiscoveryProfile(RootModel[PlatformProfile | BusinessProfile]): root: PlatformProfile | BusinessProfile = Field( @@ -108,18 +115,3 @@ class UcpDiscoveryProfile(RootModel[PlatformProfile | BusinessProfile]): """ Schema for UCP discovery profiles. Business profiles are hosted at /.well-known/ucp; platform profiles are hosted at URIs advertised in request headers. """ - - -class Base(BaseModel): - """ - Base discovery profile with shared properties for all profile types. - """ - - model_config = ConfigDict( - extra="allow", - ) - ucp: ucp_1.BaseModel1 - signing_keys: list[SigningKey] | None = None - """ - Public keys for signature verification (JWK format). Used to verify signed responses, webhooks, and other authenticated messages from this party. - """ diff --git a/src/ucp_sdk/models/schemas/_internal.py b/src/ucp_sdk/models/schemas/_internal.py new file mode 100644 index 0000000..47ec9ef --- /dev/null +++ b/src/ucp_sdk/models/schemas/_internal.py @@ -0,0 +1,579 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from typing import Any, Literal + +from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel + +from .transports import embedded_config + + +class UcpCapability(RootModel[Any]): + root: Any = Field(..., title="UCP Capability") + """ + Schema for UCP capabilities and extensions. Extensions are capabilities with an 'extends' field. Uses reverse-domain naming for governance. + """ + + +class Base(Entity): + model_config = ConfigDict( + extra="allow", + ) + extends: str | None = Field( + None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$" + ) + """ + Parent capability this extends. Present for extensions, absent for root capabilities. + """ + + +class PlatformSchema(Base): + """ + Full capability declaration for platform-level discovery. Includes spec/schema URLs for agent fetching. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class BusinessSchema(Base): + """ + Capability configuration for business/merchant level. May include business-specific config overrides. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class ResponseSchema(Base): + """ + Capability reference in responses. Only name/version required to confirm active capabilities. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class PaymentHandler(RootModel[Any]): + root: Any = Field(..., title="Payment Handler") + """ + Schema for UCP payment handlers. Handlers define how payment instruments are processed. + """ + + +class Base_1(Entity): + model_config = ConfigDict( + extra="allow", + ) + + +class PlatformSchema_1(Base_1): + """ + Platform declaration for discovery profiles. May include partial config state required for discovery. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class BusinessSchema_1(Base_1): + """ + Business declaration for discovery profiles. May include partial config state required for discovery. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class ResponseSchema_1(Base_1): + """ + Handler reference in responses. May include full config state for runtime usage of the handler. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class UcpService(RootModel[Any]): + root: Any = Field(..., title="UCP Service") + """ + Service binding for a specific transport. Each transport binding is a separate entry in the service array. + """ + + +class PlatformSchema_2(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" + + +class PlatformSchema5(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" + + +class PlatformSchema6(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" + + +class PlatformSchema7(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + + +class BusinessSchema_2(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" + + +class BusinessSchema4(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" + + +class BusinessSchema5(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" + + +class BusinessSchema6(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + config: embedded_config.EmbeddedTransportConfig | None = None + + +class ResponseSchema_2(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" + + +class ResponseSchema4(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" + + +class ResponseSchema5(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" + + +class ResponseSchema6(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + config: embedded_config.EmbeddedTransportConfig | None = None + + +class Base_2(Entity): + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest", "mcp", "a2a", "embedded"] + """ + Transport protocol for this service binding. + """ + endpoint: AnyUrl | None = None + """ + Endpoint URL for this transport binding. + """ + + +class PlatformSchema8(Base_2): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class PlatformSchema9(PlatformSchema_2, PlatformSchema8): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class PlatformSchema10(PlatformSchema5, PlatformSchema8): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class PlatformSchema11(PlatformSchema6, PlatformSchema8): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class PlatformSchema12(PlatformSchema7, PlatformSchema8): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class PlatformSchema3( + RootModel[ + PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 + ] +): + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + root: ( + PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 + ) = Field(..., title="Service (Platform Schema)") + """ + Full service declaration for platform-level discovery. Different transports require different fields. + """ + + +class BusinessSchema7(Base_2): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class BusinessSchema8(BusinessSchema_2, BusinessSchema7): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class BusinessSchema9(BusinessSchema4, BusinessSchema7): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class BusinessSchema10(BusinessSchema5, BusinessSchema7): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class BusinessSchema11(BusinessSchema6, BusinessSchema7): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class BusinessSchema2( + RootModel[ + BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 + ] +): + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + root: ( + BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 + ) = Field(..., title="Service (Business Schema)") + """ + Service binding for business/merchant configuration. May override platform endpoints. + """ + + +class ResponseSchema7(Base_2): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class ResponseSchema8(ResponseSchema_2, ResponseSchema7): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class ResponseSchema9(ResponseSchema4, ResponseSchema7): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class ResponseSchema10(ResponseSchema5, ResponseSchema7): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class ResponseSchema11(ResponseSchema6, ResponseSchema7): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + model_config = ConfigDict( + extra="allow", + ) + + +class ResponseSchema2( + RootModel[ + ResponseSchema8 | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 + ] +): + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + root: ( + ResponseSchema8 | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 + ) = Field(..., title="Service (Response Schema)") + """ + Service binding in API responses. Includes per-resource transport configuration via typed config. + """ + + +class UcpMetadata(RootModel[Any]): + root: Any = Field(..., title="UCP Metadata") + """ + Protocol metadata for discovery profiles and responses. Uses slim schema pattern with context-specific required fields. + """ + + +class Version(RootModel[str]): + root: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") + """ + UCP version in YYYY-MM-DD format. + """ + + +class ReverseDomainName(RootModel[str]): + root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$") + """ + Reverse-domain identifier (e.g., com.google.pay, dev.ucp.shopping.checkout) + """ + + +class Entity(BaseModel): + """ + Shared foundation for all UCP entities. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: Version + """ + Entity version in YYYY-MM-DD format. + """ + spec: AnyUrl | None = None + """ + URL to human-readable specification document. + """ + schema_: AnyUrl | None = Field(None, alias="schema") + """ + URL to JSON Schema defining this entity's structure and payloads. + """ + id: str | None = None + """ + Unique identifier for this entity instance. Used to disambiguate when multiple instances exist. + """ + config: dict[str, Any] | None = None + """ + Entity-specific configuration. Structure defined by each entity's schema. + """ + + +class Base_3(BaseModel): + """ + Base UCP metadata with shared properties for all schema types. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: Version + services: dict[ReverseDomainName, list[Base_2]] | None = None + """ + Service registry keyed by reverse-domain name. + """ + capabilities: dict[ReverseDomainName, list[Base]] | None = None + """ + Capability registry keyed by reverse-domain name. + """ + payment_handlers: dict[ReverseDomainName, list[Base_1]] | None = None + """ + Payment handler registry keyed by reverse-domain name. + """ + + +class PlatformSchema_3(Base_3): + """ + Full UCP metadata for platform-level configuration. Hosted at a URI advertised by the platform in request headers. + """ + + model_config = ConfigDict( + extra="allow", + ) + services: dict[ReverseDomainName, list[PlatformSchema3]] + """ + Service registry keyed by reverse-domain name. + """ + capabilities: dict[ReverseDomainName, list[PlatformSchema]] | None = None + """ + Capability registry keyed by reverse-domain name. + """ + payment_handlers: dict[ReverseDomainName, list[PlatformSchema_1]] + """ + Payment handler registry keyed by reverse-domain name. + """ + + +class BusinessSchema_3(Base_3): + """ + UCP metadata for business/merchant-level configuration. Subset of platform schema with business-specific settings. + """ + + model_config = ConfigDict( + extra="allow", + ) + services: dict[ReverseDomainName, list[BusinessSchema2]] + """ + Service registry keyed by reverse-domain name. + """ + capabilities: dict[ReverseDomainName, list[BusinessSchema]] | None = None + """ + Capability registry keyed by reverse-domain name. + """ + payment_handlers: dict[ReverseDomainName, list[BusinessSchema_1]] + """ + Payment handler registry keyed by reverse-domain name. + """ + + +class ResponseCheckoutSchema(Base_3): + """ + UCP metadata for checkout responses. + """ + + model_config = ConfigDict( + extra="allow", + ) + services: dict[ReverseDomainName, list[ResponseSchema2]] | None = None + """ + Service registry keyed by reverse-domain name. + """ + capabilities: dict[ReverseDomainName, list[ResponseSchema]] | None = None + """ + Capability registry keyed by reverse-domain name. + """ + payment_handlers: dict[ReverseDomainName, list[ResponseSchema_1]] + """ + Payment handler registry keyed by reverse-domain name. + """ + + +class ResponseOrderSchema(Base_3): + """ + UCP metadata for order responses. No payment handlers needed post-purchase. + """ + + model_config = ConfigDict( + extra="allow", + ) + capabilities: dict[ReverseDomainName, list[ResponseSchema]] | None = None + """ + Capability registry keyed by reverse-domain name. + """ diff --git a/src/ucp_sdk/models/schemas/capability.py b/src/ucp_sdk/models/schemas/capability.py index 5145d47..9ba07e7 100644 --- a/src/ucp_sdk/models/schemas/capability.py +++ b/src/ucp_sdk/models/schemas/capability.py @@ -18,38 +18,18 @@ from __future__ import annotations -from typing import Any - -from pydantic import Field, RootModel - - -class UcpCapability(RootModel[Any]): - root: Any = Field(..., title="UCP Capability") - """ - Schema for UCP capabilities and extensions. Extensions are capabilities with an 'extends' field. Uses reverse-domain naming for governance. - """ - - -class PlatformSchema(RootModel[Any]): - root: Any = Field(..., title="Capability (Platform Schema)") - """ - Full capability declaration for platform-level discovery. Includes spec/schema URLs for agent fetching. - """ - - -class Base(RootModel[Any]): - root: Any - - -class BusinessSchema(RootModel[Base]): - root: Base = Field(..., title="Capability (Business Schema)") - """ - Capability configuration for business/merchant level. May include business-specific config overrides. - """ - - -class ResponseSchema(RootModel[Base]): - root: Base = Field(..., title="Capability (Response Schema)") - """ - Capability reference in responses. Only name/version required to confirm active capabilities. - """ +from ._internal import ( + Base, + BusinessSchema, + PlatformSchema, + ResponseSchema, + UcpCapability, +) + +__all__ = [ + "Base", + "BusinessSchema", + "PlatformSchema", + "ResponseSchema", + "UcpCapability", +] diff --git a/src/ucp_sdk/models/schemas/payment_handler.py b/src/ucp_sdk/models/schemas/payment_handler.py index 5ddf666..1342388 100644 --- a/src/ucp_sdk/models/schemas/payment_handler.py +++ b/src/ucp_sdk/models/schemas/payment_handler.py @@ -18,38 +18,16 @@ from __future__ import annotations -from typing import Any - -from pydantic import Field, RootModel - - -class PaymentHandler(RootModel[Any]): - root: Any = Field(..., title="Payment Handler") - """ - Schema for UCP payment handlers. Handlers define how payment instruments are processed. - """ - - -class PlatformSchema(RootModel[Any]): - root: Any = Field(..., title="Payment Handler (Platform Schema)") - """ - Platform declaration for discovery profiles. May include partial config state required for discovery. - """ - - -class Base(RootModel[Any]): - root: Any - - -class BusinessSchema(RootModel[Base]): - root: Base = Field(..., title="Payment Handler (Business Schema)") - """ - Business declaration for discovery profiles. May include partial config state required for discovery. - """ - - -class ResponseSchema(RootModel[Base]): - root: Base = Field(..., title="Payment Handler (Response Schema)") - """ - Handler reference in responses. May include full config state for runtime usage of the handler. - """ +from ._internal import Base_1 as Base +from ._internal import BusinessSchema_1 as BusinessSchema +from ._internal import PaymentHandler +from ._internal import PlatformSchema_1 as PlatformSchema +from ._internal import ResponseSchema_1 as ResponseSchema + +__all__ = [ + "Base", + "BusinessSchema", + "PaymentHandler", + "PlatformSchema", + "ResponseSchema", +] diff --git a/src/ucp_sdk/models/schemas/service.py b/src/ucp_sdk/models/schemas/service.py index dd2ac08..cd55f8b 100644 --- a/src/ucp_sdk/models/schemas/service.py +++ b/src/ucp_sdk/models/schemas/service.py @@ -18,188 +18,72 @@ from __future__ import annotations -from typing import Any, Literal - -from pydantic import BaseModel, ConfigDict, Field, RootModel - -from .transports import embedded_config - - -class UcpService(RootModel[Any]): - root: Any = Field(..., title="UCP Service") - """ - Service binding for a specific transport. Each transport binding is a separate entry in the service array. - """ - - -class PlatformSchema(BaseModel): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["rest"] = "rest" - - -class PlatformSchema5(BaseModel): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["mcp"] = "mcp" - - -class PlatformSchema6(BaseModel): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["a2a"] = "a2a" - - -class PlatformSchema7(BaseModel): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["embedded"] = "embedded" - - -class PlatformSchema3( - RootModel[ - PlatformSchema | PlatformSchema5 | PlatformSchema6 | PlatformSchema7 - ] -): - root: ( - PlatformSchema | PlatformSchema5 | PlatformSchema6 | PlatformSchema7 - ) = Field(..., title="Service (Platform Schema)") - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ - - -class BusinessSchema(BaseModel): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["rest"] = "rest" - - -class BusinessSchema4(BaseModel): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["mcp"] = "mcp" - - -class BusinessSchema5(BaseModel): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["a2a"] = "a2a" - - -class BusinessSchema6(BaseModel): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["embedded"] = "embedded" - config: embedded_config.EmbeddedTransportConfig | None = None - - -class BusinessSchema2( - RootModel[ - BusinessSchema | BusinessSchema4 | BusinessSchema5 | BusinessSchema6 - ] -): - root: ( - BusinessSchema | BusinessSchema4 | BusinessSchema5 | BusinessSchema6 - ) = Field(..., title="Service (Business Schema)") - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ - - -class ResponseSchema(BaseModel): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["rest"] = "rest" - - -class ResponseSchema4(BaseModel): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["mcp"] = "mcp" - - -class ResponseSchema5(BaseModel): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["a2a"] = "a2a" - - -class ResponseSchema6(BaseModel): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["embedded"] = "embedded" - config: embedded_config.EmbeddedTransportConfig | None = None - - -class ResponseSchema2( - RootModel[ - ResponseSchema | ResponseSchema4 | ResponseSchema5 | ResponseSchema6 - ] -): - root: ( - ResponseSchema | ResponseSchema4 | ResponseSchema5 | ResponseSchema6 - ) = Field(..., title="Service (Response Schema)") - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ +from ._internal import Base_2 as Base +from ._internal import ( + BusinessSchema2, + BusinessSchema4, + BusinessSchema5, + BusinessSchema6, + BusinessSchema7, + BusinessSchema8, + BusinessSchema9, + BusinessSchema10, + BusinessSchema11, + PlatformSchema3, + PlatformSchema5, + PlatformSchema6, + PlatformSchema7, + PlatformSchema8, + PlatformSchema9, + PlatformSchema10, + PlatformSchema11, + PlatformSchema12, + ResponseSchema2, + ResponseSchema4, + ResponseSchema5, + ResponseSchema6, + ResponseSchema7, + ResponseSchema8, + ResponseSchema9, + ResponseSchema10, + ResponseSchema11, + UcpService, +) +from ._internal import BusinessSchema_2 as BusinessSchema +from ._internal import PlatformSchema_2 as PlatformSchema +from ._internal import ResponseSchema_2 as ResponseSchema + +__all__ = [ + "Base", + "BusinessSchema", + "BusinessSchema10", + "BusinessSchema11", + "BusinessSchema2", + "BusinessSchema4", + "BusinessSchema5", + "BusinessSchema6", + "BusinessSchema7", + "BusinessSchema8", + "BusinessSchema9", + "PlatformSchema", + "PlatformSchema10", + "PlatformSchema11", + "PlatformSchema12", + "PlatformSchema3", + "PlatformSchema5", + "PlatformSchema6", + "PlatformSchema7", + "PlatformSchema8", + "PlatformSchema9", + "ResponseSchema", + "ResponseSchema10", + "ResponseSchema11", + "ResponseSchema2", + "ResponseSchema4", + "ResponseSchema5", + "ResponseSchema6", + "ResponseSchema7", + "ResponseSchema8", + "ResponseSchema9", + "UcpService", +] diff --git a/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py b/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py index 04db2f3..26569ed 100644 --- a/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py +++ b/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py @@ -22,6 +22,8 @@ from pydantic import BaseModel, ConfigDict, Field, RootModel +from .checkout import Checkout as Checkout_1 + class Ap2MandateExtension(RootModel[Any]): root: Any = Field(..., title="AP2 Mandate Extension") @@ -80,6 +82,12 @@ class Ap2WithCheckoutMandate(BaseModel): """ +class Ap2(Ap2WithMerchantAuthorization, Ap2WithCheckoutMandate): + model_config = ConfigDict( + extra="allow", + ) + + class ErrorCode( RootModel[ Literal[ @@ -105,3 +113,14 @@ class ErrorCode( """ Error codes specific to AP2 mandate verification. """ + + +class Checkout(Checkout_1): + """ + Checkout extended with AP2 mandate support. + """ + + model_config = ConfigDict( + extra="allow", + ) + ap2: Ap2 | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/buyer_consent.py b/src/ucp_sdk/models/schemas/shopping/buyer_consent.py index d7b3c74..019446e 100644 --- a/src/ucp_sdk/models/schemas/shopping/buyer_consent.py +++ b/src/ucp_sdk/models/schemas/shopping/buyer_consent.py @@ -22,6 +22,9 @@ from pydantic import BaseModel, ConfigDict, Field, RootModel +from .checkout import Checkout as Checkout_1 +from .types.buyer import Buyer as Buyer_1 + class BuyerConsentExtension(RootModel[Any]): root: Any = Field(..., title="Buyer Consent Extension") @@ -54,3 +57,31 @@ class Consent(BaseModel): """ Consent for selling data to third parties (CCPA). """ + + +class Buyer(Buyer_1): + """ + Buyer object extended with consent tracking. + """ + + model_config = ConfigDict( + extra="allow", + ) + consent: Consent | None = None + """ + Consent tracking fields. + """ + + +class Checkout(Checkout_1): + """ + Checkout extended with consent tracking via buyer object. + """ + + model_config = ConfigDict( + extra="allow", + ) + buyer: Buyer | None = None + """ + Buyer with consent tracking. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/checkout.py b/src/ucp_sdk/models/schemas/shopping/checkout.py index 1356cc0..76ca068 100644 --- a/src/ucp_sdk/models/schemas/shopping/checkout.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout.py @@ -22,7 +22,7 @@ from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict -from .. import ucp as ucp_1 +from .._internal import ResponseCheckoutSchema from . import payment as payment_1 from .types import buyer as buyer_1 from .types import context as context_1 @@ -37,7 +37,7 @@ class Checkout(BaseModel): model_config = ConfigDict( extra="allow", ) - ucp: ucp_1.ResponseCheckoutSchema + ucp: ResponseCheckoutSchema id: str """ Unique identifier of the checkout session. diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py deleted file mode 100644 index 5799fc2..0000000 --- a/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - -from . import payment as payment_1 - - -class CheckoutCompleteRequest(BaseModel): - """ - Base checkout schema. Extensions compose onto this using allOf. - """ - - model_config = ConfigDict( - extra="allow", - ) - payment: payment_1.Payment diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py deleted file mode 100644 index 0e23017..0000000 --- a/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - -from . import payment as payment_1 -from .types import buyer as buyer_1 -from .types import context as context_1 -from .types import line_item_create_request - - -class CheckoutCreateRequest(BaseModel): - """ - Base checkout schema. Extensions compose onto this using allOf. - """ - - model_config = ConfigDict( - extra="allow", - ) - line_items: list[line_item_create_request.LineItemCreateRequest] - """ - List of line items being checked out. - """ - buyer: buyer_1.Buyer | None = None - """ - Representation of the buyer. - """ - context: context_1.Context | None = None - payment: payment_1.Payment | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py deleted file mode 100644 index 5390a98..0000000 --- a/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - -from . import payment as payment_1 -from .types import buyer as buyer_1 -from .types import context as context_1 -from .types import line_item_update_request - - -class CheckoutUpdateRequest(BaseModel): - """ - Base checkout schema. Extensions compose onto this using allOf. - """ - - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Unique identifier of the checkout session. - """ - line_items: list[line_item_update_request.LineItemUpdateRequest] - """ - List of line items being checked out. - """ - buyer: buyer_1.Buyer | None = None - """ - Representation of the buyer. - """ - context: context_1.Context | None = None - payment: payment_1.Payment | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/discount.py b/src/ucp_sdk/models/schemas/shopping/discount.py index 952ded6..6bc440d 100644 --- a/src/ucp_sdk/models/schemas/shopping/discount.py +++ b/src/ucp_sdk/models/schemas/shopping/discount.py @@ -22,6 +22,8 @@ from pydantic import BaseModel, ConfigDict, Field, RootModel +from .checkout import Checkout as Checkout_1 + class DiscountExtension(RootModel[Any]): root: Any = Field(..., title="Discount Extension") @@ -102,3 +104,14 @@ class DiscountsObject(BaseModel): """ Discounts successfully applied (code-based and automatic). """ + + +class Checkout(Checkout_1): + """ + Checkout extended with discount capability. + """ + + model_config = ConfigDict( + extra="allow", + ) + discounts: DiscountsObject | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py b/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py index 0d4c0aa..57d7a2a 100644 --- a/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py +++ b/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py @@ -20,10 +20,11 @@ from typing import Any -from pydantic import Field, RootModel +from pydantic import ConfigDict, Field, RootModel +from ..checkout import Checkout as Checkout_1 +from ..types import fulfillment as fulfillment_1 from ..types import ( - fulfillment, fulfillment_available_method, fulfillment_group, fulfillment_method, @@ -56,5 +57,19 @@ class FulfillmentMethod(RootModel[fulfillment_method.FulfillmentMethod]): root: fulfillment_method.FulfillmentMethod -class Fulfillment(RootModel[fulfillment.Fulfillment]): - root: fulfillment.Fulfillment +class Fulfillment(RootModel[fulfillment_1.Fulfillment]): + root: fulfillment_1.Fulfillment + + +class Checkout(Checkout_1): + """ + Checkout extended with hierarchical fulfillment. + """ + + model_config = ConfigDict( + extra="allow", + ) + fulfillment: Fulfillment | None = None + """ + Fulfillment details. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/order.py b/src/ucp_sdk/models/schemas/shopping/order.py index e747417..5538eae 100644 --- a/src/ucp_sdk/models/schemas/shopping/order.py +++ b/src/ucp_sdk/models/schemas/shopping/order.py @@ -20,7 +20,7 @@ from pydantic import AnyUrl, BaseModel, ConfigDict -from .. import ucp as ucp_1 +from .._internal import ResponseOrderSchema from .types import ( adjustment, expectation, @@ -70,7 +70,7 @@ class Order(BaseModel): model_config = ConfigDict( extra="allow", ) - ucp: ucp_1.ResponseOrderSchema + ucp: ResponseOrderSchema id: str """ Unique order identifier. diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py deleted file mode 100644 index 54854b7..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class FulfillmentAvailableMethodCreateRequest(BaseModel): - """ - Inventory availability hint for a fulfillment method type. - """ - - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py deleted file mode 100644 index 678c052..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class FulfillmentAvailableMethodUpdateRequest(BaseModel): - """ - Inventory availability hint for a fulfillment method type. - """ - - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py deleted file mode 100644 index 32accc9..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - -from . import fulfillment_method_create_request - - -class FulfillmentCreateRequest(BaseModel): - """ - Container for fulfillment methods and availability. - """ - - model_config = ConfigDict( - extra="allow", - ) - methods: ( - list[fulfillment_method_create_request.FulfillmentMethodCreateRequest] - | None - ) = None - """ - Fulfillment methods for cart items. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py deleted file mode 100644 index 99489e4..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class FulfillmentGroupCreateRequest(BaseModel): - """ - A merchant-generated package/group of line items with fulfillment options. - """ - - model_config = ConfigDict( - extra="allow", - ) - selected_option_id: str | None = None - """ - ID of the selected fulfillment option for this group. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py deleted file mode 100644 index c830c71..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class FulfillmentGroupUpdateRequest(BaseModel): - """ - A merchant-generated package/group of line items with fulfillment options. - """ - - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Group identifier for referencing merchant-generated groups in updates. - """ - selected_option_id: str | None = None - """ - ID of the selected fulfillment option for this group. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py deleted file mode 100644 index b268341..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from typing import Literal - -from pydantic import BaseModel, ConfigDict - -from . import fulfillment_destination, fulfillment_group_create_request - - -class FulfillmentMethodCreateRequest(BaseModel): - """ - A fulfillment method (shipping or pickup) with destinations and groups. - """ - - model_config = ConfigDict( - extra="allow", - ) - type: Literal["shipping", "pickup"] - """ - Fulfillment method type. - """ - line_item_ids: list[str] | None = None - """ - Line item IDs fulfilled via this method. - """ - destinations: ( - list[fulfillment_destination.FulfillmentDestination] | None - ) = None - """ - Available destinations. For shipping: addresses. For pickup: retail locations. - """ - selected_destination_id: str | None = None - """ - ID of the selected destination. - """ - groups: ( - list[fulfillment_group_create_request.FulfillmentGroupCreateRequest] - | None - ) = None - """ - Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py deleted file mode 100644 index d6062e6..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - -from . import fulfillment_destination, fulfillment_group_update_request - - -class FulfillmentMethodUpdateRequest(BaseModel): - """ - A fulfillment method (shipping or pickup) with destinations and groups. - """ - - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Unique fulfillment method identifier. - """ - line_item_ids: list[str] - """ - Line item IDs fulfilled via this method. - """ - destinations: ( - list[fulfillment_destination.FulfillmentDestination] | None - ) = None - """ - Available destinations. For shipping: addresses. For pickup: retail locations. - """ - selected_destination_id: str | None = None - """ - ID of the selected destination. - """ - groups: ( - list[fulfillment_group_update_request.FulfillmentGroupUpdateRequest] - | None - ) = None - """ - Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py deleted file mode 100644 index d08ee75..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class FulfillmentOptionCreateRequest(BaseModel): - """ - A fulfillment option within a group (e.g., Standard Shipping $5, Express $15). - """ - - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py deleted file mode 100644 index 363e7f3..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class FulfillmentOptionUpdateRequest(BaseModel): - """ - A fulfillment option within a group (e.g., Standard Shipping $5, Express $15). - """ - - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py deleted file mode 100644 index 849b10a..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - -from . import fulfillment_method_update_request - - -class FulfillmentUpdateRequest(BaseModel): - """ - Container for fulfillment methods and availability. - """ - - model_config = ConfigDict( - extra="allow", - ) - methods: ( - list[fulfillment_method_update_request.FulfillmentMethodUpdateRequest] - | None - ) = None - """ - Fulfillment methods for cart items. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py deleted file mode 100644 index fd3f850..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class ItemCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py deleted file mode 100644 index 735b984..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class ItemUpdateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ - Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py deleted file mode 100644 index 754e4fe..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict, Field - -from . import item_create_request - - -class LineItemCreateRequest(BaseModel): - """ - Line item object. Expected to use the currency of the parent object. - """ - - model_config = ConfigDict( - extra="allow", - ) - item: item_create_request.ItemCreateRequest - quantity: int = Field(..., ge=1) - """ - Quantity of the item being purchased. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py deleted file mode 100644 index fc43593..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict, Field - -from . import item_update_request - - -class LineItemUpdateRequest(BaseModel): - """ - Line item object. Expected to use the currency of the parent object. - """ - - model_config = ConfigDict( - extra="allow", - ) - id: str | None = None - item: item_update_request.ItemUpdateRequest - quantity: int = Field(..., ge=1) - """ - Quantity of the item being purchased. - """ - parent_id: str | None = None - """ - Parent line item identifier for any nested structures. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py b/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py index c8d897d..4b7bf78 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py +++ b/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py @@ -54,13 +54,9 @@ class PaymentInstrument(BaseModel): """ Display information for this payment instrument. Each payment instrument schema defines its specific display properties, as outlined by the payment handler. """ - selected: bool | None = None - """ - Whether this instrument is selected by the user. - """ -class SelectedPaymentInstrument(BaseModel): +class SelectedPaymentInstrument(PaymentInstrument): """ A payment instrument with selection state. """ @@ -68,27 +64,6 @@ class SelectedPaymentInstrument(BaseModel): model_config = ConfigDict( extra="allow", ) - id: str - """ - A unique identifier for this instrument instance, assigned by the platform. - """ - handler_id: str - """ - The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition. - """ - type: str - """ - The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value. - """ - billing_address: postal_address.PostalAddress | None = None - """ - The billing address associated with this payment method. - """ - credential: payment_credential.PaymentCredential | None = None - display: dict[str, Any] | None = None - """ - Display information for this payment instrument. Each payment instrument schema defines its specific display properties, as outlined by the payment handler. - """ selected: bool | None = None """ Whether this instrument is selected by the user. diff --git a/src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py deleted file mode 100644 index 9de6eb1..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - -from . import postal_address - - -class RetailLocationCreateRequest(BaseModel): - """ - A pickup location (retail store, locker, etc.). - """ - - model_config = ConfigDict( - extra="allow", - ) - name: str - """ - Location name (e.g., store name). - """ - address: postal_address.PostalAddress | None = None - """ - Physical address of the location. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py deleted file mode 100644 index 8e83ff4..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - -from . import postal_address - - -class RetailLocationUpdateRequest(BaseModel): - """ - A pickup location (retail store, locker, etc.). - """ - - model_config = ConfigDict( - extra="allow", - ) - name: str - """ - Location name (e.g., store name). - """ - address: postal_address.PostalAddress | None = None - """ - Physical address of the location. - """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/total_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/total_create_request.py deleted file mode 100644 index 6318099..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/total_create_request.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class TotalCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/total_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/total_update_request.py deleted file mode 100644 index e8ca037..0000000 --- a/src/ucp_sdk/models/schemas/shopping/types/total_update_request.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2026 UCP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generated by datamodel-codegen -# pylint: disable=all -# pyformat: disable - -from __future__ import annotations - -from pydantic import BaseModel, ConfigDict - - -class TotalUpdateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - ) diff --git a/src/ucp_sdk/models/schemas/ucp.py b/src/ucp_sdk/models/schemas/ucp.py index f8d1fdd..d6fd460 100644 --- a/src/ucp_sdk/models/schemas/ucp.py +++ b/src/ucp_sdk/models/schemas/ucp.py @@ -18,399 +18,26 @@ from __future__ import annotations -from typing import Any, Literal - -from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel, constr - - -class UcpMetadata(RootModel[Any]): - root: Any = Field(..., title="UCP Metadata") - """ - Protocol metadata for discovery profiles and responses. Uses slim schema pattern with context-specific required fields. - """ - - -class Version(RootModel[str]): - root: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") - """ - UCP version in YYYY-MM-DD format. - """ - - -class ReverseDomainName(RootModel[str]): - root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$") - """ - Reverse-domain identifier (e.g., com.google.pay, dev.ucp.shopping.checkout) - """ - - -class Entity(BaseModel): - """ - Shared foundation for all UCP entities. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: Version - """ - Entity version in YYYY-MM-DD format. - """ - spec: AnyUrl | None = None - """ - URL to human-readable specification document. - """ - schema_: AnyUrl | None = Field(None, alias="schema") - """ - URL to JSON Schema defining this entity's structure and payloads. - """ - id: str | None = None - """ - Unique identifier for this entity instance. Used to disambiguate when multiple instances exist. - """ - config: dict[str, Any] | None = None - """ - Entity-specific configuration. Structure defined by each entity's schema. - """ - - -class Base(RootModel[Any]): - root: Any - - -class PlatformSchema9(BaseModel): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["rest"] = "rest" - - -class PlatformSchema10(BaseModel): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["mcp"] = "mcp" - - -class PlatformSchema11(BaseModel): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["a2a"] = "a2a" - - -class PlatformSchema12(BaseModel): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["embedded"] = "embedded" - - -class PlatformSchema8( - RootModel[ - PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 - ] -): - root: ( - PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 - ) = Field(..., title="Service (Platform Schema)") - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ - - -class BusinessSchema8(BaseModel): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["rest"] = "rest" - - -class BusinessSchema9(BaseModel): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["mcp"] = "mcp" - - -class BusinessSchema10(BaseModel): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["a2a"] = "a2a" - - -class EmbeddedConfig(BaseModel): - """ - Per-checkout configuration for embedded transport binding. Allows businesses to vary ECP availability and delegations based on cart contents, agent authorization, or policy. - """ - - model_config = ConfigDict( - extra="allow", - ) - delegate: list[str] | None = None - """ - Delegations the business allows. At service-level, declares available delegations. In checkout responses, confirms accepted delegations for this session. - """ - - -class ResponseSchema(BaseModel): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["rest"] = "rest" - - -class ResponseSchema9(BaseModel): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["mcp"] = "mcp" - - -class ResponseSchema10(BaseModel): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["a2a"] = "a2a" - - -class ResponseSchema11(BaseModel): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["embedded"] = "embedded" - config: EmbeddedConfig | None = None - - -class ResponseSchema7( - RootModel[ - ResponseSchema | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 - ] -): - root: ( - ResponseSchema | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 - ) = Field(..., title="Service (Response Schema)") - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ - - -class PlatformSchema13(RootModel[Any]): - root: Any = Field(..., title="Capability (Platform Schema)") - """ - Full capability declaration for platform-level discovery. Includes spec/schema URLs for agent fetching. - """ - - -class BusinessSchema12(RootModel[Base]): - root: Base = Field(..., title="Capability (Business Schema)") - """ - Capability configuration for business/merchant level. May include business-specific config overrides. - """ - - -class ResponseSchema12(RootModel[Base]): - root: Base = Field(..., title="Capability (Response Schema)") - """ - Capability reference in responses. Only name/version required to confirm active capabilities. - """ - - -class PlatformSchema14(RootModel[Any]): - root: Any = Field(..., title="Payment Handler (Platform Schema)") - """ - Platform declaration for discovery profiles. May include partial config state required for discovery. - """ - - -class BusinessSchema13(RootModel[Base]): - root: Base = Field(..., title="Payment Handler (Business Schema)") - """ - Business declaration for discovery profiles. May include partial config state required for discovery. - """ - - -class ResponseSchema13(RootModel[Base]): - root: Base = Field(..., title="Payment Handler (Response Schema)") - """ - Handler reference in responses. May include full config state for runtime usage of the handler. - """ - - -class PlatformSchema(BaseModel): - """ - Full UCP metadata for platform-level configuration. Hosted at a URI advertised by the platform in request headers. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") - """ - UCP version in YYYY-MM-DD format. - """ - services: Any - capabilities: Any | None = None - payment_handlers: Any - - -class BusinessSchema(BaseModel): - """ - UCP metadata for business/merchant-level configuration. Subset of platform schema with business-specific settings. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") - """ - UCP version in YYYY-MM-DD format. - """ - services: Any - capabilities: Any | None = None - payment_handlers: Any - - -class ResponseCheckoutSchema(BaseModel): - """ - UCP metadata for checkout responses. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") - """ - UCP version in YYYY-MM-DD format. - """ - services: Any | None = None - capabilities: Any | None = None - payment_handlers: Any - - -class ResponseOrderSchema(BaseModel): - """ - UCP metadata for order responses. No payment handlers needed post-purchase. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") - """ - UCP version in YYYY-MM-DD format. - """ - services: ( - dict[ - constr(pattern=r"^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9_]*)+$"), - list[Base], - ] - | None - ) = None - """ - Service registry keyed by reverse-domain name. - """ - capabilities: Any | None = None - payment_handlers: ( - dict[ - constr(pattern=r"^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9_]*)+$"), - list[Base], - ] - | None - ) = None - """ - Payment handler registry keyed by reverse-domain name. - """ - - -class BaseModel1(BaseModel): - """ - Base UCP metadata with shared properties for all schema types. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: Version - services: dict[ReverseDomainName, list[Base]] | None = None - """ - Service registry keyed by reverse-domain name. - """ - capabilities: dict[ReverseDomainName, list[Base]] | None = None - """ - Capability registry keyed by reverse-domain name. - """ - payment_handlers: dict[ReverseDomainName, list[Base]] | None = None - """ - Payment handler registry keyed by reverse-domain name. - """ - - -class BusinessSchema11(BaseModel): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ - - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["embedded"] = "embedded" - config: EmbeddedConfig | None = None - - -class BusinessSchema7( - RootModel[ - BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 - ] -): - root: ( - BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 - ) = Field(..., title="Service (Business Schema)") - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ +from ._internal import Base_3 as Base +from ._internal import BusinessSchema_3 as BusinessSchema +from ._internal import ( + Entity, + ResponseCheckoutSchema, + ResponseOrderSchema, + ReverseDomainName, + UcpMetadata, + Version, +) +from ._internal import PlatformSchema_3 as PlatformSchema + +__all__ = [ + "Base", + "BusinessSchema", + "Entity", + "PlatformSchema", + "ResponseCheckoutSchema", + "ResponseOrderSchema", + "ReverseDomainName", + "UcpMetadata", + "Version", +] diff --git a/ucp b/ucp new file mode 160000 index 0000000..2ee92ff --- /dev/null +++ b/ucp @@ -0,0 +1 @@ +Subproject commit 2ee92ffdee356e4480be05e7437d1038bec6c779 diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..ea43603 --- /dev/null +++ b/uv.lock @@ -0,0 +1,762 @@ +version = 1 +revision = 3 +requires-python = ">=3.10" + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/annotated-types/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/annotated-types/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53" }, +] + +[[package]] +name = "anyio" +version = "4.12.1" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/anyio/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/anyio/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c" }, +] + +[[package]] +name = "argcomplete" +version = "3.6.3" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/argcomplete/argcomplete-3.6.3.tar.gz", hash = "sha256:62e8ed4fd6a45864acc8235409461b72c9a28ee785a2011cc5eb78318786c89c" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/argcomplete/argcomplete-3.6.3-py3-none-any.whl", hash = "sha256:f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce" }, +] + +[[package]] +name = "black" +version = "26.1.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "pytokens" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0.tar.gz", hash = "sha256:d294ac3340eef9c9eb5d29288e96dc719ff269a88e27b396340459dd85da4c58" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ca699710dece84e3ebf6e92ee15f5b8f72870ef984bf944a57a777a48357c168" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e8e75dabb6eb83d064b0db46392b25cabb6e784ea624219736e8985a6b3675d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb07665d9a907a1a645ee41a0df8a25ffac8ad9c26cdb557b7b88eeeeec934e0" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:7ed300200918147c963c87700ccf9966dceaefbbb7277450a8d646fc5646bf24" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:c5b7713daea9bf943f79f8c3b46f361cc5229e0e604dcef6a8bb6d1c37d9df89" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3cee1487a9e4c640dc7467aaa543d6c0097c391dc8ac74eb313f2fbf9d7a7cb5" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d62d14ca31c92adf561ebb2e5f2741bf8dea28aef6deb400d49cca011d186c68" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb1dafbbaa3b1ee8b4550a84425aac8874e5f390200f5502cf3aee4a2acb2f14" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:101540cb2a77c680f4f80e628ae98bd2bd8812fb9d72ade4f8995c5ff019e82c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:6f3977a16e347f1b115662be07daa93137259c711e526402aa444d7a88fdc9d4" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6eeca41e70b5f5c84f2f913af857cf2ce17410847e1d54642e658e078da6544f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dd39eef053e58e60204f2cdf059e2442e2eb08f15989eefe259870f89614c8b6" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9459ad0d6cd483eacad4c6566b0f8e42af5e8b583cee917d90ffaa3778420a0a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a19915ec61f3a8746e8b10adbac4a577c6ba9851fa4a9e9fbfbcf319887a5791" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:643d27fb5facc167c0b1b59d0315f2674a6e950341aed0fc05cf307d22bf4954" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ba1d768fbfb6930fc93b0ecc32a43d8861ded16f47a40f14afa9bb04ab93d304" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2b807c240b64609cb0e80d2200a35b23c7df82259f80bef1b2c96eb422b4aac9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1de0f7d01cc894066a1153b738145b194414cc6eeaad8ef4397ac9abacf40f6b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:91a68ae46bf07868963671e4d05611b179c2313301bd756a89ad4e3b3db2325b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:be5e2fe860b9bd9edbf676d5b60a9282994c03fbbd40fe8f5e75d194f96064ca" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9dc8c71656a79ca49b8d3e2ce8103210c9481c57798b48deeb3a8bb02db5f115" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b22b3810451abe359a964cc88121d57f7bce482b53a066de0f1584988ca36e79" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53c62883b3f999f14e5d30b5a79bd437236658ad45b2f853906c7cbe79de00af" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:f016baaadc423dc960cdddf9acae679e71ee02c4c341f78f3179d7e4819c095f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:66912475200b67ef5a0ab665011964bf924745103f51977a78b4fb92a9fc1bf0" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-py3-none-any.whl", hash = "sha256:1054e8e47ebd686e078c0bb0eaf31e6ce69c966058d122f2c0c950311f9f3ede" }, +] + +[[package]] +name = "certifi" +version = "2026.2.25" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/certifi/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/certifi/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa" }, +] + +[[package]] +name = "click" +version = "8.3.1" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/click/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/click/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/colorama/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/colorama/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" }, +] + +[[package]] +name = "datamodel-code-generator" +version = "0.54.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "argcomplete" }, + { name = "black" }, + { name = "genson" }, + { name = "inflect" }, + { name = "isort" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "pyyaml" }, + { name = "tomli", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/datamodel-code-generator/datamodel_code_generator-0.54.0.tar.gz", hash = "sha256:2b183598d049e265146a8224c35d1bb96a80a641ea8ecd2a82e6a0e97b56da6b" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/datamodel-code-generator/datamodel_code_generator-0.54.0-py3-none-any.whl", hash = "sha256:3156df7a7e8fa5a7c9a6d50836e5ba5abe0532f6b71eee6d73a0c8e1fb5b7e47" }, +] + +[package.optional-dependencies] +http = [ + { name = "httpx" }, +] +ruff = [ + { name = "ruff" }, +] + +[[package]] +name = "dnspython" +version = "2.8.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/dnspython/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/dnspython/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af" }, +] + +[[package]] +name = "email-validator" +version = "2.3.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "dnspython" }, + { name = "idna" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/email-validator/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/email-validator/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/exceptiongroup/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/exceptiongroup/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598" }, +] + +[[package]] +name = "genson" +version = "1.3.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/genson/genson-1.3.0.tar.gz", hash = "sha256:e02db9ac2e3fd29e65b5286f7135762e2cd8a986537c075b06fc5f1517308e37" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/genson/genson-1.3.0-py3-none-any.whl", hash = "sha256:468feccd00274cc7e4c09e84b08704270ba8d95232aa280f65b986139cec67f7" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/h11/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/h11/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/httpcore/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/httpcore/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/httpx/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/httpx/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/idna/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/idna/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea" }, +] + +[[package]] +name = "inflect" +version = "7.5.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "more-itertools" }, + { name = "typeguard" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/inflect/inflect-7.5.0.tar.gz", hash = "sha256:faf19801c3742ed5a05a8ce388e0d8fe1a07f8d095c82201eb904f5d27ad571f" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/inflect/inflect-7.5.0-py3-none-any.whl", hash = "sha256:2aea70e5e70c35d8350b8097396ec155ffd68def678c7ff97f51aa69c1d92344" }, +] + +[[package]] +name = "isort" +version = "7.0.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/isort/isort-7.0.0.tar.gz", hash = "sha256:5513527951aadb3ac4292a41a16cbc50dd1642432f5e8c20057d414bdafb4187" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/isort/isort-7.0.0-py3-none-any.whl", hash = "sha256:1bcabac8bc3c36c7fb7b98a76c8abb18e0f841a3ba81decac7691008592499c1" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/jinja2/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/jinja2/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa" }, +] + +[[package]] +name = "more-itertools" +version = "10.8.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/more-itertools/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/more-itertools/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/mypy-extensions/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/mypy-extensions/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505" }, +] + +[[package]] +name = "packaging" +version = "26.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/packaging/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/packaging/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529" }, +] + +[[package]] +name = "pathspec" +version = "1.0.4" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pathspec/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pathspec/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723" }, +] + +[[package]] +name = "platformdirs" +version = "4.9.2" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/platformdirs/platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/platformdirs/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd" }, +] + +[[package]] +name = "pydantic" +version = "2.12.5" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d" }, +] + +[[package]] +name = "pydantic-core" +version = "2.41.5" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51" }, +] + +[[package]] +name = "pytokens" +version = "0.4.1" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b" }, +] + +[[package]] +name = "ruff" +version = "0.15.4" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4.tar.gz", hash = "sha256:3412195319e42d634470cc97aa9803d07e9d5c9223b99bcb1518f0c725f26ae1" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-linux_armv6l.whl", hash = "sha256:a1810931c41606c686bae8b5b9a8072adac2f611bb433c0ba476acba17a332e0" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5a1632c66672b8b4d3e1d1782859e98d6e0b4e70829530666644286600a33992" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a4386ba2cd6c0f4ff75252845906acc7c7c8e1ac567b7bc3d373686ac8c222ba" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2496488bdfd3732747558b6f95ae427ff066d1fcd054daf75f5a50674411e75" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3f1c4893841ff2d54cbda1b2860fa3260173df5ddd7b95d370186f8a5e66a4ac" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:820b8766bd65503b6c30aaa6331e8ef3a6e564f7999c844e9a547c40179e440a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9fb74bab47139c1751f900f857fa503987253c3ef89129b24ed375e72873e85" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f80c98765949c518142b3a50a5db89343aa90f2c2bf7799de9986498ae6176db" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451a2e224151729b3b6c9ffb36aed9091b2996fe4bdbd11f47e27d8f2e8888ec" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a8f157f2e583c513c4f5f896163a93198297371f34c04220daf40d133fdd4f7f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:917cc68503357021f541e69b35361c99387cdbbf99bd0ea4aa6f28ca99ff5338" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e9737c8161da79fd7cfec19f1e35620375bd8b2a50c3e77fa3d2c16f574105cc" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:291258c917539e18f6ba40482fe31d6f5ac023994ee11d7bdafd716f2aab8a68" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3f83c45911da6f2cd5936c436cf86b9f09f09165f033a99dcf7477e34041cbc3" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-win32.whl", hash = "sha256:65594a2d557d4ee9f02834fcdf0a28daa8b3b9f6cb2cb93846025a36db47ef22" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-win_amd64.whl", hash = "sha256:04196ad44f0df220c2ece5b0e959c2f37c777375ec744397d21d15b50a75264f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-win_arm64.whl", hash = "sha256:60d5177e8cfc70e51b9c5fad936c634872a74209f934c1e79107d11787ad5453" }, +] + +[[package]] +name = "tomli" +version = "2.4.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4" }, + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a" }, +] + +[[package]] +name = "typeguard" +version = "4.5.1" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typeguard/typeguard-4.5.1.tar.gz", hash = "sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typeguard/typeguard-4.5.1-py3-none-any.whl", hash = "sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typing-extensions/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typing-extensions/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typing-inspection/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464" } +wheels = [ + { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typing-inspection/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7" }, +] + +[[package]] +name = "ucp-sdk" +version = "2026.1.23" +source = { editable = "." } +dependencies = [ + { name = "email-validator" }, + { name = "pydantic" }, +] + +[package.dev-dependencies] +dev = [ + { name = "datamodel-code-generator", extra = ["http", "ruff"] }, +] + +[package.metadata] +requires-dist = [ + { name = "email-validator", specifier = ">=2.0.0" }, + { name = "pydantic", specifier = ">=2.5.0" }, +] + +[package.metadata.requires-dev] +dev = [{ name = "datamodel-code-generator", extras = ["http", "ruff"], specifier = ">=0.50.0" }] From 8ef89ee7268639f43072e199304085d0aef9dfe8 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 15:33:22 +0100 Subject: [PATCH 14/22] update readme Change-Id: I2e70bdaf468ef7663b6c8e7542f2acf822d9df06 --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4a3bd74..0a11848 100644 --- a/README.md +++ b/README.md @@ -59,16 +59,14 @@ To regenerate the models: ```bash uv sync -./generate_models.sh +./generate_models.sh ``` -By default, it uses the version `release-2026.01.23`. You can specify a different tag or branch as an argument: +Where `` is the version of the UCP specification to use (for example, "2026-01-23"). -```bash -./generate_models.sh v2026.03.01 -``` +If no version is specified, the `main` branch of the [UCP repo](https://github.com/Universal-Commerce-Protocol/ucp) will be used. -The latest version of the [UCP repo](https://github.com/Universal-Commerce-Protocol/ucp) is automatically downloaded and used to generate the models. The generated code is automatically formatted using `ruff`. +The generated code is automatically formatted using `ruff`. ## Contributing From 926077a2e17bbb9de294a2f4e86dac2586229a49 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 15:35:16 +0100 Subject: [PATCH 15/22] re-run of generate_models.sh Change-Id: Id33ccc029b86af2486c82dc85d8bb12b3c55c680 --- src/ucp_sdk/models/__init__.py | 1 + src/ucp_sdk/models/discovery/__init__.py | 1 + src/ucp_sdk/models/handlers/__init__.py | 1 + src/ucp_sdk/models/handlers/tokenization/__init__.py | 1 + src/ucp_sdk/models/schemas/__init__.py | 1 + src/ucp_sdk/models/schemas/shopping/__init__.py | 1 + src/ucp_sdk/models/schemas/shopping/types/__init__.py | 1 + src/ucp_sdk/models/services/__init__.py | 1 + src/ucp_sdk/models/services/shopping/__init__.py | 1 + 9 files changed, 9 insertions(+) diff --git a/src/ucp_sdk/models/__init__.py b/src/ucp_sdk/models/__init__.py index 1252d6b..421dc21 100644 --- a/src/ucp_sdk/models/__init__.py +++ b/src/ucp_sdk/models/__init__.py @@ -15,3 +15,4 @@ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable + diff --git a/src/ucp_sdk/models/discovery/__init__.py b/src/ucp_sdk/models/discovery/__init__.py index 1252d6b..421dc21 100644 --- a/src/ucp_sdk/models/discovery/__init__.py +++ b/src/ucp_sdk/models/discovery/__init__.py @@ -15,3 +15,4 @@ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable + diff --git a/src/ucp_sdk/models/handlers/__init__.py b/src/ucp_sdk/models/handlers/__init__.py index 1252d6b..421dc21 100644 --- a/src/ucp_sdk/models/handlers/__init__.py +++ b/src/ucp_sdk/models/handlers/__init__.py @@ -15,3 +15,4 @@ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable + diff --git a/src/ucp_sdk/models/handlers/tokenization/__init__.py b/src/ucp_sdk/models/handlers/tokenization/__init__.py index 1252d6b..421dc21 100644 --- a/src/ucp_sdk/models/handlers/tokenization/__init__.py +++ b/src/ucp_sdk/models/handlers/tokenization/__init__.py @@ -15,3 +15,4 @@ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable + diff --git a/src/ucp_sdk/models/schemas/__init__.py b/src/ucp_sdk/models/schemas/__init__.py index 1252d6b..421dc21 100644 --- a/src/ucp_sdk/models/schemas/__init__.py +++ b/src/ucp_sdk/models/schemas/__init__.py @@ -15,3 +15,4 @@ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable + diff --git a/src/ucp_sdk/models/schemas/shopping/__init__.py b/src/ucp_sdk/models/schemas/shopping/__init__.py index 1252d6b..421dc21 100644 --- a/src/ucp_sdk/models/schemas/shopping/__init__.py +++ b/src/ucp_sdk/models/schemas/shopping/__init__.py @@ -15,3 +15,4 @@ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable + diff --git a/src/ucp_sdk/models/schemas/shopping/types/__init__.py b/src/ucp_sdk/models/schemas/shopping/types/__init__.py index 1252d6b..421dc21 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/__init__.py +++ b/src/ucp_sdk/models/schemas/shopping/types/__init__.py @@ -15,3 +15,4 @@ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable + diff --git a/src/ucp_sdk/models/services/__init__.py b/src/ucp_sdk/models/services/__init__.py index 1252d6b..421dc21 100644 --- a/src/ucp_sdk/models/services/__init__.py +++ b/src/ucp_sdk/models/services/__init__.py @@ -15,3 +15,4 @@ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable + diff --git a/src/ucp_sdk/models/services/shopping/__init__.py b/src/ucp_sdk/models/services/shopping/__init__.py index 1252d6b..421dc21 100644 --- a/src/ucp_sdk/models/services/shopping/__init__.py +++ b/src/ucp_sdk/models/services/shopping/__init__.py @@ -15,3 +15,4 @@ # generated by datamodel-codegen # pylint: disable=all # pyformat: disable + From 8818a261f9b24ba8626efd5052a2da5f172a0179 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 15:49:00 +0100 Subject: [PATCH 16/22] move ruff config Change-Id: Ia518ec52de6906da7262f7a76704a676a6318c40 --- pyproject.toml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 632ab81..84e809d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,21 +25,6 @@ build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/ucp_sdk"] -[tool.ruff] -line-length = 80 -target-version = "py311" - -[tool.ruff.lint] -select = ["E", "F", "I"] -ignore = ["E501"] - -[tool.ruff.lint.pydocstyle] -convention = "google" - -[tool.ruff.lint.per-file-ignores] -"__init__.py" = ["D104"] -"*.py" = ["D100", "D101", "D102", "D103", "D200", "D205", "D212"] - [tool.datamodel-codegen] custom-file-header = """ # Copyright 2026 UCP Authors @@ -60,3 +45,18 @@ custom-file-header = """ # pylint: disable=all # pyformat: disable """ + +[tool.ruff] +line-length = 80 +target-version = "py311" + +[tool.ruff.lint] +select = ["E", "F", "I"] +ignore = ["E501"] + +[tool.ruff.lint.pydocstyle] +convention = "google" + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["D104"] +"*.py" = ["D100", "D101", "D102", "D103", "D200", "D205", "D212"] \ No newline at end of file From c83b40e06798d23cffbc60f34ce81428bb088355 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 15:50:32 +0100 Subject: [PATCH 17/22] delete temp files Change-Id: I113bf00366152f552140a0f6410f738813c44007 --- ucp | 1 - uv.lock | 762 -------------------------------------------------------- 2 files changed, 763 deletions(-) delete mode 160000 ucp delete mode 100644 uv.lock diff --git a/ucp b/ucp deleted file mode 160000 index 2ee92ff..0000000 --- a/ucp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2ee92ffdee356e4480be05e7437d1038bec6c779 diff --git a/uv.lock b/uv.lock deleted file mode 100644 index ea43603..0000000 --- a/uv.lock +++ /dev/null @@ -1,762 +0,0 @@ -version = 1 -revision = 3 -requires-python = ">=3.10" - -[[package]] -name = "annotated-types" -version = "0.7.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/annotated-types/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/annotated-types/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53" }, -] - -[[package]] -name = "anyio" -version = "4.12.1" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, - { name = "idna" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/anyio/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/anyio/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c" }, -] - -[[package]] -name = "argcomplete" -version = "3.6.3" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/argcomplete/argcomplete-3.6.3.tar.gz", hash = "sha256:62e8ed4fd6a45864acc8235409461b72c9a28ee785a2011cc5eb78318786c89c" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/argcomplete/argcomplete-3.6.3-py3-none-any.whl", hash = "sha256:f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce" }, -] - -[[package]] -name = "black" -version = "26.1.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "click" }, - { name = "mypy-extensions" }, - { name = "packaging" }, - { name = "pathspec" }, - { name = "platformdirs" }, - { name = "pytokens" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0.tar.gz", hash = "sha256:d294ac3340eef9c9eb5d29288e96dc719ff269a88e27b396340459dd85da4c58" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ca699710dece84e3ebf6e92ee15f5b8f72870ef984bf944a57a777a48357c168" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e8e75dabb6eb83d064b0db46392b25cabb6e784ea624219736e8985a6b3675d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb07665d9a907a1a645ee41a0df8a25ffac8ad9c26cdb557b7b88eeeeec934e0" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:7ed300200918147c963c87700ccf9966dceaefbbb7277450a8d646fc5646bf24" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:c5b7713daea9bf943f79f8c3b46f361cc5229e0e604dcef6a8bb6d1c37d9df89" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3cee1487a9e4c640dc7467aaa543d6c0097c391dc8ac74eb313f2fbf9d7a7cb5" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d62d14ca31c92adf561ebb2e5f2741bf8dea28aef6deb400d49cca011d186c68" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb1dafbbaa3b1ee8b4550a84425aac8874e5f390200f5502cf3aee4a2acb2f14" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:101540cb2a77c680f4f80e628ae98bd2bd8812fb9d72ade4f8995c5ff019e82c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:6f3977a16e347f1b115662be07daa93137259c711e526402aa444d7a88fdc9d4" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6eeca41e70b5f5c84f2f913af857cf2ce17410847e1d54642e658e078da6544f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dd39eef053e58e60204f2cdf059e2442e2eb08f15989eefe259870f89614c8b6" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9459ad0d6cd483eacad4c6566b0f8e42af5e8b583cee917d90ffaa3778420a0a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a19915ec61f3a8746e8b10adbac4a577c6ba9851fa4a9e9fbfbcf319887a5791" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:643d27fb5facc167c0b1b59d0315f2674a6e950341aed0fc05cf307d22bf4954" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ba1d768fbfb6930fc93b0ecc32a43d8861ded16f47a40f14afa9bb04ab93d304" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2b807c240b64609cb0e80d2200a35b23c7df82259f80bef1b2c96eb422b4aac9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1de0f7d01cc894066a1153b738145b194414cc6eeaad8ef4397ac9abacf40f6b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:91a68ae46bf07868963671e4d05611b179c2313301bd756a89ad4e3b3db2325b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:be5e2fe860b9bd9edbf676d5b60a9282994c03fbbd40fe8f5e75d194f96064ca" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9dc8c71656a79ca49b8d3e2ce8103210c9481c57798b48deeb3a8bb02db5f115" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b22b3810451abe359a964cc88121d57f7bce482b53a066de0f1584988ca36e79" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53c62883b3f999f14e5d30b5a79bd437236658ad45b2f853906c7cbe79de00af" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:f016baaadc423dc960cdddf9acae679e71ee02c4c341f78f3179d7e4819c095f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:66912475200b67ef5a0ab665011964bf924745103f51977a78b4fb92a9fc1bf0" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/black/black-26.1.0-py3-none-any.whl", hash = "sha256:1054e8e47ebd686e078c0bb0eaf31e6ce69c966058d122f2c0c950311f9f3ede" }, -] - -[[package]] -name = "certifi" -version = "2026.2.25" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/certifi/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/certifi/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa" }, -] - -[[package]] -name = "click" -version = "8.3.1" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/click/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/click/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6" }, -] - -[[package]] -name = "colorama" -version = "0.4.6" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/colorama/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/colorama/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" }, -] - -[[package]] -name = "datamodel-code-generator" -version = "0.54.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "argcomplete" }, - { name = "black" }, - { name = "genson" }, - { name = "inflect" }, - { name = "isort" }, - { name = "jinja2" }, - { name = "packaging" }, - { name = "pydantic" }, - { name = "pyyaml" }, - { name = "tomli", marker = "python_full_version < '3.12'" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/datamodel-code-generator/datamodel_code_generator-0.54.0.tar.gz", hash = "sha256:2b183598d049e265146a8224c35d1bb96a80a641ea8ecd2a82e6a0e97b56da6b" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/datamodel-code-generator/datamodel_code_generator-0.54.0-py3-none-any.whl", hash = "sha256:3156df7a7e8fa5a7c9a6d50836e5ba5abe0532f6b71eee6d73a0c8e1fb5b7e47" }, -] - -[package.optional-dependencies] -http = [ - { name = "httpx" }, -] -ruff = [ - { name = "ruff" }, -] - -[[package]] -name = "dnspython" -version = "2.8.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/dnspython/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/dnspython/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af" }, -] - -[[package]] -name = "email-validator" -version = "2.3.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "dnspython" }, - { name = "idna" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/email-validator/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/email-validator/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4" }, -] - -[[package]] -name = "exceptiongroup" -version = "1.3.1" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/exceptiongroup/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/exceptiongroup/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598" }, -] - -[[package]] -name = "genson" -version = "1.3.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/genson/genson-1.3.0.tar.gz", hash = "sha256:e02db9ac2e3fd29e65b5286f7135762e2cd8a986537c075b06fc5f1517308e37" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/genson/genson-1.3.0-py3-none-any.whl", hash = "sha256:468feccd00274cc7e4c09e84b08704270ba8d95232aa280f65b986139cec67f7" }, -] - -[[package]] -name = "h11" -version = "0.16.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/h11/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/h11/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" }, -] - -[[package]] -name = "httpcore" -version = "1.0.9" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "certifi" }, - { name = "h11" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/httpcore/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/httpcore/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55" }, -] - -[[package]] -name = "httpx" -version = "0.28.1" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "anyio" }, - { name = "certifi" }, - { name = "httpcore" }, - { name = "idna" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/httpx/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/httpx/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad" }, -] - -[[package]] -name = "idna" -version = "3.11" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/idna/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/idna/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea" }, -] - -[[package]] -name = "inflect" -version = "7.5.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "more-itertools" }, - { name = "typeguard" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/inflect/inflect-7.5.0.tar.gz", hash = "sha256:faf19801c3742ed5a05a8ce388e0d8fe1a07f8d095c82201eb904f5d27ad571f" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/inflect/inflect-7.5.0-py3-none-any.whl", hash = "sha256:2aea70e5e70c35d8350b8097396ec155ffd68def678c7ff97f51aa69c1d92344" }, -] - -[[package]] -name = "isort" -version = "7.0.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/isort/isort-7.0.0.tar.gz", hash = "sha256:5513527951aadb3ac4292a41a16cbc50dd1642432f5e8c20057d414bdafb4187" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/isort/isort-7.0.0-py3-none-any.whl", hash = "sha256:1bcabac8bc3c36c7fb7b98a76c8abb18e0f841a3ba81decac7691008592499c1" }, -] - -[[package]] -name = "jinja2" -version = "3.1.6" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "markupsafe" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/jinja2/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/jinja2/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67" }, -] - -[[package]] -name = "markupsafe" -version = "3.0.3" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/markupsafe/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa" }, -] - -[[package]] -name = "more-itertools" -version = "10.8.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/more-itertools/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/more-itertools/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b" }, -] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/mypy-extensions/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/mypy-extensions/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505" }, -] - -[[package]] -name = "packaging" -version = "26.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/packaging/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/packaging/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529" }, -] - -[[package]] -name = "pathspec" -version = "1.0.4" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pathspec/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pathspec/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723" }, -] - -[[package]] -name = "platformdirs" -version = "4.9.2" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/platformdirs/platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/platformdirs/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd" }, -] - -[[package]] -name = "pydantic" -version = "2.12.5" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "annotated-types" }, - { name = "pydantic-core" }, - { name = "typing-extensions" }, - { name = "typing-inspection" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d" }, -] - -[[package]] -name = "pydantic-core" -version = "2.41.5" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pydantic-core/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51" }, -] - -[[package]] -name = "pytokens" -version = "0.4.1" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pytokens/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de" }, -] - -[[package]] -name = "pyyaml" -version = "6.0.3" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/pyyaml/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b" }, -] - -[[package]] -name = "ruff" -version = "0.15.4" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4.tar.gz", hash = "sha256:3412195319e42d634470cc97aa9803d07e9d5c9223b99bcb1518f0c725f26ae1" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-linux_armv6l.whl", hash = "sha256:a1810931c41606c686bae8b5b9a8072adac2f611bb433c0ba476acba17a332e0" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5a1632c66672b8b4d3e1d1782859e98d6e0b4e70829530666644286600a33992" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a4386ba2cd6c0f4ff75252845906acc7c7c8e1ac567b7bc3d373686ac8c222ba" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2496488bdfd3732747558b6f95ae427ff066d1fcd054daf75f5a50674411e75" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3f1c4893841ff2d54cbda1b2860fa3260173df5ddd7b95d370186f8a5e66a4ac" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:820b8766bd65503b6c30aaa6331e8ef3a6e564f7999c844e9a547c40179e440a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9fb74bab47139c1751f900f857fa503987253c3ef89129b24ed375e72873e85" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f80c98765949c518142b3a50a5db89343aa90f2c2bf7799de9986498ae6176db" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451a2e224151729b3b6c9ffb36aed9091b2996fe4bdbd11f47e27d8f2e8888ec" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a8f157f2e583c513c4f5f896163a93198297371f34c04220daf40d133fdd4f7f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:917cc68503357021f541e69b35361c99387cdbbf99bd0ea4aa6f28ca99ff5338" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e9737c8161da79fd7cfec19f1e35620375bd8b2a50c3e77fa3d2c16f574105cc" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:291258c917539e18f6ba40482fe31d6f5ac023994ee11d7bdafd716f2aab8a68" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3f83c45911da6f2cd5936c436cf86b9f09f09165f033a99dcf7477e34041cbc3" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-win32.whl", hash = "sha256:65594a2d557d4ee9f02834fcdf0a28daa8b3b9f6cb2cb93846025a36db47ef22" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-win_amd64.whl", hash = "sha256:04196ad44f0df220c2ece5b0e959c2f37c777375ec744397d21d15b50a75264f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/ruff/ruff-0.15.4-py3-none-win_arm64.whl", hash = "sha256:60d5177e8cfc70e51b9c5fad936c634872a74209f934c1e79107d11787ad5453" }, -] - -[[package]] -name = "tomli" -version = "2.4.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4" }, - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/tomli/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a" }, -] - -[[package]] -name = "typeguard" -version = "4.5.1" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typeguard/typeguard-4.5.1.tar.gz", hash = "sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typeguard/typeguard-4.5.1-py3-none-any.whl", hash = "sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40" }, -] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typing-extensions/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typing-extensions/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548" }, -] - -[[package]] -name = "typing-inspection" -version = "0.4.2" -source = { registry = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/simple/" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typing-inspection/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464" } -wheels = [ - { url = "https://us-python.pkg.dev/artifact-foundry-prod/ah-3p-staging-python/typing-inspection/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7" }, -] - -[[package]] -name = "ucp-sdk" -version = "2026.1.23" -source = { editable = "." } -dependencies = [ - { name = "email-validator" }, - { name = "pydantic" }, -] - -[package.dev-dependencies] -dev = [ - { name = "datamodel-code-generator", extra = ["http", "ruff"] }, -] - -[package.metadata] -requires-dist = [ - { name = "email-validator", specifier = ">=2.0.0" }, - { name = "pydantic", specifier = ">=2.5.0" }, -] - -[package.metadata.requires-dev] -dev = [{ name = "datamodel-code-generator", extras = ["http", "ruff"], specifier = ">=0.50.0" }] From 9e47cf119df1b695a830e3936304f6d86df8b18b Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 15:56:28 +0100 Subject: [PATCH 18/22] add LICENSE reference Change-Id: I8413a4ad2e3886df6684ff7f654faa2ed2a95043 --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 84e809d..f793a11 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,6 +3,7 @@ name = "ucp-sdk" version = "2026.01.23" description = "UCP Python SDK" readme = "README.md" +license-files = ["LICENSE"] authors = [ { name = "Florin Iucha", email = "fiucha@google.com" }, { name = "Federico D'Amato", email = "damaz@google.com" }, From 74aa3bc5c3b91f082e6e066052dc555ed37b3ce1 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 16:22:53 +0100 Subject: [PATCH 19/22] add preprocessing to handle request type class generation Change-Id: I63be54dcfc253861c05a9143483fd73a98f2c232 --- generate_models.sh | 5 +- preprocess_schemas.py | 180 ++++++ pyproject.toml | 22 +- .../models/discovery/profile_schema.py | 102 ++- .../models/handlers/tokenization/openapi.py | 2 +- src/ucp_sdk/models/schemas/_internal.py | 598 +++++++++--------- src/ucp_sdk/models/schemas/capability.py | 20 +- src/ucp_sdk/models/schemas/payment_handler.py | 10 +- src/ucp_sdk/models/schemas/service.py | 124 ++-- .../models/schemas/shopping/ap2_mandate.py | 121 ++-- .../models/schemas/shopping/buyer_consent.py | 67 +- .../models/schemas/shopping/checkout.py | 75 ++- .../shopping/complete_checkout_request.py | 33 + .../shopping/create_checkout_request.py | 45 ++ .../models/schemas/shopping/discount.py | 100 ++- .../schemas/shopping/fulfillment/__init__.py | 41 +- .../shopping/fulfillment/dev/ucp/shopping.py | 2 +- src/ucp_sdk/models/schemas/shopping/order.py | 85 ++- .../models/schemas/shopping/payment.py | 17 +- .../schemas/shopping/types/account_info.py | 15 +- .../schemas/shopping/types/adjustment.py | 53 +- .../models/schemas/shopping/types/binding.py | 19 +- .../types/business_fulfillment_config.py | 46 +- .../models/schemas/shopping/types/buyer.py | 22 +- .../schemas/shopping/types/card_credential.py | 47 +- .../shopping/types/card_payment_instrument.py | 54 +- .../models/schemas/shopping/types/context.py | 23 +- .../types/create_fulfillment_group_request.py | 34 + .../create_fulfillment_method_request.py | 58 ++ .../types/create_line_item_request.py | 37 ++ .../schemas/shopping/types/expectation.py | 49 +- .../schemas/shopping/types/fulfillment.py | 23 +- .../types/fulfillment_available_method.py | 27 +- .../shopping/types/fulfillment_destination.py | 16 +- .../shopping/types/fulfillment_event.py | 57 +- .../shopping/types/fulfillment_group.py | 27 +- .../shopping/types/fulfillment_method.py | 41 +- .../shopping/types/fulfillment_option.py | 39 +- .../models/schemas/shopping/types/item.py | 22 +- .../schemas/shopping/types/line_item.py | 27 +- .../models/schemas/shopping/types/link.py | 18 +- .../types/merchant_fulfillment_config.py | 46 +- .../models/schemas/shopping/types/message.py | 22 +- .../schemas/shopping/types/message_error.py | 34 +- .../schemas/shopping/types/message_info.py | 26 +- .../schemas/shopping/types/message_warning.py | 26 +- .../shopping/types/order_confirmation.py | 19 +- .../schemas/shopping/types/order_line_item.py | 49 +- .../shopping/types/payment_credential.py | 15 +- .../shopping/types/payment_identity.py | 15 +- .../shopping/types/payment_instrument.py | 48 +- .../types/platform_fulfillment_config.py | 15 +- .../schemas/shopping/types/postal_address.py | 42 +- .../schemas/shopping/types/retail_location.py | 23 +- .../shopping/types/shipping_destination.py | 15 +- .../shopping/types/token_credential.py | 19 +- .../models/schemas/shopping/types/total.py | 34 +- .../types/update_fulfillment_group_request.py | 38 ++ .../update_fulfillment_method_request.py | 56 ++ .../types/update_line_item_request.py | 42 ++ .../shopping/update_checkout_request.py | 49 ++ .../schemas/transports/embedded_config.py | 15 +- src/ucp_sdk/models/schemas/ucp.py | 32 +- .../models/services/shopping/embedded.py | 4 +- .../models/services/shopping/openapi.py | 2 +- .../models/services/shopping/openrpc.py | 2 +- 66 files changed, 1795 insertions(+), 1296 deletions(-) create mode 100644 preprocess_schemas.py create mode 100644 src/ucp_sdk/models/schemas/shopping/complete_checkout_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/create_checkout_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_group_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_method_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/create_line_item_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_group_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_method_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/update_line_item_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/update_checkout_request.py diff --git a/generate_models.sh b/generate_models.sh index a0f78b7..273030a 100755 --- a/generate_models.sh +++ b/generate_models.sh @@ -4,6 +4,9 @@ # Ensure we are in the script's directory cd "$(dirname "$0")" || exit +# Add ~/.local/bin to PATH for uv +export PATH="$HOME/.local/bin:$PATH" + # Check if git is installed if ! command -v git &> /dev/null; then echo "Error: git not found. Please install git." @@ -30,7 +33,7 @@ OUTPUT_DIR="src/ucp_sdk/models" SCHEMA_DIR="ucp/source" echo "Preprocessing schemas..." -# uv run python preprocess_schemas.py +uv run python preprocess_schemas.py echo "Generating Pydantic models from preprocessed schemas..." diff --git a/preprocess_schemas.py b/preprocess_schemas.py new file mode 100644 index 0000000..60053e9 --- /dev/null +++ b/preprocess_schemas.py @@ -0,0 +1,180 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import copy +from pathlib import Path +import sys + + +def process_file(schema_file, all_variant_needs): + """Analyzes a schema file to see which request variants it needs.""" + try: + with open(schema_file, "r") as f: + schema = json.load(f) + except Exception as e: + print(f"Error loading {schema_file}: {e}") + return None + + if ( + not isinstance(schema, dict) + or schema.get("type") != "object" + or "properties" not in schema + ): + return None + + ops_found = set() + for prop_name, prop_data in schema.get("properties", {}).items(): + if not isinstance(prop_data, dict): + continue + ucp_req = prop_data.get("ucp_request") + if isinstance(ucp_req, str): + if ucp_req != "omit": + ops_found.update(["create", "update", "complete"]) + elif isinstance(ucp_req, dict): + for op in ucp_req: + ops_found.add(op) + + if ops_found: + all_variant_needs[str(schema_file.resolve())] = ops_found + return schema + + +def get_variant_filename(base_path, op): + p = Path(base_path) + return p.parent / f"{op}_{p.stem}_request.json" + + +def generate_variants(schema_file, schema, ops, all_variant_needs): + schema_file_path = Path(schema_file) + for op in ops: + variant_schema = copy.deepcopy(schema) + + # Update title and id + base_title = schema.get("title", schema_file_path.stem) + variant_schema["title"] = f"{op.capitalize()} {base_title} Request" + + # Update $id if present + if "$id" in variant_schema: + old_id = variant_schema["$id"] + if "/" in old_id: + old_id_parts = old_id.split("/") + old_id_filename = old_id_parts[-1] + if "." in old_id_filename: + stem = old_id_filename.split(".")[0] + ext = old_id_filename.split(".")[-1] + new_id_filename = f"{op}_{stem}_request.{ext}" + variant_schema["$id"] = "/".join( + old_id_parts[:-1] + [new_id_filename] + ) + + new_properties = {} + new_required = [] + + for prop_name, prop_data in schema.get("properties", {}).items(): + if not isinstance(prop_data, dict): + new_properties[prop_name] = prop_data + continue + + ucp_req = prop_data.get("ucp_request") + + include = True + is_required = False + + if ucp_req is not None: + if isinstance(ucp_req, str): + if ucp_req == "omit": + include = False + elif ucp_req == "required": + is_required = True + elif isinstance(ucp_req, dict): + op_val = ucp_req.get(op) + if op_val == "omit" or op_val is None: + include = False + elif op_val == "required": + is_required = True + else: + # No ucp_request. Include if it was required in base? + if prop_name in schema.get("required", []): + is_required = True + + if include: + prop_copy = copy.deepcopy(prop_data) + if "ucp_request" in prop_copy: + del prop_copy["ucp_request"] + + # Recursive reference check (deep) + def update_refs(obj): + if isinstance(obj, dict): + if "$ref" in obj: + ref = obj["$ref"] + if "#" not in ref: + ref_path = Path(ref) + target_base_abs = (schema_file_path.parent / ref_path).resolve() + if ( + str(target_base_abs) in all_variant_needs + and op in all_variant_needs[str(target_base_abs)] + ): + variant_ref_filename = f"{op}_{ref_path.stem}_request.json" + obj["$ref"] = str(ref_path.parent / variant_ref_filename) + for k, v in obj.items(): + update_refs(v) + elif isinstance(obj, list): + for item in obj: + update_refs(item) + + update_refs(prop_copy) + + new_properties[prop_name] = prop_copy + if is_required: + new_required.append(prop_name) + + if new_properties: + variant_schema["properties"] = new_properties + variant_schema["required"] = new_required + + variant_path = get_variant_filename(schema_file_path, op) + with open(variant_path, "w") as f: + json.dump(variant_schema, f, indent=2) + print(f"Generated {variant_path}") + + +def main(): + schema_dir = "ucp/source" + if len(sys.argv) > 1: + schema_dir = sys.argv[1] + + schema_dir_path = Path(schema_dir) + if not schema_dir_path.exists(): + print(f"Directory {schema_dir} does not exist.") + return + + all_files = list(schema_dir_path.rglob("*.json")) + + all_variant_needs = {} + schemas_cache = {} + + for f in all_files: + if "_request.json" in f.name: + continue + s = process_file(f, all_variant_needs) + if s: + schemas_cache[str(f.resolve())] = s + + for f_abs, ops in all_variant_needs.items(): + generate_variants(f_abs, schemas_cache[f_abs], ops, all_variant_needs) + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml index f793a11..b6f679c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,15 +49,19 @@ custom-file-header = """ [tool.ruff] line-length = 80 -target-version = "py311" +indent-width = 2 -[tool.ruff.lint] -select = ["E", "F", "I"] -ignore = ["E501"] +[tool.ruff.format] +quote-style = "double" +indent-style = "space" +skip-magic-trailing-comma = false +line-ending = "auto" +docstring-code-format = true -[tool.ruff.lint.pydocstyle] -convention = "google" +[tool.ruff.lint] +select = ["E", "F", "W", "B", "C4", "SIM", "N", "UP", "D", "PTH", "T20"] -[tool.ruff.lint.per-file-ignores] -"__init__.py" = ["D104"] -"*.py" = ["D100", "D101", "D102", "D103", "D200", "D205", "D212"] \ No newline at end of file +[tool.ruff.lint.isort] +combine-as-imports = true +force-sort-within-sections = true +case-sensitive = true \ No newline at end of file diff --git a/src/ucp_sdk/models/discovery/profile_schema.py b/src/ucp_sdk/models/discovery/profile_schema.py index 5d3c08f..f9b18c3 100644 --- a/src/ucp_sdk/models/discovery/profile_schema.py +++ b/src/ucp_sdk/models/discovery/profile_schema.py @@ -26,92 +26,88 @@ class SigningKey(BaseModel): - """ - Public key for signature verification in JWK format. - """ - - model_config = ConfigDict( - extra="allow", - ) - kid: str - """ + """Public key for signature verification in JWK format. + """ + + model_config = ConfigDict( + extra="allow", + ) + kid: str + """ Key ID. Referenced in signature headers to identify which key to use for verification. """ - kty: str - """ + kty: str + """ Key type (e.g., 'EC', 'RSA'). """ - crv: str | None = None - """ + crv: str | None = None + """ Curve name for EC keys (e.g., 'P-256'). """ - x: str | None = None - """ + x: str | None = None + """ X coordinate for EC public keys (base64url encoded). """ - y: str | None = None - """ + y: str | None = None + """ Y coordinate for EC public keys (base64url encoded). """ - n: str | None = None - """ + n: str | None = None + """ Modulus for RSA public keys (base64url encoded). """ - e: str | None = None - """ + e: str | None = None + """ Exponent for RSA public keys (base64url encoded). """ - use: Literal["sig", "enc"] | None = None - """ + use: Literal["sig", "enc"] | None = None + """ Key usage. Should be 'sig' for signing keys. """ - alg: str | None = None - """ + alg: str | None = None + """ Algorithm (e.g., 'ES256', 'RS256'). """ class Base(BaseModel): - """ - Base discovery profile with shared properties for all profile types. - """ - - model_config = ConfigDict( - extra="allow", - ) - ucp: Base_3 - signing_keys: list[SigningKey] | None = None - """ + """Base discovery profile with shared properties for all profile types. + """ + + model_config = ConfigDict( + extra="allow", + ) + ucp: Base_3 + signing_keys: list[SigningKey] | None = None + """ Public keys for signature verification (JWK format). Used to verify signed responses, webhooks, and other authenticated messages from this party. """ class PlatformProfile(Base): - """ - Full discovery profile for platforms. Exposes complete service, capability, and payment handler registries. - """ + """Full discovery profile for platforms. Exposes complete service, capability, and payment handler registries. + """ - model_config = ConfigDict( - extra="allow", - ) - ucp: PlatformSchema_3 | None = None + model_config = ConfigDict( + extra="allow", + ) + ucp: PlatformSchema_3 | None = None class BusinessProfile(Base): - """ - Discovery profile for businesses/merchants. Subset of platform profile with business-specific configuration. - """ + """Discovery profile for businesses/merchants. Subset of platform profile with business-specific configuration. + """ - model_config = ConfigDict( - extra="allow", - ) - ucp: BusinessSchema_3 | None = None + model_config = ConfigDict( + extra="allow", + ) + ucp: BusinessSchema_3 | None = None class UcpDiscoveryProfile(RootModel[PlatformProfile | BusinessProfile]): - root: PlatformProfile | BusinessProfile = Field( - ..., title="UCP Discovery Profile" - ) - """ + root: PlatformProfile | BusinessProfile = Field( + ..., title="UCP Discovery Profile" + ) + """ Schema for UCP discovery profiles. Business profiles are hosted at /.well-known/ucp; platform profiles are hosted at URIs advertised in request headers. """ diff --git a/src/ucp_sdk/models/handlers/tokenization/openapi.py b/src/ucp_sdk/models/handlers/tokenization/openapi.py index 66b2502..0f53946 100644 --- a/src/ucp_sdk/models/handlers/tokenization/openapi.py +++ b/src/ucp_sdk/models/handlers/tokenization/openapi.py @@ -24,4 +24,4 @@ class Model(RootModel[Any]): - root: Any + root: Any diff --git a/src/ucp_sdk/models/schemas/_internal.py b/src/ucp_sdk/models/schemas/_internal.py index 47ec9ef..e8a126b 100644 --- a/src/ucp_sdk/models/schemas/_internal.py +++ b/src/ucp_sdk/models/schemas/_internal.py @@ -26,554 +26,524 @@ class UcpCapability(RootModel[Any]): - root: Any = Field(..., title="UCP Capability") - """ + root: Any = Field(..., title="UCP Capability") + """ Schema for UCP capabilities and extensions. Extensions are capabilities with an 'extends' field. Uses reverse-domain naming for governance. """ class Base(Entity): - model_config = ConfigDict( - extra="allow", - ) - extends: str | None = Field( - None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$" - ) - """ + model_config = ConfigDict( + extra="allow", + ) + extends: str | None = Field( + None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$" + ) + """ Parent capability this extends. Present for extensions, absent for root capabilities. """ class PlatformSchema(Base): - """ - Full capability declaration for platform-level discovery. Includes spec/schema URLs for agent fetching. - """ + """Full capability declaration for platform-level discovery. Includes spec/schema URLs for agent fetching. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class BusinessSchema(Base): - """ - Capability configuration for business/merchant level. May include business-specific config overrides. - """ + """Capability configuration for business/merchant level. May include business-specific config overrides. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class ResponseSchema(Base): - """ - Capability reference in responses. Only name/version required to confirm active capabilities. - """ + """Capability reference in responses. Only name/version required to confirm active capabilities. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class PaymentHandler(RootModel[Any]): - root: Any = Field(..., title="Payment Handler") - """ + root: Any = Field(..., title="Payment Handler") + """ Schema for UCP payment handlers. Handlers define how payment instruments are processed. """ class Base_1(Entity): - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class PlatformSchema_1(Base_1): - """ - Platform declaration for discovery profiles. May include partial config state required for discovery. - """ + """Platform declaration for discovery profiles. May include partial config state required for discovery. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class BusinessSchema_1(Base_1): - """ - Business declaration for discovery profiles. May include partial config state required for discovery. - """ + """Business declaration for discovery profiles. May include partial config state required for discovery. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class ResponseSchema_1(Base_1): - """ - Handler reference in responses. May include full config state for runtime usage of the handler. - """ + """Handler reference in responses. May include full config state for runtime usage of the handler. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class UcpService(RootModel[Any]): - root: Any = Field(..., title="UCP Service") - """ + root: Any = Field(..., title="UCP Service") + """ Service binding for a specific transport. Each transport binding is a separate entry in the service array. """ class PlatformSchema_2(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["rest"] = "rest" + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" class PlatformSchema5(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["mcp"] = "mcp" + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" class PlatformSchema6(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["a2a"] = "a2a" + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" class PlatformSchema7(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["embedded"] = "embedded" + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" class BusinessSchema_2(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["rest"] = "rest" + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" class BusinessSchema4(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["mcp"] = "mcp" + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" class BusinessSchema5(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["a2a"] = "a2a" + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" class BusinessSchema6(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["embedded"] = "embedded" - config: embedded_config.EmbeddedTransportConfig | None = None + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + config: embedded_config.EmbeddedTransportConfig | None = None class ResponseSchema_2(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["rest"] = "rest" + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest"] = "rest" class ResponseSchema4(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["mcp"] = "mcp" + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["mcp"] = "mcp" class ResponseSchema5(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["a2a"] = "a2a" + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["a2a"] = "a2a" class ResponseSchema6(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["embedded"] = "embedded" - config: embedded_config.EmbeddedTransportConfig | None = None + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["embedded"] = "embedded" + config: embedded_config.EmbeddedTransportConfig | None = None class Base_2(Entity): - model_config = ConfigDict( - extra="allow", - ) - transport: Literal["rest", "mcp", "a2a", "embedded"] - """ + model_config = ConfigDict( + extra="allow", + ) + transport: Literal["rest", "mcp", "a2a", "embedded"] + """ Transport protocol for this service binding. """ - endpoint: AnyUrl | None = None - """ + endpoint: AnyUrl | None = None + """ Endpoint URL for this transport binding. """ class PlatformSchema8(Base_2): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ + """Full service declaration for platform-level discovery. Different transports require different fields. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class PlatformSchema9(PlatformSchema_2, PlatformSchema8): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ + """Full service declaration for platform-level discovery. Different transports require different fields. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class PlatformSchema10(PlatformSchema5, PlatformSchema8): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ + """Full service declaration for platform-level discovery. Different transports require different fields. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class PlatformSchema11(PlatformSchema6, PlatformSchema8): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ + """Full service declaration for platform-level discovery. Different transports require different fields. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class PlatformSchema12(PlatformSchema7, PlatformSchema8): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ + """Full service declaration for platform-level discovery. Different transports require different fields. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class PlatformSchema3( - RootModel[ - PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 - ] + RootModel[ + PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 + ] ): - """ - Full service declaration for platform-level discovery. Different transports require different fields. - """ + """Full service declaration for platform-level discovery. Different transports require different fields. + """ - root: ( - PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 - ) = Field(..., title="Service (Platform Schema)") - """ + root: ( + PlatformSchema9 | PlatformSchema10 | PlatformSchema11 | PlatformSchema12 + ) = Field(..., title="Service (Platform Schema)") + """ Full service declaration for platform-level discovery. Different transports require different fields. """ class BusinessSchema7(Base_2): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ + """Service binding for business/merchant configuration. May override platform endpoints. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class BusinessSchema8(BusinessSchema_2, BusinessSchema7): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ + """Service binding for business/merchant configuration. May override platform endpoints. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class BusinessSchema9(BusinessSchema4, BusinessSchema7): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ + """Service binding for business/merchant configuration. May override platform endpoints. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class BusinessSchema10(BusinessSchema5, BusinessSchema7): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ + """Service binding for business/merchant configuration. May override platform endpoints. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class BusinessSchema11(BusinessSchema6, BusinessSchema7): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ + """Service binding for business/merchant configuration. May override platform endpoints. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class BusinessSchema2( - RootModel[ - BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 - ] + RootModel[ + BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 + ] ): - """ - Service binding for business/merchant configuration. May override platform endpoints. - """ + """Service binding for business/merchant configuration. May override platform endpoints. + """ - root: ( - BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 - ) = Field(..., title="Service (Business Schema)") - """ + root: ( + BusinessSchema8 | BusinessSchema9 | BusinessSchema10 | BusinessSchema11 + ) = Field(..., title="Service (Business Schema)") + """ Service binding for business/merchant configuration. May override platform endpoints. """ class ResponseSchema7(Base_2): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ + """Service binding in API responses. Includes per-resource transport configuration via typed config. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class ResponseSchema8(ResponseSchema_2, ResponseSchema7): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ + """Service binding in API responses. Includes per-resource transport configuration via typed config. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class ResponseSchema9(ResponseSchema4, ResponseSchema7): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ + """Service binding in API responses. Includes per-resource transport configuration via typed config. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class ResponseSchema10(ResponseSchema5, ResponseSchema7): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ + """Service binding in API responses. Includes per-resource transport configuration via typed config. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class ResponseSchema11(ResponseSchema6, ResponseSchema7): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ + """Service binding in API responses. Includes per-resource transport configuration via typed config. + """ - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class ResponseSchema2( - RootModel[ - ResponseSchema8 | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 - ] + RootModel[ + ResponseSchema8 | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 + ] ): - """ - Service binding in API responses. Includes per-resource transport configuration via typed config. - """ + """Service binding in API responses. Includes per-resource transport configuration via typed config. + """ - root: ( - ResponseSchema8 | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 - ) = Field(..., title="Service (Response Schema)") - """ + root: ( + ResponseSchema8 | ResponseSchema9 | ResponseSchema10 | ResponseSchema11 + ) = Field(..., title="Service (Response Schema)") + """ Service binding in API responses. Includes per-resource transport configuration via typed config. """ class UcpMetadata(RootModel[Any]): - root: Any = Field(..., title="UCP Metadata") - """ + root: Any = Field(..., title="UCP Metadata") + """ Protocol metadata for discovery profiles and responses. Uses slim schema pattern with context-specific required fields. """ class Version(RootModel[str]): - root: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") - """ + root: str = Field(..., pattern="^\\d{4}-\\d{2}-\\d{2}$") + """ UCP version in YYYY-MM-DD format. """ class ReverseDomainName(RootModel[str]): - root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$") - """ + root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$") + """ Reverse-domain identifier (e.g., com.google.pay, dev.ucp.shopping.checkout) """ class Entity(BaseModel): - """ - Shared foundation for all UCP entities. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: Version - """ + """Shared foundation for all UCP entities. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: Version + """ Entity version in YYYY-MM-DD format. """ - spec: AnyUrl | None = None - """ + spec: AnyUrl | None = None + """ URL to human-readable specification document. """ - schema_: AnyUrl | None = Field(None, alias="schema") - """ + schema_: AnyUrl | None = Field(None, alias="schema") + """ URL to JSON Schema defining this entity's structure and payloads. """ - id: str | None = None - """ + id: str | None = None + """ Unique identifier for this entity instance. Used to disambiguate when multiple instances exist. """ - config: dict[str, Any] | None = None - """ + config: dict[str, Any] | None = None + """ Entity-specific configuration. Structure defined by each entity's schema. """ class Base_3(BaseModel): - """ - Base UCP metadata with shared properties for all schema types. - """ - - model_config = ConfigDict( - extra="allow", - ) - version: Version - services: dict[ReverseDomainName, list[Base_2]] | None = None - """ + """Base UCP metadata with shared properties for all schema types. + """ + + model_config = ConfigDict( + extra="allow", + ) + version: Version + services: dict[ReverseDomainName, list[Base_2]] | None = None + """ Service registry keyed by reverse-domain name. """ - capabilities: dict[ReverseDomainName, list[Base]] | None = None - """ + capabilities: dict[ReverseDomainName, list[Base]] | None = None + """ Capability registry keyed by reverse-domain name. """ - payment_handlers: dict[ReverseDomainName, list[Base_1]] | None = None - """ + payment_handlers: dict[ReverseDomainName, list[Base_1]] | None = None + """ Payment handler registry keyed by reverse-domain name. """ class PlatformSchema_3(Base_3): - """ - Full UCP metadata for platform-level configuration. Hosted at a URI advertised by the platform in request headers. - """ - - model_config = ConfigDict( - extra="allow", - ) - services: dict[ReverseDomainName, list[PlatformSchema3]] - """ + """Full UCP metadata for platform-level configuration. Hosted at a URI advertised by the platform in request headers. + """ + + model_config = ConfigDict( + extra="allow", + ) + services: dict[ReverseDomainName, list[PlatformSchema3]] + """ Service registry keyed by reverse-domain name. """ - capabilities: dict[ReverseDomainName, list[PlatformSchema]] | None = None - """ + capabilities: dict[ReverseDomainName, list[PlatformSchema]] | None = None + """ Capability registry keyed by reverse-domain name. """ - payment_handlers: dict[ReverseDomainName, list[PlatformSchema_1]] - """ + payment_handlers: dict[ReverseDomainName, list[PlatformSchema_1]] + """ Payment handler registry keyed by reverse-domain name. """ class BusinessSchema_3(Base_3): - """ - UCP metadata for business/merchant-level configuration. Subset of platform schema with business-specific settings. - """ - - model_config = ConfigDict( - extra="allow", - ) - services: dict[ReverseDomainName, list[BusinessSchema2]] - """ + """UCP metadata for business/merchant-level configuration. Subset of platform schema with business-specific settings. + """ + + model_config = ConfigDict( + extra="allow", + ) + services: dict[ReverseDomainName, list[BusinessSchema2]] + """ Service registry keyed by reverse-domain name. """ - capabilities: dict[ReverseDomainName, list[BusinessSchema]] | None = None - """ + capabilities: dict[ReverseDomainName, list[BusinessSchema]] | None = None + """ Capability registry keyed by reverse-domain name. """ - payment_handlers: dict[ReverseDomainName, list[BusinessSchema_1]] - """ + payment_handlers: dict[ReverseDomainName, list[BusinessSchema_1]] + """ Payment handler registry keyed by reverse-domain name. """ class ResponseCheckoutSchema(Base_3): - """ - UCP metadata for checkout responses. - """ - - model_config = ConfigDict( - extra="allow", - ) - services: dict[ReverseDomainName, list[ResponseSchema2]] | None = None - """ + """UCP metadata for checkout responses. + """ + + model_config = ConfigDict( + extra="allow", + ) + services: dict[ReverseDomainName, list[ResponseSchema2]] | None = None + """ Service registry keyed by reverse-domain name. """ - capabilities: dict[ReverseDomainName, list[ResponseSchema]] | None = None - """ + capabilities: dict[ReverseDomainName, list[ResponseSchema]] | None = None + """ Capability registry keyed by reverse-domain name. """ - payment_handlers: dict[ReverseDomainName, list[ResponseSchema_1]] - """ + payment_handlers: dict[ReverseDomainName, list[ResponseSchema_1]] + """ Payment handler registry keyed by reverse-domain name. """ class ResponseOrderSchema(Base_3): - """ - UCP metadata for order responses. No payment handlers needed post-purchase. - """ - - model_config = ConfigDict( - extra="allow", - ) - capabilities: dict[ReverseDomainName, list[ResponseSchema]] | None = None - """ + """UCP metadata for order responses. No payment handlers needed post-purchase. + """ + + model_config = ConfigDict( + extra="allow", + ) + capabilities: dict[ReverseDomainName, list[ResponseSchema]] | None = None + """ Capability registry keyed by reverse-domain name. """ diff --git a/src/ucp_sdk/models/schemas/capability.py b/src/ucp_sdk/models/schemas/capability.py index 9ba07e7..1dc558f 100644 --- a/src/ucp_sdk/models/schemas/capability.py +++ b/src/ucp_sdk/models/schemas/capability.py @@ -19,17 +19,17 @@ from __future__ import annotations from ._internal import ( - Base, - BusinessSchema, - PlatformSchema, - ResponseSchema, - UcpCapability, + Base, + BusinessSchema, + PlatformSchema, + ResponseSchema, + UcpCapability, ) __all__ = [ - "Base", - "BusinessSchema", - "PlatformSchema", - "ResponseSchema", - "UcpCapability", + "Base", + "BusinessSchema", + "PlatformSchema", + "ResponseSchema", + "UcpCapability", ] diff --git a/src/ucp_sdk/models/schemas/payment_handler.py b/src/ucp_sdk/models/schemas/payment_handler.py index 1342388..2f4ed2b 100644 --- a/src/ucp_sdk/models/schemas/payment_handler.py +++ b/src/ucp_sdk/models/schemas/payment_handler.py @@ -25,9 +25,9 @@ from ._internal import ResponseSchema_1 as ResponseSchema __all__ = [ - "Base", - "BusinessSchema", - "PaymentHandler", - "PlatformSchema", - "ResponseSchema", + "Base", + "BusinessSchema", + "PaymentHandler", + "PlatformSchema", + "ResponseSchema", ] diff --git a/src/ucp_sdk/models/schemas/service.py b/src/ucp_sdk/models/schemas/service.py index cd55f8b..e1c5eb3 100644 --- a/src/ucp_sdk/models/schemas/service.py +++ b/src/ucp_sdk/models/schemas/service.py @@ -20,70 +20,74 @@ from ._internal import Base_2 as Base from ._internal import ( - BusinessSchema2, - BusinessSchema4, - BusinessSchema5, - BusinessSchema6, - BusinessSchema7, - BusinessSchema8, - BusinessSchema9, - BusinessSchema10, - BusinessSchema11, - PlatformSchema3, - PlatformSchema5, - PlatformSchema6, - PlatformSchema7, - PlatformSchema8, - PlatformSchema9, - PlatformSchema10, - PlatformSchema11, - PlatformSchema12, - ResponseSchema2, - ResponseSchema4, - ResponseSchema5, - ResponseSchema6, - ResponseSchema7, - ResponseSchema8, - ResponseSchema9, - ResponseSchema10, - ResponseSchema11, - UcpService, + BusinessSchema2, + BusinessSchema4, + BusinessSchema5, + BusinessSchema6, + BusinessSchema7, + BusinessSchema8, + BusinessSchema9, + BusinessSchema10, + BusinessSchema11, ) from ._internal import BusinessSchema_2 as BusinessSchema +from ._internal import ( + PlatformSchema3, + PlatformSchema5, + PlatformSchema6, + PlatformSchema7, + PlatformSchema8, + PlatformSchema9, + PlatformSchema10, + PlatformSchema11, + PlatformSchema12, +) from ._internal import PlatformSchema_2 as PlatformSchema +from ._internal import ( + ResponseSchema2, + ResponseSchema4, + ResponseSchema5, + ResponseSchema6, + ResponseSchema7, + ResponseSchema8, + ResponseSchema9, + ResponseSchema10, + ResponseSchema11, +) from ._internal import ResponseSchema_2 as ResponseSchema +from ._internal import UcpService __all__ = [ - "Base", - "BusinessSchema", - "BusinessSchema10", - "BusinessSchema11", - "BusinessSchema2", - "BusinessSchema4", - "BusinessSchema5", - "BusinessSchema6", - "BusinessSchema7", - "BusinessSchema8", - "BusinessSchema9", - "PlatformSchema", - "PlatformSchema10", - "PlatformSchema11", - "PlatformSchema12", - "PlatformSchema3", - "PlatformSchema5", - "PlatformSchema6", - "PlatformSchema7", - "PlatformSchema8", - "PlatformSchema9", - "ResponseSchema", - "ResponseSchema10", - "ResponseSchema11", - "ResponseSchema2", - "ResponseSchema4", - "ResponseSchema5", - "ResponseSchema6", - "ResponseSchema7", - "ResponseSchema8", - "ResponseSchema9", - "UcpService", + "Base", + "BusinessSchema", + "BusinessSchema10", + "BusinessSchema11", + "BusinessSchema2", + "BusinessSchema4", + "BusinessSchema5", + "BusinessSchema6", + "BusinessSchema7", + "BusinessSchema8", + "BusinessSchema9", + "PlatformSchema", + "PlatformSchema10", + "PlatformSchema11", + "PlatformSchema12", + "PlatformSchema3", + "PlatformSchema5", + "PlatformSchema6", + "PlatformSchema7", + "PlatformSchema8", + "PlatformSchema9", + "ResponseSchema", + "ResponseSchema10", + "ResponseSchema11", + "ResponseSchema2", + "ResponseSchema4", + "ResponseSchema5", + "ResponseSchema6", + "ResponseSchema7", + "ResponseSchema8", + "ResponseSchema9", + "UcpService", ] diff --git a/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py b/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py index 26569ed..7504199 100644 --- a/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py +++ b/src/ucp_sdk/models/schemas/shopping/ap2_mandate.py @@ -26,101 +26,98 @@ class Ap2MandateExtension(RootModel[Any]): - root: Any = Field(..., title="AP2 Mandate Extension") - """ + root: Any = Field(..., title="AP2 Mandate Extension") + """ Extends Checkout with cryptographic mandate support for non-repudiable authorization per the AP2 protocol. Uses embedded signature model with ap2 namespace. """ class MerchantAuthorization(RootModel[str]): - root: str = Field( - ..., - pattern="^[A-Za-z0-9_-]+\\.\\.[A-Za-z0-9_-]+$", - title="Merchant Authorization", - ) - """ + root: str = Field( + ..., + pattern="^[A-Za-z0-9_-]+\\.\\.[A-Za-z0-9_-]+$", + title="Merchant Authorization", + ) + """ JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: `..`. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload. """ class CheckoutMandate(RootModel[str]): - root: str = Field( - ..., - pattern="^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]+(~[A-Za-z0-9_-]+)*$", - title="Checkout Mandate", - ) - """ + root: str = Field( + ..., + pattern="^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]+(~[A-Za-z0-9_-]+)*$", + title="Checkout Mandate", + ) + """ SD-JWT+kb credential in `ap2.checkout_mandate`. Proving user authorization for the checkout. Contains the full checkout including `ap2.merchant_authorization`. """ class Ap2WithMerchantAuthorization(BaseModel): - """ - AP2 extension data including merchant authorization. - """ - - model_config = ConfigDict( - extra="allow", - ) - merchant_authorization: MerchantAuthorization | None = None - """ + """AP2 extension data including merchant authorization. + """ + + model_config = ConfigDict( + extra="allow", + ) + merchant_authorization: MerchantAuthorization | None = None + """ Merchant's signature proving checkout terms are authentic. """ class Ap2WithCheckoutMandate(BaseModel): - """ - AP2 extension data including checkout mandate. - """ - - model_config = ConfigDict( - extra="allow", - ) - checkout_mandate: CheckoutMandate | None = None - """ + """AP2 extension data including checkout mandate. + """ + + model_config = ConfigDict( + extra="allow", + ) + checkout_mandate: CheckoutMandate | None = None + """ SD-JWT+kb proving user authorized this checkout. """ class Ap2(Ap2WithMerchantAuthorization, Ap2WithCheckoutMandate): - model_config = ConfigDict( - extra="allow", - ) + model_config = ConfigDict( + extra="allow", + ) class ErrorCode( - RootModel[ - Literal[ - "mandate_required", - "agent_missing_key", - "mandate_invalid_signature", - "mandate_expired", - "mandate_scope_mismatch", - "merchant_authorization_invalid", - "merchant_authorization_missing", - ] + RootModel[ + Literal[ + "mandate_required", + "agent_missing_key", + "mandate_invalid_signature", + "mandate_expired", + "mandate_scope_mismatch", + "merchant_authorization_invalid", + "merchant_authorization_missing", ] + ] ): - root: Literal[ - "mandate_required", - "agent_missing_key", - "mandate_invalid_signature", - "mandate_expired", - "mandate_scope_mismatch", - "merchant_authorization_invalid", - "merchant_authorization_missing", - ] = Field(..., title="AP2 Error Code") - """ + root: Literal[ + "mandate_required", + "agent_missing_key", + "mandate_invalid_signature", + "mandate_expired", + "mandate_scope_mismatch", + "merchant_authorization_invalid", + "merchant_authorization_missing", + ] = Field(..., title="AP2 Error Code") + """ Error codes specific to AP2 mandate verification. """ class Checkout(Checkout_1): - """ - Checkout extended with AP2 mandate support. - """ + """Checkout extended with AP2 mandate support. + """ - model_config = ConfigDict( - extra="allow", - ) - ap2: Ap2 | None = None + model_config = ConfigDict( + extra="allow", + ) + ap2: Ap2 | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/buyer_consent.py b/src/ucp_sdk/models/schemas/shopping/buyer_consent.py index 019446e..7bf0623 100644 --- a/src/ucp_sdk/models/schemas/shopping/buyer_consent.py +++ b/src/ucp_sdk/models/schemas/shopping/buyer_consent.py @@ -27,61 +27,58 @@ class BuyerConsentExtension(RootModel[Any]): - root: Any = Field(..., title="Buyer Consent Extension") - """ + root: Any = Field(..., title="Buyer Consent Extension") + """ Extends Checkout with buyer consent tracking for privacy compliance via the buyer object. """ class Consent(BaseModel): - """ - User consent states for data processing - """ - - model_config = ConfigDict( - extra="allow", - ) - analytics: bool | None = None - """ + """User consent states for data processing + """ + + model_config = ConfigDict( + extra="allow", + ) + analytics: bool | None = None + """ Consent for analytics and performance tracking. """ - preferences: bool | None = None - """ + preferences: bool | None = None + """ Consent for storing user preferences. """ - marketing: bool | None = None - """ + marketing: bool | None = None + """ Consent for marketing communications. """ - sale_of_data: bool | None = None - """ + sale_of_data: bool | None = None + """ Consent for selling data to third parties (CCPA). """ class Buyer(Buyer_1): - """ - Buyer object extended with consent tracking. - """ - - model_config = ConfigDict( - extra="allow", - ) - consent: Consent | None = None - """ + """Buyer object extended with consent tracking. + """ + + model_config = ConfigDict( + extra="allow", + ) + consent: Consent | None = None + """ Consent tracking fields. """ class Checkout(Checkout_1): - """ - Checkout extended with consent tracking via buyer object. - """ - - model_config = ConfigDict( - extra="allow", - ) - buyer: Buyer | None = None - """ + """Checkout extended with consent tracking via buyer object. + """ + + model_config = ConfigDict( + extra="allow", + ) + buyer: Buyer | None = None + """ Buyer with consent tracking. """ diff --git a/src/ucp_sdk/models/schemas/shopping/checkout.py b/src/ucp_sdk/models/schemas/shopping/checkout.py index 76ca068..f3abfc8 100644 --- a/src/ucp_sdk/models/schemas/shopping/checkout.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout.py @@ -30,64 +30,63 @@ class Checkout(BaseModel): - """ - Base checkout schema. Extensions compose onto this using allOf. - """ + """Base checkout schema. Extensions compose onto this using allOf. + """ - model_config = ConfigDict( - extra="allow", - ) - ucp: ResponseCheckoutSchema - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + ucp: ResponseCheckoutSchema + id: str + """ Unique identifier of the checkout session. """ - line_items: list[line_item.LineItem] - """ + line_items: list[line_item.LineItem] + """ List of line items being checked out. """ - buyer: buyer_1.Buyer | None = None - """ + buyer: buyer_1.Buyer | None = None + """ Representation of the buyer. """ - context: context_1.Context | None = None - status: Literal[ - "incomplete", - "requires_escalation", - "ready_for_complete", - "complete_in_progress", - "completed", - "canceled", - ] - """ + context: context_1.Context | None = None + status: Literal[ + "incomplete", + "requires_escalation", + "ready_for_complete", + "complete_in_progress", + "completed", + "canceled", + ] + """ Checkout state indicating the current phase and required action. See Checkout Status lifecycle documentation for state transition details. """ - currency: str - """ + currency: str + """ ISO 4217 currency code reflecting the merchant's market determination. Derived from address, context, and geo IP—buyers provide signals, merchants determine currency. """ - totals: list[total.Total] - """ + totals: list[total.Total] + """ Different cart totals. """ - messages: list[message.Message] | None = None - """ + messages: list[message.Message] | None = None + """ List of messages with error and info about the checkout session state. """ - links: list[link.Link] - """ + links: list[link.Link] + """ Links to be displayed by the platform (Privacy Policy, TOS). Mandatory for legal compliance. """ - expires_at: AwareDatetime | None = None - """ + expires_at: AwareDatetime | None = None + """ RFC 3339 expiry timestamp. Default TTL is 6 hours from creation if not sent. """ - continue_url: AnyUrl | None = None - """ + continue_url: AnyUrl | None = None + """ URL for checkout handoff and session recovery. MUST be provided when status is requires_escalation. See specification for format and availability requirements. """ - payment: payment_1.Payment | None = None - order: order_confirmation.OrderConfirmation | None = None - """ + payment: payment_1.Payment | None = None + order: order_confirmation.OrderConfirmation | None = None + """ Details about an order created for this checkout session. """ diff --git a/src/ucp_sdk/models/schemas/shopping/complete_checkout_request.py b/src/ucp_sdk/models/schemas/shopping/complete_checkout_request.py new file mode 100644 index 0000000..c2df263 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/complete_checkout_request.py @@ -0,0 +1,33 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import payment as payment_1 + + +class CompleteCheckoutRequest(BaseModel): + """Base checkout schema. Extensions compose onto this using allOf. + """ + + model_config = ConfigDict( + extra="allow", + ) + payment: payment_1.Payment diff --git a/src/ucp_sdk/models/schemas/shopping/create_checkout_request.py b/src/ucp_sdk/models/schemas/shopping/create_checkout_request.py new file mode 100644 index 0000000..4cf505e --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/create_checkout_request.py @@ -0,0 +1,45 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import payment as payment_1 +from .types import buyer as buyer_1 +from .types import context as context_1 +from .types import create_line_item_request + + +class CreateCheckoutRequest(BaseModel): + """Base checkout schema. Extensions compose onto this using allOf. + """ + + model_config = ConfigDict( + extra="allow", + ) + line_items: list[create_line_item_request.CreateLineItemRequest] + """ + List of line items being checked out. + """ + buyer: buyer_1.Buyer | None = None + """ + Representation of the buyer. + """ + context: context_1.Context | None = None + payment: payment_1.Payment | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/discount.py b/src/ucp_sdk/models/schemas/shopping/discount.py index 6bc440d..d44f3e2 100644 --- a/src/ucp_sdk/models/schemas/shopping/discount.py +++ b/src/ucp_sdk/models/schemas/shopping/discount.py @@ -26,92 +26,88 @@ class DiscountExtension(RootModel[Any]): - root: Any = Field(..., title="Discount Extension") - """ + root: Any = Field(..., title="Discount Extension") + """ Extends Checkout with discount code support, enabling agents to apply promotional, loyalty, referral, and other discount codes. """ class Allocation(BaseModel): - """ - Breakdown of how a discount amount was allocated to a specific target. - """ - - model_config = ConfigDict( - extra="allow", - ) - path: str - """ + """Breakdown of how a discount amount was allocated to a specific target. + """ + + model_config = ConfigDict( + extra="allow", + ) + path: str + """ JSONPath to the allocation target (e.g., '$.line_items[0]', '$.totals.shipping'). """ - amount: int = Field(..., ge=0) - """ + amount: int = Field(..., ge=0) + """ Amount allocated to this target in minor (cents) currency units. """ class AppliedDiscount(BaseModel): - """ - A discount that was successfully applied. - """ - - model_config = ConfigDict( - extra="allow", - ) - code: str | None = None - """ + """A discount that was successfully applied. + """ + + model_config = ConfigDict( + extra="allow", + ) + code: str | None = None + """ The discount code. Omitted for automatic discounts. """ - title: str - """ + title: str + """ Human-readable discount name (e.g., 'Summer Sale 20% Off'). """ - amount: int = Field(..., ge=0) - """ + amount: int = Field(..., ge=0) + """ Total discount amount in minor (cents) currency units. """ - automatic: bool | None = False - """ + automatic: bool | None = False + """ True if applied automatically by merchant rules (no code required). """ - method: Literal["each", "across"] | None = None - """ + method: Literal["each", "across"] | None = None + """ Allocation method. 'each' = applied independently per item. 'across' = split proportionally by value. """ - priority: int | None = Field(None, ge=1) - """ + priority: int | None = Field(None, ge=1) + """ Stacking order for discount calculation. Lower numbers applied first (1 = first). """ - allocations: list[Allocation] | None = None - """ + allocations: list[Allocation] | None = None + """ Breakdown of where this discount was allocated. Sum of allocation amounts equals total amount. """ class DiscountsObject(BaseModel): - """ - Discount codes input and applied discounts output. - """ - - model_config = ConfigDict( - extra="allow", - ) - codes: list[str] | None = None - """ + """Discount codes input and applied discounts output. + """ + + model_config = ConfigDict( + extra="allow", + ) + codes: list[str] | None = None + """ Discount codes to apply. Case-insensitive. Replaces previously submitted codes. Send empty array to clear. """ - applied: list[AppliedDiscount] | None = None - """ + applied: list[AppliedDiscount] | None = None + """ Discounts successfully applied (code-based and automatic). """ class Checkout(Checkout_1): - """ - Checkout extended with discount capability. - """ + """Checkout extended with discount capability. + """ - model_config = ConfigDict( - extra="allow", - ) - discounts: DiscountsObject | None = None + model_config = ConfigDict( + extra="allow", + ) + discounts: DiscountsObject | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py b/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py index 57d7a2a..c966542 100644 --- a/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py +++ b/src/ucp_sdk/models/schemas/shopping/fulfillment/__init__.py @@ -25,51 +25,50 @@ from ..checkout import Checkout as Checkout_1 from ..types import fulfillment as fulfillment_1 from ..types import ( - fulfillment_available_method, - fulfillment_group, - fulfillment_method, - fulfillment_option, + fulfillment_available_method, + fulfillment_group, + fulfillment_method, + fulfillment_option, ) class FulfillmentExtension(RootModel[Any]): - root: Any = Field(..., title="Fulfillment Extension") - """ + root: Any = Field(..., title="Fulfillment Extension") + """ Extends Checkout with fulfillment support using methods, destinations, and groups. """ class FulfillmentAvailableMethod( - RootModel[fulfillment_available_method.FulfillmentAvailableMethod] + RootModel[fulfillment_available_method.FulfillmentAvailableMethod] ): - root: fulfillment_available_method.FulfillmentAvailableMethod + root: fulfillment_available_method.FulfillmentAvailableMethod class FulfillmentOption(RootModel[fulfillment_option.FulfillmentOption]): - root: fulfillment_option.FulfillmentOption + root: fulfillment_option.FulfillmentOption class FulfillmentGroup(RootModel[fulfillment_group.FulfillmentGroup]): - root: fulfillment_group.FulfillmentGroup + root: fulfillment_group.FulfillmentGroup class FulfillmentMethod(RootModel[fulfillment_method.FulfillmentMethod]): - root: fulfillment_method.FulfillmentMethod + root: fulfillment_method.FulfillmentMethod class Fulfillment(RootModel[fulfillment_1.Fulfillment]): - root: fulfillment_1.Fulfillment + root: fulfillment_1.Fulfillment class Checkout(Checkout_1): - """ - Checkout extended with hierarchical fulfillment. - """ - - model_config = ConfigDict( - extra="allow", - ) - fulfillment: Fulfillment | None = None - """ + """Checkout extended with hierarchical fulfillment. + """ + + model_config = ConfigDict( + extra="allow", + ) + fulfillment: Fulfillment | None = None + """ Fulfillment details. """ diff --git a/src/ucp_sdk/models/schemas/shopping/fulfillment/dev/ucp/shopping.py b/src/ucp_sdk/models/schemas/shopping/fulfillment/dev/ucp/shopping.py index cc3e02d..7919ae3 100644 --- a/src/ucp_sdk/models/schemas/shopping/fulfillment/dev/ucp/shopping.py +++ b/src/ucp_sdk/models/schemas/shopping/fulfillment/dev/ucp/shopping.py @@ -24,4 +24,4 @@ class Fulfillment(RootModel[Any]): - root: Any + root: Any diff --git a/src/ucp_sdk/models/schemas/shopping/order.py b/src/ucp_sdk/models/schemas/shopping/order.py index 5538eae..abbbde0 100644 --- a/src/ucp_sdk/models/schemas/shopping/order.py +++ b/src/ucp_sdk/models/schemas/shopping/order.py @@ -22,80 +22,77 @@ from .._internal import ResponseOrderSchema from .types import ( - adjustment, - expectation, - fulfillment_event, - order_line_item, - total, + adjustment, + expectation, + fulfillment_event, + order_line_item, + total, ) class PlatformSchema(BaseModel): - """ - Platform's order capability configuration. - """ + """Platform's order capability configuration. + """ - model_config = ConfigDict( - extra="allow", - ) - webhook_url: AnyUrl - """ + model_config = ConfigDict( + extra="allow", + ) + webhook_url: AnyUrl + """ URL where merchant sends order lifecycle events (webhooks). """ class Fulfillment(BaseModel): - """ - Fulfillment data: buyer expectations and what actually happened. - """ + """Fulfillment data: buyer expectations and what actually happened. + """ - model_config = ConfigDict( - extra="allow", - ) - expectations: list[expectation.Expectation] | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + expectations: list[expectation.Expectation] | None = None + """ Buyer-facing groups representing when/how items will be delivered. Can be split, merged, or adjusted post-order. """ - events: list[fulfillment_event.FulfillmentEvent] | None = None - """ + events: list[fulfillment_event.FulfillmentEvent] | None = None + """ Append-only event log of actual shipments. Each event references line items by ID. """ class Order(BaseModel): - """ - Order schema with immutable line items, buyer-facing fulfillment expectations, and append-only event logs. - """ + """Order schema with immutable line items, buyer-facing fulfillment expectations, and append-only event logs. + """ - model_config = ConfigDict( - extra="allow", - ) - ucp: ResponseOrderSchema - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + ucp: ResponseOrderSchema + id: str + """ Unique order identifier. """ - checkout_id: str - """ + checkout_id: str + """ Associated checkout ID for reconciliation. """ - permalink_url: AnyUrl - """ + permalink_url: AnyUrl + """ Permalink to access the order on merchant site. """ - line_items: list[order_line_item.OrderLineItem] - """ + line_items: list[order_line_item.OrderLineItem] + """ Immutable line items — source of truth for what was ordered. """ - fulfillment: Fulfillment - """ + fulfillment: Fulfillment + """ Fulfillment data: buyer expectations and what actually happened. """ - adjustments: list[adjustment.Adjustment] | None = None - """ + adjustments: list[adjustment.Adjustment] | None = None + """ Append-only event log of money movements (refunds, returns, credits, disputes, cancellations, etc.) that exist independently of fulfillment. """ - totals: list[total.Total] - """ + totals: list[total.Total] + """ Different totals for the order. """ diff --git a/src/ucp_sdk/models/schemas/shopping/payment.py b/src/ucp_sdk/models/schemas/shopping/payment.py index ba698c7..b590dfb 100644 --- a/src/ucp_sdk/models/schemas/shopping/payment.py +++ b/src/ucp_sdk/models/schemas/shopping/payment.py @@ -24,16 +24,13 @@ class Payment(BaseModel): - """ - Payment configuration containing handlers. - """ + """Payment configuration containing handlers. + """ - model_config = ConfigDict( - extra="allow", - ) - instruments: list[payment_instrument.SelectedPaymentInstrument] | None = ( - None - ) - """ + model_config = ConfigDict( + extra="allow", + ) + instruments: list[payment_instrument.SelectedPaymentInstrument] | None = None + """ The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/account_info.py b/src/ucp_sdk/models/schemas/shopping/types/account_info.py index aeb2665..a7d771d 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/account_info.py +++ b/src/ucp_sdk/models/schemas/shopping/types/account_info.py @@ -22,14 +22,13 @@ class PaymentAccountInfo(BaseModel): - """ - Non-sensitive backend identifiers for linking. - """ + """Non-sensitive backend identifiers for linking. + """ - model_config = ConfigDict( - extra="allow", - ) - payment_account_reference: str | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + payment_account_reference: str | None = None + """ EMVCo PAR. A unique identifier linking a payment card to a specific account, enabling tracking across tokens (Apple Pay, physical card, etc). """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/adjustment.py b/src/ucp_sdk/models/schemas/shopping/types/adjustment.py index f28c0ea..36600ff 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/adjustment.py +++ b/src/ucp_sdk/models/schemas/shopping/types/adjustment.py @@ -24,52 +24,51 @@ class LineItem(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Line item ID reference. """ - quantity: int = Field(..., ge=1) - """ + quantity: int = Field(..., ge=1) + """ Quantity affected by this adjustment. """ class Adjustment(BaseModel): - """ - Append-only event that exists independently of fulfillment. Typically represents money movements but can be any post-order change. Polymorphic type that can optionally reference line items. - """ + """Append-only event that exists independently of fulfillment. Typically represents money movements but can be any post-order change. Polymorphic type that can optionally reference line items. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Adjustment event identifier. """ - type: str - """ + type: str + """ Type of adjustment (open string). Typically money-related like: refund, return, credit, price_adjustment, dispute, cancellation. Can be any value that makes sense for the merchant's business. """ - occurred_at: AwareDatetime - """ + occurred_at: AwareDatetime + """ RFC 3339 timestamp when this adjustment occurred. """ - status: Literal["pending", "completed", "failed"] - """ + status: Literal["pending", "completed", "failed"] + """ Adjustment status. """ - line_items: list[LineItem] | None = None - """ + line_items: list[LineItem] | None = None + """ Which line items and quantities are affected (optional). """ - amount: int | None = None - """ + amount: int | None = None + """ Amount in minor units (cents) for refunds, credits, price adjustments (optional). """ - description: str | None = None - """ + description: str | None = None + """ Human-readable reason or description (e.g., 'Defective item', 'Customer requested'). """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/binding.py b/src/ucp_sdk/models/schemas/shopping/types/binding.py index 16f6961..1d4ad02 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/binding.py +++ b/src/ucp_sdk/models/schemas/shopping/types/binding.py @@ -24,18 +24,17 @@ class Binding(BaseModel): - """ - Binds a token to a specific checkout session and participant. Prevents token reuse across different checkouts or participants. - """ + """Binds a token to a specific checkout session and participant. Prevents token reuse across different checkouts or participants. + """ - model_config = ConfigDict( - extra="allow", - ) - checkout_id: str - """ + model_config = ConfigDict( + extra="allow", + ) + checkout_id: str + """ The checkout session identifier this token is bound to. """ - identity: payment_identity.PaymentIdentity | None = None - """ + identity: payment_identity.PaymentIdentity | None = None + """ The participant this token is bound to. Required when acting on behalf of another participant (e.g., agent tokenizing for merchant). Omit when the authenticated caller is the binding target. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py b/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py index 53e3bd5..07227b6 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py +++ b/src/ucp_sdk/models/schemas/shopping/types/business_fulfillment_config.py @@ -24,38 +24,36 @@ class AllowsMultiDestination(BaseModel): - """ - Permits multiple destinations per method type. - """ - - model_config = ConfigDict( - extra="allow", - ) - shipping: bool | None = None - """ + """Permits multiple destinations per method type. + """ + + model_config = ConfigDict( + extra="allow", + ) + shipping: bool | None = None + """ Multiple shipping destinations allowed. """ - pickup: bool | None = None - """ + pickup: bool | None = None + """ Multiple pickup locations allowed. """ class BusinessFulfillmentConfig(BaseModel): - """ - Business's fulfillment configuration. - """ - - model_config = ConfigDict( - extra="allow", - ) - allows_multi_destination: AllowsMultiDestination | None = None - """ + """Business's fulfillment configuration. + """ + + model_config = ConfigDict( + extra="allow", + ) + allows_multi_destination: AllowsMultiDestination | None = None + """ Permits multiple destinations per method type. """ - allows_method_combinations: ( - list[list[Literal["shipping", "pickup"]]] | None - ) = None - """ + allows_method_combinations: ( + list[list[Literal["shipping", "pickup"]]] | None + ) = None + """ Allowed method type combinations. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/buyer.py b/src/ucp_sdk/models/schemas/shopping/types/buyer.py index ff8ef6a..c1c09ee 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/buyer.py +++ b/src/ucp_sdk/models/schemas/shopping/types/buyer.py @@ -22,22 +22,22 @@ class Buyer(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - first_name: str | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + first_name: str | None = None + """ First name of the buyer. """ - last_name: str | None = None - """ + last_name: str | None = None + """ Last name of the buyer. """ - email: str | None = None - """ + email: str | None = None + """ Email of the buyer. """ - phone_number: str | None = None - """ + phone_number: str | None = None + """ E.164 standard. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/card_credential.py b/src/ucp_sdk/models/schemas/shopping/types/card_credential.py index 43b231a..614ec6c 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/card_credential.py +++ b/src/ucp_sdk/models/schemas/shopping/types/card_credential.py @@ -26,46 +26,45 @@ class CardCredential(PaymentCredential): - """ - A card credential containing sensitive payment card details including raw Primary Account Numbers (PANs). This credential type MUST NOT be used for checkout, only with payment handlers that tokenize or encrypt credentials. CRITICAL: Both parties handling CardCredential (sender and receiver) MUST be PCI DSS compliant. Transmission MUST use HTTPS/TLS with strong cipher suites. - """ + """A card credential containing sensitive payment card details including raw Primary Account Numbers (PANs). This credential type MUST NOT be used for checkout, only with payment handlers that tokenize or encrypt credentials. CRITICAL: Both parties handling CardCredential (sender and receiver) MUST be PCI DSS compliant. Transmission MUST use HTTPS/TLS with strong cipher suites. + """ - model_config = ConfigDict( - extra="allow", - ) - type: Literal["card"] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal["card"] + """ The credential type identifier for card credentials. """ - card_number_type: Literal["fpan", "network_token", "dpan"] - """ + card_number_type: Literal["fpan", "network_token", "dpan"] + """ The type of card number. Network tokens are preferred with fallback to FPAN. See PCI Scope for more details. """ - number: str | None = Field(None, examples=["4242424242424242"]) - """ + number: str | None = Field(None, examples=["4242424242424242"]) + """ Card number. """ - expiry_month: int | None = None - """ + expiry_month: int | None = None + """ The month of the card's expiration date (1-12). """ - expiry_year: int | None = None - """ + expiry_year: int | None = None + """ The year of the card's expiration date. """ - name: str | None = Field(None, examples=["Jane Doe"]) - """ + name: str | None = Field(None, examples=["Jane Doe"]) + """ Cardholder name. """ - cvc: str | None = Field(None, examples=["223"], max_length=4) - """ + cvc: str | None = Field(None, examples=["223"], max_length=4) + """ Card CVC number. """ - cryptogram: str | None = Field(None, examples=["gXc5UCLnM6ckD7pjM1TdPA=="]) - """ + cryptogram: str | None = Field(None, examples=["gXc5UCLnM6ckD7pjM1TdPA=="]) + """ Cryptogram provided with network tokens. """ - eci_value: str | None = Field(None, examples=["07"]) - """ + eci_value: str | None = Field(None, examples=["07"]) + """ Electronic Commerce Indicator / Security Level Indicator provided with network tokens. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/card_payment_instrument.py b/src/ucp_sdk/models/schemas/shopping/types/card_payment_instrument.py index e5cffa1..c4b1c14 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/card_payment_instrument.py +++ b/src/ucp_sdk/models/schemas/shopping/types/card_payment_instrument.py @@ -26,52 +26,50 @@ class Display(BaseModel): - """ - Display information for this card payment instrument. - """ + """Display information for this card payment instrument. + """ - model_config = ConfigDict( - extra="allow", - ) - brand: str | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + brand: str | None = None + """ The card brand/network (e.g., visa, mastercard, amex). """ - last_digits: str | None = None - """ + last_digits: str | None = None + """ Last 4 digits of the card number. """ - expiry_month: int | None = None - """ + expiry_month: int | None = None + """ The month of the card's expiration date (1-12). """ - expiry_year: int | None = None - """ + expiry_year: int | None = None + """ The year of the card's expiration date. """ - description: str | None = None - """ + description: str | None = None + """ An optional rich text description of the card to display to the user (e.g., 'Visa ending in 1234, expires 12/2025'). """ - card_art: AnyUrl | None = None - """ + card_art: AnyUrl | None = None + """ An optional URI to a rich image representing the card (e.g., card art provided by the issuer). """ class CardPaymentInstrument(PaymentInstrument): - """ - A basic card payment instrument with visible card details. Can be inherited by a handler's instrument schema to define handler-specific display details or more complex credential structures. - """ + """A basic card payment instrument with visible card details. Can be inherited by a handler's instrument schema to define handler-specific display details or more complex credential structures. + """ - model_config = ConfigDict( - extra="allow", - ) - type: Literal["card"] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal["card"] + """ Indicates this is a card payment instrument. """ - display: Display | None = None - """ + display: Display | None = None + """ Display information for this card payment instrument. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/context.py b/src/ucp_sdk/models/schemas/shopping/types/context.py index d501c00..fccb800 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/context.py +++ b/src/ucp_sdk/models/schemas/shopping/types/context.py @@ -22,22 +22,21 @@ class Context(BaseModel): - """ - Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. - """ + """Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. + """ - model_config = ConfigDict( - extra="allow", - ) - address_country: str | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + address_country: str | None = None + """ The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. """ - address_region: str | None = None - """ + address_region: str | None = None + """ The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. """ - postal_code: str | None = None - """ + postal_code: str | None = None + """ The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_group_request.py b/src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_group_request.py new file mode 100644 index 0000000..9a87100 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_group_request.py @@ -0,0 +1,34 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class CreateFulfillmentGroupRequest(BaseModel): + """A merchant-generated package/group of line items with fulfillment options. + """ + + model_config = ConfigDict( + extra="allow", + ) + selected_option_id: str | None = None + """ + ID of the selected fulfillment option for this group. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_method_request.py b/src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_method_request.py new file mode 100644 index 0000000..1963f13 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_method_request.py @@ -0,0 +1,58 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from typing import Literal + +from pydantic import BaseModel, ConfigDict + +from . import create_fulfillment_group_request, fulfillment_destination + + +class CreateFulfillmentMethodRequest(BaseModel): + """A fulfillment method (shipping or pickup) with destinations and groups. + """ + + model_config = ConfigDict( + extra="allow", + ) + type: Literal["shipping", "pickup"] + """ + Fulfillment method type. + """ + line_item_ids: list[str] | None = None + """ + Line item IDs fulfilled via this method. + """ + destinations: list[fulfillment_destination.FulfillmentDestination] | None = ( + None + ) + """ + Available destinations. For shipping: addresses. For pickup: retail locations. + """ + selected_destination_id: str | None = None + """ + ID of the selected destination. + """ + groups: ( + list[create_fulfillment_group_request.CreateFulfillmentGroupRequest] | None + ) = None + """ + Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/create_line_item_request.py b/src/ucp_sdk/models/schemas/shopping/types/create_line_item_request.py new file mode 100644 index 0000000..a0837ec --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/create_line_item_request.py @@ -0,0 +1,37 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict, Field + +from . import item as item_1 + + +class CreateLineItemRequest(BaseModel): + """Line item object. Expected to use the currency of the parent object. + """ + + model_config = ConfigDict( + extra="allow", + ) + item: item_1.Item + quantity: int = Field(..., ge=1) + """ + Quantity of the item being purchased. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/expectation.py b/src/ucp_sdk/models/schemas/shopping/types/expectation.py index 03e8182..1b89c5d 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/expectation.py +++ b/src/ucp_sdk/models/schemas/shopping/types/expectation.py @@ -26,48 +26,47 @@ class LineItem(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Line item ID reference. """ - quantity: int = Field(..., ge=1) - """ + quantity: int = Field(..., ge=1) + """ Quantity of this item in this expectation. """ class Expectation(BaseModel): - """ - Buyer-facing fulfillment expectation representing logical groupings of items (e.g., 'package'). Can be split, merged, or adjusted post-order to set buyer expectations for when/how items arrive. - """ + """Buyer-facing fulfillment expectation representing logical groupings of items (e.g., 'package'). Can be split, merged, or adjusted post-order to set buyer expectations for when/how items arrive. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Expectation identifier. """ - line_items: list[LineItem] - """ + line_items: list[LineItem] + """ Which line items and quantities are in this expectation. """ - method_type: Literal["shipping", "pickup", "digital"] - """ + method_type: Literal["shipping", "pickup", "digital"] + """ Delivery method type (shipping, pickup, digital). """ - destination: postal_address.PostalAddress - """ + destination: postal_address.PostalAddress + """ Delivery destination address. """ - description: str | None = None - """ + description: str | None = None + """ Human-readable delivery description (e.g., 'Arrives in 5-8 business days'). """ - fulfillable_on: str | None = None - """ + fulfillable_on: str | None = None + """ When this expectation can be fulfilled: 'now' or ISO 8601 timestamp for future date (backorder, pre-order). """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment.py index 8ff2c27..9c7fe11 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment.py @@ -24,20 +24,19 @@ class Fulfillment(BaseModel): - """ - Container for fulfillment methods and availability. - """ + """Container for fulfillment methods and availability. + """ - model_config = ConfigDict( - extra="allow", - ) - methods: list[fulfillment_method.FulfillmentMethod] | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + methods: list[fulfillment_method.FulfillmentMethod] | None = None + """ Fulfillment methods for cart items. """ - available_methods: ( - list[fulfillment_available_method.FulfillmentAvailableMethod] | None - ) = None - """ + available_methods: ( + list[fulfillment_available_method.FulfillmentAvailableMethod] | None + ) = None + """ Inventory availability hints. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method.py index 4c9a1bb..1ebd1f6 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method.py @@ -24,26 +24,25 @@ class FulfillmentAvailableMethod(BaseModel): - """ - Inventory availability hint for a fulfillment method type. - """ + """Inventory availability hint for a fulfillment method type. + """ - model_config = ConfigDict( - extra="allow", - ) - type: Literal["shipping", "pickup"] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal["shipping", "pickup"] + """ Fulfillment method type this availability applies to. """ - line_item_ids: list[str] - """ + line_item_ids: list[str] + """ Line items available for this fulfillment method. """ - fulfillable_on: str | None = None - """ + fulfillable_on: str | None = None + """ 'now' for immediate availability, or ISO 8601 date for future (preorders, transfers). """ - description: str | None = None - """ + description: str | None = None + """ Human-readable availability info (e.g., 'Available for pickup at Downtown Store today'). """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py index 4e1ac65..73e4a6c 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_destination.py @@ -24,15 +24,13 @@ class FulfillmentDestination( - RootModel[ - shipping_destination.ShippingDestination - | retail_location.RetailLocation - ] + RootModel[ + shipping_destination.ShippingDestination | retail_location.RetailLocation + ] ): - root: ( - shipping_destination.ShippingDestination - | retail_location.RetailLocation - ) = Field(..., title="Fulfillment Destination") - """ + root: ( + shipping_destination.ShippingDestination | retail_location.RetailLocation + ) = Field(..., title="Fulfillment Destination") + """ A destination for fulfillment. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_event.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_event.py index 68e09c6..4f3fca6 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_event.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_event.py @@ -22,56 +22,55 @@ class LineItem(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Line item ID reference. """ - quantity: int = Field(..., ge=1) - """ + quantity: int = Field(..., ge=1) + """ Quantity fulfilled in this event. """ class FulfillmentEvent(BaseModel): - """ - Append-only fulfillment event representing an actual shipment. References line items by ID. - """ + """Append-only fulfillment event representing an actual shipment. References line items by ID. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Fulfillment event identifier. """ - occurred_at: AwareDatetime - """ + occurred_at: AwareDatetime + """ RFC 3339 timestamp when this fulfillment event occurred. """ - type: str - """ + type: str + """ Fulfillment event type. Common values include: processing (preparing to ship), shipped (handed to carrier), in_transit (in delivery network), delivered (received by buyer), failed_attempt (delivery attempt failed), canceled (fulfillment canceled), undeliverable (cannot be delivered), returned_to_sender (returned to merchant). """ - line_items: list[LineItem] - """ + line_items: list[LineItem] + """ Which line items and quantities are fulfilled in this event. """ - tracking_number: str | None = None - """ + tracking_number: str | None = None + """ Carrier tracking number (required if type != processing). """ - tracking_url: AnyUrl | None = None - """ + tracking_url: AnyUrl | None = None + """ URL to track this shipment (required if type != processing). """ - carrier: str | None = None - """ + carrier: str | None = None + """ Carrier name (e.g., 'FedEx', 'USPS'). """ - description: str | None = None - """ + description: str | None = None + """ Human-readable description of the shipment status or delivery information (e.g., 'Delivered to front door', 'Out for delivery'). """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group.py index b3646b8..886f86b 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group.py @@ -24,26 +24,25 @@ class FulfillmentGroup(BaseModel): - """ - A merchant-generated package/group of line items with fulfillment options. - """ + """A merchant-generated package/group of line items with fulfillment options. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Group identifier for referencing merchant-generated groups in updates. """ - line_item_ids: list[str] - """ + line_item_ids: list[str] + """ Line item IDs included in this group/package. """ - options: list[fulfillment_option.FulfillmentOption] | None = None - """ + options: list[fulfillment_option.FulfillmentOption] | None = None + """ Available fulfillment options for this group. """ - selected_option_id: str | None = None - """ + selected_option_id: str | None = None + """ ID of the selected fulfillment option for this group. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py index e022d8d..830cec2 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method.py @@ -26,36 +26,35 @@ class FulfillmentMethod(BaseModel): - """ - A fulfillment method (shipping or pickup) with destinations and groups. - """ - - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + """A fulfillment method (shipping or pickup) with destinations and groups. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Unique fulfillment method identifier. """ - type: Literal["shipping", "pickup"] - """ + type: Literal["shipping", "pickup"] + """ Fulfillment method type. """ - line_item_ids: list[str] - """ + line_item_ids: list[str] + """ Line item IDs fulfilled via this method. """ - destinations: ( - list[fulfillment_destination.FulfillmentDestination] | None - ) = None - """ + destinations: list[fulfillment_destination.FulfillmentDestination] | None = ( + None + ) + """ Available destinations. For shipping: addresses. For pickup: retail locations. """ - selected_destination_id: str | None = None - """ + selected_destination_id: str | None = None + """ ID of the selected destination. """ - groups: list[fulfillment_group.FulfillmentGroup] | None = None - """ + groups: list[fulfillment_group.FulfillmentGroup] | None = None + """ Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option.py index 93b3bf8..83c0d74 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option.py @@ -24,38 +24,37 @@ class FulfillmentOption(BaseModel): - """ - A fulfillment option within a group (e.g., Standard Shipping $5, Express $15). - """ + """A fulfillment option within a group (e.g., Standard Shipping $5, Express $15). + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Unique fulfillment option identifier. """ - title: str - """ + title: str + """ Short label (e.g., 'Express Shipping', 'Curbside Pickup'). """ - description: str | None = None - """ + description: str | None = None + """ Complete context for buyer decision (e.g., 'Arrives Dec 12-15 via FedEx'). """ - carrier: str | None = None - """ + carrier: str | None = None + """ Carrier name (for shipping). """ - earliest_fulfillment_time: AwareDatetime | None = None - """ + earliest_fulfillment_time: AwareDatetime | None = None + """ Earliest fulfillment date. """ - latest_fulfillment_time: AwareDatetime | None = None - """ + latest_fulfillment_time: AwareDatetime | None = None + """ Latest fulfillment date. """ - totals: list[total.Total] - """ + totals: list[total.Total] + """ Fulfillment option totals breakdown. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item.py b/src/ucp_sdk/models/schemas/shopping/types/item.py index e2b1954..c1d407a 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/item.py +++ b/src/ucp_sdk/models/schemas/shopping/types/item.py @@ -22,22 +22,22 @@ class Item(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. """ - title: str - """ + title: str + """ Product title. """ - price: int = Field(..., ge=0) - """ + price: int = Field(..., ge=0) + """ Unit price in minor (cents) currency units. """ - image_url: AnyUrl | None = None - """ + image_url: AnyUrl | None = None + """ Product image URI. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item.py b/src/ucp_sdk/models/schemas/shopping/types/line_item.py index 9f2befe..38f2f30 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/line_item.py +++ b/src/ucp_sdk/models/schemas/shopping/types/line_item.py @@ -25,24 +25,23 @@ class LineItem(BaseModel): - """ - Line item object. Expected to use the currency of the parent object. - """ + """Line item object. Expected to use the currency of the parent object. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - item: item_1.Item - quantity: int = Field(..., ge=1) - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + item: item_1.Item + quantity: int = Field(..., ge=1) + """ Quantity of the item being purchased. """ - totals: list[total.Total] - """ + totals: list[total.Total] + """ Line item totals breakdown. """ - parent_id: str | None = None - """ + parent_id: str | None = None + """ Parent line item identifier for any nested structures. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/link.py b/src/ucp_sdk/models/schemas/shopping/types/link.py index c3cdd02..ada733f 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/link.py +++ b/src/ucp_sdk/models/schemas/shopping/types/link.py @@ -22,18 +22,18 @@ class Link(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - type: str - """ + model_config = ConfigDict( + extra="allow", + ) + type: str + """ Type of link. Well-known values: `privacy_policy`, `terms_of_service`, `refund_policy`, `shipping_policy`, `faq`. Consumers SHOULD handle unknown values gracefully by displaying them using the `title` field or omitting the link. """ - url: AnyUrl - """ + url: AnyUrl + """ The actual URL pointing to the content to be displayed. """ - title: str | None = None - """ + title: str | None = None + """ Optional display text for the link. When provided, use this instead of generating from type. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py b/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py index b908e47..87a6928 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py +++ b/src/ucp_sdk/models/schemas/shopping/types/merchant_fulfillment_config.py @@ -24,38 +24,36 @@ class AllowsMultiDestination(BaseModel): - """ - Permits multiple destinations per method type. - """ - - model_config = ConfigDict( - extra="allow", - ) - shipping: bool | None = None - """ + """Permits multiple destinations per method type. + """ + + model_config = ConfigDict( + extra="allow", + ) + shipping: bool | None = None + """ Multiple shipping destinations allowed. """ - pickup: bool | None = None - """ + pickup: bool | None = None + """ Multiple pickup locations allowed. """ class MerchantFulfillmentConfig(BaseModel): - """ - Merchant's fulfillment configuration. - """ - - model_config = ConfigDict( - extra="allow", - ) - allows_multi_destination: AllowsMultiDestination | None = None - """ + """Merchant's fulfillment configuration. + """ + + model_config = ConfigDict( + extra="allow", + ) + allows_multi_destination: AllowsMultiDestination | None = None + """ Permits multiple destinations per method type. """ - allows_method_combinations: ( - list[list[Literal["shipping", "pickup"]]] | None - ) = None - """ + allows_method_combinations: ( + list[list[Literal["shipping", "pickup"]]] | None + ) = None + """ Allowed method type combinations. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/message.py b/src/ucp_sdk/models/schemas/shopping/types/message.py index 42964ae..28c8dbd 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/message.py +++ b/src/ucp_sdk/models/schemas/shopping/types/message.py @@ -24,17 +24,17 @@ class Message( - RootModel[ - message_error.MessageError - | message_warning.MessageWarning - | message_info.MessageInfo - ] + RootModel[ + message_error.MessageError + | message_warning.MessageWarning + | message_info.MessageInfo + ] ): - root: ( - message_error.MessageError - | message_warning.MessageWarning - | message_info.MessageInfo - ) = Field(..., title="Message") - """ + root: ( + message_error.MessageError + | message_warning.MessageWarning + | message_info.MessageInfo + ) = Field(..., title="Message") + """ Container for error, warning, or info messages. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/message_error.py b/src/ucp_sdk/models/schemas/shopping/types/message_error.py index d1e6adb..3a1a2a9 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/message_error.py +++ b/src/ucp_sdk/models/schemas/shopping/types/message_error.py @@ -24,32 +24,32 @@ class MessageError(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - type: Literal["error"] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal["error"] + """ Message type discriminator. """ - code: str - """ + code: str + """ Error code. Possible values include: missing, invalid, out_of_stock, payment_declined, requires_sign_in, requires_3ds, requires_identity_linking. Freeform codes also allowed. """ - path: str | None = None - """ + path: str | None = None + """ RFC 9535 JSONPath to the component the message refers to (e.g., $.items[1]). """ - content_type: Literal["plain", "markdown"] | None = "plain" - """ + content_type: Literal["plain", "markdown"] | None = "plain" + """ Content format, default = plain. """ - content: str - """ + content: str + """ Human-readable message. """ - severity: Literal[ - "recoverable", "requires_buyer_input", "requires_buyer_review" - ] - """ + severity: Literal[ + "recoverable", "requires_buyer_input", "requires_buyer_review" + ] + """ Declares who resolves this error. 'recoverable': agent can fix via API. 'requires_buyer_input': merchant requires information their API doesn't support collecting programmatically (checkout incomplete). 'requires_buyer_review': buyer must authorize before order placement due to policy, regulatory, or entitlement rules (checkout complete). Errors with 'requires_*' severity contribute to 'status: requires_escalation'. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/message_info.py b/src/ucp_sdk/models/schemas/shopping/types/message_info.py index e0bcb31..7528d5b 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/message_info.py +++ b/src/ucp_sdk/models/schemas/shopping/types/message_info.py @@ -24,26 +24,26 @@ class MessageInfo(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - type: Literal["info"] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal["info"] + """ Message type discriminator. """ - path: str | None = None - """ + path: str | None = None + """ RFC 9535 JSONPath to the component the message refers to. """ - code: str | None = None - """ + code: str | None = None + """ Info code for programmatic handling. """ - content_type: Literal["plain", "markdown"] | None = "plain" - """ + content_type: Literal["plain", "markdown"] | None = "plain" + """ Content format, default = plain. """ - content: str - """ + content: str + """ Human-readable message. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/message_warning.py b/src/ucp_sdk/models/schemas/shopping/types/message_warning.py index f5eee46..6b055c9 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/message_warning.py +++ b/src/ucp_sdk/models/schemas/shopping/types/message_warning.py @@ -24,26 +24,26 @@ class MessageWarning(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - type: Literal["warning"] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal["warning"] + """ Message type discriminator. """ - path: str | None = None - """ + path: str | None = None + """ JSONPath (RFC 9535) to related field (e.g., $.line_items[0]). """ - code: str - """ + code: str + """ Warning code. Machine-readable identifier for the warning type (e.g., final_sale, prop65, fulfillment_changed, age_restricted, etc.). """ - content: str - """ + content: str + """ Human-readable warning message that MUST be displayed. """ - content_type: Literal["plain", "markdown"] | None = "plain" - """ + content_type: Literal["plain", "markdown"] | None = "plain" + """ Content format, default = plain. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/order_confirmation.py b/src/ucp_sdk/models/schemas/shopping/types/order_confirmation.py index b17864a..17772d2 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/order_confirmation.py +++ b/src/ucp_sdk/models/schemas/shopping/types/order_confirmation.py @@ -22,18 +22,17 @@ class OrderConfirmation(BaseModel): - """ - Order details available at the time of checkout completion. - """ + """Order details available at the time of checkout completion. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Unique order identifier. """ - permalink_url: AnyUrl - """ + permalink_url: AnyUrl + """ Permalink to access the order on merchant site. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/order_line_item.py b/src/ucp_sdk/models/schemas/shopping/types/order_line_item.py index 8f991bc..06baa80 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/order_line_item.py +++ b/src/ucp_sdk/models/schemas/shopping/types/order_line_item.py @@ -27,48 +27,47 @@ class Quantity(BaseModel): - """ - Quantity tracking. Both total and fulfilled are derived from events. - """ + """Quantity tracking. Both total and fulfilled are derived from events. + """ - model_config = ConfigDict( - extra="allow", - ) - total: int = Field(..., ge=0) - """ + model_config = ConfigDict( + extra="allow", + ) + total: int = Field(..., ge=0) + """ Current total quantity. """ - fulfilled: int = Field(..., ge=0) - """ + fulfilled: int = Field(..., ge=0) + """ Quantity fulfilled (sum from fulfillment events). """ class OrderLineItem(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Line item identifier. """ - item: item_1.Item - """ + item: item_1.Item + """ Product data (id, title, price, image_url). """ - quantity: Quantity - """ + quantity: Quantity + """ Quantity tracking. Both total and fulfilled are derived from events. """ - totals: list[total_1.Total] - """ + totals: list[total_1.Total] + """ Line item totals breakdown. """ - status: Literal["processing", "partial", "fulfilled"] - """ + status: Literal["processing", "partial", "fulfilled"] + """ Derived status: fulfilled if quantity.fulfilled == quantity.total, partial if quantity.fulfilled > 0, otherwise processing. """ - parent_id: str | None = None - """ + parent_id: str | None = None + """ Parent line item identifier for any nested structures. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_credential.py b/src/ucp_sdk/models/schemas/shopping/types/payment_credential.py index 4a4e09d..31ec712 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_credential.py +++ b/src/ucp_sdk/models/schemas/shopping/types/payment_credential.py @@ -22,14 +22,13 @@ class PaymentCredential(BaseModel): - """ - The base definition for any payment credential. Handlers define specific credential types. - """ + """The base definition for any payment credential. Handlers define specific credential types. + """ - model_config = ConfigDict( - extra="allow", - ) - type: str - """ + model_config = ConfigDict( + extra="allow", + ) + type: str + """ The credential type discriminator. Specific schemas will constrain this to a constant value. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_identity.py b/src/ucp_sdk/models/schemas/shopping/types/payment_identity.py index b30f85d..9baa241 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_identity.py +++ b/src/ucp_sdk/models/schemas/shopping/types/payment_identity.py @@ -22,14 +22,13 @@ class PaymentIdentity(BaseModel): - """ - Identity of a participant for token binding. The access_token uniquely identifies the participant who tokens should be bound to. - """ + """Identity of a participant for token binding. The access_token uniquely identifies the participant who tokens should be bound to. + """ - model_config = ConfigDict( - extra="allow", - ) - access_token: str - """ + model_config = ConfigDict( + extra="allow", + ) + access_token: str + """ Unique identifier for this participant, obtained during onboarding with the tokenizer. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py b/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py index 4b7bf78..8c06b17 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py +++ b/src/ucp_sdk/models/schemas/shopping/types/payment_instrument.py @@ -26,45 +26,43 @@ class PaymentInstrument(BaseModel): - """ - The base definition for any payment instrument. It links the instrument to a specific payment handler. - """ + """The base definition for any payment instrument. It links the instrument to a specific payment handler. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ A unique identifier for this instrument instance, assigned by the platform. """ - handler_id: str - """ + handler_id: str + """ The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition. """ - type: str - """ + type: str + """ The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value. """ - billing_address: postal_address.PostalAddress | None = None - """ + billing_address: postal_address.PostalAddress | None = None + """ The billing address associated with this payment method. """ - credential: payment_credential.PaymentCredential | None = None - display: dict[str, Any] | None = None - """ + credential: payment_credential.PaymentCredential | None = None + display: dict[str, Any] | None = None + """ Display information for this payment instrument. Each payment instrument schema defines its specific display properties, as outlined by the payment handler. """ class SelectedPaymentInstrument(PaymentInstrument): - """ - A payment instrument with selection state. - """ + """A payment instrument with selection state. + """ - model_config = ConfigDict( - extra="allow", - ) - selected: bool | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + selected: bool | None = None + """ Whether this instrument is selected by the user. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/platform_fulfillment_config.py b/src/ucp_sdk/models/schemas/shopping/types/platform_fulfillment_config.py index 5757821..74dc8da 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/platform_fulfillment_config.py +++ b/src/ucp_sdk/models/schemas/shopping/types/platform_fulfillment_config.py @@ -22,14 +22,13 @@ class PlatformFulfillmentConfig(BaseModel): - """ - Platform's fulfillment configuration. - """ + """Platform's fulfillment configuration. + """ - model_config = ConfigDict( - extra="allow", - ) - supports_multi_group: bool | None = False - """ + model_config = ConfigDict( + extra="allow", + ) + supports_multi_group: bool | None = False + """ Enables multiple groups per method. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/postal_address.py b/src/ucp_sdk/models/schemas/shopping/types/postal_address.py index 7c57364..3df5114 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/postal_address.py +++ b/src/ucp_sdk/models/schemas/shopping/types/postal_address.py @@ -22,42 +22,42 @@ class PostalAddress(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - extended_address: str | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + extended_address: str | None = None + """ An address extension such as an apartment number, C/O or alternative name. """ - street_address: str | None = None - """ + street_address: str | None = None + """ The street address. """ - address_locality: str | None = None - """ + address_locality: str | None = None + """ The locality in which the street address is, and which is in the region. For example, Mountain View. """ - address_region: str | None = None - """ + address_region: str | None = None + """ The region in which the locality is, and which is in the country. Required for applicable countries (i.e. state in US, province in CA). For example, California or another appropriate first-level Administrative division. """ - address_country: str | None = None - """ + address_country: str | None = None + """ The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. """ - postal_code: str | None = None - """ + postal_code: str | None = None + """ The postal code. For example, 94043. """ - first_name: str | None = None - """ + first_name: str | None = None + """ Optional. First name of the contact associated with the address. """ - last_name: str | None = None - """ + last_name: str | None = None + """ Optional. Last name of the contact associated with the address. """ - phone_number: str | None = None - """ + phone_number: str | None = None + """ Optional. Phone number of the contact associated with the address. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/retail_location.py b/src/ucp_sdk/models/schemas/shopping/types/retail_location.py index c0353af..a7f9cf7 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/retail_location.py +++ b/src/ucp_sdk/models/schemas/shopping/types/retail_location.py @@ -24,22 +24,21 @@ class RetailLocation(BaseModel): - """ - A pickup location (retail store, locker, etc.). - """ + """A pickup location (retail store, locker, etc.). + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ Unique location identifier. """ - name: str - """ + name: str + """ Location name (e.g., store name). """ - address: postal_address.PostalAddress | None = None - """ + address: postal_address.PostalAddress | None = None + """ Physical address of the location. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/shipping_destination.py b/src/ucp_sdk/models/schemas/shopping/types/shipping_destination.py index f8b929d..f3ef9eb 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/shipping_destination.py +++ b/src/ucp_sdk/models/schemas/shopping/types/shipping_destination.py @@ -24,14 +24,13 @@ class ShippingDestination(PostalAddress): - """ - Shipping destination. - """ + """Shipping destination. + """ - model_config = ConfigDict( - extra="allow", - ) - id: str - """ + model_config = ConfigDict( + extra="allow", + ) + id: str + """ ID specific to this shipping destination. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/token_credential.py b/src/ucp_sdk/models/schemas/shopping/types/token_credential.py index 596f097..8d51dd5 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/token_credential.py +++ b/src/ucp_sdk/models/schemas/shopping/types/token_credential.py @@ -24,18 +24,17 @@ class TokenCredential(PaymentCredential): - """ - Base token credential schema. Concrete payment handlers may extend this schema with additional fields and define their own constraints. - """ + """Base token credential schema. Concrete payment handlers may extend this schema with additional fields and define their own constraints. + """ - model_config = ConfigDict( - extra="allow", - ) - type: str - """ + model_config = ConfigDict( + extra="allow", + ) + type: str + """ The specific type of token produced by the handler (e.g., 'stripe_token'). """ - token: str - """ + token: str + """ The token value. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/total.py b/src/ucp_sdk/models/schemas/shopping/types/total.py index 623c2dd..1574a17 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/total.py +++ b/src/ucp_sdk/models/schemas/shopping/types/total.py @@ -24,26 +24,26 @@ class Total(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - type: Literal[ - "items_discount", - "subtotal", - "discount", - "fulfillment", - "tax", - "fee", - "total", - ] - """ + model_config = ConfigDict( + extra="allow", + ) + type: Literal[ + "items_discount", + "subtotal", + "discount", + "fulfillment", + "tax", + "fee", + "total", + ] + """ Type of total categorization. """ - display_text: str | None = None - """ + display_text: str | None = None + """ Text to display against the amount. Should reflect appropriate method (e.g., 'Shipping', 'Delivery'). """ - amount: int = Field(..., ge=0) - """ + amount: int = Field(..., ge=0) + """ If type == total, sums subtotal - discount + fulfillment + tax + fee. Should be >= 0. Amount in minor (cents) currency units. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_group_request.py b/src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_group_request.py new file mode 100644 index 0000000..077e368 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_group_request.py @@ -0,0 +1,38 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class UpdateFulfillmentGroupRequest(BaseModel): + """A merchant-generated package/group of line items with fulfillment options. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + Group identifier for referencing merchant-generated groups in updates. + """ + selected_option_id: str | None = None + """ + ID of the selected fulfillment option for this group. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_method_request.py b/src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_method_request.py new file mode 100644 index 0000000..a2acff9 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_method_request.py @@ -0,0 +1,56 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import fulfillment_destination, update_fulfillment_group_request + + +class UpdateFulfillmentMethodRequest(BaseModel): + """A fulfillment method (shipping or pickup) with destinations and groups. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + Unique fulfillment method identifier. + """ + line_item_ids: list[str] + """ + Line item IDs fulfilled via this method. + """ + destinations: list[fulfillment_destination.FulfillmentDestination] | None = ( + None + ) + """ + Available destinations. For shipping: addresses. For pickup: retail locations. + """ + selected_destination_id: str | None = None + """ + ID of the selected destination. + """ + groups: ( + list[update_fulfillment_group_request.UpdateFulfillmentGroupRequest] | None + ) = None + """ + Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/update_line_item_request.py b/src/ucp_sdk/models/schemas/shopping/types/update_line_item_request.py new file mode 100644 index 0000000..9eef25b --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/update_line_item_request.py @@ -0,0 +1,42 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict, Field + +from . import item as item_1 + + +class UpdateLineItemRequest(BaseModel): + """Line item object. Expected to use the currency of the parent object. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str | None = None + item: item_1.Item + quantity: int = Field(..., ge=1) + """ + Quantity of the item being purchased. + """ + parent_id: str | None = None + """ + Parent line item identifier for any nested structures. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/update_checkout_request.py b/src/ucp_sdk/models/schemas/shopping/update_checkout_request.py new file mode 100644 index 0000000..0eb10ba --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/update_checkout_request.py @@ -0,0 +1,49 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import payment as payment_1 +from .types import buyer as buyer_1 +from .types import context as context_1 +from .types import update_line_item_request + + +class UpdateCheckoutRequest(BaseModel): + """Base checkout schema. Extensions compose onto this using allOf. + """ + + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + Unique identifier of the checkout session. + """ + line_items: list[update_line_item_request.UpdateLineItemRequest] + """ + List of line items being checked out. + """ + buyer: buyer_1.Buyer | None = None + """ + Representation of the buyer. + """ + context: context_1.Context | None = None + payment: payment_1.Payment | None = None diff --git a/src/ucp_sdk/models/schemas/transports/embedded_config.py b/src/ucp_sdk/models/schemas/transports/embedded_config.py index 8f3cba7..1e5b298 100644 --- a/src/ucp_sdk/models/schemas/transports/embedded_config.py +++ b/src/ucp_sdk/models/schemas/transports/embedded_config.py @@ -22,14 +22,13 @@ class EmbeddedTransportConfig(BaseModel): - """ - Per-checkout configuration for embedded transport binding. Allows businesses to vary ECP availability and delegations based on cart contents, agent authorization, or policy. - """ + """Per-checkout configuration for embedded transport binding. Allows businesses to vary ECP availability and delegations based on cart contents, agent authorization, or policy. + """ - model_config = ConfigDict( - extra="allow", - ) - delegate: list[str] | None = None - """ + model_config = ConfigDict( + extra="allow", + ) + delegate: list[str] | None = None + """ Delegations the business allows. At service-level, declares available delegations. In checkout responses, confirms accepted delegations for this session. """ diff --git a/src/ucp_sdk/models/schemas/ucp.py b/src/ucp_sdk/models/schemas/ucp.py index d6fd460..6d1be0c 100644 --- a/src/ucp_sdk/models/schemas/ucp.py +++ b/src/ucp_sdk/models/schemas/ucp.py @@ -20,24 +20,24 @@ from ._internal import Base_3 as Base from ._internal import BusinessSchema_3 as BusinessSchema +from ._internal import Entity +from ._internal import PlatformSchema_3 as PlatformSchema from ._internal import ( - Entity, - ResponseCheckoutSchema, - ResponseOrderSchema, - ReverseDomainName, - UcpMetadata, - Version, + ResponseCheckoutSchema, + ResponseOrderSchema, + ReverseDomainName, + UcpMetadata, + Version, ) -from ._internal import PlatformSchema_3 as PlatformSchema __all__ = [ - "Base", - "BusinessSchema", - "Entity", - "PlatformSchema", - "ResponseCheckoutSchema", - "ResponseOrderSchema", - "ReverseDomainName", - "UcpMetadata", - "Version", + "Base", + "BusinessSchema", + "Entity", + "PlatformSchema", + "ResponseCheckoutSchema", + "ResponseOrderSchema", + "ReverseDomainName", + "UcpMetadata", + "Version", ] diff --git a/src/ucp_sdk/models/services/shopping/embedded.py b/src/ucp_sdk/models/services/shopping/embedded.py index 7da4251..cc5f288 100644 --- a/src/ucp_sdk/models/services/shopping/embedded.py +++ b/src/ucp_sdk/models/services/shopping/embedded.py @@ -24,7 +24,7 @@ class EmbeddedProtocol(RootModel[Any]): - root: Any = Field(..., title="Embedded Protocol") - """ + root: Any = Field(..., title="Embedded Protocol") + """ Embedded Protocol (EP) methods for UCP capabilities. Methods are sent from Merchant to Host via postMessage/JSON-RPC 2.0. Method prefixes indicate capability scope: ec.* (checkout). Future capabilities may define additional prefixes (e.g., eo.* for order). """ diff --git a/src/ucp_sdk/models/services/shopping/openapi.py b/src/ucp_sdk/models/services/shopping/openapi.py index 66b2502..0f53946 100644 --- a/src/ucp_sdk/models/services/shopping/openapi.py +++ b/src/ucp_sdk/models/services/shopping/openapi.py @@ -24,4 +24,4 @@ class Model(RootModel[Any]): - root: Any + root: Any diff --git a/src/ucp_sdk/models/services/shopping/openrpc.py b/src/ucp_sdk/models/services/shopping/openrpc.py index 66b2502..0f53946 100644 --- a/src/ucp_sdk/models/services/shopping/openrpc.py +++ b/src/ucp_sdk/models/services/shopping/openrpc.py @@ -24,4 +24,4 @@ class Model(RootModel[Any]): - root: Any + root: Any From dcfadbaf424a195742abc3db58dd0cff600ab7a2 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 16:27:12 +0100 Subject: [PATCH 20/22] change naming convention Change-Id: If59a9d92e40d71bc9d69d171b7020310ee9e26a1 --- preprocess_schemas.py | 8 ++++---- ...e_checkout_request.py => checkout_complete_request.py} | 2 +- ...ate_checkout_request.py => checkout_create_request.py} | 6 +++--- ...ate_checkout_request.py => checkout_update_request.py} | 6 +++--- ...oup_request.py => fulfillment_group_create_request.py} | 2 +- ...oup_request.py => fulfillment_group_update_request.py} | 2 +- ...od_request.py => fulfillment_method_create_request.py} | 6 +++--- ...od_request.py => fulfillment_method_update_request.py} | 6 +++--- ...e_line_item_request.py => line_item_create_request.py} | 2 +- ...e_line_item_request.py => line_item_update_request.py} | 2 +- 10 files changed, 21 insertions(+), 21 deletions(-) rename src/ucp_sdk/models/schemas/shopping/{complete_checkout_request.py => checkout_complete_request.py} (95%) rename src/ucp_sdk/models/schemas/shopping/{create_checkout_request.py => checkout_create_request.py} (89%) rename src/ucp_sdk/models/schemas/shopping/{update_checkout_request.py => checkout_update_request.py} (89%) rename src/ucp_sdk/models/schemas/shopping/types/{create_fulfillment_group_request.py => fulfillment_group_create_request.py} (95%) rename src/ucp_sdk/models/schemas/shopping/types/{update_fulfillment_group_request.py => fulfillment_group_update_request.py} (95%) rename src/ucp_sdk/models/schemas/shopping/types/{create_fulfillment_method_request.py => fulfillment_method_create_request.py} (89%) rename src/ucp_sdk/models/schemas/shopping/types/{update_fulfillment_method_request.py => fulfillment_method_update_request.py} (89%) rename src/ucp_sdk/models/schemas/shopping/types/{create_line_item_request.py => line_item_create_request.py} (96%) rename src/ucp_sdk/models/schemas/shopping/types/{update_line_item_request.py => line_item_update_request.py} (96%) diff --git a/preprocess_schemas.py b/preprocess_schemas.py index 60053e9..843f281 100644 --- a/preprocess_schemas.py +++ b/preprocess_schemas.py @@ -53,7 +53,7 @@ def process_file(schema_file, all_variant_needs): def get_variant_filename(base_path, op): p = Path(base_path) - return p.parent / f"{op}_{p.stem}_request.json" + return p.parent / f"{p.stem}_{op}_request.json" def generate_variants(schema_file, schema, ops, all_variant_needs): @@ -63,7 +63,7 @@ def generate_variants(schema_file, schema, ops, all_variant_needs): # Update title and id base_title = schema.get("title", schema_file_path.stem) - variant_schema["title"] = f"{op.capitalize()} {base_title} Request" + variant_schema["title"] = f"{base_title} {op.capitalize()} Request" # Update $id if present if "$id" in variant_schema: @@ -74,7 +74,7 @@ def generate_variants(schema_file, schema, ops, all_variant_needs): if "." in old_id_filename: stem = old_id_filename.split(".")[0] ext = old_id_filename.split(".")[-1] - new_id_filename = f"{op}_{stem}_request.{ext}" + new_id_filename = f"{stem}_{op}_request.{ext}" variant_schema["$id"] = "/".join( old_id_parts[:-1] + [new_id_filename] ) @@ -126,7 +126,7 @@ def update_refs(obj): str(target_base_abs) in all_variant_needs and op in all_variant_needs[str(target_base_abs)] ): - variant_ref_filename = f"{op}_{ref_path.stem}_request.json" + variant_ref_filename = f"{ref_path.stem}_{op}_request.json" obj["$ref"] = str(ref_path.parent / variant_ref_filename) for k, v in obj.items(): update_refs(v) diff --git a/src/ucp_sdk/models/schemas/shopping/complete_checkout_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py similarity index 95% rename from src/ucp_sdk/models/schemas/shopping/complete_checkout_request.py rename to src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py index c2df263..e8226ef 100644 --- a/src/ucp_sdk/models/schemas/shopping/complete_checkout_request.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py @@ -23,7 +23,7 @@ from . import payment as payment_1 -class CompleteCheckoutRequest(BaseModel): +class CheckoutCompleteRequest(BaseModel): """Base checkout schema. Extensions compose onto this using allOf. """ diff --git a/src/ucp_sdk/models/schemas/shopping/create_checkout_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py similarity index 89% rename from src/ucp_sdk/models/schemas/shopping/create_checkout_request.py rename to src/ucp_sdk/models/schemas/shopping/checkout_create_request.py index 4cf505e..4f82926 100644 --- a/src/ucp_sdk/models/schemas/shopping/create_checkout_request.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py @@ -23,17 +23,17 @@ from . import payment as payment_1 from .types import buyer as buyer_1 from .types import context as context_1 -from .types import create_line_item_request +from .types import line_item_create_request -class CreateCheckoutRequest(BaseModel): +class CheckoutCreateRequest(BaseModel): """Base checkout schema. Extensions compose onto this using allOf. """ model_config = ConfigDict( extra="allow", ) - line_items: list[create_line_item_request.CreateLineItemRequest] + line_items: list[line_item_create_request.LineItemCreateRequest] """ List of line items being checked out. """ diff --git a/src/ucp_sdk/models/schemas/shopping/update_checkout_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py similarity index 89% rename from src/ucp_sdk/models/schemas/shopping/update_checkout_request.py rename to src/ucp_sdk/models/schemas/shopping/checkout_update_request.py index 0eb10ba..d022448 100644 --- a/src/ucp_sdk/models/schemas/shopping/update_checkout_request.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py @@ -23,10 +23,10 @@ from . import payment as payment_1 from .types import buyer as buyer_1 from .types import context as context_1 -from .types import update_line_item_request +from .types import line_item_update_request -class UpdateCheckoutRequest(BaseModel): +class CheckoutUpdateRequest(BaseModel): """Base checkout schema. Extensions compose onto this using allOf. """ @@ -37,7 +37,7 @@ class UpdateCheckoutRequest(BaseModel): """ Unique identifier of the checkout session. """ - line_items: list[update_line_item_request.UpdateLineItemRequest] + line_items: list[line_item_update_request.LineItemUpdateRequest] """ List of line items being checked out. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_group_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py similarity index 95% rename from src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_group_request.py rename to src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py index 9a87100..a91ea1e 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_group_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_create_request.py @@ -21,7 +21,7 @@ from pydantic import BaseModel, ConfigDict -class CreateFulfillmentGroupRequest(BaseModel): +class FulfillmentGroupCreateRequest(BaseModel): """A merchant-generated package/group of line items with fulfillment options. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_group_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py similarity index 95% rename from src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_group_request.py rename to src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py index 077e368..270ca8e 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_group_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_group_update_request.py @@ -21,7 +21,7 @@ from pydantic import BaseModel, ConfigDict -class UpdateFulfillmentGroupRequest(BaseModel): +class FulfillmentGroupUpdateRequest(BaseModel): """A merchant-generated package/group of line items with fulfillment options. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_method_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py similarity index 89% rename from src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_method_request.py rename to src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py index 1963f13..3763339 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/create_fulfillment_method_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_create_request.py @@ -22,10 +22,10 @@ from pydantic import BaseModel, ConfigDict -from . import create_fulfillment_group_request, fulfillment_destination +from . import fulfillment_destination, fulfillment_group_create_request -class CreateFulfillmentMethodRequest(BaseModel): +class FulfillmentMethodCreateRequest(BaseModel): """A fulfillment method (shipping or pickup) with destinations and groups. """ @@ -51,7 +51,7 @@ class CreateFulfillmentMethodRequest(BaseModel): ID of the selected destination. """ groups: ( - list[create_fulfillment_group_request.CreateFulfillmentGroupRequest] | None + list[fulfillment_group_create_request.FulfillmentGroupCreateRequest] | None ) = None """ Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. diff --git a/src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_method_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py similarity index 89% rename from src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_method_request.py rename to src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py index a2acff9..10e2dae 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/update_fulfillment_method_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_method_update_request.py @@ -20,10 +20,10 @@ from pydantic import BaseModel, ConfigDict -from . import fulfillment_destination, update_fulfillment_group_request +from . import fulfillment_destination, fulfillment_group_update_request -class UpdateFulfillmentMethodRequest(BaseModel): +class FulfillmentMethodUpdateRequest(BaseModel): """A fulfillment method (shipping or pickup) with destinations and groups. """ @@ -49,7 +49,7 @@ class UpdateFulfillmentMethodRequest(BaseModel): ID of the selected destination. """ groups: ( - list[update_fulfillment_group_request.UpdateFulfillmentGroupRequest] | None + list[fulfillment_group_update_request.FulfillmentGroupUpdateRequest] | None ) = None """ Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. diff --git a/src/ucp_sdk/models/schemas/shopping/types/create_line_item_request.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py similarity index 96% rename from src/ucp_sdk/models/schemas/shopping/types/create_line_item_request.py rename to src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py index a0837ec..aba7e29 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/create_line_item_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py @@ -23,7 +23,7 @@ from . import item as item_1 -class CreateLineItemRequest(BaseModel): +class LineItemCreateRequest(BaseModel): """Line item object. Expected to use the currency of the parent object. """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/update_line_item_request.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py similarity index 96% rename from src/ucp_sdk/models/schemas/shopping/types/update_line_item_request.py rename to src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py index 9eef25b..7b99fe0 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/update_line_item_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py @@ -23,7 +23,7 @@ from . import item as item_1 -class UpdateLineItemRequest(BaseModel): +class LineItemUpdateRequest(BaseModel): """Line item object. Expected to use the currency of the parent object. """ From c9014f3a10beebbfb1130abeb9b4149834d70111 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 16:44:51 +0100 Subject: [PATCH 21/22] update preprocessing to include more request types Change-Id: I79bccca52f3a1d9d721c6a6f10d128f544411840 --- preprocess_schemas.py | 137 +++++++++++++----- .../shopping/checkout_complete_request.py | 4 +- .../shopping/checkout_create_request.py | 16 +- .../shopping/checkout_update_request.py | 16 +- .../shopping/payment_complete_request.py | 36 +++++ .../shopping/payment_create_request.py | 36 +++++ .../shopping/payment_update_request.py | 36 +++++ .../shopping/types/buyer_create_request.py | 43 ++++++ .../shopping/types/buyer_update_request.py | 43 ++++++ .../shopping/types/context_create_request.py | 42 ++++++ .../shopping/types/context_update_request.py | 42 ++++++ ...illment_available_method_create_request.py | 30 ++++ ...illment_available_method_update_request.py | 30 ++++ .../types/fulfillment_create_request.py | 39 +++++ .../fulfillment_option_create_request.py | 30 ++++ .../fulfillment_option_update_request.py | 30 ++++ .../types/fulfillment_update_request.py | 39 +++++ .../shopping/types/item_create_request.py | 31 ++++ .../shopping/types/item_update_request.py | 31 ++++ .../types/line_item_create_request.py | 4 +- .../types/line_item_update_request.py | 4 +- .../types/postal_address_create_request.py | 63 ++++++++ .../types/postal_address_update_request.py | 63 ++++++++ .../types/retail_location_create_request.py | 42 ++++++ .../types/retail_location_update_request.py | 42 ++++++ .../shopping/types/total_create_request.py | 27 ++++ .../shopping/types/total_update_request.py | 27 ++++ ucp | 1 + 28 files changed, 929 insertions(+), 55 deletions(-) create mode 100644 src/ucp_sdk/models/schemas/shopping/payment_complete_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/payment_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/payment_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/buyer_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/buyer_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/context_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/context_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/item_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/item_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/postal_address_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/postal_address_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/total_create_request.py create mode 100644 src/ucp_sdk/models/schemas/shopping/types/total_update_request.py create mode 160000 ucp diff --git a/preprocess_schemas.py b/preprocess_schemas.py index 843f281..3a84cc7 100644 --- a/preprocess_schemas.py +++ b/preprocess_schemas.py @@ -18,37 +18,45 @@ import sys -def process_file(schema_file, all_variant_needs): - """Analyzes a schema file to see which request variants it needs.""" - try: - with open(schema_file, "r") as f: - schema = json.load(f) - except Exception as e: - print(f"Error loading {schema_file}: {e}") - return None - - if ( - not isinstance(schema, dict) - or schema.get("type") != "object" - or "properties" not in schema - ): - return None - - ops_found = set() - for prop_name, prop_data in schema.get("properties", {}).items(): +def get_explicit_ops(schema): + """Finds ops explicitly mentioned in ucp_request fields.""" + ops = set() + properties = schema.get("properties", {}) + for prop_data in properties.values(): if not isinstance(prop_data, dict): continue ucp_req = prop_data.get("ucp_request") if isinstance(ucp_req, str): - if ucp_req != "omit": - ops_found.update(["create", "update", "complete"]) + # Strings like "omit" or "required" only imply standard ops. + # "complete" request should only be generated when it's explicitly defined in a dict. + ops.update(["create", "update"]) elif isinstance(ucp_req, dict): for op in ucp_req: - ops_found.add(op) + ops.add(op) + return ops - if ops_found: - all_variant_needs[str(schema_file.resolve())] = ops_found - return schema + +def get_props_with_refs(schema, schema_file_path): + """Finds all external schema references associated with their properties.""" + results = [] # list of (prop_name, abs_ref_path) + + def find_refs(obj, prop_name): + if isinstance(obj, dict): + if "$ref" in obj: + ref = obj["$ref"] + if "#" not in ref: + ref_path = (schema_file_path.parent / ref).resolve() + results.append((prop_name, str(ref_path))) + for v in obj.values(): + find_refs(v, prop_name) + elif isinstance(obj, list): + for item in obj: + find_refs(item, prop_name) + + properties = schema.get("properties", {}) + for prop_name, prop_data in properties.items(): + find_refs(prop_data, prop_name) + return results def get_variant_filename(base_path, op): @@ -140,14 +148,14 @@ def update_refs(obj): if is_required: new_required.append(prop_name) - if new_properties: - variant_schema["properties"] = new_properties - variant_schema["required"] = new_required + # Always generate the variant schema to avoid breaking refs in parents + variant_schema["properties"] = new_properties + variant_schema["required"] = new_required - variant_path = get_variant_filename(schema_file_path, op) - with open(variant_path, "w") as f: - json.dump(variant_schema, f, indent=2) - print(f"Generated {variant_path}") + variant_path = get_variant_filename(schema_file_path, op) + with open(variant_path, "w") as f: + json.dump(variant_schema, f, indent=2) + print(f"Generated {variant_path}") def main(): @@ -162,16 +170,75 @@ def main(): all_files = list(schema_dir_path.rglob("*.json")) - all_variant_needs = {} schemas_cache = {} + schema_props_refs = {} + all_variant_needs = {} + # 1. First pass: load all schemas and find properties with refs for f in all_files: if "_request.json" in f.name: continue - s = process_file(f, all_variant_needs) - if s: - schemas_cache[str(f.resolve())] = s + try: + with open(f, "r") as open_f: + schema = json.load(open_f) + if ( + not isinstance(schema, dict) + or schema.get("type") != "object" + or "properties" not in schema + ): + continue + + abs_path = str(f.resolve()) + schemas_cache[abs_path] = schema + schema_props_refs[abs_path] = get_props_with_refs(schema, f) + + # 2. Get explicit needs defined in the schema itself + explicit_ops = get_explicit_ops(schema) + if explicit_ops: + all_variant_needs[abs_path] = explicit_ops + except Exception as e: + print(f"Error processing {f}: {e}") + + # 3. Transitive dependency tracking (Parent -> Child): + # If P needs variant OP, and P includes property S (not omitted for OP), + # then S also needs variant OP to ensure ref matching works correctly. + changed = True + while changed: + changed = False + for abs_path, props_refs in schema_props_refs.items(): + if abs_path not in all_variant_needs: + continue + parent_schema = schemas_cache[abs_path] + parent_ops = all_variant_needs[abs_path] + + for op in list(parent_ops): + for prop_name, ref_path in props_refs: + if ref_path not in schemas_cache: + continue + + # Check if this property is omitted for this op in parent + prop_data = parent_schema["properties"].get(prop_name, {}) + ucp_req = prop_data.get("ucp_request") + + include = True + if ucp_req is not None: + if isinstance(ucp_req, str): + if ucp_req == "omit": + include = False + elif isinstance(ucp_req, dict): + op_val = ucp_req.get(op) + if op_val == "omit" or op_val is None: + include = False + + if include: + # Propagate op from parent to child + child_needs = all_variant_needs.get(ref_path, set()) + if op not in child_needs: + all_variant_needs.setdefault(ref_path, set()).add(op) + changed = True + + # 4. Final pass: generate variants for f_abs, ops in all_variant_needs.items(): generate_variants(f_abs, schemas_cache[f_abs], ops, all_variant_needs) diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py index e8226ef..3c8c487 100644 --- a/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout_complete_request.py @@ -20,7 +20,7 @@ from pydantic import BaseModel, ConfigDict -from . import payment as payment_1 +from . import payment_complete_request class CheckoutCompleteRequest(BaseModel): @@ -30,4 +30,4 @@ class CheckoutCompleteRequest(BaseModel): model_config = ConfigDict( extra="allow", ) - payment: payment_1.Payment + payment: payment_complete_request.PaymentCompleteRequest diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py index 4f82926..7a0ec30 100644 --- a/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout_create_request.py @@ -20,10 +20,12 @@ from pydantic import BaseModel, ConfigDict -from . import payment as payment_1 -from .types import buyer as buyer_1 -from .types import context as context_1 -from .types import line_item_create_request +from . import payment_create_request +from .types import ( + buyer_create_request, + context_create_request, + line_item_create_request, +) class CheckoutCreateRequest(BaseModel): @@ -37,9 +39,9 @@ class CheckoutCreateRequest(BaseModel): """ List of line items being checked out. """ - buyer: buyer_1.Buyer | None = None + buyer: buyer_create_request.BuyerCreateRequest | None = None """ Representation of the buyer. """ - context: context_1.Context | None = None - payment: payment_1.Payment | None = None + context: context_create_request.ContextCreateRequest | None = None + payment: payment_create_request.PaymentCreateRequest | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py b/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py index d022448..bedba40 100644 --- a/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py +++ b/src/ucp_sdk/models/schemas/shopping/checkout_update_request.py @@ -20,10 +20,12 @@ from pydantic import BaseModel, ConfigDict -from . import payment as payment_1 -from .types import buyer as buyer_1 -from .types import context as context_1 -from .types import line_item_update_request +from . import payment_update_request +from .types import ( + buyer_update_request, + context_update_request, + line_item_update_request, +) class CheckoutUpdateRequest(BaseModel): @@ -41,9 +43,9 @@ class CheckoutUpdateRequest(BaseModel): """ List of line items being checked out. """ - buyer: buyer_1.Buyer | None = None + buyer: buyer_update_request.BuyerUpdateRequest | None = None """ Representation of the buyer. """ - context: context_1.Context | None = None - payment: payment_1.Payment | None = None + context: context_update_request.ContextUpdateRequest | None = None + payment: payment_update_request.PaymentUpdateRequest | None = None diff --git a/src/ucp_sdk/models/schemas/shopping/payment_complete_request.py b/src/ucp_sdk/models/schemas/shopping/payment_complete_request.py new file mode 100644 index 0000000..8c157ba --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/payment_complete_request.py @@ -0,0 +1,36 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from .types import payment_instrument + + +class PaymentCompleteRequest(BaseModel): + """Payment configuration containing handlers. + """ + + model_config = ConfigDict( + extra="allow", + ) + instruments: list[payment_instrument.SelectedPaymentInstrument] | None = None + """ + The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/payment_create_request.py b/src/ucp_sdk/models/schemas/shopping/payment_create_request.py new file mode 100644 index 0000000..382cd4a --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/payment_create_request.py @@ -0,0 +1,36 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from .types import payment_instrument + + +class PaymentCreateRequest(BaseModel): + """Payment configuration containing handlers. + """ + + model_config = ConfigDict( + extra="allow", + ) + instruments: list[payment_instrument.SelectedPaymentInstrument] | None = None + """ + The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/payment_update_request.py b/src/ucp_sdk/models/schemas/shopping/payment_update_request.py new file mode 100644 index 0000000..046cbe3 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/payment_update_request.py @@ -0,0 +1,36 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from .types import payment_instrument + + +class PaymentUpdateRequest(BaseModel): + """Payment configuration containing handlers. + """ + + model_config = ConfigDict( + extra="allow", + ) + instruments: list[payment_instrument.SelectedPaymentInstrument] | None = None + """ + The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/buyer_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/buyer_create_request.py new file mode 100644 index 0000000..34b26f0 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/buyer_create_request.py @@ -0,0 +1,43 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class BuyerCreateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + first_name: str | None = None + """ + First name of the buyer. + """ + last_name: str | None = None + """ + Last name of the buyer. + """ + email: str | None = None + """ + Email of the buyer. + """ + phone_number: str | None = None + """ + E.164 standard. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/buyer_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/buyer_update_request.py new file mode 100644 index 0000000..cacbb99 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/buyer_update_request.py @@ -0,0 +1,43 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class BuyerUpdateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + first_name: str | None = None + """ + First name of the buyer. + """ + last_name: str | None = None + """ + Last name of the buyer. + """ + email: str | None = None + """ + Email of the buyer. + """ + phone_number: str | None = None + """ + E.164 standard. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/context_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/context_create_request.py new file mode 100644 index 0000000..0e507e4 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/context_create_request.py @@ -0,0 +1,42 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class ContextCreateRequest(BaseModel): + """Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. + """ + + model_config = ConfigDict( + extra="allow", + ) + address_country: str | None = None + """ + The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. + """ + address_region: str | None = None + """ + The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. + """ + postal_code: str | None = None + """ + The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/context_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/context_update_request.py new file mode 100644 index 0000000..54c0dc4 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/context_update_request.py @@ -0,0 +1,42 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class ContextUpdateRequest(BaseModel): + """Provisional buyer signals for relevance and localization: product availability, pricing, currency, tax, shipping, payment methods, and eligibility (e.g., student or affiliation discounts). Businesses SHOULD use these values when authoritative data (e.g., address) is absent, and MAY ignore unsupported values without returning errors. Context can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. Platforms SHOULD progressively enhance context throughout the buyer journey. + """ + + model_config = ConfigDict( + extra="allow", + ) + address_country: str | None = None + """ + The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. Optional hint for market context (currency, availability, pricing)—higher-resolution data (e.g., shipping address) supersedes this value. + """ + address_region: str | None = None + """ + The region in which the locality is, and which is in the country. For example, California or another appropriate first-level Administrative division. Optional hint for progressive localization—higher-resolution data (e.g., shipping address) supersedes this value. + """ + postal_code: str | None = None + """ + The postal code. For example, 94043. Optional hint for regional refinement—higher-resolution data (e.g., shipping address) supersedes this value. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py new file mode 100644 index 0000000..f105e39 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_create_request.py @@ -0,0 +1,30 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class FulfillmentAvailableMethodCreateRequest(BaseModel): + """Inventory availability hint for a fulfillment method type. + """ + + model_config = ConfigDict( + extra="allow", + ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py new file mode 100644 index 0000000..c768eb8 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_available_method_update_request.py @@ -0,0 +1,30 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class FulfillmentAvailableMethodUpdateRequest(BaseModel): + """Inventory availability hint for a fulfillment method type. + """ + + model_config = ConfigDict( + extra="allow", + ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py new file mode 100644 index 0000000..cf2685c --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_create_request.py @@ -0,0 +1,39 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import fulfillment_method_create_request + + +class FulfillmentCreateRequest(BaseModel): + """Container for fulfillment methods and availability. + """ + + model_config = ConfigDict( + extra="allow", + ) + methods: ( + list[fulfillment_method_create_request.FulfillmentMethodCreateRequest] + | None + ) = None + """ + Fulfillment methods for cart items. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py new file mode 100644 index 0000000..3bf78a5 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_create_request.py @@ -0,0 +1,30 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class FulfillmentOptionCreateRequest(BaseModel): + """A fulfillment option within a group (e.g., Standard Shipping $5, Express $15). + """ + + model_config = ConfigDict( + extra="allow", + ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py new file mode 100644 index 0000000..e37bc04 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_option_update_request.py @@ -0,0 +1,30 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class FulfillmentOptionUpdateRequest(BaseModel): + """A fulfillment option within a group (e.g., Standard Shipping $5, Express $15). + """ + + model_config = ConfigDict( + extra="allow", + ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py new file mode 100644 index 0000000..a97ef41 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/fulfillment_update_request.py @@ -0,0 +1,39 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import fulfillment_method_update_request + + +class FulfillmentUpdateRequest(BaseModel): + """Container for fulfillment methods and availability. + """ + + model_config = ConfigDict( + extra="allow", + ) + methods: ( + list[fulfillment_method_update_request.FulfillmentMethodUpdateRequest] + | None + ) = None + """ + Fulfillment methods for cart items. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py new file mode 100644 index 0000000..19e0d07 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/item_create_request.py @@ -0,0 +1,31 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class ItemCreateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py new file mode 100644 index 0000000..156fe97 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/item_update_request.py @@ -0,0 +1,31 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class ItemUpdateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + id: str + """ + Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py index aba7e29..1d4a506 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/line_item_create_request.py @@ -20,7 +20,7 @@ from pydantic import BaseModel, ConfigDict, Field -from . import item as item_1 +from . import item_create_request class LineItemCreateRequest(BaseModel): @@ -30,7 +30,7 @@ class LineItemCreateRequest(BaseModel): model_config = ConfigDict( extra="allow", ) - item: item_1.Item + item: item_create_request.ItemCreateRequest quantity: int = Field(..., ge=1) """ Quantity of the item being purchased. diff --git a/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py index 7b99fe0..9899712 100644 --- a/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py +++ b/src/ucp_sdk/models/schemas/shopping/types/line_item_update_request.py @@ -20,7 +20,7 @@ from pydantic import BaseModel, ConfigDict, Field -from . import item as item_1 +from . import item_update_request class LineItemUpdateRequest(BaseModel): @@ -31,7 +31,7 @@ class LineItemUpdateRequest(BaseModel): extra="allow", ) id: str | None = None - item: item_1.Item + item: item_update_request.ItemUpdateRequest quantity: int = Field(..., ge=1) """ Quantity of the item being purchased. diff --git a/src/ucp_sdk/models/schemas/shopping/types/postal_address_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/postal_address_create_request.py new file mode 100644 index 0000000..cbeb315 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/postal_address_create_request.py @@ -0,0 +1,63 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class PostalAddressCreateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + extended_address: str | None = None + """ + An address extension such as an apartment number, C/O or alternative name. + """ + street_address: str | None = None + """ + The street address. + """ + address_locality: str | None = None + """ + The locality in which the street address is, and which is in the region. For example, Mountain View. + """ + address_region: str | None = None + """ + The region in which the locality is, and which is in the country. Required for applicable countries (i.e. state in US, province in CA). For example, California or another appropriate first-level Administrative division. + """ + address_country: str | None = None + """ + The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. + """ + postal_code: str | None = None + """ + The postal code. For example, 94043. + """ + first_name: str | None = None + """ + Optional. First name of the contact associated with the address. + """ + last_name: str | None = None + """ + Optional. Last name of the contact associated with the address. + """ + phone_number: str | None = None + """ + Optional. Phone number of the contact associated with the address. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/postal_address_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/postal_address_update_request.py new file mode 100644 index 0000000..e3442ba --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/postal_address_update_request.py @@ -0,0 +1,63 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class PostalAddressUpdateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + extended_address: str | None = None + """ + An address extension such as an apartment number, C/O or alternative name. + """ + street_address: str | None = None + """ + The street address. + """ + address_locality: str | None = None + """ + The locality in which the street address is, and which is in the region. For example, Mountain View. + """ + address_region: str | None = None + """ + The region in which the locality is, and which is in the country. Required for applicable countries (i.e. state in US, province in CA). For example, California or another appropriate first-level Administrative division. + """ + address_country: str | None = None + """ + The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as "SGP" or a full country name such as "Singapore" can also be used. + """ + postal_code: str | None = None + """ + The postal code. For example, 94043. + """ + first_name: str | None = None + """ + Optional. First name of the contact associated with the address. + """ + last_name: str | None = None + """ + Optional. Last name of the contact associated with the address. + """ + phone_number: str | None = None + """ + Optional. Phone number of the contact associated with the address. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py new file mode 100644 index 0000000..87bb6af --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/retail_location_create_request.py @@ -0,0 +1,42 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import postal_address_create_request + + +class RetailLocationCreateRequest(BaseModel): + """A pickup location (retail store, locker, etc.). + """ + + model_config = ConfigDict( + extra="allow", + ) + name: str + """ + Location name (e.g., store name). + """ + address: postal_address_create_request.PostalAddressCreateRequest | None = ( + None + ) + """ + Physical address of the location. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py new file mode 100644 index 0000000..602b3a8 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/retail_location_update_request.py @@ -0,0 +1,42 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + +from . import postal_address_update_request + + +class RetailLocationUpdateRequest(BaseModel): + """A pickup location (retail store, locker, etc.). + """ + + model_config = ConfigDict( + extra="allow", + ) + name: str + """ + Location name (e.g., store name). + """ + address: postal_address_update_request.PostalAddressUpdateRequest | None = ( + None + ) + """ + Physical address of the location. + """ diff --git a/src/ucp_sdk/models/schemas/shopping/types/total_create_request.py b/src/ucp_sdk/models/schemas/shopping/types/total_create_request.py new file mode 100644 index 0000000..ab0c7d2 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/total_create_request.py @@ -0,0 +1,27 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class TotalCreateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) diff --git a/src/ucp_sdk/models/schemas/shopping/types/total_update_request.py b/src/ucp_sdk/models/schemas/shopping/types/total_update_request.py new file mode 100644 index 0000000..ef0dfe3 --- /dev/null +++ b/src/ucp_sdk/models/schemas/shopping/types/total_update_request.py @@ -0,0 +1,27 @@ +# Copyright 2026 UCP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# generated by datamodel-codegen +# pylint: disable=all +# pyformat: disable + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict + + +class TotalUpdateRequest(BaseModel): + model_config = ConfigDict( + extra="allow", + ) diff --git a/ucp b/ucp new file mode 160000 index 0000000..2ee92ff --- /dev/null +++ b/ucp @@ -0,0 +1 @@ +Subproject commit 2ee92ffdee356e4480be05e7437d1038bec6c779 From f919b254deef722feb49737bb0965dbf233436e3 Mon Sep 17 00:00:00 2001 From: "damaz@google.com" Date: Mon, 2 Mar 2026 16:46:41 +0100 Subject: [PATCH 22/22] delete ucp Change-Id: I0ac8995f2d15caa97ce57e9a1be574f012d5b9f2 --- ucp | 1 - 1 file changed, 1 deletion(-) delete mode 160000 ucp diff --git a/ucp b/ucp deleted file mode 160000 index 2ee92ff..0000000 --- a/ucp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2ee92ffdee356e4480be05e7437d1038bec6c779