aws-lambda-powertools 3.11.1a3__py3-none-any.whl → 3.11.1a5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,7 @@ from aws_lambda_powertools.event_handler.api_gateway import (
11
11
  Response,
12
12
  )
13
13
  from aws_lambda_powertools.event_handler.appsync import AppSyncResolver
14
- from aws_lambda_powertools.event_handler.bedrock_agent import BedrockAgentResolver
14
+ from aws_lambda_powertools.event_handler.bedrock_agent import BedrockAgentResolver, BedrockResponse
15
15
  from aws_lambda_powertools.event_handler.events_appsync.appsync_events import AppSyncEventsResolver
16
16
  from aws_lambda_powertools.event_handler.lambda_function_url import (
17
17
  LambdaFunctionUrlResolver,
@@ -26,6 +26,7 @@ __all__ = [
26
26
  "ALBResolver",
27
27
  "ApiGatewayResolver",
28
28
  "BedrockAgentResolver",
29
+ "BedrockResponse",
29
30
  "CORSConfig",
30
31
  "LambdaFunctionUrlResolver",
31
32
  "Response",
@@ -73,6 +73,7 @@ _NAMED_GROUP_BOUNDARY_PATTERN = rf"(?P\1[{_SAFE_URI}{_UNSAFE_URI}\\w]+)"
73
73
  _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION = "Successful Response"
74
74
  _ROUTE_REGEX = "^{}$"
75
75
  _JSON_DUMP_CALL = partial(json.dumps, separators=(",", ":"), cls=Encoder)
76
+ _DEFAULT_CONTENT_TYPE = "application/json"
76
77
 
77
78
  ResponseEventT = TypeVar("ResponseEventT", bound=BaseProxyEvent)
78
79
  ResponseT = TypeVar("ResponseT")
@@ -255,6 +256,35 @@ class CORSConfig:
255
256
  return ",".join(sorted(methods))
256
257
 
257
258
 
259
+ class BedrockResponse(Generic[ResponseT]):
260
+ """
261
+ Contains the response body, status code, content type, and optional attributes
262
+ for session management and knowledge base configuration.
263
+ """
264
+
265
+ def __init__(
266
+ self,
267
+ body: Any = None,
268
+ status_code: int = 200,
269
+ content_type: str = _DEFAULT_CONTENT_TYPE,
270
+ session_attributes: dict[str, Any] | None = None,
271
+ prompt_session_attributes: dict[str, Any] | None = None,
272
+ knowledge_bases_configuration: list[dict[str, Any]] | None = None,
273
+ ) -> None:
274
+ self.body = body
275
+ self.status_code = status_code
276
+ self.content_type = content_type
277
+ self.session_attributes = session_attributes
278
+ self.prompt_session_attributes = prompt_session_attributes
279
+ self.knowledge_bases_configuration = knowledge_bases_configuration
280
+
281
+ def is_json(self) -> bool:
282
+ """
283
+ Returns True if the response is JSON, based on the Content-Type.
284
+ """
285
+ return True
286
+
287
+
258
288
  class Response(Generic[ResponseT]):
259
289
  """Response data class that provides greater control over what is returned from the proxy event"""
260
290
 
@@ -300,7 +330,7 @@ class Response(Generic[ResponseT]):
300
330
  content_type = self.headers.get("Content-Type", "")
301
331
  if isinstance(content_type, list):
302
332
  content_type = content_type[0]
303
- return content_type.startswith("application/json")
333
+ return content_type.startswith(_DEFAULT_CONTENT_TYPE)
304
334
 
305
335
 
306
336
  class Route:
@@ -572,7 +602,7 @@ class Route:
572
602
  operation_responses: dict[int, OpenAPIResponse] = {
573
603
  422: {
574
604
  "description": "Validation Error",
575
- "content": {"application/json": {"schema": {"$ref": f"{COMPONENT_REF_PREFIX}HTTPValidationError"}}},
605
+ "content": {_DEFAULT_CONTENT_TYPE: {"schema": {"$ref": f"{COMPONENT_REF_PREFIX}HTTPValidationError"}}},
576
606
  },
577
607
  }
578
608
 
@@ -581,7 +611,9 @@ class Route:
581
611
  http_code = self.custom_response_validation_http_code.value
582
612
  operation_responses[http_code] = {
583
613
  "description": "Response Validation Error",
584
- "content": {"application/json": {"schema": {"$ref": f"{COMPONENT_REF_PREFIX}ResponseValidationError"}}},
614
+ "content": {
615
+ _DEFAULT_CONTENT_TYPE: {"schema": {"$ref": f"{COMPONENT_REF_PREFIX}ResponseValidationError"}},
616
+ },
585
617
  }
586
618
  # Add model definition
587
619
  definitions["ResponseValidationError"] = response_validation_error_response_definition
@@ -594,7 +626,7 @@ class Route:
594
626
  # Case 1: there is not 'content' key
595
627
  if "content" not in response:
596
628
  response["content"] = {
597
- "application/json": self._openapi_operation_return(
629
+ _DEFAULT_CONTENT_TYPE: self._openapi_operation_return(
598
630
  param=dependant.return_param,
599
631
  model_name_map=model_name_map,
600
632
  field_mapping=field_mapping,
@@ -645,7 +677,7 @@ class Route:
645
677
  # Add the response schema to the OpenAPI 200 response
646
678
  operation_responses[200] = {
647
679
  "description": self.response_description or _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION,
648
- "content": {"application/json": response_schema},
680
+ "content": {_DEFAULT_CONTENT_TYPE: response_schema},
649
681
  }
650
682
 
651
683
  operation["responses"] = operation_responses
@@ -1474,7 +1506,10 @@ class MiddlewareFrame:
1474
1506
  return self.current_middleware(app, self.next_middleware)
1475
1507
 
1476
1508
 
1477
- def _registered_api_adapter(app: ApiGatewayResolver, next_middleware: Callable[..., Any]) -> dict | tuple | Response:
1509
+ def _registered_api_adapter(
1510
+ app: ApiGatewayResolver,
1511
+ next_middleware: Callable[..., Any],
1512
+ ) -> dict | tuple | Response | BedrockResponse:
1478
1513
  """
1479
1514
  Calls the registered API using the "_route_args" from the Resolver context to ensure the last call
1480
1515
  in the chain will match the API route function signature and ensure that Powertools passes the API
@@ -1632,7 +1667,7 @@ class ApiGatewayResolver(BaseRouter):
1632
1667
  response_validation_error_response = {
1633
1668
  "description": "Response Validation Error",
1634
1669
  "content": {
1635
- "application/json": {
1670
+ _DEFAULT_CONTENT_TYPE: {
1636
1671
  "schema": {"$ref": f"{COMPONENT_REF_PREFIX}ResponseValidationError"},
1637
1672
  },
1638
1673
  },
@@ -2151,7 +2186,7 @@ class ApiGatewayResolver(BaseRouter):
2151
2186
  if query_params.get("format") == "json":
2152
2187
  return Response(
2153
2188
  status_code=200,
2154
- content_type="application/json",
2189
+ content_type=_DEFAULT_CONTENT_TYPE,
2155
2190
  body=escaped_spec,
2156
2191
  )
2157
2192
 
@@ -2538,7 +2573,7 @@ class ApiGatewayResolver(BaseRouter):
2538
2573
  self._reset_processed_stack()
2539
2574
 
2540
2575
  return self._response_builder_class(
2541
- response=self._to_response(
2576
+ response=self._to_response( # type: ignore[arg-type]
2542
2577
  route(router_middlewares=self._router_middlewares, app=self, route_arguments=route_arguments),
2543
2578
  ),
2544
2579
  serializer=self._serializer,
@@ -2627,7 +2662,7 @@ class ApiGatewayResolver(BaseRouter):
2627
2662
 
2628
2663
  return None
2629
2664
 
2630
- def _to_response(self, result: dict | tuple | Response) -> Response:
2665
+ def _to_response(self, result: dict | tuple | Response | BedrockResponse) -> Response | BedrockResponse:
2631
2666
  """Convert the route's result to a Response
2632
2667
 
2633
2668
  3 main result types are supported:
@@ -2638,7 +2673,7 @@ class ApiGatewayResolver(BaseRouter):
2638
2673
  - Response: returned as is, and allows for more flexibility
2639
2674
  """
2640
2675
  status_code = HTTPStatus.OK
2641
- if isinstance(result, Response):
2676
+ if isinstance(result, (Response, BedrockResponse)):
2642
2677
  return result
2643
2678
  elif isinstance(result, tuple) and len(result) == 2:
2644
2679
  # Unpack result dict and status code from tuple
@@ -2971,8 +3006,9 @@ class ALBResolver(ApiGatewayResolver):
2971
3006
  # ALB doesn't have a stage variable, so we just return an empty string
2972
3007
  return ""
2973
3008
 
3009
+ # BedrockResponse is not used here but adding the same signature to keep strong typing
2974
3010
  @override
2975
- def _to_response(self, result: dict | tuple | Response) -> Response:
3011
+ def _to_response(self, result: dict | tuple | Response | BedrockResponse) -> Response | BedrockResponse:
2976
3012
  """Convert the route's result to a Response
2977
3013
 
2978
3014
  ALB requires a non-null body otherwise it converts as HTTP 5xx
@@ -8,6 +8,7 @@ from typing_extensions import override
8
8
  from aws_lambda_powertools.event_handler import ApiGatewayResolver
9
9
  from aws_lambda_powertools.event_handler.api_gateway import (
10
10
  _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION,
11
+ BedrockResponse,
11
12
  ProxyEventType,
12
13
  ResponseBuilder,
13
14
  )
@@ -32,14 +33,11 @@ class BedrockResponseBuilder(ResponseBuilder):
32
33
 
33
34
  @override
34
35
  def build(self, event: BedrockAgentEvent, *args) -> dict[str, Any]:
35
- """Build the full response dict to be returned by the lambda"""
36
- self._route(event, None)
37
-
38
36
  body = self.response.body
39
37
  if self.response.is_json() and not isinstance(self.response.body, str):
40
38
  body = self.serializer(self.response.body)
41
39
 
42
- return {
40
+ response = {
43
41
  "messageVersion": "1.0",
44
42
  "response": {
45
43
  "actionGroup": event.action_group,
@@ -54,6 +52,19 @@ class BedrockResponseBuilder(ResponseBuilder):
54
52
  },
55
53
  }
56
54
 
55
+ # Add Bedrock-specific attributes
56
+ if isinstance(self.response, BedrockResponse):
57
+ if self.response.session_attributes:
58
+ response["sessionAttributes"] = self.response.session_attributes
59
+
60
+ if self.response.prompt_session_attributes:
61
+ response["promptSessionAttributes"] = self.response.prompt_session_attributes
62
+
63
+ if self.response.knowledge_bases_configuration:
64
+ response["knowledgeBasesConfiguration"] = self.response.knowledge_bases_configuration
65
+
66
+ return response
67
+
57
68
 
58
69
  class BedrockAgentResolver(ApiGatewayResolver):
59
70
  """Bedrock Agent Resolver
@@ -1,3 +1,3 @@
1
1
  """Exposes version constant to avoid circular dependencies."""
2
2
 
3
- VERSION = "3.11.1a3"
3
+ VERSION = "3.11.1a5"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: aws_lambda_powertools
3
- Version: 3.11.1a3
3
+ Version: 3.11.1a5
4
4
  Summary: Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity.
5
5
  License: MIT
6
6
  Keywords: aws_lambda_powertools,aws,tracing,logging,lambda,powertools,feature_flags,idempotency,middleware
@@ -1,8 +1,8 @@
1
1
  aws_lambda_powertools/__init__.py,sha256=o4iEHU0MfWC0_TfVmisxi0VOAUw5uQfqLQWr0t29ZaE,676
2
- aws_lambda_powertools/event_handler/__init__.py,sha256=Wz6aiAibULxZ38XTXMqnraRAjhO0rShRe7UwLR2WBcM,1030
3
- aws_lambda_powertools/event_handler/api_gateway.py,sha256=iDF0FIWao1bP12_KlbYU3yjz458544pf05PO3LaDa8k,119414
2
+ aws_lambda_powertools/event_handler/__init__.py,sha256=rbT-fYV_Lz8bcoecrtqkk0ZXh5-ccrWr1qvNecRCloc,1070
3
+ aws_lambda_powertools/event_handler/api_gateway.py,sha256=4gfszkCNZP5Tm9i9YIA0pqVub-784NWu7R1qYwONCQs,120763
4
4
  aws_lambda_powertools/event_handler/appsync.py,sha256=MNUlaM-4Ioaejei4L5hoW_DuDgOkQWAtMmKZU_Jwce4,18530
5
- aws_lambda_powertools/event_handler/bedrock_agent.py,sha256=i3F5uq3Wme6IY2KcodysvabqEwmh6uvW7-kHR8RXoCM,14619
5
+ aws_lambda_powertools/event_handler/bedrock_agent.py,sha256=4vWmF3wyoFn2u1SUgf0Rdz1KnrTZpcVUiU2KY-lhPMQ,15105
6
6
  aws_lambda_powertools/event_handler/content_types.py,sha256=0MKsKNu-SSrxbULVKnUjwgK-lVXhVD7BBjZ4Js0kEsI,163
7
7
  aws_lambda_powertools/event_handler/events_appsync/__init__.py,sha256=_SkA-qYoSdpDhPFHLxpFz8RacjMRMY6R8FFElQ3Otzs,144
8
8
  aws_lambda_powertools/event_handler/events_appsync/_registry.py,sha256=pzFQfv662Y0DPZQXCgJgabYZq-1gfasV5Mdl_aC9FBc,3071
@@ -97,7 +97,7 @@ aws_lambda_powertools/shared/json_encoder.py,sha256=JQeWNu-4M7_xI_hqYExrxsb3OcEH
97
97
  aws_lambda_powertools/shared/lazy_import.py,sha256=TbXQm2bcwXdZrYdBaJJXIswyLlumM85RJ_A_0w-h-GU,2019
98
98
  aws_lambda_powertools/shared/types.py,sha256=EZ_tbX3F98LA4Zcra1hTEjzRacpZAtggK957Zcv1oKg,135
99
99
  aws_lambda_powertools/shared/user_agent.py,sha256=DrCMFQuT4a4iIrpcWpAIjY37EFqR9-QxlxDGD-Nn9Gg,7081
100
- aws_lambda_powertools/shared/version.py,sha256=VsEAyblbdhoErQoLGNXPAK_-YxphBlLMMOaKb5fbWqE,85
100
+ aws_lambda_powertools/shared/version.py,sha256=tpebLyqeFBmWgLDVTdO0On09OhXsJSXjtR6bqTcyFDM,85
101
101
  aws_lambda_powertools/tracing/__init__.py,sha256=f4bMThOPBPWTPVcYqcAIErAJPerMsf3H_Z4gCXCsK9I,141
102
102
  aws_lambda_powertools/tracing/base.py,sha256=WSO986XGBOe9K0F2SnG6ustJokIrtO0m0mcL8N7mfno,4544
103
103
  aws_lambda_powertools/tracing/extensions.py,sha256=APOfXOq-hRBKaK5WyfIyrd_6M1_9SWJZ3zxLA9jDZzU,492
@@ -268,7 +268,7 @@ aws_lambda_powertools/utilities/validation/envelopes.py,sha256=YD5HOFx6IClQgii0n
268
268
  aws_lambda_powertools/utilities/validation/exceptions.py,sha256=PKy_19zQMBJGCMMFl-sMkcm-cc0v3zZBn_bhGE4wKNo,2084
269
269
  aws_lambda_powertools/utilities/validation/validator.py,sha256=khCqFhACSdn0nKyYRRPiC5Exht956hTfSfhlV3IRmpg,10099
270
270
  aws_lambda_powertools/warnings/__init__.py,sha256=vqDVeZz8wGtD8WGYNSkQE7AHwqtIrPGRxuoJR_BBnSs,1193
271
- aws_lambda_powertools-3.11.1a3.dist-info/LICENSE,sha256=vMHS2eBgmwPUIMPb7LQ4p7ib_FPVQXarVjAasflrTwo,951
272
- aws_lambda_powertools-3.11.1a3.dist-info/METADATA,sha256=XR3fq0Dwxsr_vp6OGI0VnAjFF_zg0xeP99HpXtH2i70,11187
273
- aws_lambda_powertools-3.11.1a3.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
274
- aws_lambda_powertools-3.11.1a3.dist-info/RECORD,,
271
+ aws_lambda_powertools-3.11.1a5.dist-info/LICENSE,sha256=vMHS2eBgmwPUIMPb7LQ4p7ib_FPVQXarVjAasflrTwo,951
272
+ aws_lambda_powertools-3.11.1a5.dist-info/METADATA,sha256=zehfjzFPRhMumTXmpvO22S1gOEIhfHHS-6THV56KIus,11187
273
+ aws_lambda_powertools-3.11.1a5.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
274
+ aws_lambda_powertools-3.11.1a5.dist-info/RECORD,,