localstack-core 4.6.1.dev60__py3-none-any.whl → 4.10.1.dev12__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.
Files changed (672) hide show
  1. localstack/aws/api/apigateway/__init__.py +87 -110
  2. localstack/aws/api/cloudformation/__init__.py +18 -4
  3. localstack/aws/api/cloudwatch/__init__.py +41 -1
  4. localstack/aws/api/config/__init__.py +4 -0
  5. localstack/aws/api/core.py +8 -5
  6. localstack/aws/api/dynamodb/__init__.py +30 -0
  7. localstack/aws/api/ec2/__init__.py +1545 -66
  8. localstack/aws/api/events/__init__.py +12 -16
  9. localstack/aws/api/iam/__init__.py +7 -0
  10. localstack/aws/api/kinesis/__init__.py +19 -0
  11. localstack/aws/api/kms/__init__.py +6 -0
  12. localstack/aws/api/lambda_/__init__.py +36 -23
  13. localstack/aws/api/logs/__init__.py +20 -8
  14. localstack/aws/api/opensearch/__init__.py +16 -0
  15. localstack/aws/api/pipes/__init__.py +24 -32
  16. localstack/aws/api/redshift/__init__.py +9 -3
  17. localstack/aws/api/route53/__init__.py +5 -0
  18. localstack/aws/api/s3/__init__.py +12 -0
  19. localstack/aws/api/s3control/__init__.py +56 -0
  20. localstack/aws/api/scheduler/__init__.py +14 -16
  21. localstack/aws/api/ssm/__init__.py +2 -0
  22. localstack/aws/api/stepfunctions/__init__.py +88 -114
  23. localstack/aws/api/support/__init__.py +8 -9
  24. localstack/aws/api/transcribe/__init__.py +17 -0
  25. localstack/aws/chain.py +2 -2
  26. localstack/aws/client.py +14 -11
  27. localstack/aws/connect.py +42 -41
  28. localstack/aws/forwarder.py +57 -9
  29. localstack/aws/gateway.py +1 -3
  30. localstack/aws/handlers/analytics.py +2 -3
  31. localstack/aws/handlers/cors.py +4 -5
  32. localstack/aws/handlers/internal_requests.py +6 -1
  33. localstack/aws/handlers/logging.py +13 -4
  34. localstack/aws/handlers/metric_handler.py +44 -5
  35. localstack/aws/handlers/service.py +48 -28
  36. localstack/aws/mocking.py +18 -27
  37. localstack/aws/patches.py +2 -2
  38. localstack/aws/protocol/op_router.py +11 -10
  39. localstack/aws/protocol/parser.py +475 -49
  40. localstack/aws/protocol/serializer.py +723 -106
  41. localstack/aws/protocol/service_router.py +133 -33
  42. localstack/aws/protocol/validate.py +6 -6
  43. localstack/aws/scaffold.py +9 -10
  44. localstack/aws/serving/edge.py +5 -6
  45. localstack/aws/serving/hypercorn.py +2 -2
  46. localstack/aws/serving/twisted.py +1 -2
  47. localstack/aws/serving/werkzeug.py +2 -2
  48. localstack/aws/skeleton.py +12 -11
  49. localstack/aws/spec-patches.json +58 -0
  50. localstack/aws/spec.py +66 -46
  51. localstack/cli/exceptions.py +1 -1
  52. localstack/cli/localstack.py +11 -11
  53. localstack/cli/lpm.py +4 -5
  54. localstack/cli/plugins.py +1 -1
  55. localstack/cli/profiles.py +1 -2
  56. localstack/config.py +44 -30
  57. localstack/constants.py +4 -29
  58. localstack/deprecations.py +5 -5
  59. localstack/dev/kubernetes/__main__.py +130 -7
  60. localstack/dev/run/__main__.py +5 -5
  61. localstack/dev/run/configurators.py +1 -4
  62. localstack/dev/run/paths.py +6 -6
  63. localstack/dns/models.py +2 -1
  64. localstack/dns/plugins.py +5 -1
  65. localstack/dns/server.py +16 -6
  66. localstack/http/dispatcher.py +1 -2
  67. localstack/http/response.py +2 -2
  68. localstack/http/router.py +1 -1
  69. localstack/http/trace.py +2 -1
  70. localstack/logging/format.py +6 -6
  71. localstack/packages/api.py +13 -12
  72. localstack/packages/core.py +4 -4
  73. localstack/packages/debugpy.py +1 -3
  74. localstack/packages/ffmpeg.py +1 -2
  75. localstack/packages/java.py +38 -12
  76. localstack/packages/plugins.py +0 -8
  77. localstack/runtime/analytics.py +3 -0
  78. localstack/runtime/hooks.py +1 -1
  79. localstack/runtime/init.py +8 -9
  80. localstack/runtime/main.py +5 -5
  81. localstack/runtime/patches.py +2 -2
  82. localstack/runtime/shutdown.py +2 -1
  83. localstack/services/apigateway/exporter.py +1 -2
  84. localstack/services/apigateway/helpers.py +7 -10
  85. localstack/services/apigateway/legacy/context.py +21 -21
  86. localstack/services/apigateway/legacy/helpers.py +27 -28
  87. localstack/services/apigateway/legacy/integration.py +11 -10
  88. localstack/services/apigateway/legacy/invocations.py +6 -5
  89. localstack/services/apigateway/legacy/provider.py +148 -68
  90. localstack/services/apigateway/legacy/router_asf.py +2 -2
  91. localstack/services/apigateway/legacy/templates.py +6 -6
  92. localstack/services/apigateway/models.py +16 -16
  93. localstack/services/apigateway/next_gen/execute_api/api.py +2 -2
  94. localstack/services/apigateway/next_gen/execute_api/context.py +25 -25
  95. localstack/services/apigateway/next_gen/execute_api/handlers/api_key_validation.py +2 -5
  96. localstack/services/apigateway/next_gen/execute_api/handlers/method_request.py +7 -2
  97. localstack/services/apigateway/next_gen/execute_api/handlers/parse.py +1 -2
  98. localstack/services/apigateway/next_gen/execute_api/handlers/resource_router.py +2 -3
  99. localstack/services/apigateway/next_gen/execute_api/header_utils.py +1 -1
  100. localstack/services/apigateway/next_gen/execute_api/helpers.py +2 -2
  101. localstack/services/apigateway/next_gen/execute_api/integrations/aws.py +9 -6
  102. localstack/services/apigateway/next_gen/execute_api/integrations/http.py +12 -12
  103. localstack/services/apigateway/next_gen/execute_api/router.py +31 -0
  104. localstack/services/apigateway/next_gen/execute_api/template_mapping.py +2 -2
  105. localstack/services/apigateway/next_gen/execute_api/test_invoke.py +114 -9
  106. localstack/services/apigateway/next_gen/execute_api/variables.py +63 -63
  107. localstack/services/apigateway/next_gen/provider.py +5 -0
  108. localstack/services/apigateway/resource_providers/aws_apigateway_account.py +3 -3
  109. localstack/services/apigateway/resource_providers/aws_apigateway_account_plugin.py +1 -3
  110. localstack/services/apigateway/resource_providers/aws_apigateway_apikey.py +14 -14
  111. localstack/services/apigateway/resource_providers/aws_apigateway_apikey_plugin.py +1 -3
  112. localstack/services/apigateway/resource_providers/aws_apigateway_basepathmapping.py +5 -5
  113. localstack/services/apigateway/resource_providers/aws_apigateway_basepathmapping_plugin.py +1 -3
  114. localstack/services/apigateway/resource_providers/aws_apigateway_deployment.py +46 -46
  115. localstack/services/apigateway/resource_providers/aws_apigateway_deployment_plugin.py +1 -3
  116. localstack/services/apigateway/resource_providers/aws_apigateway_domainname.py +18 -18
  117. localstack/services/apigateway/resource_providers/aws_apigateway_domainname_plugin.py +1 -3
  118. localstack/services/apigateway/resource_providers/aws_apigateway_gatewayresponse.py +7 -7
  119. localstack/services/apigateway/resource_providers/aws_apigateway_gatewayresponse_plugin.py +1 -3
  120. localstack/services/apigateway/resource_providers/aws_apigateway_method.py +36 -36
  121. localstack/services/apigateway/resource_providers/aws_apigateway_method_plugin.py +1 -3
  122. localstack/services/apigateway/resource_providers/aws_apigateway_model.py +6 -6
  123. localstack/services/apigateway/resource_providers/aws_apigateway_model_plugin.py +1 -3
  124. localstack/services/apigateway/resource_providers/aws_apigateway_requestvalidator.py +6 -6
  125. localstack/services/apigateway/resource_providers/aws_apigateway_requestvalidator_plugin.py +1 -3
  126. localstack/services/apigateway/resource_providers/aws_apigateway_resource.py +6 -6
  127. localstack/services/apigateway/resource_providers/aws_apigateway_resource_plugin.py +1 -3
  128. localstack/services/apigateway/resource_providers/aws_apigateway_restapi.py +26 -26
  129. localstack/services/apigateway/resource_providers/aws_apigateway_restapi_plugin.py +1 -3
  130. localstack/services/apigateway/resource_providers/aws_apigateway_stage.py +33 -33
  131. localstack/services/apigateway/resource_providers/aws_apigateway_stage_plugin.py +1 -3
  132. localstack/services/apigateway/resource_providers/aws_apigateway_usageplan.py +18 -18
  133. localstack/services/apigateway/resource_providers/aws_apigateway_usageplan_plugin.py +1 -3
  134. localstack/services/apigateway/resource_providers/aws_apigateway_usageplankey.py +5 -5
  135. localstack/services/apigateway/resource_providers/aws_apigateway_usageplankey_plugin.py +1 -3
  136. localstack/services/cdk/resource_providers/cdk_metadata.py +4 -3
  137. localstack/services/cdk/resource_providers/cdk_metadata_plugin.py +1 -3
  138. localstack/services/certificatemanager/resource_providers/aws_certificatemanager_certificate.py +14 -14
  139. localstack/services/certificatemanager/resource_providers/aws_certificatemanager_certificate_plugin.py +1 -3
  140. localstack/services/cloudformation/api_utils.py +4 -8
  141. localstack/services/cloudformation/cfn_utils.py +2 -2
  142. localstack/services/cloudformation/deployment_utils.py +14 -12
  143. localstack/services/cloudformation/engine/changes.py +3 -3
  144. localstack/services/cloudformation/engine/entities.py +27 -17
  145. localstack/services/cloudformation/engine/parameters.py +4 -4
  146. localstack/services/cloudformation/engine/template_deployer.py +15 -14
  147. localstack/services/cloudformation/engine/template_utils.py +34 -12
  148. localstack/services/cloudformation/engine/transformers.py +11 -8
  149. localstack/services/cloudformation/engine/types.py +5 -4
  150. localstack/services/cloudformation/engine/v2/change_set_model.py +336 -39
  151. localstack/services/cloudformation/engine/v2/change_set_model_describer.py +96 -17
  152. localstack/services/cloudformation/engine/v2/change_set_model_executor.py +289 -136
  153. localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +315 -146
  154. localstack/services/cloudformation/engine/v2/change_set_model_transform.py +380 -105
  155. localstack/services/cloudformation/engine/v2/change_set_model_validator.py +183 -0
  156. localstack/services/cloudformation/engine/v2/change_set_model_visitor.py +6 -0
  157. localstack/services/cloudformation/engine/v2/resolving.py +102 -0
  158. localstack/services/cloudformation/engine/yaml_parser.py +9 -2
  159. localstack/services/cloudformation/provider.py +11 -6
  160. localstack/services/cloudformation/provider_utils.py +34 -4
  161. localstack/services/cloudformation/resource_provider.py +31 -21
  162. localstack/services/cloudformation/resource_providers/aws_cloudformation_macro.py +7 -7
  163. localstack/services/cloudformation/resource_providers/aws_cloudformation_macro_plugin.py +1 -3
  164. localstack/services/cloudformation/resource_providers/aws_cloudformation_stack.py +9 -9
  165. localstack/services/cloudformation/resource_providers/aws_cloudformation_stack_plugin.py +1 -3
  166. localstack/services/cloudformation/resource_providers/aws_cloudformation_waitcondition.py +6 -6
  167. localstack/services/cloudformation/resource_providers/aws_cloudformation_waitcondition_plugin.py +1 -3
  168. localstack/services/cloudformation/resource_providers/aws_cloudformation_waitconditionhandle.py +2 -2
  169. localstack/services/cloudformation/resource_providers/aws_cloudformation_waitconditionhandle_plugin.py +1 -3
  170. localstack/services/cloudformation/resources.py +24149 -0
  171. localstack/services/cloudformation/scaffolding/__main__.py +13 -12
  172. localstack/services/cloudformation/scaffolding/propgen.py +2 -2
  173. localstack/services/cloudformation/service_models.py +2 -2
  174. localstack/services/cloudformation/stores.py +33 -22
  175. localstack/services/cloudformation/v2/entities.py +103 -88
  176. localstack/services/cloudformation/v2/provider.py +872 -131
  177. localstack/services/cloudformation/v2/types.py +38 -0
  178. localstack/services/cloudformation/v2/utils.py +4 -1
  179. localstack/services/cloudwatch/alarm_scheduler.py +11 -8
  180. localstack/services/cloudwatch/cloudwatch_database_helper.py +4 -5
  181. localstack/services/cloudwatch/models.py +5 -7
  182. localstack/services/cloudwatch/provider.py +30 -25
  183. localstack/services/cloudwatch/provider_v2.py +27 -32
  184. localstack/services/cloudwatch/resource_providers/aws_cloudwatch_alarm.py +40 -40
  185. localstack/services/cloudwatch/resource_providers/aws_cloudwatch_alarm_plugin.py +1 -3
  186. localstack/services/cloudwatch/resource_providers/aws_cloudwatch_compositealarm.py +12 -12
  187. localstack/services/cloudwatch/resource_providers/aws_cloudwatch_compositealarm_plugin.py +1 -3
  188. localstack/services/dynamodb/packages.py +3 -3
  189. localstack/services/dynamodb/provider.py +159 -18
  190. localstack/services/dynamodb/resource_providers/aws_dynamodb_globaltable.py +63 -63
  191. localstack/services/dynamodb/resource_providers/aws_dynamodb_globaltable_plugin.py +1 -3
  192. localstack/services/dynamodb/resource_providers/aws_dynamodb_table.py +57 -57
  193. localstack/services/dynamodb/resource_providers/aws_dynamodb_table_plugin.py +1 -3
  194. localstack/services/dynamodb/server.py +2 -2
  195. localstack/services/dynamodb/utils.py +13 -14
  196. localstack/services/dynamodb/v2/provider.py +157 -18
  197. localstack/services/dynamodbstreams/dynamodbstreams_api.py +2 -2
  198. localstack/services/dynamodbstreams/models.py +1 -3
  199. localstack/services/ec2/patches.py +26 -5
  200. localstack/services/ec2/provider.py +3 -3
  201. localstack/services/ec2/resource_providers/aws_ec2_dhcpoptions.py +10 -10
  202. localstack/services/ec2/resource_providers/aws_ec2_dhcpoptions_plugin.py +1 -3
  203. localstack/services/ec2/resource_providers/aws_ec2_instance.py +96 -96
  204. localstack/services/ec2/resource_providers/aws_ec2_instance_plugin.py +1 -3
  205. localstack/services/ec2/resource_providers/aws_ec2_internetgateway.py +5 -5
  206. localstack/services/ec2/resource_providers/aws_ec2_internetgateway_plugin.py +1 -3
  207. localstack/services/ec2/resource_providers/aws_ec2_keypair.py +10 -10
  208. localstack/services/ec2/resource_providers/aws_ec2_keypair_plugin.py +1 -3
  209. localstack/services/ec2/resource_providers/aws_ec2_natgateway.py +13 -13
  210. localstack/services/ec2/resource_providers/aws_ec2_natgateway_plugin.py +1 -3
  211. localstack/services/ec2/resource_providers/aws_ec2_networkacl.py +6 -6
  212. localstack/services/ec2/resource_providers/aws_ec2_networkacl_plugin.py +1 -3
  213. localstack/services/ec2/resource_providers/aws_ec2_prefixlist.py +14 -14
  214. localstack/services/ec2/resource_providers/aws_ec2_prefixlist_plugin.py +1 -3
  215. localstack/services/ec2/resource_providers/aws_ec2_route.py +15 -15
  216. localstack/services/ec2/resource_providers/aws_ec2_route_plugin.py +1 -3
  217. localstack/services/ec2/resource_providers/aws_ec2_routetable.py +6 -6
  218. localstack/services/ec2/resource_providers/aws_ec2_routetable_plugin.py +1 -3
  219. localstack/services/ec2/resource_providers/aws_ec2_securitygroup.py +29 -29
  220. localstack/services/ec2/resource_providers/aws_ec2_securitygroup_plugin.py +1 -3
  221. localstack/services/ec2/resource_providers/aws_ec2_subnet.py +19 -19
  222. localstack/services/ec2/resource_providers/aws_ec2_subnet_plugin.py +1 -3
  223. localstack/services/ec2/resource_providers/aws_ec2_subnetroutetableassociation.py +4 -4
  224. localstack/services/ec2/resource_providers/aws_ec2_subnetroutetableassociation_plugin.py +1 -3
  225. localstack/services/ec2/resource_providers/aws_ec2_transitgateway.py +16 -16
  226. localstack/services/ec2/resource_providers/aws_ec2_transitgateway_plugin.py +1 -3
  227. localstack/services/ec2/resource_providers/aws_ec2_transitgatewayattachment.py +9 -9
  228. localstack/services/ec2/resource_providers/aws_ec2_transitgatewayattachment_plugin.py +1 -3
  229. localstack/services/ec2/resource_providers/aws_ec2_vpc.py +15 -15
  230. localstack/services/ec2/resource_providers/aws_ec2_vpc_plugin.py +1 -3
  231. localstack/services/ec2/resource_providers/aws_ec2_vpcendpoint.py +29 -22
  232. localstack/services/ec2/resource_providers/aws_ec2_vpcendpoint_plugin.py +1 -3
  233. localstack/services/ec2/resource_providers/aws_ec2_vpcgatewayattachment.py +5 -5
  234. localstack/services/ec2/resource_providers/aws_ec2_vpcgatewayattachment_plugin.py +1 -3
  235. localstack/services/ecr/resource_providers/aws_ecr_repository.py +22 -19
  236. localstack/services/ecr/resource_providers/aws_ecr_repository_plugin.py +1 -3
  237. localstack/services/edge.py +6 -6
  238. localstack/services/es/provider.py +21 -21
  239. localstack/services/events/archive.py +2 -2
  240. localstack/services/events/connection.py +5 -5
  241. localstack/services/events/event_bus.py +9 -9
  242. localstack/services/events/event_rule_engine.py +31 -13
  243. localstack/services/events/models.py +29 -30
  244. localstack/services/events/provider.py +29 -26
  245. localstack/services/events/replay.py +3 -3
  246. localstack/services/events/resource_providers/aws_events_apidestination.py +8 -8
  247. localstack/services/events/resource_providers/aws_events_apidestination_plugin.py +1 -3
  248. localstack/services/events/resource_providers/aws_events_connection.py +27 -27
  249. localstack/services/events/resource_providers/aws_events_connection_plugin.py +1 -3
  250. localstack/services/events/resource_providers/aws_events_eventbus.py +9 -9
  251. localstack/services/events/resource_providers/aws_events_eventbus_plugin.py +1 -3
  252. localstack/services/events/resource_providers/aws_events_eventbuspolicy.py +11 -11
  253. localstack/services/events/resource_providers/aws_events_eventbuspolicy_plugin.py +1 -3
  254. localstack/services/events/resource_providers/aws_events_rule.py +82 -82
  255. localstack/services/events/resource_providers/aws_events_rule_plugin.py +1 -3
  256. localstack/services/events/rule.py +15 -15
  257. localstack/services/events/target.py +21 -13
  258. localstack/services/events/utils.py +7 -7
  259. localstack/services/events/v1/models.py +1 -3
  260. localstack/services/events/v1/provider.py +15 -15
  261. localstack/services/firehose/models.py +1 -3
  262. localstack/services/firehose/provider.py +25 -16
  263. localstack/services/iam/iam_patches.py +5 -6
  264. localstack/services/iam/provider.py +14 -119
  265. localstack/services/iam/resource_providers/aws_iam_accesskey.py +6 -6
  266. localstack/services/iam/resource_providers/aws_iam_accesskey_plugin.py +1 -3
  267. localstack/services/iam/resource_providers/aws_iam_group.py +9 -9
  268. localstack/services/iam/resource_providers/aws_iam_group_plugin.py +1 -3
  269. localstack/services/iam/resource_providers/aws_iam_instanceprofile.py +5 -5
  270. localstack/services/iam/resource_providers/aws_iam_instanceprofile_plugin.py +1 -3
  271. localstack/services/iam/resource_providers/aws_iam_managedpolicy.py +9 -9
  272. localstack/services/iam/resource_providers/aws_iam_managedpolicy_plugin.py +1 -3
  273. localstack/services/iam/resource_providers/aws_iam_policy.py +7 -7
  274. localstack/services/iam/resource_providers/aws_iam_policy_plugin.py +1 -3
  275. localstack/services/iam/resource_providers/aws_iam_role.py +16 -16
  276. localstack/services/iam/resource_providers/aws_iam_role_plugin.py +1 -3
  277. localstack/services/iam/resource_providers/aws_iam_servercertificate.py +10 -10
  278. localstack/services/iam/resource_providers/aws_iam_servercertificate_plugin.py +1 -3
  279. localstack/services/iam/resource_providers/aws_iam_servicelinkedrole.py +5 -5
  280. localstack/services/iam/resource_providers/aws_iam_servicelinkedrole_plugin.py +1 -3
  281. localstack/services/iam/resource_providers/aws_iam_user.py +17 -17
  282. localstack/services/iam/resource_providers/aws_iam_user_plugin.py +1 -3
  283. localstack/services/iam/resources/policy_simulator.py +133 -0
  284. localstack/services/kinesis/kinesis_mock_server.py +7 -8
  285. localstack/services/kinesis/models.py +17 -5
  286. localstack/services/kinesis/packages.py +3 -3
  287. localstack/services/kinesis/provider.py +86 -3
  288. localstack/services/kinesis/resource_providers/aws_kinesis_stream.py +13 -13
  289. localstack/services/kinesis/resource_providers/aws_kinesis_stream_plugin.py +1 -3
  290. localstack/services/kinesis/resource_providers/aws_kinesis_streamconsumer.py +7 -7
  291. localstack/services/kinesis/resource_providers/aws_kinesis_streamconsumer_plugin.py +1 -3
  292. localstack/services/kinesisfirehose/resource_providers/aws_kinesisfirehose_deliverystream.py +191 -191
  293. localstack/services/kinesisfirehose/resource_providers/aws_kinesisfirehose_deliverystream_plugin.py +1 -3
  294. localstack/services/kms/models.py +21 -18
  295. localstack/services/kms/provider.py +62 -26
  296. localstack/services/kms/resource_providers/aws_kms_alias.py +3 -3
  297. localstack/services/kms/resource_providers/aws_kms_alias_plugin.py +1 -3
  298. localstack/services/kms/resource_providers/aws_kms_key.py +14 -14
  299. localstack/services/kms/resource_providers/aws_kms_key_plugin.py +1 -3
  300. localstack/services/kms/utils.py +4 -3
  301. localstack/services/lambda_/api_utils.py +19 -16
  302. localstack/services/lambda_/custom_endpoints.py +2 -2
  303. localstack/services/lambda_/event_source_mapping/esm_worker_factory.py +4 -7
  304. localstack/services/lambda_/event_source_mapping/pipe_utils.py +2 -2
  305. localstack/services/lambda_/event_source_mapping/pollers/stream_poller.py +1 -1
  306. localstack/services/lambda_/event_source_mapping/senders/sender_utils.py +2 -1
  307. localstack/services/lambda_/hooks.py +6 -1
  308. localstack/services/lambda_/invocation/assignment.py +1 -2
  309. localstack/services/lambda_/invocation/docker_runtime_executor.py +7 -11
  310. localstack/services/lambda_/invocation/event_manager.py +1 -1
  311. localstack/services/lambda_/invocation/execution_environment.py +4 -4
  312. localstack/services/lambda_/invocation/executor_endpoint.py +8 -11
  313. localstack/services/lambda_/invocation/internal_sqs_queue.py +6 -10
  314. localstack/services/lambda_/invocation/lambda_models.py +33 -30
  315. localstack/services/lambda_/invocation/lambda_service.py +12 -5
  316. localstack/services/lambda_/invocation/logs.py +2 -3
  317. localstack/services/lambda_/invocation/runtime_executor.py +3 -3
  318. localstack/services/lambda_/invocation/version_manager.py +31 -8
  319. localstack/services/lambda_/ldm.py +14 -0
  320. localstack/services/lambda_/packages.py +3 -4
  321. localstack/services/lambda_/provider.py +9 -26
  322. localstack/services/lambda_/provider_utils.py +1 -1
  323. localstack/services/lambda_/resource_providers/aws_lambda_codesigningconfig.py +8 -8
  324. localstack/services/lambda_/resource_providers/aws_lambda_codesigningconfig_plugin.py +1 -3
  325. localstack/services/lambda_/resource_providers/aws_lambda_eventinvokeconfig.py +11 -11
  326. localstack/services/lambda_/resource_providers/aws_lambda_eventinvokeconfig_plugin.py +1 -3
  327. localstack/services/lambda_/resource_providers/aws_lambda_eventsourcemapping.py +39 -39
  328. localstack/services/lambda_/resource_providers/aws_lambda_eventsourcemapping_plugin.py +1 -3
  329. localstack/services/lambda_/resource_providers/aws_lambda_function.py +54 -54
  330. localstack/services/lambda_/resource_providers/aws_lambda_function_plugin.py +1 -3
  331. localstack/services/lambda_/resource_providers/aws_lambda_layerversion.py +11 -11
  332. localstack/services/lambda_/resource_providers/aws_lambda_layerversion_plugin.py +1 -3
  333. localstack/services/lambda_/resource_providers/aws_lambda_layerversionpermission.py +6 -6
  334. localstack/services/lambda_/resource_providers/aws_lambda_layerversionpermission_plugin.py +1 -3
  335. localstack/services/lambda_/resource_providers/aws_lambda_permission.py +10 -10
  336. localstack/services/lambda_/resource_providers/aws_lambda_permission_plugin.py +1 -3
  337. localstack/services/lambda_/resource_providers/aws_lambda_url.py +15 -15
  338. localstack/services/lambda_/resource_providers/aws_lambda_url_plugin.py +1 -3
  339. localstack/services/lambda_/resource_providers/aws_lambda_version.py +8 -8
  340. localstack/services/lambda_/resource_providers/aws_lambda_version_plugin.py +1 -3
  341. localstack/services/lambda_/resource_providers/lambda_alias.py +12 -12
  342. localstack/services/lambda_/resource_providers/lambda_alias_plugin.py +1 -3
  343. localstack/services/lambda_/runtimes.py +1 -3
  344. localstack/services/lambda_/urlrouter.py +14 -1
  345. localstack/services/logs/models.py +1 -3
  346. localstack/services/logs/provider.py +39 -22
  347. localstack/services/logs/resource_providers/aws_logs_loggroup.py +9 -9
  348. localstack/services/logs/resource_providers/aws_logs_loggroup_plugin.py +1 -3
  349. localstack/services/logs/resource_providers/aws_logs_logstream.py +4 -4
  350. localstack/services/logs/resource_providers/aws_logs_logstream_plugin.py +1 -3
  351. localstack/services/logs/resource_providers/aws_logs_subscriptionfilter.py +7 -7
  352. localstack/services/logs/resource_providers/aws_logs_subscriptionfilter_plugin.py +1 -3
  353. localstack/services/moto.py +5 -4
  354. localstack/services/opensearch/cluster.py +28 -20
  355. localstack/services/opensearch/cluster_manager.py +13 -14
  356. localstack/services/opensearch/models.py +1 -3
  357. localstack/services/opensearch/packages.py +27 -9
  358. localstack/services/opensearch/provider.py +15 -10
  359. localstack/services/opensearch/resource_providers/aws_elasticsearch_domain.py +61 -61
  360. localstack/services/opensearch/resource_providers/aws_elasticsearch_domain_plugin.py +1 -3
  361. localstack/services/opensearch/resource_providers/aws_opensearchservice_domain.py +89 -89
  362. localstack/services/opensearch/resource_providers/aws_opensearchservice_domain_plugin.py +1 -3
  363. localstack/services/opensearch/versions.py +57 -10
  364. localstack/services/plugins.py +37 -32
  365. localstack/services/providers.py +10 -2
  366. localstack/services/redshift/provider.py +0 -21
  367. localstack/services/redshift/resource_providers/aws_redshift_cluster.py +57 -57
  368. localstack/services/redshift/resource_providers/aws_redshift_cluster_plugin.py +1 -3
  369. localstack/services/resource_groups/resource_providers/aws_resourcegroups_group.py +21 -21
  370. localstack/services/resource_groups/resource_providers/aws_resourcegroups_group_plugin.py +1 -3
  371. localstack/services/route53/models.py +1 -3
  372. localstack/services/route53/provider.py +1 -2
  373. localstack/services/route53/resource_providers/aws_route53_healthcheck.py +6 -6
  374. localstack/services/route53/resource_providers/aws_route53_healthcheck_plugin.py +1 -3
  375. localstack/services/route53/resource_providers/aws_route53_recordset.py +27 -27
  376. localstack/services/route53/resource_providers/aws_route53_recordset_plugin.py +1 -3
  377. localstack/services/route53resolver/models.py +8 -10
  378. localstack/services/route53resolver/provider.py +12 -12
  379. localstack/services/s3/codec.py +2 -2
  380. localstack/services/s3/constants.py +5 -2
  381. localstack/services/s3/cors.py +8 -8
  382. localstack/services/s3/models.py +73 -73
  383. localstack/services/s3/notifications.py +74 -58
  384. localstack/services/s3/presigned_url.py +41 -59
  385. localstack/services/s3/provider.py +86 -29
  386. localstack/services/s3/resource_providers/aws_s3_bucket.py +180 -180
  387. localstack/services/s3/resource_providers/aws_s3_bucket_plugin.py +1 -3
  388. localstack/services/s3/resource_providers/aws_s3_bucketpolicy.py +4 -4
  389. localstack/services/s3/resource_providers/aws_s3_bucketpolicy_plugin.py +1 -3
  390. localstack/services/s3/storage/core.py +4 -3
  391. localstack/services/s3/storage/ephemeral.py +7 -6
  392. localstack/services/s3/utils.py +51 -31
  393. localstack/services/s3/validation.py +47 -33
  394. localstack/services/s3/website_hosting.py +9 -7
  395. localstack/services/scheduler/resource_providers/aws_scheduler_schedule.py +60 -60
  396. localstack/services/scheduler/resource_providers/aws_scheduler_schedule_plugin.py +1 -3
  397. localstack/services/scheduler/resource_providers/aws_scheduler_schedulegroup.py +9 -9
  398. localstack/services/scheduler/resource_providers/aws_scheduler_schedulegroup_plugin.py +1 -3
  399. localstack/services/secretsmanager/provider.py +10 -12
  400. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_resourcepolicy.py +5 -5
  401. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_resourcepolicy_plugin.py +1 -3
  402. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_rotationschedule.py +21 -21
  403. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_rotationschedule_plugin.py +1 -3
  404. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secret.py +23 -23
  405. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secret_plugin.py +1 -3
  406. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secrettargetattachment.py +5 -5
  407. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secrettargetattachment_plugin.py +1 -3
  408. localstack/services/ses/models.py +8 -1
  409. localstack/services/ses/provider.py +128 -55
  410. localstack/services/ses/resource_providers/aws_ses_emailidentity.py +21 -21
  411. localstack/services/ses/resource_providers/aws_ses_emailidentity_plugin.py +1 -3
  412. localstack/services/sns/constants.py +7 -1
  413. localstack/services/sns/executor.py +9 -2
  414. localstack/services/sns/models.py +25 -25
  415. localstack/services/sns/provider.py +9 -7
  416. localstack/services/sns/publisher.py +37 -23
  417. localstack/services/sns/resource_providers/aws_sns_subscription.py +13 -13
  418. localstack/services/sns/resource_providers/aws_sns_subscription_plugin.py +1 -3
  419. localstack/services/sns/resource_providers/aws_sns_topic.py +16 -16
  420. localstack/services/sns/resource_providers/aws_sns_topic_plugin.py +1 -3
  421. localstack/services/sns/resource_providers/aws_sns_topicpolicy.py +4 -4
  422. localstack/services/sns/resource_providers/aws_sns_topicpolicy_plugin.py +1 -3
  423. localstack/services/sns/v2/models.py +167 -0
  424. localstack/services/sns/v2/provider.py +867 -0
  425. localstack/services/sns/v2/utils.py +130 -0
  426. localstack/services/sqs/constants.py +2 -2
  427. localstack/services/sqs/developer_api.py +205 -0
  428. localstack/services/sqs/models.py +71 -36
  429. localstack/services/sqs/provider.py +56 -332
  430. localstack/services/sqs/query_api.py +8 -5
  431. localstack/services/sqs/resource_providers/aws_sqs_queue.py +21 -21
  432. localstack/services/sqs/resource_providers/aws_sqs_queue_plugin.py +1 -3
  433. localstack/services/sqs/resource_providers/aws_sqs_queuepolicy.py +7 -5
  434. localstack/services/sqs/resource_providers/aws_sqs_queuepolicy_plugin.py +1 -3
  435. localstack/services/sqs/utils.py +123 -4
  436. localstack/services/ssm/provider.py +3 -4
  437. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindow.py +15 -15
  438. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindow_plugin.py +1 -3
  439. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtarget.py +10 -10
  440. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtarget_plugin.py +1 -3
  441. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtask.py +48 -48
  442. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtask_plugin.py +1 -3
  443. localstack/services/ssm/resource_providers/aws_ssm_parameter.py +10 -10
  444. localstack/services/ssm/resource_providers/aws_ssm_parameter_plugin.py +1 -3
  445. localstack/services/ssm/resource_providers/aws_ssm_patchbaseline.py +29 -29
  446. localstack/services/ssm/resource_providers/aws_ssm_patchbaseline_plugin.py +1 -3
  447. localstack/services/stepfunctions/asl/antlt4utils/antlr4utils.py +3 -4
  448. localstack/services/stepfunctions/asl/component/common/assign/assign_decl.py +1 -1
  449. localstack/services/stepfunctions/asl/component/common/assign/assign_decl_binding.py +1 -1
  450. localstack/services/stepfunctions/asl/component/common/assign/assign_template_value_array.py +1 -1
  451. localstack/services/stepfunctions/asl/component/common/assign/assign_template_value_object.py +1 -1
  452. localstack/services/stepfunctions/asl/component/common/catch/catcher_decl.py +9 -9
  453. localstack/services/stepfunctions/asl/component/common/error_name/custom_error_name.py +2 -2
  454. localstack/services/stepfunctions/asl/component/common/error_name/error_name.py +4 -4
  455. localstack/services/stepfunctions/asl/component/common/error_name/failure_event.py +8 -8
  456. localstack/services/stepfunctions/asl/component/common/error_name/states_error_name_type.py +1 -1
  457. localstack/services/stepfunctions/asl/component/common/jsonata/jsonata_template_binding.py +2 -2
  458. localstack/services/stepfunctions/asl/component/common/jsonata/jsonata_template_value_array.py +1 -1
  459. localstack/services/stepfunctions/asl/component/common/jsonata/jsonata_template_value_object.py +1 -1
  460. localstack/services/stepfunctions/asl/component/common/path/input_path.py +4 -4
  461. localstack/services/stepfunctions/asl/component/common/path/output_path.py +4 -4
  462. localstack/services/stepfunctions/asl/component/common/path/result_path.py +3 -3
  463. localstack/services/stepfunctions/asl/component/common/payload/payloadvalue/payloadarr/payload_arr.py +1 -1
  464. localstack/services/stepfunctions/asl/component/common/payload/payloadvalue/payloadbinding/payload_binding.py +3 -3
  465. localstack/services/stepfunctions/asl/component/common/payload/payloadvalue/payloadtmpl/payload_tmpl.py +1 -1
  466. localstack/services/stepfunctions/asl/component/common/retry/retrier_decl.py +8 -8
  467. localstack/services/stepfunctions/asl/component/common/string/string_expression.py +3 -3
  468. localstack/services/stepfunctions/asl/component/common/timeouts/timeout.py +3 -3
  469. localstack/services/stepfunctions/asl/component/eval_component.py +2 -3
  470. localstack/services/stepfunctions/asl/component/intrinsic/argument/argument.py +4 -4
  471. localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/array/array_partition.py +1 -1
  472. localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/generic/string_format.py +1 -1
  473. localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/states_function_array.py +1 -1
  474. localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/states_function_format.py +1 -1
  475. localstack/services/stepfunctions/asl/component/intrinsic/jsonata.py +3 -3
  476. localstack/services/stepfunctions/asl/component/intrinsic/member.py +1 -1
  477. localstack/services/stepfunctions/asl/component/program/program.py +9 -9
  478. localstack/services/stepfunctions/asl/component/program/states.py +1 -1
  479. localstack/services/stepfunctions/asl/component/state/state.py +10 -11
  480. localstack/services/stepfunctions/asl/component/state/state_choice/choice_rule.py +11 -11
  481. localstack/services/stepfunctions/asl/component/state/state_choice/comparison/comparison.py +5 -11
  482. localstack/services/stepfunctions/asl/component/state/state_choice/comparison/operator/implementations/is_operator.py +2 -2
  483. localstack/services/stepfunctions/asl/component/state/state_choice/state_choice.py +3 -5
  484. localstack/services/stepfunctions/asl/component/state/state_execution/execute_state.py +9 -9
  485. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/item_reader_decl.py +7 -7
  486. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/reader_config/reader_config_decl.py +5 -5
  487. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/resource_eval/resource_eval_s3.py +2 -1
  488. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/resource_eval/resource_output_transformer/resource_output_transformer_csv.py +2 -2
  489. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/distributed_iteration_component.py +8 -8
  490. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/inline_iteration_component.py +7 -7
  491. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/itemprocessor/distributed_item_processor_worker.py +4 -4
  492. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/itemprocessor/inline_item_processor_worker.py +5 -5
  493. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/itemprocessor/map_run_record.py +10 -10
  494. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iteration_component.py +3 -3
  495. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iteration_declaration.py +3 -3
  496. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iteration_worker.py +2 -2
  497. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iterator/distributed_iterator_worker.py +3 -5
  498. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iterator/inline_iterator.py +1 -2
  499. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iterator/inline_iterator_worker.py +5 -5
  500. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/job.py +9 -9
  501. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/result_writer/resource_eval/resource_eval_s3.py +2 -1
  502. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/state_map.py +12 -13
  503. localstack/services/stepfunctions/asl/component/state/state_execution/state_parallel/branch_worker.py +3 -3
  504. localstack/services/stepfunctions/asl/component/state/state_execution/state_parallel/branches_decl.py +7 -7
  505. localstack/services/stepfunctions/asl/component/state/state_execution/state_parallel/state_parallel.py +2 -3
  506. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/lambda_eval_utils.py +7 -7
  507. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/resource.py +3 -3
  508. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service.py +10 -10
  509. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_api_gateway.py +18 -18
  510. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_aws_sdk.py +1 -1
  511. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_batch.py +8 -7
  512. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_callback.py +18 -17
  513. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_dynamodb.py +2 -2
  514. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_ecs.py +5 -4
  515. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_events.py +4 -4
  516. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_glue.py +7 -6
  517. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_lambda.py +4 -4
  518. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_sfn.py +9 -8
  519. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_sns.py +2 -2
  520. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_sqs.py +4 -4
  521. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/state_task.py +5 -5
  522. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/state_task_lambda.py +2 -2
  523. localstack/services/stepfunctions/asl/component/state/state_fail/state_fail.py +3 -5
  524. localstack/services/stepfunctions/asl/component/state/state_pass/state_pass.py +5 -7
  525. localstack/services/stepfunctions/asl/component/state/state_succeed/state_succeed.py +1 -1
  526. localstack/services/stepfunctions/asl/component/state/state_wait/state_wait.py +1 -1
  527. localstack/services/stepfunctions/asl/component/state/state_wait/wait_function/timestamp.py +2 -2
  528. localstack/services/stepfunctions/asl/eval/callback/callback.py +18 -18
  529. localstack/services/stepfunctions/asl/eval/environment.py +22 -24
  530. localstack/services/stepfunctions/asl/eval/evaluation_details.py +3 -5
  531. localstack/services/stepfunctions/asl/eval/event/event_manager.py +10 -10
  532. localstack/services/stepfunctions/asl/eval/event/logging.py +3 -3
  533. localstack/services/stepfunctions/asl/eval/program_state.py +8 -8
  534. localstack/services/stepfunctions/asl/eval/states.py +12 -12
  535. localstack/services/stepfunctions/asl/eval/test_state/environment.py +3 -5
  536. localstack/services/stepfunctions/asl/eval/variable_store.py +6 -6
  537. localstack/services/stepfunctions/asl/jsonata/jsonata.py +7 -6
  538. localstack/services/stepfunctions/asl/parse/asl_parser.py +1 -1
  539. localstack/services/stepfunctions/asl/parse/intrinsic/preprocessor.py +2 -3
  540. localstack/services/stepfunctions/asl/parse/preprocessor.py +44 -44
  541. localstack/services/stepfunctions/asl/parse/typed_props.py +2 -2
  542. localstack/services/stepfunctions/asl/static_analyser/intrinsic/variable_names_intrinsic_static_analyser.py +1 -1
  543. localstack/services/stepfunctions/asl/static_analyser/variable_references_static_analyser.py +2 -2
  544. localstack/services/stepfunctions/asl/utils/encoding.py +2 -2
  545. localstack/services/stepfunctions/asl/utils/json_path.py +2 -2
  546. localstack/services/stepfunctions/backend/activity.py +4 -4
  547. localstack/services/stepfunctions/backend/alias.py +8 -8
  548. localstack/services/stepfunctions/backend/execution.py +29 -30
  549. localstack/services/stepfunctions/backend/execution_worker.py +7 -7
  550. localstack/services/stepfunctions/backend/state_machine.py +28 -28
  551. localstack/services/stepfunctions/backend/test_state/execution.py +3 -4
  552. localstack/services/stepfunctions/backend/test_state/execution_worker.py +1 -3
  553. localstack/services/stepfunctions/mocking/mock_config.py +9 -9
  554. localstack/services/stepfunctions/mocking/mock_config_file.py +10 -10
  555. localstack/services/stepfunctions/packages.py +14 -5
  556. localstack/services/stepfunctions/provider.py +34 -44
  557. localstack/services/stepfunctions/quotas.py +2 -3
  558. localstack/services/stepfunctions/resource_providers/aws_stepfunctions_activity.py +6 -6
  559. localstack/services/stepfunctions/resource_providers/aws_stepfunctions_activity_plugin.py +1 -3
  560. localstack/services/stepfunctions/resource_providers/aws_stepfunctions_statemachine.py +25 -25
  561. localstack/services/stepfunctions/resource_providers/aws_stepfunctions_statemachine_plugin.py +1 -3
  562. localstack/services/stepfunctions/stepfunctions_utils.py +1 -2
  563. localstack/services/stores.py +8 -8
  564. localstack/services/transcribe/packages.py +1 -3
  565. localstack/services/transcribe/provider.py +8 -3
  566. localstack/state/codecs.py +61 -0
  567. localstack/state/core.py +11 -5
  568. localstack/state/inspect.py +4 -4
  569. localstack/state/pickle.py +36 -23
  570. localstack/testing/aws/asf_utils.py +3 -2
  571. localstack/testing/aws/cloudformation_utils.py +1 -1
  572. localstack/testing/aws/lambda_utils.py +15 -14
  573. localstack/testing/aws/util.py +3 -2
  574. localstack/testing/pytest/cloudformation/fixtures.py +68 -18
  575. localstack/testing/pytest/container.py +5 -5
  576. localstack/testing/pytest/filters.py +1 -3
  577. localstack/testing/pytest/fixtures.py +188 -49
  578. localstack/testing/pytest/in_memory_localstack.py +1 -3
  579. localstack/testing/pytest/marking.py +42 -15
  580. localstack/testing/pytest/path_filter.py +1 -1
  581. localstack/testing/pytest/stepfunctions/fixtures.py +4 -4
  582. localstack/testing/pytest/stepfunctions/utils.py +11 -10
  583. localstack/testing/pytest/util.py +1 -1
  584. localstack/testing/pytest/validation_tracking.py +3 -4
  585. localstack/testing/scenario/provisioning.py +11 -10
  586. localstack/testing/snapshots/transformer_utility.py +8 -3
  587. localstack/testing/testselection/matching.py +2 -2
  588. localstack/testing/testselection/opt_out.py +1 -1
  589. localstack/testing/testselection/scripts/filter_by_test_selection.py +1 -1
  590. localstack/testing/testselection/scripts/generate_test_selection.py +1 -1
  591. localstack/testing/testselection/testselection.py +2 -2
  592. localstack/utils/analytics/cli.py +2 -3
  593. localstack/utils/analytics/client.py +5 -5
  594. localstack/utils/analytics/events.py +2 -2
  595. localstack/utils/analytics/metadata.py +6 -4
  596. localstack/utils/analytics/metrics/counter.py +11 -18
  597. localstack/utils/analytics/metrics/registry.py +2 -2
  598. localstack/utils/analytics/publisher.py +4 -5
  599. localstack/utils/analytics/service_providers.py +19 -0
  600. localstack/utils/analytics/service_request_aggregator.py +4 -4
  601. localstack/utils/archives.py +12 -12
  602. localstack/utils/asyncio.py +2 -2
  603. localstack/utils/aws/arns.py +26 -31
  604. localstack/utils/aws/aws_responses.py +21 -28
  605. localstack/utils/aws/aws_stack.py +7 -12
  606. localstack/utils/aws/dead_letter_queue.py +4 -9
  607. localstack/utils/aws/message_forwarding.py +8 -11
  608. localstack/utils/aws/request_context.py +5 -6
  609. localstack/utils/aws/resources.py +1 -1
  610. localstack/utils/aws/templating.py +4 -4
  611. localstack/utils/batch_policy.py +4 -4
  612. localstack/utils/bootstrap.py +37 -30
  613. localstack/utils/catalog/catalog.py +139 -0
  614. localstack/utils/catalog/catalog_loader.py +119 -0
  615. localstack/utils/catalog/common.py +58 -0
  616. localstack/utils/catalog/plugins.py +28 -0
  617. localstack/utils/cloudwatch/cloudwatch_util.py +5 -5
  618. localstack/utils/collections.py +33 -27
  619. localstack/utils/config_listener.py +2 -2
  620. localstack/utils/container_networking.py +5 -6
  621. localstack/utils/container_utils/container_client.py +156 -160
  622. localstack/utils/container_utils/docker_cmd_client.py +97 -81
  623. localstack/utils/container_utils/docker_sdk_client.py +75 -72
  624. localstack/utils/crypto.py +12 -13
  625. localstack/utils/diagnose.py +11 -12
  626. localstack/utils/docker_utils.py +11 -7
  627. localstack/utils/files.py +34 -15
  628. localstack/utils/functions.py +5 -4
  629. localstack/utils/http.py +14 -14
  630. localstack/utils/iputils.py +2 -1
  631. localstack/utils/json.py +21 -7
  632. localstack/utils/kinesis/kinesis_connector.py +2 -1
  633. localstack/utils/net.py +25 -17
  634. localstack/utils/no_exit_argument_parser.py +2 -2
  635. localstack/utils/numbers.py +9 -2
  636. localstack/utils/objects.py +15 -14
  637. localstack/utils/patch.py +14 -7
  638. localstack/utils/platform.py +2 -2
  639. localstack/utils/run.py +15 -14
  640. localstack/utils/scheduler.py +13 -12
  641. localstack/utils/server/tcp_proxy.py +2 -2
  642. localstack/utils/serving.py +3 -4
  643. localstack/utils/strings.py +15 -16
  644. localstack/utils/sync.py +126 -1
  645. localstack/utils/tagging.py +10 -8
  646. localstack/utils/testutil.py +17 -17
  647. localstack/utils/threads.py +3 -3
  648. localstack/utils/time.py +12 -4
  649. localstack/utils/urls.py +1 -3
  650. localstack/utils/xml.py +1 -1
  651. localstack/utils/xray/traceid.py +1 -1
  652. localstack/version.py +16 -3
  653. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/METADATA +18 -13
  654. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/RECORD +663 -655
  655. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/entry_points.txt +8 -4
  656. localstack_core-4.10.1.dev12.dist-info/plux.json +1 -0
  657. localstack/packages/terraform.py +0 -47
  658. localstack/services/cloudformation/deploy.html +0 -144
  659. localstack/services/cloudformation/deploy_ui.py +0 -47
  660. localstack/services/cloudformation/plugins.py +0 -12
  661. localstack/services/lambda_/lambda_debug_mode/ldm.py +0 -375
  662. localstack/services/lambda_/lambda_debug_mode/ldm_config_file.py +0 -178
  663. localstack/services/lambda_/lambda_debug_mode/ldm_types.py +0 -11
  664. localstack/services/lambda_/lambda_debug_mode/ldm_utils.py +0 -43
  665. localstack_core-4.6.1.dev60.dist-info/plux.json +0 -1
  666. /localstack/{services/lambda_/lambda_debug_mode/__init__.py → testing/pytest/cloudformation/transformers.py} +0 -0
  667. {localstack_core-4.6.1.dev60.data → localstack_core-4.10.1.dev12.data}/scripts/localstack +0 -0
  668. {localstack_core-4.6.1.dev60.data → localstack_core-4.10.1.dev12.data}/scripts/localstack-supervisor +0 -0
  669. {localstack_core-4.6.1.dev60.data → localstack_core-4.10.1.dev12.data}/scripts/localstack.bat +0 -0
  670. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/WHEEL +0 -0
  671. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/licenses/LICENSE.txt +0 -0
  672. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/top_level.txt +0 -0
