diff --git a/packages/smithy-core/.changes/next-release/smithy-core-bugfix-7c2e4f1a9b8d4e6f8a3c5d2b1e0f9a7c.json b/packages/smithy-core/.changes/next-release/smithy-core-bugfix-7c2e4f1a9b8d4e6f8a3c5d2b1e0f9a7c.json new file mode 100644 index 000000000..bb651e154 --- /dev/null +++ b/packages/smithy-core/.changes/next-release/smithy-core-bugfix-7c2e4f1a9b8d4e6f8a3c5d2b1e0f9a7c.json @@ -0,0 +1,4 @@ +{ + "type": "bugfix", + "description": "Fixed the registered Smithy IDs for `DefaultTrait`, `IdempotencyTokenTrait`, and `UnitTypeTrait` so schemas resolve these traits correctly." +} diff --git a/packages/smithy-core/src/smithy_core/traits.py b/packages/smithy-core/src/smithy_core/traits.py index 99a5ae8cc..63ad9199e 100644 --- a/packages/smithy-core/src/smithy_core/traits.py +++ b/packages/smithy-core/src/smithy_core/traits.py @@ -93,7 +93,7 @@ def new(id: ShapeID, value: "DocumentValue" = None) -> "Trait | DynamicTrait": @dataclass(init=False, frozen=True) -class DefaultTrait(Trait, id=ShapeID("smithy.appi#default")): +class DefaultTrait(Trait, id=ShapeID("smithy.api#default")): @property def value(self) -> "DocumentValue": return self.document_value @@ -161,7 +161,7 @@ def __post_init__(self): @dataclass(init=False, frozen=True) -class UnitTypeTrait(Trait, id=ShapeID("smithy.api#UnitTypeTrait")): +class UnitTypeTrait(Trait, id=ShapeID("smithy.api#unitType")): def __post_init__(self): assert self.document_value is None @@ -203,7 +203,7 @@ def value(self) -> str: @dataclass(init=False, frozen=True) -class IdempotencyTokenTrait(Trait, id=ShapeID("smithy.api#IdempotencyToken")): +class IdempotencyTokenTrait(Trait, id=ShapeID("smithy.api#idempotencyToken")): def __post_init__(self): assert self.document_value is None diff --git a/packages/smithy-core/tests/unit/test_schemas.py b/packages/smithy-core/tests/unit/test_schemas.py index c6b835228..30fbe4db0 100644 --- a/packages/smithy-core/tests/unit/test_schemas.py +++ b/packages/smithy-core/tests/unit/test_schemas.py @@ -4,13 +4,15 @@ from typing import Any import pytest +from smithy_core.documents import TypeRegistry from smithy_core.exceptions import ExpectationNotMetError -from smithy_core.schemas import Schema +from smithy_core.schemas import APIOperation, Schema from smithy_core.shapes import ShapeID, ShapeType from smithy_core.traits import ( DynamicTrait, InternalTrait, SensitiveTrait, + Trait, ) ID: ShapeID = ShapeID("ns.foo#bar") @@ -171,3 +173,29 @@ def test_contains(item: Any, contains: bool): ) assert (item in schema) == contains + + +def test_operation_idempotency_token_member(): + input_schema = Schema.collection( + id=ShapeID("com.example#OperationInput"), + members={ + "other": {"target": STRING}, + "token": { + "target": STRING, + "traits": [Trait.new(id=ShapeID("smithy.api#idempotencyToken"))], + }, + }, + ) + operation = APIOperation[Any, Any]( + input=object, + output=object, + schema=Schema( + id=ShapeID("com.example#Operation"), shape_type=ShapeType.OPERATION + ), + input_schema=input_schema, + output_schema=input_schema, + error_registry=TypeRegistry({}), + effective_auth_schemes=[], + error_schemas=[], + ) + assert operation.idempotency_token_member is input_schema.members["token"] diff --git a/packages/smithy-core/tests/unit/test_traits.py b/packages/smithy-core/tests/unit/test_traits.py index 5d60970ef..623387411 100644 --- a/packages/smithy-core/tests/unit/test_traits.py +++ b/packages/smithy-core/tests/unit/test_traits.py @@ -3,13 +3,16 @@ from dataclasses import dataclass import pytest +from smithy_core.prelude import UNIT from smithy_core.shapes import ShapeID from smithy_core.traits import ( + DefaultTrait, DynamicTrait, ErrorFault, ErrorTrait, JSONNameTrait, Trait, + UnitTypeTrait, ) @@ -40,6 +43,17 @@ class NewTrait(Trait, id=trait_id): assert NewTrait.id is trait_id +def test_trait_factory_constructs_default_trait(): + trait = Trait.new(ShapeID("smithy.api#default"), 0) + assert isinstance(trait, DefaultTrait) + assert trait.value == 0 + + +def test_unit_schema_uses_canonical_trait_id(): + trait = UNIT.get_trait(ShapeID("smithy.api#unitType")) + assert isinstance(trait, UnitTypeTrait) + + def test_cant_construct_base_trait(): with pytest.raises(TypeError): Trait("foo")