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.
- localstack/aws/api/apigateway/__init__.py +87 -110
- localstack/aws/api/cloudformation/__init__.py +18 -4
- localstack/aws/api/cloudwatch/__init__.py +41 -1
- localstack/aws/api/config/__init__.py +4 -0
- localstack/aws/api/core.py +8 -5
- localstack/aws/api/dynamodb/__init__.py +30 -0
- localstack/aws/api/ec2/__init__.py +1545 -66
- localstack/aws/api/events/__init__.py +12 -16
- localstack/aws/api/iam/__init__.py +7 -0
- localstack/aws/api/kinesis/__init__.py +19 -0
- localstack/aws/api/kms/__init__.py +6 -0
- localstack/aws/api/lambda_/__init__.py +36 -23
- localstack/aws/api/logs/__init__.py +20 -8
- localstack/aws/api/opensearch/__init__.py +16 -0
- localstack/aws/api/pipes/__init__.py +24 -32
- localstack/aws/api/redshift/__init__.py +9 -3
- localstack/aws/api/route53/__init__.py +5 -0
- localstack/aws/api/s3/__init__.py +12 -0
- localstack/aws/api/s3control/__init__.py +56 -0
- localstack/aws/api/scheduler/__init__.py +14 -16
- localstack/aws/api/ssm/__init__.py +2 -0
- localstack/aws/api/stepfunctions/__init__.py +88 -114
- localstack/aws/api/support/__init__.py +8 -9
- localstack/aws/api/transcribe/__init__.py +17 -0
- localstack/aws/chain.py +2 -2
- localstack/aws/client.py +14 -11
- localstack/aws/connect.py +42 -41
- localstack/aws/forwarder.py +57 -9
- localstack/aws/gateway.py +1 -3
- localstack/aws/handlers/analytics.py +2 -3
- localstack/aws/handlers/cors.py +4 -5
- localstack/aws/handlers/internal_requests.py +6 -1
- localstack/aws/handlers/logging.py +13 -4
- localstack/aws/handlers/metric_handler.py +44 -5
- localstack/aws/handlers/service.py +48 -28
- localstack/aws/mocking.py +18 -27
- localstack/aws/patches.py +2 -2
- localstack/aws/protocol/op_router.py +11 -10
- localstack/aws/protocol/parser.py +475 -49
- localstack/aws/protocol/serializer.py +723 -106
- localstack/aws/protocol/service_router.py +133 -33
- localstack/aws/protocol/validate.py +6 -6
- localstack/aws/scaffold.py +9 -10
- localstack/aws/serving/edge.py +5 -6
- localstack/aws/serving/hypercorn.py +2 -2
- localstack/aws/serving/twisted.py +1 -2
- localstack/aws/serving/werkzeug.py +2 -2
- localstack/aws/skeleton.py +12 -11
- localstack/aws/spec-patches.json +58 -0
- localstack/aws/spec.py +66 -46
- localstack/cli/exceptions.py +1 -1
- localstack/cli/localstack.py +11 -11
- localstack/cli/lpm.py +4 -5
- localstack/cli/plugins.py +1 -1
- localstack/cli/profiles.py +1 -2
- localstack/config.py +44 -30
- localstack/constants.py +4 -29
- localstack/deprecations.py +5 -5
- localstack/dev/kubernetes/__main__.py +130 -7
- localstack/dev/run/__main__.py +5 -5
- localstack/dev/run/configurators.py +1 -4
- localstack/dev/run/paths.py +6 -6
- localstack/dns/models.py +2 -1
- localstack/dns/plugins.py +5 -1
- localstack/dns/server.py +16 -6
- localstack/http/dispatcher.py +1 -2
- localstack/http/response.py +2 -2
- localstack/http/router.py +1 -1
- localstack/http/trace.py +2 -1
- localstack/logging/format.py +6 -6
- localstack/packages/api.py +13 -12
- localstack/packages/core.py +4 -4
- localstack/packages/debugpy.py +1 -3
- localstack/packages/ffmpeg.py +1 -2
- localstack/packages/java.py +38 -12
- localstack/packages/plugins.py +0 -8
- localstack/runtime/analytics.py +3 -0
- localstack/runtime/hooks.py +1 -1
- localstack/runtime/init.py +8 -9
- localstack/runtime/main.py +5 -5
- localstack/runtime/patches.py +2 -2
- localstack/runtime/shutdown.py +2 -1
- localstack/services/apigateway/exporter.py +1 -2
- localstack/services/apigateway/helpers.py +7 -10
- localstack/services/apigateway/legacy/context.py +21 -21
- localstack/services/apigateway/legacy/helpers.py +27 -28
- localstack/services/apigateway/legacy/integration.py +11 -10
- localstack/services/apigateway/legacy/invocations.py +6 -5
- localstack/services/apigateway/legacy/provider.py +148 -68
- localstack/services/apigateway/legacy/router_asf.py +2 -2
- localstack/services/apigateway/legacy/templates.py +6 -6
- localstack/services/apigateway/models.py +16 -16
- localstack/services/apigateway/next_gen/execute_api/api.py +2 -2
- localstack/services/apigateway/next_gen/execute_api/context.py +25 -25
- localstack/services/apigateway/next_gen/execute_api/handlers/api_key_validation.py +2 -5
- localstack/services/apigateway/next_gen/execute_api/handlers/method_request.py +7 -2
- localstack/services/apigateway/next_gen/execute_api/handlers/parse.py +1 -2
- localstack/services/apigateway/next_gen/execute_api/handlers/resource_router.py +2 -3
- localstack/services/apigateway/next_gen/execute_api/header_utils.py +1 -1
- localstack/services/apigateway/next_gen/execute_api/helpers.py +2 -2
- localstack/services/apigateway/next_gen/execute_api/integrations/aws.py +9 -6
- localstack/services/apigateway/next_gen/execute_api/integrations/http.py +12 -12
- localstack/services/apigateway/next_gen/execute_api/router.py +31 -0
- localstack/services/apigateway/next_gen/execute_api/template_mapping.py +2 -2
- localstack/services/apigateway/next_gen/execute_api/test_invoke.py +114 -9
- localstack/services/apigateway/next_gen/execute_api/variables.py +63 -63
- localstack/services/apigateway/next_gen/provider.py +5 -0
- localstack/services/apigateway/resource_providers/aws_apigateway_account.py +3 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_account_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_apikey.py +14 -14
- localstack/services/apigateway/resource_providers/aws_apigateway_apikey_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_basepathmapping.py +5 -5
- localstack/services/apigateway/resource_providers/aws_apigateway_basepathmapping_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_deployment.py +46 -46
- localstack/services/apigateway/resource_providers/aws_apigateway_deployment_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_domainname.py +18 -18
- localstack/services/apigateway/resource_providers/aws_apigateway_domainname_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_gatewayresponse.py +7 -7
- localstack/services/apigateway/resource_providers/aws_apigateway_gatewayresponse_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_method.py +36 -36
- localstack/services/apigateway/resource_providers/aws_apigateway_method_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_model.py +6 -6
- localstack/services/apigateway/resource_providers/aws_apigateway_model_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_requestvalidator.py +6 -6
- localstack/services/apigateway/resource_providers/aws_apigateway_requestvalidator_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_resource.py +6 -6
- localstack/services/apigateway/resource_providers/aws_apigateway_resource_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_restapi.py +26 -26
- localstack/services/apigateway/resource_providers/aws_apigateway_restapi_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_stage.py +33 -33
- localstack/services/apigateway/resource_providers/aws_apigateway_stage_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_usageplan.py +18 -18
- localstack/services/apigateway/resource_providers/aws_apigateway_usageplan_plugin.py +1 -3
- localstack/services/apigateway/resource_providers/aws_apigateway_usageplankey.py +5 -5
- localstack/services/apigateway/resource_providers/aws_apigateway_usageplankey_plugin.py +1 -3
- localstack/services/cdk/resource_providers/cdk_metadata.py +4 -3
- localstack/services/cdk/resource_providers/cdk_metadata_plugin.py +1 -3
- localstack/services/certificatemanager/resource_providers/aws_certificatemanager_certificate.py +14 -14
- localstack/services/certificatemanager/resource_providers/aws_certificatemanager_certificate_plugin.py +1 -3
- localstack/services/cloudformation/api_utils.py +4 -8
- localstack/services/cloudformation/cfn_utils.py +2 -2
- localstack/services/cloudformation/deployment_utils.py +14 -12
- localstack/services/cloudformation/engine/changes.py +3 -3
- localstack/services/cloudformation/engine/entities.py +27 -17
- localstack/services/cloudformation/engine/parameters.py +4 -4
- localstack/services/cloudformation/engine/template_deployer.py +15 -14
- localstack/services/cloudformation/engine/template_utils.py +34 -12
- localstack/services/cloudformation/engine/transformers.py +11 -8
- localstack/services/cloudformation/engine/types.py +5 -4
- localstack/services/cloudformation/engine/v2/change_set_model.py +336 -39
- localstack/services/cloudformation/engine/v2/change_set_model_describer.py +96 -17
- localstack/services/cloudformation/engine/v2/change_set_model_executor.py +289 -136
- localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +315 -146
- localstack/services/cloudformation/engine/v2/change_set_model_transform.py +380 -105
- localstack/services/cloudformation/engine/v2/change_set_model_validator.py +183 -0
- localstack/services/cloudformation/engine/v2/change_set_model_visitor.py +6 -0
- localstack/services/cloudformation/engine/v2/resolving.py +102 -0
- localstack/services/cloudformation/engine/yaml_parser.py +9 -2
- localstack/services/cloudformation/provider.py +11 -6
- localstack/services/cloudformation/provider_utils.py +34 -4
- localstack/services/cloudformation/resource_provider.py +31 -21
- localstack/services/cloudformation/resource_providers/aws_cloudformation_macro.py +7 -7
- localstack/services/cloudformation/resource_providers/aws_cloudformation_macro_plugin.py +1 -3
- localstack/services/cloudformation/resource_providers/aws_cloudformation_stack.py +9 -9
- localstack/services/cloudformation/resource_providers/aws_cloudformation_stack_plugin.py +1 -3
- localstack/services/cloudformation/resource_providers/aws_cloudformation_waitcondition.py +6 -6
- localstack/services/cloudformation/resource_providers/aws_cloudformation_waitcondition_plugin.py +1 -3
- localstack/services/cloudformation/resource_providers/aws_cloudformation_waitconditionhandle.py +2 -2
- localstack/services/cloudformation/resource_providers/aws_cloudformation_waitconditionhandle_plugin.py +1 -3
- localstack/services/cloudformation/resources.py +24149 -0
- localstack/services/cloudformation/scaffolding/__main__.py +13 -12
- localstack/services/cloudformation/scaffolding/propgen.py +2 -2
- localstack/services/cloudformation/service_models.py +2 -2
- localstack/services/cloudformation/stores.py +33 -22
- localstack/services/cloudformation/v2/entities.py +103 -88
- localstack/services/cloudformation/v2/provider.py +872 -131
- localstack/services/cloudformation/v2/types.py +38 -0
- localstack/services/cloudformation/v2/utils.py +4 -1
- localstack/services/cloudwatch/alarm_scheduler.py +11 -8
- localstack/services/cloudwatch/cloudwatch_database_helper.py +4 -5
- localstack/services/cloudwatch/models.py +5 -7
- localstack/services/cloudwatch/provider.py +30 -25
- localstack/services/cloudwatch/provider_v2.py +27 -32
- localstack/services/cloudwatch/resource_providers/aws_cloudwatch_alarm.py +40 -40
- localstack/services/cloudwatch/resource_providers/aws_cloudwatch_alarm_plugin.py +1 -3
- localstack/services/cloudwatch/resource_providers/aws_cloudwatch_compositealarm.py +12 -12
- localstack/services/cloudwatch/resource_providers/aws_cloudwatch_compositealarm_plugin.py +1 -3
- localstack/services/dynamodb/packages.py +3 -3
- localstack/services/dynamodb/provider.py +159 -18
- localstack/services/dynamodb/resource_providers/aws_dynamodb_globaltable.py +63 -63
- localstack/services/dynamodb/resource_providers/aws_dynamodb_globaltable_plugin.py +1 -3
- localstack/services/dynamodb/resource_providers/aws_dynamodb_table.py +57 -57
- localstack/services/dynamodb/resource_providers/aws_dynamodb_table_plugin.py +1 -3
- localstack/services/dynamodb/server.py +2 -2
- localstack/services/dynamodb/utils.py +13 -14
- localstack/services/dynamodb/v2/provider.py +157 -18
- localstack/services/dynamodbstreams/dynamodbstreams_api.py +2 -2
- localstack/services/dynamodbstreams/models.py +1 -3
- localstack/services/ec2/patches.py +26 -5
- localstack/services/ec2/provider.py +3 -3
- localstack/services/ec2/resource_providers/aws_ec2_dhcpoptions.py +10 -10
- localstack/services/ec2/resource_providers/aws_ec2_dhcpoptions_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_instance.py +96 -96
- localstack/services/ec2/resource_providers/aws_ec2_instance_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_internetgateway.py +5 -5
- localstack/services/ec2/resource_providers/aws_ec2_internetgateway_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_keypair.py +10 -10
- localstack/services/ec2/resource_providers/aws_ec2_keypair_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_natgateway.py +13 -13
- localstack/services/ec2/resource_providers/aws_ec2_natgateway_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_networkacl.py +6 -6
- localstack/services/ec2/resource_providers/aws_ec2_networkacl_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_prefixlist.py +14 -14
- localstack/services/ec2/resource_providers/aws_ec2_prefixlist_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_route.py +15 -15
- localstack/services/ec2/resource_providers/aws_ec2_route_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_routetable.py +6 -6
- localstack/services/ec2/resource_providers/aws_ec2_routetable_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_securitygroup.py +29 -29
- localstack/services/ec2/resource_providers/aws_ec2_securitygroup_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_subnet.py +19 -19
- localstack/services/ec2/resource_providers/aws_ec2_subnet_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_subnetroutetableassociation.py +4 -4
- localstack/services/ec2/resource_providers/aws_ec2_subnetroutetableassociation_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_transitgateway.py +16 -16
- localstack/services/ec2/resource_providers/aws_ec2_transitgateway_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_transitgatewayattachment.py +9 -9
- localstack/services/ec2/resource_providers/aws_ec2_transitgatewayattachment_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_vpc.py +15 -15
- localstack/services/ec2/resource_providers/aws_ec2_vpc_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_vpcendpoint.py +29 -22
- localstack/services/ec2/resource_providers/aws_ec2_vpcendpoint_plugin.py +1 -3
- localstack/services/ec2/resource_providers/aws_ec2_vpcgatewayattachment.py +5 -5
- localstack/services/ec2/resource_providers/aws_ec2_vpcgatewayattachment_plugin.py +1 -3
- localstack/services/ecr/resource_providers/aws_ecr_repository.py +22 -19
- localstack/services/ecr/resource_providers/aws_ecr_repository_plugin.py +1 -3
- localstack/services/edge.py +6 -6
- localstack/services/es/provider.py +21 -21
- localstack/services/events/archive.py +2 -2
- localstack/services/events/connection.py +5 -5
- localstack/services/events/event_bus.py +9 -9
- localstack/services/events/event_rule_engine.py +31 -13
- localstack/services/events/models.py +29 -30
- localstack/services/events/provider.py +29 -26
- localstack/services/events/replay.py +3 -3
- localstack/services/events/resource_providers/aws_events_apidestination.py +8 -8
- localstack/services/events/resource_providers/aws_events_apidestination_plugin.py +1 -3
- localstack/services/events/resource_providers/aws_events_connection.py +27 -27
- localstack/services/events/resource_providers/aws_events_connection_plugin.py +1 -3
- localstack/services/events/resource_providers/aws_events_eventbus.py +9 -9
- localstack/services/events/resource_providers/aws_events_eventbus_plugin.py +1 -3
- localstack/services/events/resource_providers/aws_events_eventbuspolicy.py +11 -11
- localstack/services/events/resource_providers/aws_events_eventbuspolicy_plugin.py +1 -3
- localstack/services/events/resource_providers/aws_events_rule.py +82 -82
- localstack/services/events/resource_providers/aws_events_rule_plugin.py +1 -3
- localstack/services/events/rule.py +15 -15
- localstack/services/events/target.py +21 -13
- localstack/services/events/utils.py +7 -7
- localstack/services/events/v1/models.py +1 -3
- localstack/services/events/v1/provider.py +15 -15
- localstack/services/firehose/models.py +1 -3
- localstack/services/firehose/provider.py +25 -16
- localstack/services/iam/iam_patches.py +5 -6
- localstack/services/iam/provider.py +14 -119
- localstack/services/iam/resource_providers/aws_iam_accesskey.py +6 -6
- localstack/services/iam/resource_providers/aws_iam_accesskey_plugin.py +1 -3
- localstack/services/iam/resource_providers/aws_iam_group.py +9 -9
- localstack/services/iam/resource_providers/aws_iam_group_plugin.py +1 -3
- localstack/services/iam/resource_providers/aws_iam_instanceprofile.py +5 -5
- localstack/services/iam/resource_providers/aws_iam_instanceprofile_plugin.py +1 -3
- localstack/services/iam/resource_providers/aws_iam_managedpolicy.py +9 -9
- localstack/services/iam/resource_providers/aws_iam_managedpolicy_plugin.py +1 -3
- localstack/services/iam/resource_providers/aws_iam_policy.py +7 -7
- localstack/services/iam/resource_providers/aws_iam_policy_plugin.py +1 -3
- localstack/services/iam/resource_providers/aws_iam_role.py +16 -16
- localstack/services/iam/resource_providers/aws_iam_role_plugin.py +1 -3
- localstack/services/iam/resource_providers/aws_iam_servercertificate.py +10 -10
- localstack/services/iam/resource_providers/aws_iam_servercertificate_plugin.py +1 -3
- localstack/services/iam/resource_providers/aws_iam_servicelinkedrole.py +5 -5
- localstack/services/iam/resource_providers/aws_iam_servicelinkedrole_plugin.py +1 -3
- localstack/services/iam/resource_providers/aws_iam_user.py +17 -17
- localstack/services/iam/resource_providers/aws_iam_user_plugin.py +1 -3
- localstack/services/iam/resources/policy_simulator.py +133 -0
- localstack/services/kinesis/kinesis_mock_server.py +7 -8
- localstack/services/kinesis/models.py +17 -5
- localstack/services/kinesis/packages.py +3 -3
- localstack/services/kinesis/provider.py +86 -3
- localstack/services/kinesis/resource_providers/aws_kinesis_stream.py +13 -13
- localstack/services/kinesis/resource_providers/aws_kinesis_stream_plugin.py +1 -3
- localstack/services/kinesis/resource_providers/aws_kinesis_streamconsumer.py +7 -7
- localstack/services/kinesis/resource_providers/aws_kinesis_streamconsumer_plugin.py +1 -3
- localstack/services/kinesisfirehose/resource_providers/aws_kinesisfirehose_deliverystream.py +191 -191
- localstack/services/kinesisfirehose/resource_providers/aws_kinesisfirehose_deliverystream_plugin.py +1 -3
- localstack/services/kms/models.py +21 -18
- localstack/services/kms/provider.py +62 -26
- localstack/services/kms/resource_providers/aws_kms_alias.py +3 -3
- localstack/services/kms/resource_providers/aws_kms_alias_plugin.py +1 -3
- localstack/services/kms/resource_providers/aws_kms_key.py +14 -14
- localstack/services/kms/resource_providers/aws_kms_key_plugin.py +1 -3
- localstack/services/kms/utils.py +4 -3
- localstack/services/lambda_/api_utils.py +19 -16
- localstack/services/lambda_/custom_endpoints.py +2 -2
- localstack/services/lambda_/event_source_mapping/esm_worker_factory.py +4 -7
- localstack/services/lambda_/event_source_mapping/pipe_utils.py +2 -2
- localstack/services/lambda_/event_source_mapping/pollers/stream_poller.py +1 -1
- localstack/services/lambda_/event_source_mapping/senders/sender_utils.py +2 -1
- localstack/services/lambda_/hooks.py +6 -1
- localstack/services/lambda_/invocation/assignment.py +1 -2
- localstack/services/lambda_/invocation/docker_runtime_executor.py +7 -11
- localstack/services/lambda_/invocation/event_manager.py +1 -1
- localstack/services/lambda_/invocation/execution_environment.py +4 -4
- localstack/services/lambda_/invocation/executor_endpoint.py +8 -11
- localstack/services/lambda_/invocation/internal_sqs_queue.py +6 -10
- localstack/services/lambda_/invocation/lambda_models.py +33 -30
- localstack/services/lambda_/invocation/lambda_service.py +12 -5
- localstack/services/lambda_/invocation/logs.py +2 -3
- localstack/services/lambda_/invocation/runtime_executor.py +3 -3
- localstack/services/lambda_/invocation/version_manager.py +31 -8
- localstack/services/lambda_/ldm.py +14 -0
- localstack/services/lambda_/packages.py +3 -4
- localstack/services/lambda_/provider.py +9 -26
- localstack/services/lambda_/provider_utils.py +1 -1
- localstack/services/lambda_/resource_providers/aws_lambda_codesigningconfig.py +8 -8
- localstack/services/lambda_/resource_providers/aws_lambda_codesigningconfig_plugin.py +1 -3
- localstack/services/lambda_/resource_providers/aws_lambda_eventinvokeconfig.py +11 -11
- localstack/services/lambda_/resource_providers/aws_lambda_eventinvokeconfig_plugin.py +1 -3
- localstack/services/lambda_/resource_providers/aws_lambda_eventsourcemapping.py +39 -39
- localstack/services/lambda_/resource_providers/aws_lambda_eventsourcemapping_plugin.py +1 -3
- localstack/services/lambda_/resource_providers/aws_lambda_function.py +54 -54
- localstack/services/lambda_/resource_providers/aws_lambda_function_plugin.py +1 -3
- localstack/services/lambda_/resource_providers/aws_lambda_layerversion.py +11 -11
- localstack/services/lambda_/resource_providers/aws_lambda_layerversion_plugin.py +1 -3
- localstack/services/lambda_/resource_providers/aws_lambda_layerversionpermission.py +6 -6
- localstack/services/lambda_/resource_providers/aws_lambda_layerversionpermission_plugin.py +1 -3
- localstack/services/lambda_/resource_providers/aws_lambda_permission.py +10 -10
- localstack/services/lambda_/resource_providers/aws_lambda_permission_plugin.py +1 -3
- localstack/services/lambda_/resource_providers/aws_lambda_url.py +15 -15
- localstack/services/lambda_/resource_providers/aws_lambda_url_plugin.py +1 -3
- localstack/services/lambda_/resource_providers/aws_lambda_version.py +8 -8
- localstack/services/lambda_/resource_providers/aws_lambda_version_plugin.py +1 -3
- localstack/services/lambda_/resource_providers/lambda_alias.py +12 -12
- localstack/services/lambda_/resource_providers/lambda_alias_plugin.py +1 -3
- localstack/services/lambda_/runtimes.py +1 -3
- localstack/services/lambda_/urlrouter.py +14 -1
- localstack/services/logs/models.py +1 -3
- localstack/services/logs/provider.py +39 -22
- localstack/services/logs/resource_providers/aws_logs_loggroup.py +9 -9
- localstack/services/logs/resource_providers/aws_logs_loggroup_plugin.py +1 -3
- localstack/services/logs/resource_providers/aws_logs_logstream.py +4 -4
- localstack/services/logs/resource_providers/aws_logs_logstream_plugin.py +1 -3
- localstack/services/logs/resource_providers/aws_logs_subscriptionfilter.py +7 -7
- localstack/services/logs/resource_providers/aws_logs_subscriptionfilter_plugin.py +1 -3
- localstack/services/moto.py +5 -4
- localstack/services/opensearch/cluster.py +28 -20
- localstack/services/opensearch/cluster_manager.py +13 -14
- localstack/services/opensearch/models.py +1 -3
- localstack/services/opensearch/packages.py +27 -9
- localstack/services/opensearch/provider.py +15 -10
- localstack/services/opensearch/resource_providers/aws_elasticsearch_domain.py +61 -61
- localstack/services/opensearch/resource_providers/aws_elasticsearch_domain_plugin.py +1 -3
- localstack/services/opensearch/resource_providers/aws_opensearchservice_domain.py +89 -89
- localstack/services/opensearch/resource_providers/aws_opensearchservice_domain_plugin.py +1 -3
- localstack/services/opensearch/versions.py +57 -10
- localstack/services/plugins.py +37 -32
- localstack/services/providers.py +10 -2
- localstack/services/redshift/provider.py +0 -21
- localstack/services/redshift/resource_providers/aws_redshift_cluster.py +57 -57
- localstack/services/redshift/resource_providers/aws_redshift_cluster_plugin.py +1 -3
- localstack/services/resource_groups/resource_providers/aws_resourcegroups_group.py +21 -21
- localstack/services/resource_groups/resource_providers/aws_resourcegroups_group_plugin.py +1 -3
- localstack/services/route53/models.py +1 -3
- localstack/services/route53/provider.py +1 -2
- localstack/services/route53/resource_providers/aws_route53_healthcheck.py +6 -6
- localstack/services/route53/resource_providers/aws_route53_healthcheck_plugin.py +1 -3
- localstack/services/route53/resource_providers/aws_route53_recordset.py +27 -27
- localstack/services/route53/resource_providers/aws_route53_recordset_plugin.py +1 -3
- localstack/services/route53resolver/models.py +8 -10
- localstack/services/route53resolver/provider.py +12 -12
- localstack/services/s3/codec.py +2 -2
- localstack/services/s3/constants.py +5 -2
- localstack/services/s3/cors.py +8 -8
- localstack/services/s3/models.py +73 -73
- localstack/services/s3/notifications.py +74 -58
- localstack/services/s3/presigned_url.py +41 -59
- localstack/services/s3/provider.py +86 -29
- localstack/services/s3/resource_providers/aws_s3_bucket.py +180 -180
- localstack/services/s3/resource_providers/aws_s3_bucket_plugin.py +1 -3
- localstack/services/s3/resource_providers/aws_s3_bucketpolicy.py +4 -4
- localstack/services/s3/resource_providers/aws_s3_bucketpolicy_plugin.py +1 -3
- localstack/services/s3/storage/core.py +4 -3
- localstack/services/s3/storage/ephemeral.py +7 -6
- localstack/services/s3/utils.py +51 -31
- localstack/services/s3/validation.py +47 -33
- localstack/services/s3/website_hosting.py +9 -7
- localstack/services/scheduler/resource_providers/aws_scheduler_schedule.py +60 -60
- localstack/services/scheduler/resource_providers/aws_scheduler_schedule_plugin.py +1 -3
- localstack/services/scheduler/resource_providers/aws_scheduler_schedulegroup.py +9 -9
- localstack/services/scheduler/resource_providers/aws_scheduler_schedulegroup_plugin.py +1 -3
- localstack/services/secretsmanager/provider.py +10 -12
- localstack/services/secretsmanager/resource_providers/aws_secretsmanager_resourcepolicy.py +5 -5
- localstack/services/secretsmanager/resource_providers/aws_secretsmanager_resourcepolicy_plugin.py +1 -3
- localstack/services/secretsmanager/resource_providers/aws_secretsmanager_rotationschedule.py +21 -21
- localstack/services/secretsmanager/resource_providers/aws_secretsmanager_rotationschedule_plugin.py +1 -3
- localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secret.py +23 -23
- localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secret_plugin.py +1 -3
- localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secrettargetattachment.py +5 -5
- localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secrettargetattachment_plugin.py +1 -3
- localstack/services/ses/models.py +8 -1
- localstack/services/ses/provider.py +128 -55
- localstack/services/ses/resource_providers/aws_ses_emailidentity.py +21 -21
- localstack/services/ses/resource_providers/aws_ses_emailidentity_plugin.py +1 -3
- localstack/services/sns/constants.py +7 -1
- localstack/services/sns/executor.py +9 -2
- localstack/services/sns/models.py +25 -25
- localstack/services/sns/provider.py +9 -7
- localstack/services/sns/publisher.py +37 -23
- localstack/services/sns/resource_providers/aws_sns_subscription.py +13 -13
- localstack/services/sns/resource_providers/aws_sns_subscription_plugin.py +1 -3
- localstack/services/sns/resource_providers/aws_sns_topic.py +16 -16
- localstack/services/sns/resource_providers/aws_sns_topic_plugin.py +1 -3
- localstack/services/sns/resource_providers/aws_sns_topicpolicy.py +4 -4
- localstack/services/sns/resource_providers/aws_sns_topicpolicy_plugin.py +1 -3
- localstack/services/sns/v2/models.py +167 -0
- localstack/services/sns/v2/provider.py +867 -0
- localstack/services/sns/v2/utils.py +130 -0
- localstack/services/sqs/constants.py +2 -2
- localstack/services/sqs/developer_api.py +205 -0
- localstack/services/sqs/models.py +71 -36
- localstack/services/sqs/provider.py +56 -332
- localstack/services/sqs/query_api.py +8 -5
- localstack/services/sqs/resource_providers/aws_sqs_queue.py +21 -21
- localstack/services/sqs/resource_providers/aws_sqs_queue_plugin.py +1 -3
- localstack/services/sqs/resource_providers/aws_sqs_queuepolicy.py +7 -5
- localstack/services/sqs/resource_providers/aws_sqs_queuepolicy_plugin.py +1 -3
- localstack/services/sqs/utils.py +123 -4
- localstack/services/ssm/provider.py +3 -4
- localstack/services/ssm/resource_providers/aws_ssm_maintenancewindow.py +15 -15
- localstack/services/ssm/resource_providers/aws_ssm_maintenancewindow_plugin.py +1 -3
- localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtarget.py +10 -10
- localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtarget_plugin.py +1 -3
- localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtask.py +48 -48
- localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtask_plugin.py +1 -3
- localstack/services/ssm/resource_providers/aws_ssm_parameter.py +10 -10
- localstack/services/ssm/resource_providers/aws_ssm_parameter_plugin.py +1 -3
- localstack/services/ssm/resource_providers/aws_ssm_patchbaseline.py +29 -29
- localstack/services/ssm/resource_providers/aws_ssm_patchbaseline_plugin.py +1 -3
- localstack/services/stepfunctions/asl/antlt4utils/antlr4utils.py +3 -4
- localstack/services/stepfunctions/asl/component/common/assign/assign_decl.py +1 -1
- localstack/services/stepfunctions/asl/component/common/assign/assign_decl_binding.py +1 -1
- localstack/services/stepfunctions/asl/component/common/assign/assign_template_value_array.py +1 -1
- localstack/services/stepfunctions/asl/component/common/assign/assign_template_value_object.py +1 -1
- localstack/services/stepfunctions/asl/component/common/catch/catcher_decl.py +9 -9
- localstack/services/stepfunctions/asl/component/common/error_name/custom_error_name.py +2 -2
- localstack/services/stepfunctions/asl/component/common/error_name/error_name.py +4 -4
- localstack/services/stepfunctions/asl/component/common/error_name/failure_event.py +8 -8
- localstack/services/stepfunctions/asl/component/common/error_name/states_error_name_type.py +1 -1
- localstack/services/stepfunctions/asl/component/common/jsonata/jsonata_template_binding.py +2 -2
- localstack/services/stepfunctions/asl/component/common/jsonata/jsonata_template_value_array.py +1 -1
- localstack/services/stepfunctions/asl/component/common/jsonata/jsonata_template_value_object.py +1 -1
- localstack/services/stepfunctions/asl/component/common/path/input_path.py +4 -4
- localstack/services/stepfunctions/asl/component/common/path/output_path.py +4 -4
- localstack/services/stepfunctions/asl/component/common/path/result_path.py +3 -3
- localstack/services/stepfunctions/asl/component/common/payload/payloadvalue/payloadarr/payload_arr.py +1 -1
- localstack/services/stepfunctions/asl/component/common/payload/payloadvalue/payloadbinding/payload_binding.py +3 -3
- localstack/services/stepfunctions/asl/component/common/payload/payloadvalue/payloadtmpl/payload_tmpl.py +1 -1
- localstack/services/stepfunctions/asl/component/common/retry/retrier_decl.py +8 -8
- localstack/services/stepfunctions/asl/component/common/string/string_expression.py +3 -3
- localstack/services/stepfunctions/asl/component/common/timeouts/timeout.py +3 -3
- localstack/services/stepfunctions/asl/component/eval_component.py +2 -3
- localstack/services/stepfunctions/asl/component/intrinsic/argument/argument.py +4 -4
- localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/array/array_partition.py +1 -1
- localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/generic/string_format.py +1 -1
- localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/states_function_array.py +1 -1
- localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/states_function_format.py +1 -1
- localstack/services/stepfunctions/asl/component/intrinsic/jsonata.py +3 -3
- localstack/services/stepfunctions/asl/component/intrinsic/member.py +1 -1
- localstack/services/stepfunctions/asl/component/program/program.py +9 -9
- localstack/services/stepfunctions/asl/component/program/states.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state.py +10 -11
- localstack/services/stepfunctions/asl/component/state/state_choice/choice_rule.py +11 -11
- localstack/services/stepfunctions/asl/component/state/state_choice/comparison/comparison.py +5 -11
- localstack/services/stepfunctions/asl/component/state/state_choice/comparison/operator/implementations/is_operator.py +2 -2
- localstack/services/stepfunctions/asl/component/state/state_choice/state_choice.py +3 -5
- localstack/services/stepfunctions/asl/component/state/state_execution/execute_state.py +9 -9
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/item_reader_decl.py +7 -7
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/reader_config/reader_config_decl.py +5 -5
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/resource_eval/resource_eval_s3.py +2 -1
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/resource_eval/resource_output_transformer/resource_output_transformer_csv.py +2 -2
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/distributed_iteration_component.py +8 -8
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/inline_iteration_component.py +7 -7
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/itemprocessor/distributed_item_processor_worker.py +4 -4
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/itemprocessor/inline_item_processor_worker.py +5 -5
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/itemprocessor/map_run_record.py +10 -10
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iteration_component.py +3 -3
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iteration_declaration.py +3 -3
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iteration_worker.py +2 -2
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iterator/distributed_iterator_worker.py +3 -5
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iterator/inline_iterator.py +1 -2
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iterator/inline_iterator_worker.py +5 -5
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/job.py +9 -9
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/result_writer/resource_eval/resource_eval_s3.py +2 -1
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/state_map.py +12 -13
- localstack/services/stepfunctions/asl/component/state/state_execution/state_parallel/branch_worker.py +3 -3
- localstack/services/stepfunctions/asl/component/state/state_execution/state_parallel/branches_decl.py +7 -7
- localstack/services/stepfunctions/asl/component/state/state_execution/state_parallel/state_parallel.py +2 -3
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/lambda_eval_utils.py +7 -7
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/resource.py +3 -3
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service.py +10 -10
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_api_gateway.py +18 -18
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_aws_sdk.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_batch.py +8 -7
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_callback.py +18 -17
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_dynamodb.py +2 -2
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_ecs.py +5 -4
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_events.py +4 -4
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_glue.py +7 -6
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_lambda.py +4 -4
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_sfn.py +9 -8
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_sns.py +2 -2
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_sqs.py +4 -4
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/state_task.py +5 -5
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/state_task_lambda.py +2 -2
- localstack/services/stepfunctions/asl/component/state/state_fail/state_fail.py +3 -5
- localstack/services/stepfunctions/asl/component/state/state_pass/state_pass.py +5 -7
- localstack/services/stepfunctions/asl/component/state/state_succeed/state_succeed.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_wait/state_wait.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_wait/wait_function/timestamp.py +2 -2
- localstack/services/stepfunctions/asl/eval/callback/callback.py +18 -18
- localstack/services/stepfunctions/asl/eval/environment.py +22 -24
- localstack/services/stepfunctions/asl/eval/evaluation_details.py +3 -5
- localstack/services/stepfunctions/asl/eval/event/event_manager.py +10 -10
- localstack/services/stepfunctions/asl/eval/event/logging.py +3 -3
- localstack/services/stepfunctions/asl/eval/program_state.py +8 -8
- localstack/services/stepfunctions/asl/eval/states.py +12 -12
- localstack/services/stepfunctions/asl/eval/test_state/environment.py +3 -5
- localstack/services/stepfunctions/asl/eval/variable_store.py +6 -6
- localstack/services/stepfunctions/asl/jsonata/jsonata.py +7 -6
- localstack/services/stepfunctions/asl/parse/asl_parser.py +1 -1
- localstack/services/stepfunctions/asl/parse/intrinsic/preprocessor.py +2 -3
- localstack/services/stepfunctions/asl/parse/preprocessor.py +44 -44
- localstack/services/stepfunctions/asl/parse/typed_props.py +2 -2
- localstack/services/stepfunctions/asl/static_analyser/intrinsic/variable_names_intrinsic_static_analyser.py +1 -1
- localstack/services/stepfunctions/asl/static_analyser/variable_references_static_analyser.py +2 -2
- localstack/services/stepfunctions/asl/utils/encoding.py +2 -2
- localstack/services/stepfunctions/asl/utils/json_path.py +2 -2
- localstack/services/stepfunctions/backend/activity.py +4 -4
- localstack/services/stepfunctions/backend/alias.py +8 -8
- localstack/services/stepfunctions/backend/execution.py +29 -30
- localstack/services/stepfunctions/backend/execution_worker.py +7 -7
- localstack/services/stepfunctions/backend/state_machine.py +28 -28
- localstack/services/stepfunctions/backend/test_state/execution.py +3 -4
- localstack/services/stepfunctions/backend/test_state/execution_worker.py +1 -3
- localstack/services/stepfunctions/mocking/mock_config.py +9 -9
- localstack/services/stepfunctions/mocking/mock_config_file.py +10 -10
- localstack/services/stepfunctions/packages.py +14 -5
- localstack/services/stepfunctions/provider.py +34 -44
- localstack/services/stepfunctions/quotas.py +2 -3
- localstack/services/stepfunctions/resource_providers/aws_stepfunctions_activity.py +6 -6
- localstack/services/stepfunctions/resource_providers/aws_stepfunctions_activity_plugin.py +1 -3
- localstack/services/stepfunctions/resource_providers/aws_stepfunctions_statemachine.py +25 -25
- localstack/services/stepfunctions/resource_providers/aws_stepfunctions_statemachine_plugin.py +1 -3
- localstack/services/stepfunctions/stepfunctions_utils.py +1 -2
- localstack/services/stores.py +8 -8
- localstack/services/transcribe/packages.py +1 -3
- localstack/services/transcribe/provider.py +8 -3
- localstack/state/codecs.py +61 -0
- localstack/state/core.py +11 -5
- localstack/state/inspect.py +4 -4
- localstack/state/pickle.py +36 -23
- localstack/testing/aws/asf_utils.py +3 -2
- localstack/testing/aws/cloudformation_utils.py +1 -1
- localstack/testing/aws/lambda_utils.py +15 -14
- localstack/testing/aws/util.py +3 -2
- localstack/testing/pytest/cloudformation/fixtures.py +68 -18
- localstack/testing/pytest/container.py +5 -5
- localstack/testing/pytest/filters.py +1 -3
- localstack/testing/pytest/fixtures.py +188 -49
- localstack/testing/pytest/in_memory_localstack.py +1 -3
- localstack/testing/pytest/marking.py +42 -15
- localstack/testing/pytest/path_filter.py +1 -1
- localstack/testing/pytest/stepfunctions/fixtures.py +4 -4
- localstack/testing/pytest/stepfunctions/utils.py +11 -10
- localstack/testing/pytest/util.py +1 -1
- localstack/testing/pytest/validation_tracking.py +3 -4
- localstack/testing/scenario/provisioning.py +11 -10
- localstack/testing/snapshots/transformer_utility.py +8 -3
- localstack/testing/testselection/matching.py +2 -2
- localstack/testing/testselection/opt_out.py +1 -1
- localstack/testing/testselection/scripts/filter_by_test_selection.py +1 -1
- localstack/testing/testselection/scripts/generate_test_selection.py +1 -1
- localstack/testing/testselection/testselection.py +2 -2
- localstack/utils/analytics/cli.py +2 -3
- localstack/utils/analytics/client.py +5 -5
- localstack/utils/analytics/events.py +2 -2
- localstack/utils/analytics/metadata.py +6 -4
- localstack/utils/analytics/metrics/counter.py +11 -18
- localstack/utils/analytics/metrics/registry.py +2 -2
- localstack/utils/analytics/publisher.py +4 -5
- localstack/utils/analytics/service_providers.py +19 -0
- localstack/utils/analytics/service_request_aggregator.py +4 -4
- localstack/utils/archives.py +12 -12
- localstack/utils/asyncio.py +2 -2
- localstack/utils/aws/arns.py +26 -31
- localstack/utils/aws/aws_responses.py +21 -28
- localstack/utils/aws/aws_stack.py +7 -12
- localstack/utils/aws/dead_letter_queue.py +4 -9
- localstack/utils/aws/message_forwarding.py +8 -11
- localstack/utils/aws/request_context.py +5 -6
- localstack/utils/aws/resources.py +1 -1
- localstack/utils/aws/templating.py +4 -4
- localstack/utils/batch_policy.py +4 -4
- localstack/utils/bootstrap.py +37 -30
- localstack/utils/catalog/catalog.py +139 -0
- localstack/utils/catalog/catalog_loader.py +119 -0
- localstack/utils/catalog/common.py +58 -0
- localstack/utils/catalog/plugins.py +28 -0
- localstack/utils/cloudwatch/cloudwatch_util.py +5 -5
- localstack/utils/collections.py +33 -27
- localstack/utils/config_listener.py +2 -2
- localstack/utils/container_networking.py +5 -6
- localstack/utils/container_utils/container_client.py +156 -160
- localstack/utils/container_utils/docker_cmd_client.py +97 -81
- localstack/utils/container_utils/docker_sdk_client.py +75 -72
- localstack/utils/crypto.py +12 -13
- localstack/utils/diagnose.py +11 -12
- localstack/utils/docker_utils.py +11 -7
- localstack/utils/files.py +34 -15
- localstack/utils/functions.py +5 -4
- localstack/utils/http.py +14 -14
- localstack/utils/iputils.py +2 -1
- localstack/utils/json.py +21 -7
- localstack/utils/kinesis/kinesis_connector.py +2 -1
- localstack/utils/net.py +25 -17
- localstack/utils/no_exit_argument_parser.py +2 -2
- localstack/utils/numbers.py +9 -2
- localstack/utils/objects.py +15 -14
- localstack/utils/patch.py +14 -7
- localstack/utils/platform.py +2 -2
- localstack/utils/run.py +15 -14
- localstack/utils/scheduler.py +13 -12
- localstack/utils/server/tcp_proxy.py +2 -2
- localstack/utils/serving.py +3 -4
- localstack/utils/strings.py +15 -16
- localstack/utils/sync.py +126 -1
- localstack/utils/tagging.py +10 -8
- localstack/utils/testutil.py +17 -17
- localstack/utils/threads.py +3 -3
- localstack/utils/time.py +12 -4
- localstack/utils/urls.py +1 -3
- localstack/utils/xml.py +1 -1
- localstack/utils/xray/traceid.py +1 -1
- localstack/version.py +16 -3
- {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/METADATA +18 -13
- {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/RECORD +663 -655
- {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/entry_points.txt +8 -4
- localstack_core-4.10.1.dev12.dist-info/plux.json +1 -0
- localstack/packages/terraform.py +0 -47
- localstack/services/cloudformation/deploy.html +0 -144
- localstack/services/cloudformation/deploy_ui.py +0 -47
- localstack/services/cloudformation/plugins.py +0 -12
- localstack/services/lambda_/lambda_debug_mode/ldm.py +0 -375
- localstack/services/lambda_/lambda_debug_mode/ldm_config_file.py +0 -178
- localstack/services/lambda_/lambda_debug_mode/ldm_types.py +0 -11
- localstack/services/lambda_/lambda_debug_mode/ldm_utils.py +0 -43
- localstack_core-4.6.1.dev60.dist-info/plux.json +0 -1
- /localstack/{services/lambda_/lambda_debug_mode/__init__.py → testing/pytest/cloudformation/transformers.py} +0 -0
- {localstack_core-4.6.1.dev60.data → localstack_core-4.10.1.dev12.data}/scripts/localstack +0 -0
- {localstack_core-4.6.1.dev60.data → localstack_core-4.10.1.dev12.data}/scripts/localstack-supervisor +0 -0
- {localstack_core-4.6.1.dev60.data → localstack_core-4.10.1.dev12.data}/scripts/localstack.bat +0 -0
- {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/WHEEL +0 -0
- {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/licenses/LICENSE.txt +0 -0
- {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│
|
|
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 ``
|
|
53
|
-
``JSONRequestParser``
|
|
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
|
|
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:
|
|
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) ->
|
|
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
|
-
|
|
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
|
-
|
|
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 '
|
|
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_
|
|
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
|
|
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_
|
|
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.
|
|
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.
|
|
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) ->
|
|
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:
|
|
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) ->
|
|
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:
|
|
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(
|
|
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:
|
|
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(
|
|
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 (
|
|
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:
|
|
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:
|
|
849
|
+
value: dict | None,
|
|
828
850
|
uri_params: Mapping[str, Any] = None,
|
|
829
|
-
) ->
|
|
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:
|
|
874
|
+
value: dict | None,
|
|
853
875
|
uri_params: Mapping[str, Any] = None,
|
|
854
|
-
) ->
|
|
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) ->
|
|
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) ->
|
|
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
|
|
1603
|
+
and service_protocol in service_specific_parsers[service.service_name]
|
|
1178
1604
|
):
|
|
1179
|
-
return service_specific_parsers[service.service_name][
|
|
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[
|
|
1608
|
+
return protocol_specific_parsers[service_protocol](service)
|