@@ -19,22 +19,23 @@ The class hierarchy looks as follows:
19
19
  │RequestParser│
20
20
  └─────────────┘
21
21
  ▲ ▲ ▲
22
- ┌─────────────────┘ │ └────────────────────┐
23
- ┌────────┴─────────┐ ┌─────────┴───────────┐ ┌──────────┴──────────┐
24
- │QueryRequestParser│ │BaseRestRequestParser│ │BaseJSONRequestParser│
25
- └──────────────────┘ └─────────────────────┘ └─────────────────────┘
26
- ▲ ▲ ▲ ▲ ▲
27
- ┌───────┴────────┐ ┌─────────┴──────────┐ │ │
28
- │EC2RequestParser│ │RestXMLRequestParser│ │ │
29
- └────────────────┘ └────────────────────┘ │ │
30
- ┌────────────────┴───┴┐ ┌────────┴────────┐
31
- │RestJSONRequestParser│ │JSONRequestParser│
32
- └─────────────────────┘ └─────────────────┘
22
+ ┌─────────────────┘ │ └────────────────────┬───────────────────────┬───────────────────────┐
23
+ ┌────────┴─────────┐ ┌─────────┴───────────┐ ┌──────────┴──────────┐ ┌──────────┴──────────┐ ┌──────────┴───────────┐
24
+ │QueryRequestParser│ │BaseRestRequestParser│ │BaseJSONRequestParser│ │BaseCBORRequestParser│ │BaseRpcV2RequestParser│
25
+ └──────────────────┘ └─────────────────────┘ └─────────────────────┘ └─────────────────────┘ └──────────────────────┘
26
+ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
27
+ ┌───────┴────────┐ ┌─────────┴──────────┐ │ │ ┌────────┴────────┐ ┌───┴─────────────┴────┐
28
+ │EC2RequestParser│ │RestXMLRequestParser│ │ │ JSONRequestParser│ │ │RpcV2CBORRequestParser│
29
+ └────────────────┘ └────────────────────┘ │ │ └─────────────────┘ └──────────────────────┘
30
+ ┌────────────────┴───┴┐ ▲ │
31
+ │RestJSONRequestParser│ ┌───┴──────┴──────┐
32
+ └─────────────────────┘ │CBORRequestParser│
33
+ └─────────────────┘
33
34
  ::
