From f4e2bd94849c9c9313acc68c84f6f8a0dd63b83e Mon Sep 17 00:00:00 2001 From: Daniel Fangl Date: Wed, 30 Aug 2023 18:46:49 +0200 Subject: [PATCH 1/5] first refactoring, still some type errors left --- moto/amp/urls.py | 25 ++--- moto/apigateway/urls.py | 136 +++++++++++++++++++------- moto/apigatewayv2/urls.py | 109 +++++++++++++++------ moto/appconfig/urls.py | 25 ++--- moto/appsync/urls.py | 37 ++++--- moto/awslambda/urls.py | 101 ++++++++++++++----- moto/cloudfront/urls.py | 34 +++++-- moto/cognitoidp/urls.py | 4 +- moto/core/responses.py | 21 ++++ moto/databrew/urls.py | 38 +++++-- moto/ebs/urls.py | 21 ++-- moto/elastictranscoder/urls.py | 11 ++- moto/glacier/urls.py | 30 ++++-- moto/greengrass/urls.py | 114 +++++++++++++++------ moto/guardduty/urls.py | 24 +++-- moto/instance_metadata/urls.py | 8 +- moto/iot/urls.py | 15 +-- moto/managedblockchain/urls.py | 56 ++++++++--- moto/mq/urls.py | 33 ++++--- moto/pinpoint/urls.py | 25 +++-- moto/quicksight/urls.py | 35 ++++--- moto/route53/urls.py | 80 +++++++++++---- moto/s3/urls.py | 18 ++-- moto/s3control/responses.py | 3 - moto/s3control/urls.py | 18 +++- moto/scheduler/urls.py | 19 ++-- tests/test_s3/test_s3_file_handles.py | 4 +- 27 files changed, 733 insertions(+), 311 deletions(-) diff --git a/moto/amp/urls.py b/moto/amp/urls.py index 0b9abd365de3..97f51f12a9e2 100644 --- a/moto/amp/urls.py +++ b/moto/amp/urls.py @@ -6,17 +6,18 @@ ] -response = PrometheusServiceResponse() - - url_paths = { - "{0}/workspaces$": response.dispatch, - "{0}/workspaces/(?P[^/]+)$": response.dispatch, - "{0}/workspaces/(?P[^/]+)/alias$": response.dispatch, - "{0}/workspaces/(?P[^/]+)/logging$": response.dispatch, - "{0}/workspaces/(?P[^/]+)/rulegroupsnamespaces$": response.dispatch, - "{0}/workspaces/(?P[^/]+)/rulegroupsnamespaces/(?P[^/]+)$": response.dispatch, - "{0}/tags/(?P[^/]+)$": response.dispatch, - "{0}/tags/(?P[^/]+)/(?P[^/]+)$": response.tags, - "{0}/tags/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)$": response.tags, + "{0}/workspaces$": PrometheusServiceResponse.dispatch, + "{0}/workspaces/(?P[^/]+)$": PrometheusServiceResponse.dispatch, + "{0}/workspaces/(?P[^/]+)/alias$": PrometheusServiceResponse.dispatch, + "{0}/workspaces/(?P[^/]+)/logging$": PrometheusServiceResponse.dispatch, + "{0}/workspaces/(?P[^/]+)/rulegroupsnamespaces$": PrometheusServiceResponse.dispatch, + "{0}/workspaces/(?P[^/]+)/rulegroupsnamespaces/(?P[^/]+)$": PrometheusServiceResponse.dispatch, + "{0}/tags/(?P[^/]+)$": PrometheusServiceResponse.dispatch, + "{0}/tags/(?P[^/]+)/(?P[^/]+)$": PrometheusServiceResponse.method_dispatch( + PrometheusServiceResponse.tags + ), + "{0}/tags/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)$": PrometheusServiceResponse.method_dispatch( + PrometheusServiceResponse.tags + ), } diff --git a/moto/apigateway/urls.py b/moto/apigateway/urls.py index d2961c6f672a..e4ab1a566d92 100644 --- a/moto/apigateway/urls.py +++ b/moto/apigateway/urls.py @@ -1,46 +1,108 @@ from .responses import APIGatewayResponse from ..apigatewayv2.urls import url_paths as url_paths_v2 -response = APIGatewayResponse() - url_bases = [r"https?://apigateway\.(.+)\.amazonaws.com"] url_paths = { - "{0}/restapis$": response.restapis, - "{0}/restapis/(?P[^/]+)/?$": response.restapis_individual, - "{0}/restapis/(?P[^/]+)/resources$": response.resources, - "{0}/restapis/(?P[^/]+)/authorizers$": response.restapis_authorizers, - "{0}/restapis/(?P[^/]+)/authorizers/(?P[^/]+)/?$": response.authorizers, - "{0}/restapis/(?P[^/]+)/stages$": response.restapis_stages, - "{0}/tags/arn:aws:apigateway:(?P[^/]+)::/restapis/(?P[^/]+)/stages/(?P[^/]+)/?$": response.restapis_stages_tags, - "{0}/restapis/(?P[^/]+)/stages/(?P[^/]+)/?$": response.stages, - "{0}/restapis/(?P[^/]+)/stages/(?P[^/]+)/exports/(?P[^/]+)/?$": response.export, - "{0}/restapis/(?P[^/]+)/deployments$": response.deployments, - "{0}/restapis/(?P[^/]+)/deployments/(?P[^/]+)/?$": response.individual_deployment, - "{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/?$": response.resource_individual, - "{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/?$": response.resource_methods, - r"{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/responses/(?P\d+)$": response.resource_method_responses, - r"{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/integration$": response.integrations, - r"{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/integration/responses/(?P\d+)$": response.integration_responses, - r"{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/integration/responses/(?P\d+)/$": response.integration_responses, - "{0}/apikeys$": response.apikeys, - "{0}/apikeys/(?P[^/]+)": response.apikey_individual, - "{0}/usageplans$": response.usage_plans, - "{0}/domainnames$": response.domain_names, - "{0}/restapis/(?P[^/]+)/models$": response.models, - "{0}/restapis/(?P[^/]+)/models/(?P[^/]+)/?$": response.model_induvidual, - "{0}/domainnames/(?P[^/]+)/?$": response.domain_name_induvidual, - "{0}/domainnames/(?P[^/]+)/basepathmappings$": response.base_path_mappings, - "{0}/domainnames/(?P[^/]+)/basepathmappings/(?P[^/]+)$": response.base_path_mapping_individual, - "{0}/usageplans/(?P[^/]+)/?$": response.usage_plan_individual, - "{0}/usageplans/(?P[^/]+)/keys$": response.usage_plan_keys, - "{0}/usageplans/(?P[^/]+)/keys/(?P[^/]+)/?$": response.usage_plan_key_individual, - "{0}/restapis/(?P[^/]+)/requestvalidators$": response.request_validators, - "{0}/restapis/(?P[^/]+)/requestvalidators/(?P[^/]+)/?$": response.request_validator_individual, - "{0}/restapis/(?P[^/]+)/gatewayresponses/?$": response.gateway_responses, - "{0}/restapis/(?P[^/]+)/gatewayresponses/(?P[^/]+)/?$": response.gateway_response, - "{0}/vpclinks$": response.vpc_links, - "{0}/vpclinks/(?P[^/]+)": response.vpc_link, + "{0}/restapis$": APIGatewayResponse.method_dispatch(APIGatewayResponse.restapis), + "{0}/restapis/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.restapis_individual + ), + "{0}/restapis/(?P[^/]+)/resources$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.resources + ), + "{0}/restapis/(?P[^/]+)/authorizers$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.restapis_authorizers + ), + "{0}/restapis/(?P[^/]+)/authorizers/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.authorizers + ), + "{0}/restapis/(?P[^/]+)/stages$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.restapis_stages + ), + "{0}/tags/arn:aws:apigateway:(?P[^/]+)::/restapis/(?P[^/]+)/stages/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.restapis_stages_tags + ), + "{0}/restapis/(?P[^/]+)/stages/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.stages + ), + "{0}/restapis/(?P[^/]+)/stages/(?P[^/]+)/exports/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.export + ), + "{0}/restapis/(?P[^/]+)/deployments$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.deployments + ), + "{0}/restapis/(?P[^/]+)/deployments/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.individual_deployment + ), + "{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.resource_individual + ), + "{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.resource_methods + ), + r"{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/responses/(?P\d+)$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.resource_method_responses + ), + r"{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/integration$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.integrations + ), + r"{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/integration/responses/(?P\d+)$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.integration_responses + ), + r"{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/integration/responses/(?P\d+)/$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.integration_responses + ), + "{0}/apikeys$": APIGatewayResponse.method_dispatch(APIGatewayResponse.apikeys), + "{0}/apikeys/(?P[^/]+)": APIGatewayResponse.method_dispatch( + APIGatewayResponse.apikey_individual + ), + "{0}/usageplans$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.usage_plans + ), + "{0}/domainnames$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.domain_names + ), + "{0}/restapis/(?P[^/]+)/models$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.models + ), + "{0}/restapis/(?P[^/]+)/models/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.model_induvidual + ), + "{0}/domainnames/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.domain_name_induvidual + ), + "{0}/domainnames/(?P[^/]+)/basepathmappings$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.base_path_mappings + ), + "{0}/domainnames/(?P[^/]+)/basepathmappings/(?P[^/]+)$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.base_path_mapping_individual + ), + "{0}/usageplans/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.usage_plan_individual + ), + "{0}/usageplans/(?P[^/]+)/keys$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.usage_plan_keys + ), + "{0}/usageplans/(?P[^/]+)/keys/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.usage_plan_key_individual + ), + "{0}/restapis/(?P[^/]+)/requestvalidators$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.request_validators + ), + "{0}/restapis/(?P[^/]+)/requestvalidators/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.request_validator_individual + ), + "{0}/restapis/(?P[^/]+)/gatewayresponses/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.gateway_responses + ), + "{0}/restapis/(?P[^/]+)/gatewayresponses/(?P[^/]+)/?$": APIGatewayResponse.method_dispatch( + APIGatewayResponse.gateway_response + ), + "{0}/vpclinks$": APIGatewayResponse.method_dispatch(APIGatewayResponse.vpc_links), + "{0}/vpclinks/(?P[^/]+)": APIGatewayResponse.method_dispatch( + APIGatewayResponse.vpc_link + ), } # Also manages the APIGatewayV2 diff --git a/moto/apigatewayv2/urls.py b/moto/apigatewayv2/urls.py index 7826904a6b0f..56e807f18dfe 100644 --- a/moto/apigatewayv2/urls.py +++ b/moto/apigatewayv2/urls.py @@ -6,35 +6,84 @@ ] -response_v2 = ApiGatewayV2Response() - - url_paths = { - "{0}/v2/apis$": response_v2.apis, - "{0}/v2/apis/(?P[^/]+)$": response_v2.api, - "{0}/v2/apis/(?P[^/]+)/authorizers$": response_v2.authorizers, - "{0}/v2/apis/(?P[^/]+)/authorizers/(?P[^/]+)$": response_v2.authorizer, - "{0}/v2/apis/(?P[^/]+)/cors$": response_v2.cors, - "{0}/v2/apis/(?P[^/]+)/integrations$": response_v2.integrations, - "{0}/v2/apis/(?P[^/]+)/integrations/(?P[^/]+)$": response_v2.integration, - "{0}/v2/apis/(?P[^/]+)/integrations/(?P[^/]+)/integrationresponses$": response_v2.integration_responses, - "{0}/v2/apis/(?P[^/]+)/integrations/(?P[^/]+)/integrationresponses/(?P[^/]+)$": response_v2.integration_response, - "{0}/v2/apis/(?P[^/]+)/models$": response_v2.models, - "{0}/v2/apis/(?P[^/]+)/models/(?P[^/]+)$": response_v2.model, - "{0}/v2/apis/(?P[^/]+)/routes$": response_v2.routes, - "{0}/v2/apis/(?P[^/]+)/routes/(?P[^/]+)$": response_v2.route, - "{0}/v2/apis/(?P[^/]+)/routes/(?P[^/]+)/routeresponses$": response_v2.route_responses, - "{0}/v2/apis/(?P[^/]+)/routes/(?P[^/]+)/routeresponses/(?P[^/]+)$": response_v2.route_response, - "{0}/v2/apis/(?P[^/]+)/routes/(?P[^/]+)/requestparameters/(?P[^/]+)$": response_v2.route_request_parameter, - "{0}/v2/apis/(?P[^/]+)/stages$": response_v2.stages, - "{0}/v2/apis/(?P[^/]+)/stages/(?P[^/]+)$": response_v2.stage, - "{0}/v2/tags/(?P[^/]+)$": response_v2.tags, - "{0}/v2/tags/(?P[^/]+)/apis/(?P[^/]+)$": response_v2.tags, - "{0}/v2/tags/(?P[^/]+)/vpclinks/(?P[^/]+)$": response_v2.tags, - "{0}/v2/vpclinks$": response_v2.vpc_links, - "{0}/v2/vpclinks/(?P[^/]+)$": response_v2.vpc_link, - "{0}/v2/domainnames$": response_v2.domain_names, - "{0}/v2/domainnames/(?P[^/]+)$": response_v2.domain_name, - "{0}/v2/domainnames/(?P[^/]+)/apimappings$": response_v2.api_mappings, - "{0}/v2/domainnames/(?P[^/]+)/apimappings/(?P[^/]+)$": response_v2.api_mapping, + "{0}/v2/apis$": ApiGatewayV2Response.method_dispatch(ApiGatewayV2Response.apis), + "{0}/v2/apis/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.api + ), + "{0}/v2/apis/(?P[^/]+)/authorizers$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.authorizers + ), + "{0}/v2/apis/(?P[^/]+)/authorizers/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.authorizer + ), + "{0}/v2/apis/(?P[^/]+)/cors$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.cors + ), + "{0}/v2/apis/(?P[^/]+)/integrations$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.integrations + ), + "{0}/v2/apis/(?P[^/]+)/integrations/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.integration + ), + "{0}/v2/apis/(?P[^/]+)/integrations/(?P[^/]+)/integrationresponses$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.integration_responses + ), + "{0}/v2/apis/(?P[^/]+)/integrations/(?P[^/]+)/integrationresponses/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.integration_response + ), + "{0}/v2/apis/(?P[^/]+)/models$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.models + ), + "{0}/v2/apis/(?P[^/]+)/models/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.model + ), + "{0}/v2/apis/(?P[^/]+)/routes$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.routes + ), + "{0}/v2/apis/(?P[^/]+)/routes/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.route + ), + "{0}/v2/apis/(?P[^/]+)/routes/(?P[^/]+)/routeresponses$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.route_responses + ), + "{0}/v2/apis/(?P[^/]+)/routes/(?P[^/]+)/routeresponses/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.route_response + ), + "{0}/v2/apis/(?P[^/]+)/routes/(?P[^/]+)/requestparameters/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.route_request_parameter + ), + "{0}/v2/apis/(?P[^/]+)/stages$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.stages + ), + "{0}/v2/apis/(?P[^/]+)/stages/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.stage + ), + "{0}/v2/tags/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.tags + ), + "{0}/v2/tags/(?P[^/]+)/apis/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.tags + ), + "{0}/v2/tags/(?P[^/]+)/vpclinks/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.tags + ), + "{0}/v2/vpclinks$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.vpc_links + ), + "{0}/v2/vpclinks/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.vpc_link + ), + "{0}/v2/domainnames$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.domain_names + ), + "{0}/v2/domainnames/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.domain_name + ), + "{0}/v2/domainnames/(?P[^/]+)/apimappings$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.api_mappings + ), + "{0}/v2/domainnames/(?P[^/]+)/apimappings/(?P[^/]+)$": ApiGatewayV2Response.method_dispatch( + ApiGatewayV2Response.api_mapping + ), } diff --git a/moto/appconfig/urls.py b/moto/appconfig/urls.py index 560c14dee937..257fc4f36950 100644 --- a/moto/appconfig/urls.py +++ b/moto/appconfig/urls.py @@ -6,17 +6,18 @@ ] -response = AppConfigResponse() - - url_paths = { - "{0}/applications$": response.dispatch, - "{0}/applications/(?P[^/]+)$": response.dispatch, - "{0}/applications/(?P[^/]+)/configurationprofiles$": response.dispatch, - "{0}/applications/(?P[^/]+)/configurationprofiles/(?P[^/]+)$": response.dispatch, - "{0}/applications/(?P[^/]+)/configurationprofiles/(?P[^/]+)/hostedconfigurationversions$": response.dispatch, - "{0}/applications/(?P[^/]+)/configurationprofiles/(?P[^/]+)/hostedconfigurationversions/(?P[^/]+)$": response.dispatch, - "{0}/tags/(?P.+)$": response.dispatch, - "{0}/tags/(?P[^/]+)/(?P[^/]+)$": response.tags, - "{0}/tags/(?P[^/]+)/(?P[^/]+)/configurationprofile/(?P[^/]+)$": response.tags, + "{0}/applications$": AppConfigResponse.dispatch, + "{0}/applications/(?P[^/]+)$": AppConfigResponse.dispatch, + "{0}/applications/(?P[^/]+)/configurationprofiles$": AppConfigResponse.dispatch, + "{0}/applications/(?P[^/]+)/configurationprofiles/(?P[^/]+)$": AppConfigResponse.dispatch, + "{0}/applications/(?P[^/]+)/configurationprofiles/(?P[^/]+)/hostedconfigurationversions$": AppConfigResponse.dispatch, + "{0}/applications/(?P[^/]+)/configurationprofiles/(?P[^/]+)/hostedconfigurationversions/(?P[^/]+)$": AppConfigResponse.dispatch, + "{0}/tags/(?P.+)$": AppConfigResponse.dispatch, + "{0}/tags/(?P[^/]+)/(?P[^/]+)$": AppConfigResponse.method_dispatch( + AppConfigResponse.tags + ), + "{0}/tags/(?P[^/]+)/(?P[^/]+)/configurationprofile/(?P[^/]+)$": AppConfigResponse.method_dispatch( + AppConfigResponse.tags + ), } diff --git a/moto/appsync/urls.py b/moto/appsync/urls.py index 0b04b48d22e9..84116519c679 100644 --- a/moto/appsync/urls.py +++ b/moto/appsync/urls.py @@ -6,17 +6,30 @@ ] -response = AppSyncResponse() - - url_paths = { - "{0}/v1/apis$": response.graph_ql, - "{0}/v1/apis/(?P[^/]+)$": response.graph_ql_individual, - "{0}/v1/apis/(?P[^/]+)/apikeys$": response.api_key, - "{0}/v1/apis/(?P[^/]+)/apikeys/(?P[^/]+)$": response.api_key_individual, - "{0}/v1/apis/(?P[^/]+)/schemacreation$": response.schemacreation, - "{0}/v1/apis/(?P[^/]+)/schema$": response.schema, - "{0}/v1/tags/(?P.+)$": response.tags, - "{0}/v1/tags/(?P.+)/(?P.+)$": response.tags, - "{0}/v1/apis/(?P[^/]+)/types/(?P.+)$": response.types, + "{0}/v1/apis$": AppSyncResponse.method_dispatch(AppSyncResponse.graph_ql), + "{0}/v1/apis/(?P[^/]+)$": AppSyncResponse.method_dispatch( + AppSyncResponse.graph_ql_individual + ), + "{0}/v1/apis/(?P[^/]+)/apikeys$": AppSyncResponse.method_dispatch( + AppSyncResponse.api_key + ), + "{0}/v1/apis/(?P[^/]+)/apikeys/(?P[^/]+)$": AppSyncResponse.method_dispatch( + AppSyncResponse.api_key_individual + ), + "{0}/v1/apis/(?P[^/]+)/schemacreation$": AppSyncResponse.method_dispatch( + AppSyncResponse.schemacreation + ), + "{0}/v1/apis/(?P[^/]+)/schema$": AppSyncResponse.method_dispatch( + AppSyncResponse.schema + ), + "{0}/v1/tags/(?P.+)$": AppSyncResponse.method_dispatch( + AppSyncResponse.tags + ), + "{0}/v1/tags/(?P.+)/(?P.+)$": AppSyncResponse.method_dispatch( + AppSyncResponse.tags + ), + "{0}/v1/apis/(?P[^/]+)/types/(?P.+)$": AppSyncResponse.method_dispatch( + AppSyncResponse.types + ), } diff --git a/moto/awslambda/urls.py b/moto/awslambda/urls.py index 94433646153c..284a681c3a2c 100644 --- a/moto/awslambda/urls.py +++ b/moto/awslambda/urls.py @@ -2,32 +2,81 @@ url_bases = [r"https?://lambda\.(.+)\.amazonaws\.com"] -response = LambdaResponse() url_paths = { - r"{0}/(?P[^/]+)/functions$": response.root, - r"{0}/(?P[^/]+)/functions/$": response.root, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/?$": response.function, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/aliases$": response.aliases, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/aliases/(?P[\w_-]+)$": response.alias, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/versions/?$": response.versions, - r"{0}/(?P[^/]+)/event-source-mappings/$": response.event_source_mappings, - r"{0}/(?P[^/]+)/event-source-mappings/(?P[\w_-]+)/?$": response.event_source_mapping, - r"{0}/(?P[^/]+)/functions/(?P[\w_-]+)/invocations/?$": response.invoke, - r"{0}/(?P[^/]+)/functions/(?P.+)/invocations/?$": response.invoke, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/invoke-async$": response.invoke_async, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/invoke-async/$": response.invoke_async, - r"{0}/(?P[^/]+)/tags/(?P.+)": response.tag, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/policy/(?P[\w_-]+)$": response.policy, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/policy/?$": response.policy, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/configuration/?$": response.configuration, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/code/?$": response.code, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/code-signing-config$": response.code_signing_config, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/concurrency/?$": response.function_concurrency, - r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/url/?$": response.function_url_config, - r"{0}/(?P[^/]+)/layers$": response.list_layers, - r"{0}/(?P[^/]+)/layers/$": response.list_layers, - r"{0}/(?P[^/]+)/layers/(?P.+)/versions$": response.layers_versions, - r"{0}/(?P[^/]+)/layers/(?P.+)/versions/$": response.layers_versions, - r"{0}/(?P[^/]+)/layers/(?P.+)/versions/(?P[\w_-]+)$": response.layers_version, + r"{0}/(?P[^/]+)/functions$": LambdaResponse.method_dispatch( + LambdaResponse.root + ), + r"{0}/(?P[^/]+)/functions/$": LambdaResponse.method_dispatch( + LambdaResponse.root + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/?$": LambdaResponse.method_dispatch( + LambdaResponse.function + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/aliases$": LambdaResponse.method_dispatch( + LambdaResponse.aliases + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/aliases/(?P[\w_-]+)$": LambdaResponse.method_dispatch( + LambdaResponse.alias + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/versions/?$": LambdaResponse.method_dispatch( + LambdaResponse.versions + ), + r"{0}/(?P[^/]+)/event-source-mappings/$": LambdaResponse.method_dispatch( + LambdaResponse.event_source_mappings + ), + r"{0}/(?P[^/]+)/event-source-mappings/(?P[\w_-]+)/?$": LambdaResponse.method_dispatch( + LambdaResponse.event_source_mapping + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_-]+)/invocations/?$": LambdaResponse.method_dispatch( + LambdaResponse.invoke + ), + r"{0}/(?P[^/]+)/functions/(?P.+)/invocations/?$": LambdaResponse.method_dispatch( + LambdaResponse.invoke + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/invoke-async$": LambdaResponse.method_dispatch( + LambdaResponse.invoke_async + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/invoke-async/$": LambdaResponse.method_dispatch( + LambdaResponse.invoke_async + ), + r"{0}/(?P[^/]+)/tags/(?P.+)": LambdaResponse.method_dispatch( + LambdaResponse.tag + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/policy/(?P[\w_-]+)$": LambdaResponse.method_dispatch( + LambdaResponse.policy + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/policy/?$": LambdaResponse.method_dispatch( + LambdaResponse.policy + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/configuration/?$": LambdaResponse.method_dispatch( + LambdaResponse.configuration + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/code/?$": LambdaResponse.method_dispatch( + LambdaResponse.code + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/code-signing-config$": LambdaResponse.method_dispatch( + LambdaResponse.code_signing_config + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/concurrency/?$": LambdaResponse.method_dispatch( + LambdaResponse.function_concurrency + ), + r"{0}/(?P[^/]+)/functions/(?P[\w_:%-]+)/url/?$": LambdaResponse.method_dispatch( + LambdaResponse.function_url_config + ), + r"{0}/(?P[^/]+)/layers$": LambdaResponse.method_dispatch( + LambdaResponse.list_layers + ), + r"{0}/(?P[^/]+)/layers/$": LambdaResponse.method_dispatch( + LambdaResponse.list_layers + ), + r"{0}/(?P[^/]+)/layers/(?P.+)/versions$": LambdaResponse.method_dispatch( + LambdaResponse.layers_versions + ), + r"{0}/(?P[^/]+)/layers/(?P.+)/versions/$": LambdaResponse.method_dispatch( + LambdaResponse.layers_versions + ), + r"{0}/(?P[^/]+)/layers/(?P.+)/versions/(?P[\w_-]+)$": LambdaResponse.method_dispatch( + LambdaResponse.layers_version + ), } diff --git a/moto/cloudfront/urls.py b/moto/cloudfront/urls.py index 89f93a866eda..d67e96e16c4b 100644 --- a/moto/cloudfront/urls.py +++ b/moto/cloudfront/urls.py @@ -2,18 +2,32 @@ from .responses import CloudFrontResponse -response = CloudFrontResponse() - url_bases = [ r"https?://cloudfront\.amazonaws\.com", ] url_paths = { - "{0}/2020-05-31/distribution$": response.distributions, - "{0}/2020-05-31/distribution/(?P[^/]+)$": response.individual_distribution, - "{0}/2020-05-31/distribution/(?P[^/]+)/config$": response.update_distribution, - "{0}/2020-05-31/distribution/(?P[^/]+)/invalidation": response.invalidation, - "{0}/2020-05-31/tagging$": response.tags, - "{0}/2020-05-31/origin-access-control$": response.origin_access_controls, - "{0}/2020-05-31/origin-access-control/(?P[^/]+)$": response.origin_access_control, - "{0}/2020-05-31/origin-access-control/(?P[^/]+)/config$": response.origin_access_control, + "{0}/2020-05-31/distribution$": CloudFrontResponse.method_dispatch( + CloudFrontResponse.distributions + ), + "{0}/2020-05-31/distribution/(?P[^/]+)$": CloudFrontResponse.method_dispatch( + CloudFrontResponse.individual_distribution + ), + "{0}/2020-05-31/distribution/(?P[^/]+)/config$": CloudFrontResponse.method_dispatch( + CloudFrontResponse.update_distribution + ), + "{0}/2020-05-31/distribution/(?P[^/]+)/invalidation": CloudFrontResponse.method_dispatch( + CloudFrontResponse.invalidation + ), + "{0}/2020-05-31/tagging$": CloudFrontResponse.method_dispatch( + CloudFrontResponse.tags + ), + "{0}/2020-05-31/origin-access-control$": CloudFrontResponse.method_dispatch( + CloudFrontResponse.origin_access_controls + ), + "{0}/2020-05-31/origin-access-control/(?P[^/]+)$": CloudFrontResponse.method_dispatch( + CloudFrontResponse.origin_access_control + ), + "{0}/2020-05-31/origin-access-control/(?P[^/]+)/config$": CloudFrontResponse.method_dispatch( + CloudFrontResponse.origin_access_control + ), } diff --git a/moto/cognitoidp/urls.py b/moto/cognitoidp/urls.py index 7df8f3e6ec4c..f2f4e288bf02 100644 --- a/moto/cognitoidp/urls.py +++ b/moto/cognitoidp/urls.py @@ -4,5 +4,7 @@ url_paths = { "{0}/$": CognitoIdpResponse.dispatch, - "{0}/(?P[^/]+)/.well-known/jwks.json$": CognitoIdpJsonWebKeyResponse().serve_json_web_key, + "{0}/(?P[^/]+)/.well-known/jwks.json$": CognitoIdpJsonWebKeyResponse.dispatch( + CognitoIdpJsonWebKeyResponse.serve_json_web_key + ), } diff --git a/moto/core/responses.py b/moto/core/responses.py index d7b9b430f851..f1be50ee01f4 100644 --- a/moto/core/responses.py +++ b/moto/core/responses.py @@ -29,6 +29,7 @@ Set, ClassVar, Callable, + TypeVar, ) from urllib.parse import parse_qs, parse_qsl, urlparse from werkzeug.exceptions import HTTPException @@ -40,6 +41,9 @@ JINJA_ENVS: Dict[type, Environment] = {} +ResponseShape = TypeVar("ResponseShape", bound="BaseResponse") + + def _decode_dict(d: Dict[Any, Any]) -> Dict[str, Any]: decoded: Dict[str, Any] = OrderedDict() for key, value in d.items(): @@ -230,6 +234,23 @@ def __init__(self, service_name: Optional[str] = None): def dispatch(cls, *args: Any, **kwargs: Any) -> Any: # type: ignore[misc] return cls()._dispatch(*args, **kwargs) + @classmethod + def method_dispatch( # type: ignore[misc] + cls, to_call: Callable[[ResponseShape, Any, str, Any], TYPE_RESPONSE] + ) -> Callable[[Any, str, Any], TYPE_RESPONSE]: + """ + Takes a given unbound function (part of a Response class) and executes it for a new instance of this + response class. + Can be used wherever we want to specify different methods for dispatching in urls.py + :param to_call: Unbound method residing in this Response class + :return: A wrapper executing the given method on a new instance of this class + """ + + def _inner(request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: + return getattr(cls(), to_call.__name__)(request, full_url, headers) + + return _inner + def setup_class( self, request: Any, full_url: str, headers: Any, use_raw_body: bool = False ) -> None: diff --git a/moto/databrew/urls.py b/moto/databrew/urls.py index 85da691086ae..b556b3f73f95 100644 --- a/moto/databrew/urls.py +++ b/moto/databrew/urls.py @@ -3,19 +3,37 @@ url_bases = [r"https?://databrew\.(.+)\.amazonaws.com"] url_paths = { - "{0}/recipeVersions$": DataBrewResponse().list_recipe_versions, + "{0}/recipeVersions$": DataBrewResponse.method_dispatch( + DataBrewResponse.list_recipe_versions + ), "{0}/recipes$": DataBrewResponse.dispatch, - "{0}/recipes/(?P[^/]+)$": DataBrewResponse().recipe_response, - "{0}/recipes/(?P[^/]+)/recipeVersion/(?P[^/]+)": DataBrewResponse().delete_recipe_version, - "{0}/recipes/(?P[^/]+)/publishRecipe$": DataBrewResponse().publish_recipe, + "{0}/recipes/(?P[^/]+)$": DataBrewResponse.method_dispatch( + DataBrewResponse.recipe_response + ), + "{0}/recipes/(?P[^/]+)/recipeVersion/(?P[^/]+)": DataBrewResponse.method_dispatch( + DataBrewResponse.delete_recipe_version + ), + "{0}/recipes/(?P[^/]+)/publishRecipe$": DataBrewResponse.method_dispatch( + DataBrewResponse.publish_recipe + ), "{0}/rulesets$": DataBrewResponse.dispatch, - "{0}/rulesets/(?P[^/]+)$": DataBrewResponse().ruleset_response, + "{0}/rulesets/(?P[^/]+)$": DataBrewResponse.method_dispatch( + DataBrewResponse.ruleset_response + ), "{0}/datasets$": DataBrewResponse.dispatch, - "{0}/datasets/(?P[^/]+)$": DataBrewResponse().dataset_response, - "{0}/jobs$": DataBrewResponse().list_jobs, - "{0}/jobs/(?P[^/]+)$": DataBrewResponse().job_response, + "{0}/datasets/(?P[^/]+)$": DataBrewResponse.method_dispatch( + DataBrewResponse.dataset_response + ), + "{0}/jobs$": DataBrewResponse.method_dispatch(DataBrewResponse.list_jobs), + "{0}/jobs/(?P[^/]+)$": DataBrewResponse.method_dispatch( + DataBrewResponse.job_response + ), "{0}/profileJobs$": DataBrewResponse.dispatch, "{0}/recipeJobs$": DataBrewResponse.dispatch, - "{0}/profileJobs/(?P[^/]+)$": DataBrewResponse().profile_job_response, - "{0}/recipeJobs/(?P[^/]+)$": DataBrewResponse().recipe_job_response, + "{0}/profileJobs/(?P[^/]+)$": DataBrewResponse.method_dispatch( + DataBrewResponse.profile_job_response + ), + "{0}/recipeJobs/(?P[^/]+)$": DataBrewResponse.method_dispatch( + DataBrewResponse.recipe_job_response + ), } diff --git a/moto/ebs/urls.py b/moto/ebs/urls.py index d2b59e511a1d..05bf5782b9b6 100644 --- a/moto/ebs/urls.py +++ b/moto/ebs/urls.py @@ -4,13 +4,18 @@ url_bases = [r"https?://ebs\.(.+)\.amazonaws\.com"] -response = EBSResponse() - - url_paths = { - "{0}/snapshots$": response.snapshots, - "{0}/snapshots/completion/(?P[^/]+)$": response.complete_snapshot, - "{0}/snapshots/(?P[^/]+)/changedblocks$": response.snapshot_changed_blocks, - "{0}/snapshots/(?P[^/]+)/blocks$": response.snapshot_blocks, - "{0}/snapshots/(?P[^/]+)/blocks/(?P[^/]+)$": response.snapshot_block, + "{0}/snapshots$": EBSResponse.method_dispatch(EBSResponse.snapshots), + "{0}/snapshots/completion/(?P[^/]+)$": EBSResponse.method_dispatch( + EBSResponse.complete_snapshot + ), + "{0}/snapshots/(?P[^/]+)/changedblocks$": EBSResponse.method_dispatch( + EBSResponse.snapshot_changed_blocks + ), + "{0}/snapshots/(?P[^/]+)/blocks$": EBSResponse.method_dispatch( + EBSResponse.snapshot_blocks + ), + "{0}/snapshots/(?P[^/]+)/blocks/(?P[^/]+)$": EBSResponse.method_dispatch( + EBSResponse.snapshot_block + ), } diff --git a/moto/elastictranscoder/urls.py b/moto/elastictranscoder/urls.py index e751dba4e81f..e6d5189e9ad2 100644 --- a/moto/elastictranscoder/urls.py +++ b/moto/elastictranscoder/urls.py @@ -5,10 +5,11 @@ ] -response = ElasticTranscoderResponse() - - url_paths = { - r"{0}/(?P[^/]+)/pipelines/?$": response.pipelines, - r"{0}/(?P[^/]+)/pipelines/(?P[^/]+)/?$": response.individual_pipeline, + r"{0}/(?P[^/]+)/pipelines/?$": ElasticTranscoderResponse.dispatch( + ElasticTranscoderResponse.pipelines + ), + r"{0}/(?P[^/]+)/pipelines/(?P[^/]+)/?$": ElasticTranscoderResponse.dispatch( + ElasticTranscoderResponse.individual_pipeline + ), } diff --git a/moto/glacier/urls.py b/moto/glacier/urls.py index 1c35c11409bf..64a47a8f3d0f 100644 --- a/moto/glacier/urls.py +++ b/moto/glacier/urls.py @@ -2,14 +2,26 @@ url_bases = [r"https?://glacier\.(.+)\.amazonaws.com"] -response = GlacierResponse() - url_paths = { - "{0}/(?P.+)/vaults$": response.all_vault_response, - "{0}/(?P.+)/vaults/(?P[^/]+)$": response.vault_response, - "{0}/(?P.+)/vaults/(?P.+)/archives$": response.vault_archive_response, - "{0}/(?P.+)/vaults/(?P.+)/archives/(?P.+)$": response.vault_archive_individual_response, - "{0}/(?P.+)/vaults/(?P.+)/jobs$": response.vault_jobs_response, - "{0}/(?P.+)/vaults/(?P.+)/jobs/(?P[^/.]+)$": response.vault_jobs_individual_response, - "{0}/(?P.+)/vaults/(?P.+)/jobs/(?P.+)/output$": response.vault_jobs_output_response, + "{0}/(?P.+)/vaults$": GlacierResponse.method_dispatch( + GlacierResponse.all_vault_response + ), + "{0}/(?P.+)/vaults/(?P[^/]+)$": GlacierResponse.method_dispatch( + GlacierResponse.vault_response + ), + "{0}/(?P.+)/vaults/(?P.+)/archives$": GlacierResponse.method_dispatch( + GlacierResponse.vault_archive_response + ), + "{0}/(?P.+)/vaults/(?P.+)/archives/(?P.+)$": GlacierResponse.method_dispatch( + GlacierResponse.vault_archive_individual_response + ), + "{0}/(?P.+)/vaults/(?P.+)/jobs$": GlacierResponse.method_dispatch( + GlacierResponse.vault_jobs_response + ), + "{0}/(?P.+)/vaults/(?P.+)/jobs/(?P[^/.]+)$": GlacierResponse.method_dispatch( + GlacierResponse.vault_jobs_individual_response + ), + "{0}/(?P.+)/vaults/(?P.+)/jobs/(?P.+)/output$": GlacierResponse.method_dispatch( + GlacierResponse.vault_jobs_output_response + ), } diff --git a/moto/greengrass/urls.py b/moto/greengrass/urls.py index 4ca910838978..70cbedf0d40b 100644 --- a/moto/greengrass/urls.py +++ b/moto/greengrass/urls.py @@ -4,35 +4,89 @@ r"https?://greengrass\.(.+)\.amazonaws.com", ] -response = GreengrassResponse() - url_paths = { - "{0}/greengrass/definition/cores$": response.core_definitions, - "{0}/greengrass/definition/cores/(?P[^/]+)/?$": response.core_definition, - "{0}/greengrass/definition/cores/(?P[^/]+)/versions$": response.core_definition_versions, - "{0}/greengrass/definition/cores/(?P[^/]+)/versions/(?P[^/]+)/?$": response.core_definition_version, - "{0}/greengrass/definition/devices$": response.device_definitions, - "{0}/greengrass/definition/devices/(?P[^/]+)/?$": response.device_definition, - "{0}/greengrass/definition/devices/(?P[^/]+)/versions$": response.device_definition_versions, - "{0}/greengrass/definition/devices/(?P[^/]+)/versions/(?P[^/]+)/?$": response.device_definition_version, - "{0}/greengrass/definition/functions$": response.function_definitions, - "{0}/greengrass/definition/functions/(?P[^/]+)/?$": response.function_definition, - "{0}/greengrass/definition/functions/(?P[^/]+)/versions$": response.function_definition_versions, - "{0}/greengrass/definition/functions/(?P[^/]+)/versions/(?P[^/]+)/?$": response.function_definition_version, - "{0}/greengrass/definition/resources$": response.resource_definitions, - "{0}/greengrass/definition/resources/(?P[^/]+)/?$": response.resource_definition, - "{0}/greengrass/definition/resources/(?P[^/]+)/versions$": response.resource_definition_versions, - "{0}/greengrass/definition/subscriptions$": response.subscription_definitions, - "{0}/greengrass/definition/subscriptions/(?P[^/]+)/?$": response.subscription_definition, - "{0}/greengrass/definition/subscriptions/(?P[^/]+)/versions$": response.subscription_definition_versions, - "{0}/greengrass/definition/subscriptions/(?P[^/]+)/versions/(?P[^/]+)/?$": response.subscription_definition_version, - "{0}/greengrass/definition/resources/(?P[^/]+)/versions/(?P[^/]+)/?$": response.resource_definition_version, - "{0}/greengrass/groups$": response.groups, - "{0}/greengrass/groups/(?P[^/]+)/?$": response.group, - "{0}/greengrass/groups/(?P[^/]+)/role$": response.role, - "{0}/greengrass/groups/(?P[^/]+)/versions$": response.group_versions, - "{0}/greengrass/groups/(?P[^/]+)/deployments$": response.deployments, - "{0}/greengrass/groups/(?P[^/]+)/deployments/\\$reset$": response.deployments_reset, - "{0}/greengrass/groups/(?P[^/]+)/deployments/(?P[^/]+)/status$": response.deployment_satus, - "{0}/greengrass/groups/(?P[^/]+)/versions/(?P[^/]+)/?$": response.group_version, + "{0}/greengrass/definition/cores$": GreengrassResponse.method_dispatch( + GreengrassResponse.core_definitions + ), + "{0}/greengrass/definition/cores/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.core_definition + ), + "{0}/greengrass/definition/cores/(?P[^/]+)/versions$": GreengrassResponse.method_dispatch( + GreengrassResponse.core_definition_versions + ), + "{0}/greengrass/definition/cores/(?P[^/]+)/versions/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.core_definition_version + ), + "{0}/greengrass/definition/devices$": GreengrassResponse.method_dispatch( + GreengrassResponse.device_definitions + ), + "{0}/greengrass/definition/devices/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.device_definition + ), + "{0}/greengrass/definition/devices/(?P[^/]+)/versions$": GreengrassResponse.method_dispatch( + GreengrassResponse.device_definition_versions + ), + "{0}/greengrass/definition/devices/(?P[^/]+)/versions/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.device_definition_version + ), + "{0}/greengrass/definition/functions$": GreengrassResponse.method_dispatch( + GreengrassResponse.function_definitions + ), + "{0}/greengrass/definition/functions/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.function_definition + ), + "{0}/greengrass/definition/functions/(?P[^/]+)/versions$": GreengrassResponse.method_dispatch( + GreengrassResponse.function_definition_versions + ), + "{0}/greengrass/definition/functions/(?P[^/]+)/versions/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.function_definition_version + ), + "{0}/greengrass/definition/resources$": GreengrassResponse.method_dispatch( + GreengrassResponse.resource_definitions + ), + "{0}/greengrass/definition/resources/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.resource_definition + ), + "{0}/greengrass/definition/resources/(?P[^/]+)/versions$": GreengrassResponse.method_dispatch( + GreengrassResponse.resource_definition_versions + ), + "{0}/greengrass/definition/subscriptions$": GreengrassResponse.method_dispatch( + GreengrassResponse.subscription_definitions + ), + "{0}/greengrass/definition/subscriptions/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.subscription_definition + ), + "{0}/greengrass/definition/subscriptions/(?P[^/]+)/versions$": GreengrassResponse.method_dispatch( + GreengrassResponse.subscription_definition_versions + ), + "{0}/greengrass/definition/subscriptions/(?P[^/]+)/versions/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.subscription_definition_version + ), + "{0}/greengrass/definition/resources/(?P[^/]+)/versions/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.resource_definition_version + ), + "{0}/greengrass/groups$": GreengrassResponse.method_dispatch( + GreengrassResponse.groups + ), + "{0}/greengrass/groups/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.group + ), + "{0}/greengrass/groups/(?P[^/]+)/role$": GreengrassResponse.method_dispatch( + GreengrassResponse.role + ), + "{0}/greengrass/groups/(?P[^/]+)/versions$": GreengrassResponse.method_dispatch( + GreengrassResponse.group_versions + ), + "{0}/greengrass/groups/(?P[^/]+)/deployments$": GreengrassResponse.method_dispatch( + GreengrassResponse.deployments + ), + "{0}/greengrass/groups/(?P[^/]+)/deployments/\\$reset$": GreengrassResponse.method_dispatch( + GreengrassResponse.deployments_reset + ), + "{0}/greengrass/groups/(?P[^/]+)/deployments/(?P[^/]+)/status$": GreengrassResponse.method_dispatch( + GreengrassResponse.deployment_satus + ), + "{0}/greengrass/groups/(?P[^/]+)/versions/(?P[^/]+)/?$": GreengrassResponse.method_dispatch( + GreengrassResponse.group_version + ), } diff --git a/moto/guardduty/urls.py b/moto/guardduty/urls.py index 2b11aa66ab00..bbe348dda74c 100644 --- a/moto/guardduty/urls.py +++ b/moto/guardduty/urls.py @@ -1,17 +1,25 @@ from .responses import GuardDutyResponse -response = GuardDutyResponse() - url_bases = [ "https?://guardduty\\.(.+)\\.amazonaws\\.com", ] url_paths = { - "{0}/detector$": response.detectors, - "{0}/detector/(?P[^/]+)$": response.detector, - "{0}/detector/(?P[^/]+)/filter$": response.filters, - "{0}/detector/(?P[^/]+)/filter/(?P[^/]+)$": response.filter, - "{0}/admin/enable$": response.enable_organization_admin_account, - "{0}/admin$": response.list_organization_admin_accounts, + "{0}/detector$": GuardDutyResponse.method_dispatch(GuardDutyResponse.detectors), + "{0}/detector/(?P[^/]+)$": GuardDutyResponse.method_dispatch( + GuardDutyResponse.detector + ), + "{0}/detector/(?P[^/]+)/filter$": GuardDutyResponse.method_dispatch( + GuardDutyResponse.filters + ), + "{0}/detector/(?P[^/]+)/filter/(?P[^/]+)$": GuardDutyResponse.method_dispatch( + GuardDutyResponse.filter + ), + "{0}/admin/enable$": GuardDutyResponse.method_dispatch( + GuardDutyResponse.enable_organization_admin_account + ), + "{0}/admin$": GuardDutyResponse.method_dispatch( + GuardDutyResponse.list_organization_admin_accounts + ), } diff --git a/moto/instance_metadata/urls.py b/moto/instance_metadata/urls.py index f495db731b9c..b8a5941211bd 100644 --- a/moto/instance_metadata/urls.py +++ b/moto/instance_metadata/urls.py @@ -2,6 +2,8 @@ url_bases = ["http://169.254.169.254"] -instance_metadata = InstanceMetadataResponse() - -url_paths = {"{0}/(?P.+)": instance_metadata.metadata_response} +url_paths = { + "{0}/(?P.+)": InstanceMetadataResponse.dispatch( + InstanceMetadataResponse.metadata_response + ) +} diff --git a/moto/iot/urls.py b/moto/iot/urls.py index 1425e28181dd..d8364ab1d98e 100644 --- a/moto/iot/urls.py +++ b/moto/iot/urls.py @@ -3,22 +3,23 @@ url_bases = [r"https?://iot\.(.+)\.amazonaws\.com"] -response = IoTResponse() - - url_paths = { # # Paths for :class:`moto.core.models.MockAWS` # # This route requires special handling. - "{0}/attached-policies/(?P.*)$": response.dispatch_attached_policies, + "{0}/attached-policies/(?P.*)$": IoTResponse.method_dispatch( + IoTResponse.dispatch_attached_policies + ), # The remaining routes can be handled by the default dispatcher. - "{0}/.*$": response.dispatch, + "{0}/.*$": IoTResponse.dispatch, # # (Flask) Paths for :class:`moto.core.models.ServerModeMockAWS` # # This route requires special handling. - "{0}/attached-policies/$": response.dispatch_attached_policies, + "{0}/attached-policies/$": IoTResponse.method_dispatch( + IoTResponse.dispatch_attached_policies + ), # The remaining routes can be handled by the default dispatcher. - "{0}/$": response.dispatch, + "{0}/$": IoTResponse.dispatch, } diff --git a/moto/managedblockchain/urls.py b/moto/managedblockchain/urls.py index 685ab0de01dc..f3f54c134981 100644 --- a/moto/managedblockchain/urls.py +++ b/moto/managedblockchain/urls.py @@ -3,19 +3,47 @@ url_bases = [r"https?://managedblockchain\.(.+)\.amazonaws.com"] url_paths = { - "{0}/networks$": ManagedBlockchainResponse().network_response, - "{0}/networks/(?P[^/.]+)$": ManagedBlockchainResponse().networkid_response, - "{0}/networks/(?P[^/.]+)/proposals$": ManagedBlockchainResponse().proposal_response, - "{0}/networks/(?P[^/.]+)/proposals/(?P[^/.]+)$": ManagedBlockchainResponse().proposalid_response, - "{0}/networks/(?P[^/.]+)/proposals/(?P[^/.]+)/votes$": ManagedBlockchainResponse().proposal_votes_response, - "{0}/invitations$": ManagedBlockchainResponse().invitation_response, - "{0}/invitations/(?P[^/.]+)$": ManagedBlockchainResponse().invitationid_response, - "{0}/networks/(?P[^/.]+)/members$": ManagedBlockchainResponse().member_response, - "{0}/networks/(?P[^/.]+)/members/(?P[^/.]+)$": ManagedBlockchainResponse().memberid_response, - "{0}/networks/(?P[^/.]+)/members/(?P[^/.]+)/nodes$": ManagedBlockchainResponse().node_response, - "{0}/networks/(?P[^/.]+)/members/(?P[^/.]+)/nodes?(?P[^/.]+)$": ManagedBlockchainResponse().node_response, - "{0}/networks/(?P[^/.]+)/members/(?P[^/.]+)/nodes/(?P[^/.]+)$": ManagedBlockchainResponse().nodeid_response, + "{0}/networks$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.network_response + ), + "{0}/networks/(?P[^/.]+)$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.networkid_response + ), + "{0}/networks/(?P[^/.]+)/proposals$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.proposal_response + ), + "{0}/networks/(?P[^/.]+)/proposals/(?P[^/.]+)$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.proposalid_response + ), + "{0}/networks/(?P[^/.]+)/proposals/(?P[^/.]+)/votes$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.proposal_votes_response + ), + "{0}/invitations$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.invitation_response + ), + "{0}/invitations/(?P[^/.]+)$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.invitationid_response + ), + "{0}/networks/(?P[^/.]+)/members$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.member_response + ), + "{0}/networks/(?P[^/.]+)/members/(?P[^/.]+)$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.memberid_response + ), + "{0}/networks/(?P[^/.]+)/members/(?P[^/.]+)/nodes$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.node_response + ), + "{0}/networks/(?P[^/.]+)/members/(?P[^/.]+)/nodes?(?P[^/.]+)$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.node_response + ), + "{0}/networks/(?P[^/.]+)/members/(?P[^/.]+)/nodes/(?P[^/.]+)$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.nodeid_response + ), # >= botocore 1.19.41 (API change - memberId is now part of query-string or body) - "{0}/networks/(?P[^/.]+)/nodes$": ManagedBlockchainResponse().node_response, - "{0}/networks/(?P[^/.]+)/nodes/(?P[^/.]+)$": ManagedBlockchainResponse().nodeid_response, + "{0}/networks/(?P[^/.]+)/nodes$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.node_response + ), + "{0}/networks/(?P[^/.]+)/nodes/(?P[^/.]+)$": ManagedBlockchainResponse.method_dispatch( + ManagedBlockchainResponse.nodeid_response + ), } diff --git a/moto/mq/urls.py b/moto/mq/urls.py index 26cc6cd8de95..df059e42f4ae 100644 --- a/moto/mq/urls.py +++ b/moto/mq/urls.py @@ -6,17 +6,26 @@ ] -response = MQResponse() - - url_paths = { - "{0}/v1/brokers/(?P[^/]+)$": response.broker, - "{0}/v1/brokers/(?P[^/]+)/reboot$": response.reboot, - "{0}/v1/brokers/(?P[^/]+)/users$": response.users, - "{0}/v1/brokers/(?P[^/]+)/users/(?P[^/]+)$": response.user, - "{0}/v1/brokers$": response.brokers, - "{0}/v1/configurations$": response.configurations, - "{0}/v1/configurations/(?P[^/]+)$": response.configuration, - "{0}/v1/configurations/(?P[^/]+)/revisions/(?P[^/]+)$": response.configuration_revision, - "{0}/v1/tags/(?P[^/]+)$": response.tags, + "{0}/v1/brokers/(?P[^/]+)$": MQResponse.method_dispatch( + MQResponse.broker + ), + "{0}/v1/brokers/(?P[^/]+)/reboot$": MQResponse.method_dispatch( + MQResponse.reboot + ), + "{0}/v1/brokers/(?P[^/]+)/users$": MQResponse.method_dispatch( + MQResponse.users + ), + "{0}/v1/brokers/(?P[^/]+)/users/(?P[^/]+)$": MQResponse.method_dispatch( + MQResponse.user + ), + "{0}/v1/brokers$": MQResponse.method_dispatch(MQResponse.brokers), + "{0}/v1/configurations$": MQResponse.method_dispatch(MQResponse.configurations), + "{0}/v1/configurations/(?P[^/]+)$": MQResponse.method_dispatch( + MQResponse.configuration + ), + "{0}/v1/configurations/(?P[^/]+)/revisions/(?P[^/]+)$": MQResponse.method_dispatch( + MQResponse.configuration_revision + ), + "{0}/v1/tags/(?P[^/]+)$": MQResponse.method_dispatch(MQResponse.tags), } diff --git a/moto/pinpoint/urls.py b/moto/pinpoint/urls.py index 9051ffd51dcb..9d92093f84d5 100644 --- a/moto/pinpoint/urls.py +++ b/moto/pinpoint/urls.py @@ -6,14 +6,21 @@ ] -response = PinpointResponse() - - url_paths = { - "{0}/v1/apps$": response.apps, - "{0}/v1/apps/(?P[^/]+)$": response.app, - "{0}/v1/apps/(?P[^/]+)/eventstream": response.eventstream, - "{0}/v1/apps/(?P[^/]+)/settings$": response.app_settings, - "{0}/v1/tags/(?P[^/]+)$": response.tags, - "{0}/v1/tags/(?P[^/]+)/(?P[^/]+)$": response.tags, + "{0}/v1/apps$": PinpointResponse.method_dispatch(PinpointResponse.apps), + "{0}/v1/apps/(?P[^/]+)$": PinpointResponse.method_dispatch( + PinpointResponse.app + ), + "{0}/v1/apps/(?P[^/]+)/eventstream": PinpointResponse.method_dispatch( + PinpointResponse.eventstream + ), + "{0}/v1/apps/(?P[^/]+)/settings$": PinpointResponse.method_dispatch( + PinpointResponse.app_settings + ), + "{0}/v1/tags/(?P[^/]+)$": PinpointResponse.method_dispatch( + PinpointResponse.tags + ), + "{0}/v1/tags/(?P[^/]+)/(?P[^/]+)$": PinpointResponse.method_dispatch( + PinpointResponse.tags + ), } diff --git a/moto/quicksight/urls.py b/moto/quicksight/urls.py index ad2d5b45b862..35b0c81931da 100644 --- a/moto/quicksight/urls.py +++ b/moto/quicksight/urls.py @@ -6,16 +6,29 @@ ] -response = QuickSightResponse() - - url_paths = { - r"{0}/accounts/(?P[\d]+)/data-sets$": response.dataset, - r"{0}/accounts/(?P[\d]+)/data-sets/(?P[^/.]+)/ingestions/(?P[^/.]+)$": response.ingestion, - r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/groups$": response.groups, - r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/groups/(?P[^/]+)$": response.group, - r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/groups/(?P[^/]+)/members$": response.group_members, - r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/groups/(?P[^/]+)/members/(?P[^/]+)$": response.group_member, - r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/users$": response.users, - r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/users/(?P[^/]+)$": response.user, + r"{0}/accounts/(?P[\d]+)/data-sets$": QuickSightResponse.method_dispatch( + QuickSightResponse.dataset + ), + r"{0}/accounts/(?P[\d]+)/data-sets/(?P[^/.]+)/ingestions/(?P[^/.]+)$": QuickSightResponse.method_dispatch( + QuickSightResponse.ingestion + ), + r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/groups$": QuickSightResponse.method_dispatch( + QuickSightResponse.groups + ), + r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/groups/(?P[^/]+)$": QuickSightResponse.method_dispatch( + QuickSightResponse.group + ), + r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/groups/(?P[^/]+)/members$": QuickSightResponse.method_dispatch( + QuickSightResponse.group_members + ), + r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/groups/(?P[^/]+)/members/(?P[^/]+)$": QuickSightResponse.method_dispatch( + QuickSightResponse.group_member + ), + r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/users$": QuickSightResponse.method_dispatch( + QuickSightResponse.users + ), + r"{0}/accounts/(?P[\d]+)/namespaces/(?P[a-zA-Z0-9._-]+)/users/(?P[^/]+)$": QuickSightResponse.method_dispatch( + QuickSightResponse.user + ), } diff --git a/moto/route53/urls.py b/moto/route53/urls.py index ba33771f72c6..ef8b11a44ce0 100644 --- a/moto/route53/urls.py +++ b/moto/route53/urls.py @@ -19,26 +19,66 @@ def tag_response2(request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: url_paths = { - r"{0}/(?P[\d_-]+)/hostedzone$": Route53().list_or_create_hostzone_response, - r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)$": Route53().get_or_delete_hostzone_response, - r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/rrset$": Route53().rrset_response, - r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/rrset/$": Route53().rrset_response, - r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/dnssec$": Route53().get_dnssec_response, - r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/dnssec/$": Route53().get_dnssec_response, - r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/associatevpc/?$": Route53().associate_vpc_response, - r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/disassociatevpc/?$": Route53().disassociate_vpc_response, - r"{0}/(?P[\d_-]+)/hostedzonesbyname": Route53().list_hosted_zones_by_name_response, - r"{0}/(?P[\d_-]+)/hostedzonesbyvpc": Route53().list_hosted_zones_by_vpc_response, - r"{0}/(?P[\d_-]+)/hostedzonecount": Route53().get_hosted_zone_count_response, - r"{0}/(?P[\d_-]+)/healthcheck$": Route53().health_check_response1, - r"{0}/(?P[\d_-]+)/healthcheck/(?P[^/]+)$": Route53().health_check_response2, - r"{0}/(?P[\d_-]+)/healthcheck/(?P[^/]+)/status$": Route53().health_check_status_response, + r"{0}/(?P[\d_-]+)/hostedzone$": Route53.method_dispatch( + Route53.list_or_create_hostzone_response + ), + r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)$": Route53.method_dispatch( + Route53.get_or_delete_hostzone_response + ), + r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/rrset$": Route53.method_dispatch( + Route53.rrset_response + ), + r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/rrset/$": Route53.method_dispatch( + Route53.rrset_response + ), + r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/dnssec$": Route53.method_dispatch( + Route53.get_dnssec_response + ), + r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/dnssec/$": Route53.method_dispatch( + Route53.get_dnssec_response + ), + r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/associatevpc/?$": Route53.method_dispatch( + Route53.associate_vpc_response + ), + r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/disassociatevpc/?$": Route53.method_dispatch( + Route53.disassociate_vpc_response + ), + r"{0}/(?P[\d_-]+)/hostedzonesbyname": Route53.method_dispatch( + Route53.list_hosted_zones_by_name_response + ), + r"{0}/(?P[\d_-]+)/hostedzonesbyvpc": Route53.method_dispatch( + Route53.list_hosted_zones_by_vpc_response + ), + r"{0}/(?P[\d_-]+)/hostedzonecount": Route53.method_dispatch( + Route53.get_hosted_zone_count_response + ), + r"{0}/(?P[\d_-]+)/healthcheck$": Route53.method_dispatch( + Route53.health_check_response1 + ), + r"{0}/(?P[\d_-]+)/healthcheck/(?P[^/]+)$": Route53.method_dispatch( + Route53.health_check_response2 + ), + r"{0}/(?P[\d_-]+)/healthcheck/(?P[^/]+)/status$": Route53.method_dispatch( + Route53.health_check_status_response + ), r"{0}/(?P[\d_-]+)/tags/healthcheck/(?P[^/]+)$": tag_response1, r"{0}/(?P[\d_-]+)/tags/hostedzone/(?P[^/]+)$": tag_response2, - r"{0}/(?P[\d_-]+)/trafficpolicyinstances/*": Route53().not_implemented_response, - r"{0}/(?P[\d_-]+)/change/(?P[^/]+)$": Route53().get_change, - r"{0}/(?P[\d_-]+)/queryloggingconfig$": Route53().list_or_create_query_logging_config_response, - r"{0}/(?P[\d_-]+)/queryloggingconfig/(?P[^/]+)$": Route53().get_or_delete_query_logging_config_response, - r"{0}/(?P[\d_-]+)/delegationset$": Route53().reusable_delegation_sets, - r"{0}/(?P[\d_-]+)/delegationset/(?P[^/]+)$": Route53().reusable_delegation_set, + r"{0}/(?P[\d_-]+)/trafficpolicyinstances/*": Route53.method_dispatch( + Route53.not_implemented_response + ), + r"{0}/(?P[\d_-]+)/change/(?P[^/]+)$": Route53.method_dispatch( + Route53.get_change + ), + r"{0}/(?P[\d_-]+)/queryloggingconfig$": Route53.method_dispatch( + Route53.list_or_create_query_logging_config_response + ), + r"{0}/(?P[\d_-]+)/queryloggingconfig/(?P[^/]+)$": Route53.method_dispatch( + Route53.get_or_delete_query_logging_config_response + ), + r"{0}/(?P[\d_-]+)/delegationset$": Route53.method_dispatch( + Route53.reusable_delegation_sets + ), + r"{0}/(?P[\d_-]+)/delegationset/(?P[^/]+)$": Route53.method_dispatch( + Route53.reusable_delegation_set + ), } diff --git a/moto/s3/urls.py b/moto/s3/urls.py index 52fe69d504fb..572572020cdb 100644 --- a/moto/s3/urls.py +++ b/moto/s3/urls.py @@ -1,6 +1,6 @@ from moto import settings -from .responses import S3ResponseInstance +from .responses import S3Response # Catch s3.amazonaws.com, but not s3-control.amazonaws.com url_bases = [ @@ -12,12 +12,18 @@ url_paths = { # subdomain bucket - "{0}/$": S3ResponseInstance.bucket_response, + "{0}/$": S3Response.method_dispatch(S3Response.bucket_response), # subdomain key of path-based bucket - "{0}/(?P[^/]+)$": S3ResponseInstance.ambiguous_response, - "{0}/(?P[^/]+)/$": S3ResponseInstance.ambiguous_response, + "{0}/(?P[^/]+)$": S3Response.method_dispatch( + S3Response.ambiguous_response + ), + "{0}/(?P[^/]+)/$": S3Response.method_dispatch( + S3Response.ambiguous_response + ), # path-based bucket + key - "{0}/(?P[^/]+)/(?P.+)": S3ResponseInstance.key_response, + "{0}/(?P[^/]+)/(?P.+)": S3Response.method_dispatch( + S3Response.key_response + ), # subdomain bucket + key with empty first part of path - "{0}/(?P/.*)$": S3ResponseInstance.key_response, + "{0}/(?P/.*)$": S3Response.method_dispatch(S3Response.key_response), } diff --git a/moto/s3control/responses.py b/moto/s3control/responses.py index 57c314e6474b..2e1713e19612 100644 --- a/moto/s3control/responses.py +++ b/moto/s3control/responses.py @@ -155,9 +155,6 @@ def _get_accountid_and_name_from_policy(self, full_url: str) -> Tuple[str, str]: return account_id, name -S3ControlResponseInstance = S3ControlResponse() - - CREATE_ACCESS_POINT_TEMPLATE = """ 1549581b-12b7-11e3-895e-1334aEXAMPLE diff --git a/moto/s3control/urls.py b/moto/s3control/urls.py index 66029b9cb439..4d1c10d288db 100644 --- a/moto/s3control/urls.py +++ b/moto/s3control/urls.py @@ -1,5 +1,5 @@ """s3control base URL and path.""" -from .responses import S3ControlResponseInstance +from .responses import S3ControlResponse url_bases = [ r"https?://([0-9]+)\.s3-control\.(.+)\.amazonaws\.com", @@ -7,8 +7,16 @@ url_paths = { - r"{0}/v20180820/configuration/publicAccessBlock$": S3ControlResponseInstance.public_access_block, - r"{0}/v20180820/accesspoint/(?P[\w_:%-]+)$": S3ControlResponseInstance.access_point, - r"{0}/v20180820/accesspoint/(?P[\w_:%-]+)/policy$": S3ControlResponseInstance.access_point_policy, - r"{0}/v20180820/accesspoint/(?P[\w_:%-]+)/policyStatus$": S3ControlResponseInstance.access_point_policy_status, + r"{0}/v20180820/configuration/publicAccessBlock$": S3ControlResponse.method_dispatch( + S3ControlResponse.public_access_block + ), + r"{0}/v20180820/accesspoint/(?P[\w_:%-]+)$": S3ControlResponse.method_dispatch( + S3ControlResponse.access_point + ), + r"{0}/v20180820/accesspoint/(?P[\w_:%-]+)/policy$": S3ControlResponse.method_dispatch( + S3ControlResponse.access_point_policy + ), + r"{0}/v20180820/accesspoint/(?P[\w_:%-]+)/policyStatus$": S3ControlResponse.method_dispatch( + S3ControlResponse.access_point_policy_status + ), } diff --git a/moto/scheduler/urls.py b/moto/scheduler/urls.py index ddd71fa77c28..3cc3c435b45c 100644 --- a/moto/scheduler/urls.py +++ b/moto/scheduler/urls.py @@ -6,14 +6,15 @@ ] -response = EventBridgeSchedulerResponse() - - url_paths = { - "{0}/schedules$": response.dispatch, - "{0}/schedules/(?P[^/]+)$": response.dispatch, - "{0}/schedule-groups$": response.dispatch, - "{0}/schedule-groups/(?P[^/]+)$": response.dispatch, - "{0}/tags/(?P.+)$": response.tags, - "{0}/tags/arn:aws:scheduler:(?P[^/]+):(?P[^/]+):schedule/(?P[^/]+)/(?P[^/]+)/?$": response.tags, + "{0}/schedules$": EventBridgeSchedulerResponse.dispatch, + "{0}/schedules/(?P[^/]+)$": EventBridgeSchedulerResponse.dispatch, + "{0}/schedule-groups$": EventBridgeSchedulerResponse.dispatch, + "{0}/schedule-groups/(?P[^/]+)$": EventBridgeSchedulerResponse.dispatch, + "{0}/tags/(?P.+)$": EventBridgeSchedulerResponse.method_dispatch( + EventBridgeSchedulerResponse.tags + ), + "{0}/tags/arn:aws:scheduler:(?P[^/]+):(?P[^/]+):schedule/(?P[^/]+)/(?P[^/]+)/?$": EventBridgeSchedulerResponse.method_dispatch( + EventBridgeSchedulerResponse.tags + ), } diff --git a/tests/test_s3/test_s3_file_handles.py b/tests/test_s3/test_s3_file_handles.py index bd601b82b740..edc5e8a6c502 100644 --- a/tests/test_s3/test_s3_file_handles.py +++ b/tests/test_s3/test_s3_file_handles.py @@ -6,7 +6,7 @@ from moto import settings, mock_s3 from moto.dynamodb.models import DynamoDBBackend from moto.s3 import models as s3model, s3_backends -from moto.s3.responses import S3ResponseInstance +from moto.s3.responses import S3Response from unittest import SkipTest, TestCase from tests import DEFAULT_ACCOUNT_ID @@ -173,7 +173,7 @@ def test_completing_part_upload(self): ).etag mp_body = f"""{etag}1""" - body = S3ResponseInstance._complete_multipart_body(mp_body) + body = S3Response()._complete_multipart_body(mp_body) self.s3.complete_multipart_upload( bucket_name=TEST_BUCKET, multipart_id=multipart_id, body=body ) From 5c9900c8046b28404ce4acd98d6fa56a5556b1ea Mon Sep 17 00:00:00 2001 From: Daniel Fangl Date: Thu, 31 Aug 2023 10:44:44 +0200 Subject: [PATCH 2/5] fix typing errors --- moto/amp/urls.py | 4 ++-- moto/appconfig/urls.py | 4 ++-- moto/managedblockchain/exceptions.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/moto/amp/urls.py b/moto/amp/urls.py index 97f51f12a9e2..7968707e81df 100644 --- a/moto/amp/urls.py +++ b/moto/amp/urls.py @@ -15,9 +15,9 @@ "{0}/workspaces/(?P[^/]+)/rulegroupsnamespaces/(?P[^/]+)$": PrometheusServiceResponse.dispatch, "{0}/tags/(?P[^/]+)$": PrometheusServiceResponse.dispatch, "{0}/tags/(?P[^/]+)/(?P[^/]+)$": PrometheusServiceResponse.method_dispatch( - PrometheusServiceResponse.tags + PrometheusServiceResponse.tags # type: ignore ), "{0}/tags/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)$": PrometheusServiceResponse.method_dispatch( - PrometheusServiceResponse.tags + PrometheusServiceResponse.tags # type: ignore ), } diff --git a/moto/appconfig/urls.py b/moto/appconfig/urls.py index 257fc4f36950..b1a9c1662c14 100644 --- a/moto/appconfig/urls.py +++ b/moto/appconfig/urls.py @@ -15,9 +15,9 @@ "{0}/applications/(?P[^/]+)/configurationprofiles/(?P[^/]+)/hostedconfigurationversions/(?P[^/]+)$": AppConfigResponse.dispatch, "{0}/tags/(?P.+)$": AppConfigResponse.dispatch, "{0}/tags/(?P[^/]+)/(?P[^/]+)$": AppConfigResponse.method_dispatch( - AppConfigResponse.tags + AppConfigResponse.tags # type: ignore ), "{0}/tags/(?P[^/]+)/(?P[^/]+)/configurationprofile/(?P[^/]+)$": AppConfigResponse.method_dispatch( - AppConfigResponse.tags + AppConfigResponse.tags # type: ignore ), } diff --git a/moto/managedblockchain/exceptions.py b/moto/managedblockchain/exceptions.py index 8b1beb8488f1..494080c76589 100644 --- a/moto/managedblockchain/exceptions.py +++ b/moto/managedblockchain/exceptions.py @@ -6,8 +6,8 @@ def exception_handler( - f: Callable[[Any, Any, Any, Any], TYPE_RESPONSE] -) -> Callable[[Any], TYPE_RESPONSE]: + f: Callable[[Any, Any, str, Any], TYPE_RESPONSE] +) -> Callable[[Any, Any, str, Any], TYPE_RESPONSE]: @wraps(f) def _wrapper(*args: Any, **kwargs: Any) -> TYPE_RESPONSE: # type: ignore[misc] try: From 58cd704165a752d77d39da9760ebc919c5abb986 Mon Sep 17 00:00:00 2001 From: Daniel Fangl Date: Thu, 31 Aug 2023 11:48:15 +0200 Subject: [PATCH 3/5] fix wrong refactoring --- moto/cognitoidp/urls.py | 2 +- moto/elastictranscoder/urls.py | 4 ++-- moto/instance_metadata/urls.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/moto/cognitoidp/urls.py b/moto/cognitoidp/urls.py index f2f4e288bf02..a08831178cb1 100644 --- a/moto/cognitoidp/urls.py +++ b/moto/cognitoidp/urls.py @@ -4,7 +4,7 @@ url_paths = { "{0}/$": CognitoIdpResponse.dispatch, - "{0}/(?P[^/]+)/.well-known/jwks.json$": CognitoIdpJsonWebKeyResponse.dispatch( + "{0}/(?P[^/]+)/.well-known/jwks.json$": CognitoIdpJsonWebKeyResponse.method_dispatch( CognitoIdpJsonWebKeyResponse.serve_json_web_key ), } diff --git a/moto/elastictranscoder/urls.py b/moto/elastictranscoder/urls.py index e6d5189e9ad2..5c5bcf837d1b 100644 --- a/moto/elastictranscoder/urls.py +++ b/moto/elastictranscoder/urls.py @@ -6,10 +6,10 @@ url_paths = { - r"{0}/(?P[^/]+)/pipelines/?$": ElasticTranscoderResponse.dispatch( + r"{0}/(?P[^/]+)/pipelines/?$": ElasticTranscoderResponse.method_dispatch( ElasticTranscoderResponse.pipelines ), - r"{0}/(?P[^/]+)/pipelines/(?P[^/]+)/?$": ElasticTranscoderResponse.dispatch( + r"{0}/(?P[^/]+)/pipelines/(?P[^/]+)/?$": ElasticTranscoderResponse.method_dispatch( ElasticTranscoderResponse.individual_pipeline ), } diff --git a/moto/instance_metadata/urls.py b/moto/instance_metadata/urls.py index b8a5941211bd..a16ed94c7629 100644 --- a/moto/instance_metadata/urls.py +++ b/moto/instance_metadata/urls.py @@ -3,7 +3,7 @@ url_bases = ["http://169.254.169.254"] url_paths = { - "{0}/(?P.+)": InstanceMetadataResponse.dispatch( + "{0}/(?P.+)": InstanceMetadataResponse.method_dispatch( InstanceMetadataResponse.metadata_response ) } From 14a98433b461ed99e35318ae31dbbff8a7a80b09 Mon Sep 17 00:00:00 2001 From: Daniel Fangl Date: Thu, 31 Aug 2023 13:00:22 +0200 Subject: [PATCH 4/5] fix dispatching test --- moto/core/responses.py | 1 + moto/glacier/responses.py | 1 + tests/test_core/test_server.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/moto/core/responses.py b/moto/core/responses.py index f1be50ee01f4..d2fd3acf211c 100644 --- a/moto/core/responses.py +++ b/moto/core/responses.py @@ -246,6 +246,7 @@ def method_dispatch( # type: ignore[misc] :return: A wrapper executing the given method on a new instance of this class """ + @functools.wraps(to_call) def _inner(request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: return getattr(cls(), to_call.__name__)(request, full_url, headers) diff --git a/moto/glacier/responses.py b/moto/glacier/responses.py index 1909e09b90e9..ceaf27328151 100644 --- a/moto/glacier/responses.py +++ b/moto/glacier/responses.py @@ -62,6 +62,7 @@ def _vault_response_delete(self, vault_name: str, headers: Any) -> TYPE_RESPONSE def vault_archive_response( self, request: Any, full_url: str, headers: Any ) -> TYPE_RESPONSE: + self.setup_class(request, full_url, headers, use_raw_body=True) return self._vault_archive_response(request, full_url, headers) def _vault_archive_response( diff --git a/tests/test_core/test_server.py b/tests/test_core/test_server.py index 2abeee91fa7c..cf25afc1cb31 100644 --- a/tests/test_core/test_server.py +++ b/tests/test_core/test_server.py @@ -43,4 +43,4 @@ def test_domain_dispatched_with_service(): dispatcher = DomainDispatcherApplication(create_backend_app, service="s3") backend_app = dispatcher.get_application({"HTTP_HOST": "s3.us-east1.amazonaws.com"}) keys = set(backend_app.view_functions.keys()) - assert "S3Response.key_response" in keys + assert "moto.s3.responses.key_response" in keys From d8aea6fa6d5a5e25774256e270dc1aa0f5f41b31 Mon Sep 17 00:00:00 2001 From: Daniel Fangl Date: Thu, 31 Aug 2023 13:17:54 +0200 Subject: [PATCH 5/5] ignore mypy complaining about Any type --- moto/core/responses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moto/core/responses.py b/moto/core/responses.py index d2fd3acf211c..4e6be92a1995 100644 --- a/moto/core/responses.py +++ b/moto/core/responses.py @@ -246,7 +246,7 @@ def method_dispatch( # type: ignore[misc] :return: A wrapper executing the given method on a new instance of this class """ - @functools.wraps(to_call) + @functools.wraps(to_call) # type: ignore def _inner(request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: return getattr(cls(), to_call.__name__)(request, full_url, headers)