Skip to content

Commit 679c259

Browse files
committed
Address feedback
1 parent 7614b45 commit 679c259

3 files changed

Lines changed: 8 additions & 110 deletions

File tree

packages/smithy-aws-core/src/smithy_aws_core/aio/protocols.py

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0
33
from collections.abc import AsyncIterable, Callable
44
from inspect import iscoroutinefunction
5-
from string import Formatter
65
from typing import TYPE_CHECKING, Any, Final
7-
from urllib.parse import quote as urlquote
86

97
from smithy_core import URI as _URI
108
from smithy_core.aio.interfaces import AsyncByteStream, AsyncWriter
@@ -35,7 +33,7 @@
3533
from smithy_core.schemas import APIOperation, Schema
3634
from smithy_core.serializers import SerializeableShape
3735
from smithy_core.shapes import ShapeID, ShapeType
38-
from smithy_core.traits import EndpointTrait, HTTPTrait
36+
from smithy_core.traits import HTTPTrait
3937
from smithy_core.types import TimestampFormat
4038
from smithy_http import tuples_to_fields
4139
from smithy_http.aio import HTTPRequest as _HTTPRequest
@@ -296,10 +294,9 @@ def serialize_request[
296294
body = AsyncBytesReader(payload)
297295

298296
fields = tuples_to_fields(field_tuples)
299-
host = self._resolve_host_prefix(operation=operation, payload=payload)
300297
return _HTTPRequest(
301298
destination=_URI(
302-
host=host,
299+
host="",
303300
path=self._http_trait.path.pattern,
304301
query=self._http_trait.query,
305302
),
@@ -368,47 +365,6 @@ def _is_success(
368365
) -> bool:
369366
return 200 <= response.status < 300
370367

371-
def _resolve_host_prefix(
372-
self,
373-
*,
374-
operation: APIOperation[Any, Any],
375-
payload: bytes,
376-
) -> str:
377-
endpoint_trait = operation.schema.get_trait(EndpointTrait)
378-
if endpoint_trait is None:
379-
return ""
380-
381-
host_prefix = endpoint_trait.host_prefix
382-
labels = self._host_prefix_labels(host_prefix)
383-
if not labels:
384-
return host_prefix
385-
386-
deserializer = self.payload_codec.create_deserializer(source=payload)
387-
document = deserializer.read_document(schema=DOCUMENT)
388-
if document.shape_type is not ShapeType.MAP:
389-
raise ExpectationNotMetError(
390-
f"Expected input document to be a map for host labels, got {document.shape_type}"
391-
)
392-
393-
values: dict[str, str] = {}
394-
map_document = document.as_map()
395-
for label in labels:
396-
value = map_document.get(label)
397-
if value is None or value.shape_type is not ShapeType.STRING:
398-
raise ExpectationNotMetError(
399-
f"Expected host label member '{label}' to be a string in input payload"
400-
)
401-
values[label] = urlquote(value.as_string(), safe=".")
402-
403-
return host_prefix.format(**values)
404-
405-
def _host_prefix_labels(self, host_prefix: str) -> set[str]:
406-
labels: set[str] = set()
407-
for _, field_name, _, _ in Formatter().parse(host_prefix):
408-
if field_name:
409-
labels.add(field_name)
410-
return labels
411-
412368
def _coerce_json_source(
413369
self,
414370
*,
@@ -453,6 +409,10 @@ async def _create_error(
453409
error_registry: TypeRegistry,
454410
context: TypedProperties,
455411
) -> CallError:
412+
# Keeps HttpBindingClientProtocol._create_error's error ID resolution,
413+
# but awsJson operations do not use per-operation HTTP bindings. Once
414+
# the error shape is resolved, deserialize it directly from JSON and
415+
# normalize empty bodies to {} for structured errors.
456416
error_id = self.error_identifier.identify(
457417
operation=operation, response=response
458418
)

packages/smithy-aws-core/tests/unit/aio/test_protocols.py

Lines changed: 1 addition & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,12 @@
1616
from smithy_core.aio.interfaces import AsyncWriter
1717
from smithy_core.documents import TypeRegistry
1818
from smithy_core.exceptions import DiscriminatorError, ModeledError
19-
from smithy_core.prelude import STRING
2019
from smithy_core.schemas import APIOperation, Schema
2120
from smithy_core.serializers import ShapeSerializer
2221
from smithy_core.shapes import ShapeID, ShapeType
2322
from smithy_core.traits import (
24-
DynamicTrait,
25-
EndpointTrait,
26-
HostLabelTrait,
27-
HTTPHeaderTrait,
2823
HTTPTrait,
2924
StreamingTrait,
30-
Trait,
3125
)
3226
from smithy_core.types import TypedProperties
3327
from smithy_http import Fields, tuples_to_fields
@@ -125,13 +119,6 @@ def test_aws_json_document_discriminator(
125119
_EMPTY_INPUT_SCHEMA = Schema.collection(
126120
id=ShapeID("com.test#EmptyInput"),
127121
)
128-
_HEADER_AND_LABEL_INPUT_SCHEMA = Schema.collection(
129-
id=ShapeID("com.test#HeaderAndLabelInput"),
130-
members={
131-
"headerMember": {"target": STRING, "traits": [HTTPHeaderTrait("x-test")]},
132-
"label": {"target": STRING, "traits": [HostLabelTrait()]},
133-
},
134-
)
135122
_EVENT_STREAM_MEMBER_SCHEMA = Schema(
136123
id=ShapeID("com.test#InputEvents"),
137124
shape_type=ShapeType.UNION,
@@ -148,35 +135,10 @@ def serialize_members(self, serializer: ShapeSerializer) -> None:
148135
pass
149136

150137

151-
@dataclass
152-
class _HeaderAndLabelInput:
153-
header_member: str | None = None
154-
label: str | None = None
155-
156-
def serialize(self, serializer: ShapeSerializer) -> None:
157-
serializer.write_struct(_HEADER_AND_LABEL_INPUT_SCHEMA, self)
158-
159-
def serialize_members(self, serializer: ShapeSerializer) -> None:
160-
if self.header_member is not None:
161-
serializer.write_string(
162-
_HEADER_AND_LABEL_INPUT_SCHEMA.members["headerMember"],
163-
self.header_member,
164-
)
165-
if self.label is not None:
166-
serializer.write_string(
167-
_HEADER_AND_LABEL_INPUT_SCHEMA.members["label"],
168-
self.label,
169-
)
170-
171-
172-
def _operation_schema(name: str, *, endpoint: str | None = None) -> Schema:
173-
traits: list[Trait | DynamicTrait] = []
174-
if endpoint is not None:
175-
traits.append(EndpointTrait({"hostPrefix": endpoint}))
138+
def _operation_schema(name: str) -> Schema:
176139
return Schema(
177140
id=ShapeID(f"com.test#{name}"),
178141
shape_type=ShapeType.OPERATION,
179-
traits=traits,
180142
)
181143

182144

@@ -239,28 +201,6 @@ async def test_aws_json11_serializes_input_event_stream_request_with_writable_bo
239201
assert isinstance(request.body, AsyncWriter)
240202

241203

242-
@pytest.mark.asyncio
243-
async def test_aws_json_ignores_http_bindings_but_applies_host_labels() -> None:
244-
protocol = AwsJson11ClientProtocol(
245-
Schema(id=ShapeID("com.test#JsonService"), shape_type=ShapeType.SERVICE)
246-
)
247-
request = protocol.serialize_request(
248-
operation=_mock_operation(
249-
_operation_schema("EndpointOperation", endpoint="foo.{label}.")
250-
),
251-
input=_HeaderAndLabelInput(header_member="payload", label="bar"),
252-
endpoint=URI(host="example.com"),
253-
context=TypedProperties(),
254-
)
255-
256-
assert request.destination.host == "foo.bar."
257-
assert "x-test" not in request.fields
258-
assert (
259-
await request.consume_body_async()
260-
== b'{"headerMember":"payload","label":"bar"}'
261-
)
262-
263-
264204
def test_aws_json_matches_content_type_with_parameters() -> None:
265205
protocol = AwsJson11ClientProtocol(
266206
Schema(id=ShapeID("com.test#JsonService"), shape_type=ShapeType.SERVICE)

packages/smithy-json/src/smithy_json/_private/deserializers.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,7 @@ def read_big_decimal(self, schema: Schema) -> Decimal:
139139
match event.value:
140140
case Decimal():
141141
return event.value
142-
case int() | float():
143-
return Decimal.from_float(event.value)
144-
case "Infinity" | "-Infinity" | "NaN":
142+
case int() | float() | "Infinity" | "-Infinity" | "NaN":
145143
return Decimal(event.value)
146144
case _:
147145
raise JSONTokenError("number", event)

0 commit comments

Comments
 (0)