34
35
 
35
36
  The ``RequestParser`` contains the logic that is used among all the
36
37
  different protocols (``query``, ``json``, ``rest-json``, ``rest-xml``,
37
- and ``ec2``).
38
+ ``cbor`` and ``ec2``).
38
39
  The relation between the different protocols is described in the
39
40
  ``serializer``.
40
41
 
@@ -44,13 +45,21 @@ The classes are structured as follows:
44
45
  which is shared among all different protocols.
45
46
  * The ``BaseRestRequestParser`` contains the logic for the REST
46
47
  protocol specifics (i.e. specific HTTP metadata parsing).
48
+ * The ``BaseRpcV2RequestParser`` contains the logic for the RPC v2
49
+ protocol specifics (special path routing, no logic about body decoding)
47
50
  * The ``BaseJSONRequestParser`` contains the logic for the JSON body
48
51
  parsing.
52
+ * The ``BaseCBORRequestParser`` contains the logic for the CBOR body
53
+ parsing.
49
54
  * The ``RestJSONRequestParser`` inherits the ReST specific logic from
50
55
  the ``BaseRestRequestParser`` and the JSON body parsing from the
51
56
  ``BaseJSONRequestParser``.
52
- * The ``QueryRequestParser``, ``RestXMLRequestParser``, and the
53
- ``JSONRequestParser`` have a conventional inheritance structure.
57
+ * The ``CBORRequestParser`` inherits the ``json``-protocol specific
58
+ logic from the ``JSONRequestParser`` and the CBOR body parsing
59
+ from the ``BaseCBORRequestParser``.
60
+ * The ``QueryRequestParser``, ``RestXMLRequestParser``,
61
+ ``RpcV2CBORRequestParser`` and ``JSONRequestParser`` have a
62
+ conventional inheritance structure.
54
63
 
55
64
  The services and their protocols are defined by using AWS's Smithy
56
65
  (a language to define services in a - somewhat - protocol-agnostic
@@ -66,10 +75,14 @@ import abc
66
75
  import base64
67
76
  import datetime
68
77
  import functools
78
+ import io
79
+ import os
69
80
  import re
81
+ import struct
70
82
  from abc import ABC
83
+ from collections.abc import Mapping
71
84
  from email.utils import parsedate_to_datetime
72
- from typing import IO, Any, Dict, List, Mapping, Optional, Tuple, Union
85
+ from typing import IO, Any
73
86
  from xml.etree import ElementTree as ETree
74
87
 
75
88
  import dateutil.parser
@@ -88,6 +101,7 @@ from cbor2._decoder import loads as cbor2_loads
88
101
  from werkzeug.exceptions import BadRequest, NotFound
89
102
 
90
103
  from localstack.aws.protocol.op_router import RestServiceOperationRouter
104
+ from localstack.aws.spec import ProtocolName
91
105
  from localstack.http import Request
92
106
 
93
107
 
@@ -107,7 +121,7 @@ def _text_content(func):
107
121
  self,
108
122
  request: Request,
109
123
  shape: Shape,
110
- node_or_string: Union[ETree.Element, str],
124
+ node_or_string: ETree.Element | str,
111
125
  uri_params: Mapping[str, Any] = None,
112
126
  ):
113
127
  if hasattr(node_or_string, "text"):
@@ -203,7 +217,7 @@ class RequestParser(abc.ABC):
203
217
  self.service = service
204
218
 
205
219
  @_handle_exceptions
206
- def parse(self, request: Request) -> Tuple[OperationModel, Any]:
220
+ def parse(self, request: Request) -> tuple[OperationModel, Any]:
207
221
  """
208
222
  Determines which operation the request was aiming for and parses the incoming request such that the resulting
209
223
  dictionary can be used to invoke the service's function implementation.
@@ -233,13 +247,21 @@ class RequestParser(abc.ABC):
233
247
  if location is not None:
234
248
  if location == "header":
235
249
  header_name = shape.serialization.get("name")
236
- payload = request.headers.get(header_name)
237
- if payload and shape.type_name == "list":
250
+ if shape.type_name == "list":
238
251
  # headers may contain a comma separated list of values (e.g., the ObjectAttributes member in
239
252
  # s3.GetObjectAttributes), so we prepare it here for the handler, which will be `_parse_list`.
240
253
  # Header lists can contain optional whitespace, so we strip it
241
254
  # https://www.rfc-editor.org/rfc/rfc9110.html#name-lists-rule-abnf-extension
242
- payload = [value.strip() for value in payload.split(",")]
255
+ # It can also directly contain a list of headers
256
+ # See https://datatracker.ietf.org/doc/html/rfc2616
257
+ payload = request.headers.getlist(header_name) or None
258
+ if payload:
259
+ headers = ",".join(payload)
260
+ payload = [value.strip() for value in headers.split(",")]
261
+
262
+ else:
263
+ payload = request.headers.get(header_name)
264
+
243
265
  elif location == "headers":
244
266
  payload = self._parse_header_map(shape, request.headers)
245
267
  # shapes with the location trait "headers" only contain strings and are not further processed
@@ -256,12 +278,12 @@ class RequestParser(abc.ABC):
256
278
  if uri_param_name in uri_params:
257
279
  payload = uri_params[uri_param_name]
258
280
  else:
259
- raise UnknownParserError("Unknown shape location '%s'." % location)
281
+ raise UnknownParserError(f"Unknown shape location '{location}'.")
260
282
  else:
261
283
  # If we don't have to use a specific location, we use the node
262
284
  payload = node
263
285
 
264
- fn_name = "_parse_%s" % shape.type_name
286
+ fn_name = f"_parse_{shape.type_name}"
265
287
  handler = getattr(self, fn_name, self._noop_parser)
266
288
  try:
267
289
  return handler(request, shape, payload, uri_params) if payload is not None else None
@@ -313,7 +335,7 @@ class RequestParser(abc.ABC):
313
335
  return True
314
336
  if value == "false":
315
337
  return False
316
- raise ValueError("cannot parse boolean value %s" % node)
338
+ raise ValueError(f"cannot parse boolean value {node}")
317
339
 
318
340
  @_text_content
319
341
  def _noop_parser(self, _, __, node: Any, ___):
@@ -323,11 +345,11 @@ class RequestParser(abc.ABC):
323
345
  _parse_double = _parse_float
324
346
  _parse_long = _parse_integer
325
347
 
326
- def _convert_str_to_timestamp(self, value: str, timestamp_format=None):
348
+ def _convert_str_to_timestamp(self, value: str, timestamp_format=None) -> datetime.datetime:
327
349
  if timestamp_format is None:
328
350
  timestamp_format = self.TIMESTAMP_FORMAT
329
351
  timestamp_format = timestamp_format.lower()
330
- converter = getattr(self, "_timestamp_%s" % timestamp_format)
352
+ converter = getattr(self, f"_timestamp_{timestamp_format}")
331
353
  final_value = converter(value)
332
354
  return final_value
333
355
 
@@ -337,11 +359,11 @@ class RequestParser(abc.ABC):
337
359
 
338
360
  @staticmethod
339
361
  def _timestamp_unixtimestamp(timestamp_string: str) -> datetime.datetime:
340
- return datetime.datetime.utcfromtimestamp(int(timestamp_string))
362
+ return datetime.datetime.fromtimestamp(int(timestamp_string), tz=datetime.UTC)
341
363
 
342
364
  @staticmethod
343
365
  def _timestamp_unixtimestampmillis(timestamp_string: str) -> datetime.datetime:
344
- return datetime.datetime.utcfromtimestamp(float(timestamp_string) / 1000)
366
+ return datetime.datetime.fromtimestamp(float(timestamp_string) / 1000, tz=datetime.UTC)
345
367
 
346
368
  @staticmethod
347
369
  def _timestamp_rfc822(datetime_string: str) -> datetime.datetime:
@@ -367,7 +389,7 @@ class QueryRequestParser(RequestParser):
367
389
  """
368
390
 
369
391
  @_handle_exceptions
370
- def parse(self, request: Request) -> Tuple[OperationModel, Any]:
392
+ def parse(self, request: Request) -> tuple[OperationModel, Any]:
371
393
  instance = request.values
372
394
  if "Action" not in instance:
373
395
  raise ProtocolParserError(
@@ -510,7 +532,7 @@ class QueryRequestParser(RequestParser):
510
532
 
511
533
  # We collect the list value as well as the integer indicating the list position so we can
512
534
  # later sort the list by the position, in case they attribute values are unordered
513
- result: List[Tuple[int, Any]] = []
535
+ result: list[tuple[int, Any]] = []
514
536
 
515
537
  i = 0
516
538
  while True:
@@ -559,7 +581,7 @@ class BaseRestRequestParser(RequestParser):
559
581
  self._operation_router = RestServiceOperationRouter(service)
560
582
 
561
583
  @_handle_exceptions
562
- def parse(self, request: Request) -> Tuple[OperationModel, Any]:
584
+ def parse(self, request: Request) -> tuple[OperationModel, Any]:
563
585
  try:
564
586
  operation, uri_params = self._operation_router.match(request)
565
587
  except NotFound as e:
@@ -578,7 +600,7 @@ class BaseRestRequestParser(RequestParser):
578
600
  self,
579
601
  request: Request,
580
602
  shape: Shape,
581
- member_shapes: Dict[str, Shape],
603
+ member_shapes: dict[str, Shape],
582
604
  uri_params: Mapping[str, Any],
583
605
  final_parsed: dict,
584
606
  ) -> None:
@@ -662,7 +684,7 @@ class RestXMLRequestParser(BaseRestRequestParser):
662
684
  """
663
685
 
664
686
  def __init__(self, service_model: ServiceModel):
665
- super(RestXMLRequestParser, self).__init__(service_model)
687
+ super().__init__(service_model)
666
688
  self.ignore_get_body_errors = True
667
689
  self._namespace_re = re.compile("{.*}")
668
690
 
@@ -731,7 +753,7 @@ class RestXMLRequestParser(BaseRestRequestParser):
731
753
  elif tag_name == value_location_name:
732
754
  val_name = self._parse_shape(request, value_shape, single_pair, uri_params)
733
755
  else:
734
- raise ProtocolParserError("Unknown tag: %s" % tag_name)
756
+ raise ProtocolParserError(f"Unknown tag: {tag_name}")
735
757
  parsed[key_name] = val_name
736
758
  return parsed
737
759
 
@@ -749,7 +771,7 @@ class RestXMLRequestParser(BaseRestRequestParser):
749
771
  # it's flattened, and if it's not, then we make it a one element list.
750
772
  if shape.serialization.get("flattened") and not isinstance(node, list):
751
773
  node = [node]
752
- return super(RestXMLRequestParser, self)._parse_list(request, shape, node, uri_params)
774
+ return super()._parse_list(request, shape, node, uri_params)
753
775
 
754
776
  def _node_tag(self, node: ETree.Element) -> str:
755
777
  return self._namespace_re.sub("", node.tag)
@@ -777,11 +799,11 @@ class RestXMLRequestParser(BaseRestRequestParser):
777
799
  root = parser.close()
778
800
  except ETree.ParseError as e:
779
801
  raise ProtocolParserError(
780
- "Unable to parse request (%s), invalid XML received:\n%s" % (e, xml_string)
802
+ f"Unable to parse request ({e}), invalid XML received:\n{xml_string}"
781
803
  ) from e
782
804
  return root
783
805
 
784
- def _build_name_to_xml_node(self, parent_node: Union[list, ETree.Element]) -> dict:
806
+ def _build_name_to_xml_node(self, parent_node: list | ETree.Element) -> dict:
785
807
  # If the parent node is actually a list. We should not be trying
786
808
  # to serialize it to a dictionary. Instead, return the first element
787
809
  # in the list.
@@ -824,9 +846,9 @@ class BaseJSONRequestParser(RequestParser, ABC):
824
846
  self,
825
847
  request: Request,
826
848
  shape: StructureShape,
827
- value: Optional[dict],
849
+ value: dict | None,
828
850
  uri_params: Mapping[str, Any] = None,
829
- ) -> Optional[dict]:
851
+ ) -> dict | None:
830
852
  if shape.is_document_type:
831
853
  final_parsed = value
832
854
  else:
@@ -849,9 +871,9 @@ class BaseJSONRequestParser(RequestParser, ABC):
849
871
  self,
850
872
  request: Request,
851
873
  shape: MapShape,
852
- value: Optional[dict],
874
+ value: dict | None,
853
875
  uri_params: Mapping[str, Any] = None,
854
- ) -> Optional[dict]:
876
+ ) -> dict | None:
855
877
  if value is None:
856
878
  return None
857
879
  parsed = {}
@@ -916,7 +938,7 @@ class JSONRequestParser(BaseJSONRequestParser):
916
938
  """
917
939
 
918
940
  @_handle_exceptions
919
- def parse(self, request: Request) -> Tuple[OperationModel, Any]:
941
+ def parse(self, request: Request) -> tuple[OperationModel, Any]:
920
942
  target = request.headers["X-Amz-Target"]
921
943
  # assuming that the last part of the target string (e.g., "x.y.z.MyAction") contains the operation name
922
944
  operation_name = target.rpartition(".")[2]
@@ -967,6 +989,405 @@ class RestJSONRequestParser(BaseRestRequestParser, BaseJSONRequestParser):
967
989
  raise NotImplementedError
968
990
 
969
991
 
992
+ class BaseCBORRequestParser(RequestParser, ABC):
993
+ """
994
+ The ``BaseCBORRequestParser`` is the base class for all CBOR-based AWS service protocols.
995
+ This base-class handles parsing the payload / body as CBOR.
996
+ """
997
+
998
+ INDEFINITE_ITEM_ADDITIONAL_INFO = 31
999
+ BREAK_CODE = 0xFF
1000
+ # timestamp format for requests with CBOR content type
1001
+ TIMESTAMP_FORMAT = "unixtimestamp"
1002
+
1003
+ @functools.cached_property
1004
+ def major_type_to_parsing_method_map(self):
1005
+ return {
1006
+ 0: self._parse_type_unsigned_integer,
1007
+ 1: self._parse_type_negative_integer,
1008
+ 2: self._parse_type_byte_string,
1009
+ 3: self._parse_type_text_string,
1010
+ 4: self._parse_type_array,
1011
+ 5: self._parse_type_map,
1012
+ 6: self._parse_type_tag,
1013
+ 7: self._parse_type_simple_and_float,
1014
+ }
1015
+
1016
+ @staticmethod
1017
+ def get_peekable_stream_from_bytes(_bytes: bytes) -> io.BufferedReader:
1018
+ return io.BufferedReader(io.BytesIO(_bytes))
1019
+
1020
+ def parse_data_item(self, stream: io.BufferedReader) -> Any:
1021
+ # CBOR data is divided into "data items", and each data item starts
1022
+ # with an initial byte that describes how the following bytes should be parsed
1023
+ initial_byte = self._read_bytes_as_int(stream, 1)
1024
+ # The highest order three bits of the initial byte describe the CBOR major type
1025
+ major_type = initial_byte >> 5
1026
+ # The lowest order 5 bits of the initial byte tells us more information about
1027
+ # how the bytes should be parsed that will be used
1028
+ additional_info: int = initial_byte & 0b00011111
1029
+
1030
+ if major_type in self.major_type_to_parsing_method_map:
1031
+ method = self.major_type_to_parsing_method_map[major_type]
1032
+ return method(stream, additional_info)
1033
+ else:
1034
+ raise ProtocolParserError(
1035
+ f"Unsupported initial byte found for data item- "
1036
+ f"Major type:{major_type}, Additional info: "
1037
+ f"{additional_info}"
1038
+ )
1039
+
1040
+ # Major type 0 - unsigned integers
1041
+ def _parse_type_unsigned_integer(self, stream: io.BufferedReader, additional_info: int) -> int:
1042
+ additional_info_to_num_bytes = {
1043
+ 24: 1,
1044
+ 25: 2,
1045
+ 26: 4,
1046
+ 27: 8,
1047
+ }
1048
+ # Values under 24 don't need a full byte to be stored; their values are
1049
+ # instead stored as the "additional info" in the initial byte
1050
+ if additional_info < 24:
1051
+ return additional_info
1052
+ elif additional_info in additional_info_to_num_bytes:
1053
+ num_bytes = additional_info_to_num_bytes[additional_info]
1054
+ return self._read_bytes_as_int(stream, num_bytes)
1055
+ else:
1056
+ raise ProtocolParserError(
1057
+ "Invalid CBOR integer returned from the service; unparsable "
1058
+ f"additional info found for major type 0 or 1: {additional_info}"
1059
+ )
1060
+
1061
+ # Major type 1 - negative integers
1062
+ def _parse_type_negative_integer(self, stream: io.BufferedReader, additional_info: int) -> int:
1063
+ return -1 - self._parse_type_unsigned_integer(stream, additional_info)
1064
+
1065
+ # Major type 2 - byte string
1066
+ def _parse_type_byte_string(self, stream: io.BufferedReader, additional_info: int) -> bytes:
1067
+ if additional_info != self.INDEFINITE_ITEM_ADDITIONAL_INFO:
1068
+ length = self._parse_type_unsigned_integer(stream, additional_info)
1069
+ return self._read_from_stream(stream, length)
1070
+ else:
1071
+ chunks = []
1072
+ while True:
1073
+ if self._handle_break_code(stream):
1074
+ break
1075
+ initial_byte = self._read_bytes_as_int(stream, 1)
1076
+ additional_info = initial_byte & 0b00011111
1077
+ length = self._parse_type_unsigned_integer(stream, additional_info)
1078
+ chunks.append(self._read_from_stream(stream, length))
1079
+ return b"".join(chunks)
1080
+
1081
+ # Major type 3 - text string
1082
+ def _parse_type_text_string(self, stream: io.BufferedReader, additional_info: int) -> str:
1083
+ return self._parse_type_byte_string(stream, additional_info).decode("utf-8")
1084
+
1085
+ # Major type 4 - lists
1086
+ def _parse_type_array(self, stream: io.BufferedReader, additional_info: int) -> list:
1087
+ if additional_info != self.INDEFINITE_ITEM_ADDITIONAL_INFO:
1088
+ length = self._parse_type_unsigned_integer(stream, additional_info)
1089
+ return [self.parse_data_item(stream) for _ in range(length)]
1090
+ else:
1091
+ items = []
1092
+ while not self._handle_break_code(stream):
1093
+ items.append(self.parse_data_item(stream))
1094
+ return items
1095
+
1096
+ # Major type 5 - maps
1097
+ def _parse_type_map(self, stream: io.BufferedReader, additional_info: int) -> dict:
1098
+ items = {}
1099
+ if additional_info != self.INDEFINITE_ITEM_ADDITIONAL_INFO:
1100
+ length = self._parse_type_unsigned_integer(stream, additional_info)
1101
+ for _ in range(length):
1102
+ self._parse_type_key_value_pair(stream, items)
1103
+ return items
1104
+
1105
+ else:
1106
+ while not self._handle_break_code(stream):
1107
+ self._parse_type_key_value_pair(stream, items)
1108
+ return items
1109
+
1110
+ def _parse_type_key_value_pair(self, stream: io.BufferedReader, items: dict) -> None:
1111
+ key = self.parse_data_item(stream)
1112
+ value = self.parse_data_item(stream)
1113
+ if value is not None:
1114
+ items[key] = value
1115
+
1116
+ # Major type 6 is tags. The only tag we currently support is tag 1 for unix
1117
+ # timestamps
1118
+ def _parse_type_tag(self, stream: io.BufferedReader, additional_info: int):
1119
+ tag = self._parse_type_unsigned_integer(stream, additional_info)
1120
+ value = self.parse_data_item(stream)
1121
+ if tag == 1: # Epoch-based date/time in milliseconds
1122
+ return self._parse_type_datetime(value)
1123
+ else:
1124
+ raise ProtocolParserError(f"Found CBOR tag not supported by botocore: {tag}")
1125
+
1126
+ def _parse_type_datetime(self, value: int | float) -> datetime.datetime:
1127
+ if isinstance(value, (int, float)):
1128
+ return self._convert_str_to_timestamp(str(value))
1129
+ else:
1130
+ raise ProtocolParserError(f"Unable to parse datetime value: {value}")
1131
+
1132
+ # Major type 7 includes floats and "simple" types. Supported simple types are
1133
+ # currently boolean values, CBOR's null, and CBOR's undefined type. All other
1134
+ # values are either floats or invalid.
1135
+ def _parse_type_simple_and_float(
1136
+ self, stream: io.BufferedReader, additional_info: int
1137
+ ) -> bool | float | None:
1138
+ # For major type 7, values 20-23 correspond to CBOR "simple" values
1139
+ additional_info_simple_values = {
1140
+ 20: False, # CBOR false
1141
+ 21: True, # CBOR true
1142
+ 22: None, # CBOR null
1143
+ 23: None, # CBOR undefined
1144
+ }
1145
+ # First we check if the additional info corresponds to a supported simple value
1146
+ if additional_info in additional_info_simple_values:
1147
+ return additional_info_simple_values[additional_info]
1148
+
1149
+ # If it's not a simple value, we need to parse it into the correct format and
1150
+ # number fo bytes
1151
+ float_formats = {
1152
+ 25: (">e", 2),
1153
+ 26: (">f", 4),
1154
+ 27: (">d", 8),
1155
+ }
1156
+
1157
+ if additional_info in float_formats:
1158
+ float_format, num_bytes = float_formats[additional_info]
1159
+ return struct.unpack(float_format, self._read_from_stream(stream, num_bytes))[0]
1160
+ raise ProtocolParserError(
1161
+ f"Invalid additional info found for major type 7: {additional_info}. "
1162
+ f"This indicates an unsupported simple type or an indefinite float value"
1163
+ )
1164
+
1165
+ @_text_content
1166
+ def _parse_blob(self, _, __, node: bytes, ___) -> bytes:
1167
+ return node
1168
+
1169
+ @_text_content
1170
+ def _parse_timestamp(
1171
+ self, _, shape: Shape, node: datetime.datetime | str, ___
1172
+ ) -> datetime.datetime:
1173
+ if isinstance(node, datetime.datetime):
1174
+ return node
1175
+ return super()._parse_timestamp(_, shape, node, ___)
1176
+
1177
+ @_text_content
1178
+ def _parse_boolean(self, _, __, node: str | bool, ___) -> bool:
1179
+ if isinstance(node, str):
1180
+ value = node.lower()
1181
+ if value == "true":
1182
+ return True
1183
+ if value == "false":
1184
+ return False
1185
+ raise ValueError(f"cannot parse boolean value {node}")
1186
+ return node
1187
+
1188
+ # This helper method is intended for use when parsing indefinite length items.
1189
+ # It does nothing if the next byte is not the break code. If the next byte is
1190
+ # the break code, it advances past that byte and returns True so the calling
1191
+ # method knows to stop parsing that data item.
1192
+ def _handle_break_code(self, stream: io.BufferedReader) -> bool | None:
1193
+ if int.from_bytes(stream.peek(1)[:1], "big") == self.BREAK_CODE:
1194
+ stream.seek(1, os.SEEK_CUR)
1195
+ return True
1196
+
1197
+ def _read_bytes_as_int(self, stream: IO[bytes], num_bytes: int) -> int:
1198
+ byte = self._read_from_stream(stream, num_bytes)
1199
+ return int.from_bytes(byte, "big")
1200
+
1201
+ @staticmethod
1202
+ def _read_from_stream(stream: IO[bytes], num_bytes: int) -> bytes:
1203
+ value = stream.read(num_bytes)
1204
+ if len(value) != num_bytes:
1205
+ raise ProtocolParserError(
1206
+ "End of stream reached; this indicates a "
1207
+ "malformed CBOR response from the server or an "
1208
+ "issue in botocore"
1209
+ )
1210
+ return value
1211
+
1212
+
1213
+ class CBORRequestParser(BaseCBORRequestParser, JSONRequestParser):
1214
+ """
1215
+ The ``CBORRequestParser`` is responsible for parsing incoming requests for services which use the ``cbor``
1216
+ protocol.
1217
+ The requests for these services encode the majority of their parameters as CBOR in the request body.
1218
+ The operation is defined in an HTTP header field.
1219
+ This protocol is not properly defined in the specs, but it is derived from the ``json`` protocol. Only Kinesis uses
1220
+ it for now.
1221
+ """
1222
+
1223
+ # timestamp format is different from traditional CBOR, and is encoded as a milliseconds integer
1224
+ TIMESTAMP_FORMAT = "unixtimestampmillis"
1225
+
1226
+ def _do_parse(
1227
+ self, request: Request, shape: Shape, uri_params: Mapping[str, Any] = None
1228
+ ) -> dict:
1229
+ parsed = {}
1230
+ if shape is not None:
1231
+ event_name = shape.event_stream_name
1232
+ if event_name:
1233
+ parsed = self._handle_event_stream(request, shape, event_name)
1234
+ else:
1235
+ self._parse_payload(request, shape, parsed, uri_params)
1236
+ return parsed
1237
+
1238
+ def _handle_event_stream(self, request: Request, shape: Shape, event_name: str):
1239
+ # TODO handle event streams
1240
+ raise NotImplementedError
1241
+
1242
+ def _parse_payload(
1243
+ self,
1244
+ request: Request,
1245
+ shape: Shape,
1246
+ final_parsed: dict,
1247
+ uri_params: Mapping[str, Any] = None,
1248
+ ) -> None:
1249
+ original_parsed = self._initial_body_parse(request)
1250
+ body_parsed = self._parse_shape(request, shape, original_parsed, uri_params)
1251
+ final_parsed.update(body_parsed)
1252
+
1253
+ def _initial_body_parse(self, request: Request) -> Any:
1254
+ body_contents = request.data
1255
+ if body_contents == b"":
1256
+ return body_contents
1257
+ body_contents_stream = self.get_peekable_stream_from_bytes(body_contents)
1258
+ return self.parse_data_item(body_contents_stream)
1259
+
1260
+ def _parse_timestamp(
1261
+ self, request: Request, shape: Shape, node: str, uri_params: Mapping[str, Any] = None
1262
+ ) -> datetime.datetime:
1263
+ # TODO: remove once CBOR support has been removed from `JSONRequestParser`
1264
+ return super()._parse_timestamp(request, shape, node, uri_params)
1265
+
1266
+
1267
+ class BaseRpcV2RequestParser(RequestParser):
1268
+ """
1269
+ The ``BaseRpcV2RequestParser`` is the base class for all RPC V2-based AWS service protocols.
1270
+ This base class handles the routing of the request, which is specific based on the path.
1271
+ The body decoding is done in the respective subclasses.
1272
+ """
1273
+
1274
+ @_handle_exceptions
1275
+ def parse(self, request: Request) -> tuple[OperationModel, Any]:
1276
+ # see https://smithy.io/2.0/additional-specs/protocols/smithy-rpc-v2.html
1277
+ if request.method != "POST":
1278
+ raise ProtocolParserError("RPC v2 only accepts POST requests.")
1279
+
1280
+ headers = request.headers
1281
+ if "X-Amz-Target" in headers or "X-Amzn-Target" in headers:
1282
+ raise ProtocolParserError(
1283
+ "RPC v2 does not accept 'X-Amz-Target' or 'X-Amzn-Target'. "
1284
+ "Such requests are rejected for security reasons."
1285
+ )
1286
+ # The Smithy RPCv2 CBOR protocol will only use the last four segments of the URL when routing requests.
1287
+ rpc_v2_params = request.path.lstrip("/").split("/")
1288
+ if len(rpc_v2_params) < 4 or not (
1289
+ operation := self.service.operation_model(rpc_v2_params[-1])
1290
+ ):
1291
+ raise OperationNotFoundParserError(
1292
+ f"Unable to find operation for request to service "
1293
+ f"{self.service.service_name}: {request.method} {request.path}"
1294
+ )
1295
+
1296
+ # there are no URI params in RPC v2
1297
+ uri_params = {}
1298
+ shape: StructureShape = operation.input_shape
1299
+ final_parsed = self._do_parse(request, shape, uri_params)
1300
+ return operation, final_parsed
1301
+
1302
+ @_handle_exceptions
1303
+ def _do_parse(
1304
+ self, request: Request, shape: Shape, uri_params: Mapping[str, Any] = None
1305
+ ) -> dict[str, Any]:
1306
+ parsed = {}
1307
+ if shape is not None:
1308
+ event_stream_name = shape.event_stream_name
1309
+ if event_stream_name:
1310
+ parsed = self._handle_event_stream(request, shape, event_stream_name)
1311
+ else:
1312
+ parsed = {}
1313
+ self._parse_payload(request, shape, parsed, uri_params)
1314
+
1315
+ return parsed
1316
+
1317
+ def _handle_event_stream(self, request: Request, shape: Shape, event_name: str):
1318
+ # TODO handle event streams
1319
+ raise NotImplementedError
1320
+
1321
+ def _parse_structure(
1322
+ self,
1323
+ request: Request,
1324
+ shape: StructureShape,
1325
+ node: dict | None,
1326
+ uri_params: Mapping[str, Any] = None,
1327
+ ):
1328
+ if shape.is_document_type:
1329
+ final_parsed = node
1330
+ else:
1331
+ if node is None:
1332
+ # If the comes across the wire as "null" (None in python),
1333
+ # we should be returning this unchanged, instead of as an
1334
+ # empty dict.
1335
+ return None
1336
+ final_parsed = {}
1337
+ members = shape.members
1338
+ if shape.is_tagged_union:
1339
+ cleaned_value = node.copy()
1340
+ cleaned_value.pop("__type", None)
1341
+ cleaned_value = {k: v for k, v in cleaned_value.items() if v is not None}
1342
+ if len(cleaned_value) != 1:
1343
+ raise ProtocolParserError(
1344
+ f"Invalid service response: {shape.name} must have one and only one member set."
1345
+ )
1346
+
1347
+ for member_name, member_shape in members.items():
1348
+ member_value = node.get(member_name)
1349
+ if member_value is not None:
1350
+ final_parsed[member_name] = self._parse_shape(
1351
+ request, member_shape, member_value, uri_params
1352
+ )
1353
+
1354
+ return final_parsed
1355
+
1356
+ def _parse_payload(
1357
+ self,
1358
+ request: Request,
1359
+ shape: Shape,
1360
+ final_parsed: dict,
1361
+ uri_params: Mapping[str, Any] = None,
1362
+ ) -> None:
1363
+ original_parsed = self._initial_body_parse(request)
1364
+ body_parsed = self._parse_shape(request, shape, original_parsed, uri_params)
1365
+ final_parsed.update(body_parsed)
1366
+
1367
+ def _initial_body_parse(self, request: Request):
1368
+ # This method should do the initial parsing of the
1369
+ # body. We still need to walk the parsed body in order
1370
+ # to convert types, but this method will do the first round
1371
+ # of parsing.
1372
+ raise NotImplementedError("_initial_body_parse")
1373
+
1374
+
1375
+ class RpcV2CBORRequestParser(BaseRpcV2RequestParser, BaseCBORRequestParser):
1376
+ """
1377
+ The ``RpcV2CBORRequestParser`` is responsible for parsing incoming requests for services which use the
1378
+ ``rpc-v2-cbor`` protocol. The requests for these services encode all of their parameters as CBOR in the
1379
+ request body.
1380
+ """
1381
+
1382
+ # TODO: investigate datetime format for RpcV2CBOR protocol, which might be different than Kinesis CBOR
1383
+ def _initial_body_parse(self, request: Request):
1384
+ body_contents = request.data
1385
+ if body_contents == b"":
1386
+ return body_contents
1387
+ body_contents_stream = self.get_peekable_stream_from_bytes(body_contents)
1388
+ return self.parse_data_item(body_contents_stream)
1389
+
1390
+
970
1391
  class EC2RequestParser(QueryRequestParser):
971
1392
  """
972
1393
  The ``EC2RequestParser`` is responsible for parsing incoming requests for services which use the ``ec2``
@@ -1038,9 +1459,7 @@ class S3RequestParser(RestXMLRequestParser):
1038
1459
  )
1039
1460
 
1040
1461
  @staticmethod
1041
- def _set_request_props(
1042
- request: Request, path: str, host: str, raw_uri: Optional[str] = None
1043
- ):
1462
+ def _set_request_props(request: Request, path: str, host: str, raw_uri: str | None = None):
1044
1463
  """Sets the HTTP request's path and host and clears the cache in the request object."""
1045
1464
  request.path = path
1046
1465
  request.headers["Host"] = host
@@ -1072,7 +1491,7 @@ class S3RequestParser(RestXMLRequestParser):
1072
1491
  return uses_host_addressing(request.headers)
1073
1492
 
1074
1493
  @_handle_exceptions
1075
- def parse(self, request: Request) -> Tuple[OperationModel, Any]:
1494
+ def parse(self, request: Request) -> tuple[OperationModel, Any]:
1076
1495
  """Handle virtual-host-addressing for S3."""
1077
1496
  with self.VirtualHostRewriter(request):
1078
1497
  return super().parse(request)
@@ -1147,11 +1566,12 @@ class SQSQueryRequestParser(QueryRequestParser):
1147
1566
 
1148
1567
 
1149
1568
  @functools.cache
1150
- def create_parser(service: ServiceModel) -> RequestParser:
1569
+ def create_parser(service: ServiceModel, protocol: ProtocolName | None = None) -> RequestParser:
1151
1570
  """
1152
1571
  Creates the right parser for the given service model.
1153
1572
 
1154
1573
  :param service: to create the parser for
1574
+ :param protocol: the protocol for the parser. If not provided, fallback to the service's default protocol
1155
1575
  :return: RequestParser which can handle the protocol of the service
1156
1576
  """
1157
1577
  # Unfortunately, some services show subtle differences in their parsing or operation detection behavior, even though
@@ -1169,14 +1589,20 @@ def create_parser(service: ServiceModel) -> RequestParser:
1169
1589
  "rest-json": RestJSONRequestParser,
1170
1590
  "rest-xml": RestXMLRequestParser,
1171
1591
  "ec2": EC2RequestParser,
1592
+ "smithy-rpc-v2-cbor": RpcV2CBORRequestParser,
1593
+ # TODO: implement multi-protocol support for Kinesis, so that it can uses the `cbor` protocol and remove
1594
+ # CBOR handling from JSONRequestParser
1595
+ # this is not an "official" protocol defined from the spec, but is derived from ``json``
1172
1596
  }
1173
1597
 
1598
+ service_protocol = protocol or service.protocol
1599
+
1174
1600
  # Try to select a service- and protocol-specific parser implementation
1175
1601
  if (
1176
1602
  service.service_name in service_specific_parsers
1177
- and service.protocol in service_specific_parsers[service.service_name]
1603
+ and service_protocol in service_specific_parsers[service.service_name]
1178
1604
  ):
1179
- return service_specific_parsers[service.service_name][service.protocol](service)
1605
+ return service_specific_parsers[service.service_name][service_protocol](service)
1180
1606
  else:
1181
1607
  # Otherwise, pick the protocol-specific parser for the protocol of the service
1182
- return protocol_specific_parsers[service.protocol](service)
1608
+ return protocol_specific_parsers[service_protocol](service)