TechDebt: Enable MyPy on APIGateway-module (#5549)

This commit is contained in:
Bert Blommers 2022-10-11 13:16:27 +00:00 committed by GitHub
parent d60aa64abb
commit 56ca48cfdd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 718 additions and 622 deletions

View File

@ -49,7 +49,7 @@
## apigateway ## apigateway
<details> <details>
<summary>65% implemented</summary> <summary>62% implemented</summary>
- [X] create_api_key - [X] create_api_key
- [X] create_authorizer - [X] create_authorizer
@ -157,12 +157,12 @@
- [ ] update_deployment - [ ] update_deployment
- [ ] update_documentation_part - [ ] update_documentation_part
- [ ] update_documentation_version - [ ] update_documentation_version
- [X] update_domain_name - [ ] update_domain_name
- [ ] update_gateway_response - [ ] update_gateway_response
- [ ] update_integration - [ ] update_integration
- [ ] update_integration_response - [ ] update_integration_response
- [X] update_method - [ ] update_method
- [X] update_method_response - [ ] update_method_response
- [ ] update_model - [ ] update_model
- [X] update_request_validator - [X] update_request_validator
- [ ] update_resource - [ ] update_resource

View File

@ -28,7 +28,7 @@ lint:
@echo "Running pylint..." @echo "Running pylint..."
pylint -j 0 moto tests pylint -j 0 moto tests
@echo "Running MyPy..." @echo "Running MyPy..."
mypy --install-types --non-interactive moto/acm moto/amp moto/applicationautoscaling/ mypy --install-types --non-interactive
format: format:
black moto/ tests/ black moto/ tests/

View File

@ -149,12 +149,12 @@ apigateway
- [ ] update_deployment - [ ] update_deployment
- [ ] update_documentation_part - [ ] update_documentation_part
- [ ] update_documentation_version - [ ] update_documentation_version
- [X] update_domain_name - [ ] update_domain_name
- [ ] update_gateway_response - [ ] update_gateway_response
- [ ] update_integration - [ ] update_integration
- [ ] update_integration_response - [ ] update_integration_response
- [X] update_method - [ ] update_method
- [X] update_method_response - [ ] update_method_response
- [ ] update_model - [ ] update_model
- [X] update_request_validator - [X] update_request_validator
- [ ] update_resource - [ ] update_resource

View File

@ -1,4 +1,5 @@
from moto.core.exceptions import JsonRESTError from moto.core.exceptions import JsonRESTError
from typing import Any
class ApiGatewayException(JsonRESTError): class ApiGatewayException(JsonRESTError):
@ -6,12 +7,12 @@ class ApiGatewayException(JsonRESTError):
class BadRequestException(ApiGatewayException): class BadRequestException(ApiGatewayException):
def __init__(self, message): def __init__(self, message: str):
super().__init__("BadRequestException", message) super().__init__("BadRequestException", message)
class NotFoundException(ApiGatewayException): class NotFoundException(ApiGatewayException):
def __init__(self, message): def __init__(self, message: str):
super().__init__("NotFoundException", message) super().__init__("NotFoundException", message)
@ -22,199 +23,199 @@ class AccessDeniedException(ApiGatewayException):
class ConflictException(ApiGatewayException): class ConflictException(ApiGatewayException):
code = 409 code = 409
def __init__(self, message): def __init__(self, message: str):
super().__init__("ConflictException", message) super().__init__("ConflictException", message)
class AwsProxyNotAllowed(BadRequestException): class AwsProxyNotAllowed(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__( super().__init__(
"Integrations of type 'AWS_PROXY' currently only supports Lambda function and Firehose stream invocations." "Integrations of type 'AWS_PROXY' currently only supports Lambda function and Firehose stream invocations."
) )
class CrossAccountNotAllowed(AccessDeniedException): class CrossAccountNotAllowed(AccessDeniedException):
def __init__(self): def __init__(self) -> None:
super().__init__( super().__init__(
"AccessDeniedException", "Cross-account pass role is not allowed." "AccessDeniedException", "Cross-account pass role is not allowed."
) )
class RoleNotSpecified(BadRequestException): class RoleNotSpecified(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__("Role ARN must be specified for AWS integrations") super().__init__("Role ARN must be specified for AWS integrations")
class IntegrationMethodNotDefined(BadRequestException): class IntegrationMethodNotDefined(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__("Enumeration value for HttpMethod must be non-empty") super().__init__("Enumeration value for HttpMethod must be non-empty")
class InvalidOpenAPIDocumentException(BadRequestException): class InvalidOpenAPIDocumentException(BadRequestException):
def __init__(self, cause): def __init__(self, cause: Any):
super().__init__( super().__init__(
f"Failed to parse the uploaded OpenAPI document due to: {cause.message}" f"Failed to parse the uploaded OpenAPI document due to: {cause.message}"
) )
class InvalidOpenApiDocVersionException(BadRequestException): class InvalidOpenApiDocVersionException(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__("Only OpenAPI 3.x.x are currently supported") super().__init__("Only OpenAPI 3.x.x are currently supported")
class InvalidOpenApiModeException(BadRequestException): class InvalidOpenApiModeException(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__( super().__init__(
'Enumeration value of OpenAPI import mode must be "overwrite" or "merge"', 'Enumeration value of OpenAPI import mode must be "overwrite" or "merge"',
) )
class InvalidResourcePathException(BadRequestException): class InvalidResourcePathException(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__( super().__init__(
"Resource's path part only allow a-zA-Z0-9._- and curly braces at the beginning and the end and an optional plus sign before the closing brace." "Resource's path part only allow a-zA-Z0-9._- and curly braces at the beginning and the end and an optional plus sign before the closing brace."
) )
class InvalidHttpEndpoint(BadRequestException): class InvalidHttpEndpoint(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid HTTP endpoint specified for URI") super().__init__("Invalid HTTP endpoint specified for URI")
class InvalidArn(BadRequestException): class InvalidArn(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid ARN specified in the request") super().__init__("Invalid ARN specified in the request")
class InvalidIntegrationArn(BadRequestException): class InvalidIntegrationArn(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__("AWS ARN for integration must contain path or action") super().__init__("AWS ARN for integration must contain path or action")
class InvalidRequestInput(BadRequestException): class InvalidRequestInput(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid request input") super().__init__("Invalid request input")
class NoIntegrationDefined(NotFoundException): class NoIntegrationDefined(NotFoundException):
def __init__(self): def __init__(self) -> None:
super().__init__("No integration defined for method") super().__init__("No integration defined for method")
class NoIntegrationResponseDefined(NotFoundException): class NoIntegrationResponseDefined(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid Response status code specified") super().__init__("Invalid Response status code specified")
class NoMethodDefined(BadRequestException): class NoMethodDefined(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__("The REST API doesn't contain any methods") super().__init__("The REST API doesn't contain any methods")
class AuthorizerNotFoundException(NotFoundException): class AuthorizerNotFoundException(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid Authorizer identifier specified") super().__init__("Invalid Authorizer identifier specified")
class StageNotFoundException(NotFoundException): class StageNotFoundException(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid stage identifier specified") super().__init__("Invalid stage identifier specified")
class ApiKeyNotFoundException(NotFoundException): class ApiKeyNotFoundException(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid API Key identifier specified") super().__init__("Invalid API Key identifier specified")
class UsagePlanNotFoundException(NotFoundException): class UsagePlanNotFoundException(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid Usage Plan ID specified") super().__init__("Invalid Usage Plan ID specified")
class ApiKeyAlreadyExists(ApiGatewayException): class ApiKeyAlreadyExists(ApiGatewayException):
code = 409 code = 409
def __init__(self): def __init__(self) -> None:
super().__init__("ConflictException", "API Key already exists") super().__init__("ConflictException", "API Key already exists")
class InvalidDomainName(BadRequestException): class InvalidDomainName(BadRequestException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("No Domain Name specified") super().__init__("No Domain Name specified")
class DomainNameNotFound(NotFoundException): class DomainNameNotFound(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid domain name identifier specified") super().__init__("Invalid domain name identifier specified")
class InvalidRestApiId(BadRequestException): class InvalidRestApiId(BadRequestException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("No Rest API Id specified") super().__init__("No Rest API Id specified")
class InvalidModelName(BadRequestException): class InvalidModelName(BadRequestException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("No Model Name specified") super().__init__("No Model Name specified")
class RestAPINotFound(NotFoundException): class RestAPINotFound(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid Rest API Id specified") super().__init__("Invalid Rest API Id specified")
class RequestValidatorNotFound(BadRequestException): class RequestValidatorNotFound(BadRequestException):
code = 400 code = 400
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid Request Validator Id specified") super().__init__("Invalid Request Validator Id specified")
class ModelNotFound(NotFoundException): class ModelNotFound(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid Model Name specified") super().__init__("Invalid Model Name specified")
class ApiKeyValueMinLength(BadRequestException): class ApiKeyValueMinLength(BadRequestException):
code = 400 code = 400
def __init__(self): def __init__(self) -> None:
super().__init__("API Key value should be at least 20 characters") super().__init__("API Key value should be at least 20 characters")
class MethodNotFoundException(NotFoundException): class MethodNotFoundException(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid Method identifier specified") super().__init__("Invalid Method identifier specified")
class InvalidBasePathException(BadRequestException): class InvalidBasePathException(BadRequestException):
code = 400 code = 400
def __init__(self): def __init__(self) -> None:
super().__init__( super().__init__(
"API Gateway V1 doesn't support the slash character (/) in base path mappings. " "API Gateway V1 doesn't support the slash character (/) in base path mappings. "
"To create a multi-level base path mapping, use API Gateway V2." "To create a multi-level base path mapping, use API Gateway V2."
@ -222,64 +223,64 @@ class InvalidBasePathException(BadRequestException):
class DeploymentNotFoundException(NotFoundException): class DeploymentNotFoundException(NotFoundException):
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid Deployment identifier specified") super().__init__("Invalid Deployment identifier specified")
class InvalidRestApiIdForBasePathMappingException(BadRequestException): class InvalidRestApiIdForBasePathMappingException(BadRequestException):
code = 400 code = 400
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid REST API identifier specified") super().__init__("Invalid REST API identifier specified")
class InvalidStageException(BadRequestException): class InvalidStageException(BadRequestException):
code = 400 code = 400
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid stage identifier specified") super().__init__("Invalid stage identifier specified")
class BasePathConflictException(ConflictException): class BasePathConflictException(ConflictException):
def __init__(self): def __init__(self) -> None:
super().__init__("Base path already exists for this domain name") super().__init__("Base path already exists for this domain name")
class BasePathNotFoundException(NotFoundException): class BasePathNotFoundException(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid base path mapping identifier specified") super().__init__("Invalid base path mapping identifier specified")
class ResourceIdNotFoundException(NotFoundException): class ResourceIdNotFoundException(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("Invalid resource identifier specified") super().__init__("Invalid resource identifier specified")
class VpcLinkNotFound(NotFoundException): class VpcLinkNotFound(NotFoundException):
code = 404 code = 404
def __init__(self): def __init__(self) -> None:
super().__init__("VPCLink not found") super().__init__("VPCLink not found")
class ValidationException(ApiGatewayException): class ValidationException(ApiGatewayException):
code = 400 code = 400
def __init__(self, message): def __init__(self, message: str):
super().__init__("ValidationException", message) super().__init__("ValidationException", message)
class StageStillActive(BadRequestException): class StageStillActive(BadRequestException):
def __init__(self): def __init__(self) -> None:
super().__init__( super().__init__(
"Active stages pointing to this deployment must be moved or deleted" "Active stages pointing to this deployment must be moved or deleted"
) )
class GatewayResponseNotFound(NotFoundException): class GatewayResponseNotFound(NotFoundException):
def __init__(self): def __init__(self) -> None:
super().__init__("GatewayResponse not found") super().__init__("GatewayResponse not found")

View File

@ -1,7 +1,12 @@
import abc import abc
from typing import Tuple, Union
from requests.models import PreparedRequest
from ..models import Integration
class IntegrationParser: class IntegrationParser:
@abc.abstractmethod @abc.abstractmethod
def invoke(self, request, integration): def invoke(
self, request: PreparedRequest, integration: Integration
) -> Tuple[int, Union[str, bytes]]:
pass pass

View File

@ -1,10 +1,14 @@
import requests import requests
from . import IntegrationParser from . import IntegrationParser
from ..models import Integration
from typing import Tuple, Union
class TypeAwsParser(IntegrationParser): class TypeAwsParser(IntegrationParser):
def invoke(self, request, integration): def invoke(
self, request: requests.PreparedRequest, integration: Integration
) -> Tuple[int, Union[str, bytes]]:
# integration.uri = arn:aws:apigateway:{region}:{subdomain.service|service}:path|action/{service_api} # integration.uri = arn:aws:apigateway:{region}:{subdomain.service|service}:path|action/{service_api}
# example value = 'arn:aws:apigateway:us-west-2:dynamodb:action/PutItem' # example value = 'arn:aws:apigateway:us-west-2:dynamodb:action/PutItem'
try: try:

View File

@ -1,6 +1,8 @@
import requests import requests
from typing import Tuple, Union
from . import IntegrationParser from . import IntegrationParser
from ..models import Integration
class TypeHttpParser(IntegrationParser): class TypeHttpParser(IntegrationParser):
@ -8,7 +10,9 @@ class TypeHttpParser(IntegrationParser):
Parse invocations to a APIGateway resource with integration type HTTP Parse invocations to a APIGateway resource with integration type HTTP
""" """
def invoke(self, request, integration): def invoke(
self, request: requests.PreparedRequest, integration: Integration
) -> Tuple[int, Union[str, bytes]]:
uri = integration["uri"] uri = integration["uri"]
requests_func = getattr(requests, integration["httpMethod"].lower()) requests_func = getattr(requests, integration["httpMethod"].lower())
response = requests_func(uri) response = requests_func(uri)

View File

@ -1,4 +1,7 @@
import requests
from typing import Tuple, Union
from . import IntegrationParser from . import IntegrationParser
from ..models import Integration
class TypeUnknownParser(IntegrationParser): class TypeUnknownParser(IntegrationParser):
@ -6,6 +9,8 @@ class TypeUnknownParser(IntegrationParser):
Parse invocations to a APIGateway resource with an unknown integration type Parse invocations to a APIGateway resource with an unknown integration type
""" """
def invoke(self, request, integration): def invoke(
self, request: requests.PreparedRequest, integration: Integration
) -> Tuple[int, Union[str, bytes]]:
_type = integration["type"] _type = integration["type"]
raise NotImplementedError("The {0} type has not been implemented".format(_type)) raise NotImplementedError("The {0} type has not been implemented".format(_type))

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,10 @@
import json import json
from typing import Any, Dict, List, Tuple
from urllib.parse import unquote from urllib.parse import unquote
from moto.utilities.utils import merge_multiple_dicts from moto.utilities.utils import merge_multiple_dicts
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import apigateway_backends from .models import apigateway_backends, APIGatewayBackend
from .utils import deserialize_body from .utils import deserialize_body
from .exceptions import InvalidRequestInput from .exceptions import InvalidRequestInput
@ -11,21 +12,23 @@ API_KEY_SOURCES = ["AUTHORIZER", "HEADER"]
AUTHORIZER_TYPES = ["TOKEN", "REQUEST", "COGNITO_USER_POOLS"] AUTHORIZER_TYPES = ["TOKEN", "REQUEST", "COGNITO_USER_POOLS"]
ENDPOINT_CONFIGURATION_TYPES = ["PRIVATE", "EDGE", "REGIONAL"] ENDPOINT_CONFIGURATION_TYPES = ["PRIVATE", "EDGE", "REGIONAL"]
RESPONSE_TYPE = Tuple[int, Dict[str, str], str]
class APIGatewayResponse(BaseResponse): class APIGatewayResponse(BaseResponse):
def __init__(self): def __init__(self) -> None:
super().__init__(service_name="apigateway") super().__init__(service_name="apigateway")
def error(self, type_, message, status=400): def error(self, type_: str, message: str, status: int = 400) -> RESPONSE_TYPE:
headers = self.response_headers or {} headers = self.response_headers or {}
headers["X-Amzn-Errortype"] = type_ headers["X-Amzn-Errortype"] = type_
return (status, headers, json.dumps({"__type": type_, "message": message})) return (status, headers, json.dumps({"__type": type_, "message": message}))
@property @property
def backend(self): def backend(self) -> APIGatewayBackend:
return apigateway_backends[self.current_account][self.region] return apigateway_backends[self.current_account][self.region]
def __validate_api_key_source(self, api_key_source): def __validate_api_key_source(self, api_key_source: str) -> RESPONSE_TYPE: # type: ignore[return]
if api_key_source and api_key_source not in API_KEY_SOURCES: if api_key_source and api_key_source not in API_KEY_SOURCES:
return self.error( return self.error(
"ValidationException", "ValidationException",
@ -37,7 +40,7 @@ class APIGatewayResponse(BaseResponse):
).format(api_key_source=api_key_source), ).format(api_key_source=api_key_source),
) )
def __validate_endpoint_configuration(self, endpoint_configuration): def __validate_endpoint_configuration(self, endpoint_configuration: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
if endpoint_configuration and "types" in endpoint_configuration: if endpoint_configuration and "types" in endpoint_configuration:
invalid_types = list( invalid_types = list(
set(endpoint_configuration["types"]) - set(ENDPOINT_CONFIGURATION_TYPES) set(endpoint_configuration["types"]) - set(ENDPOINT_CONFIGURATION_TYPES)
@ -53,7 +56,7 @@ class APIGatewayResponse(BaseResponse):
).format(endpoint_type=invalid_types[0]), ).format(endpoint_type=invalid_types[0]),
) )
def restapis(self, request, full_url, headers): def restapis(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
if self.method == "GET": if self.method == "GET":
@ -62,7 +65,7 @@ class APIGatewayResponse(BaseResponse):
elif self.method == "POST": elif self.method == "POST":
api_doc = deserialize_body(self.body) api_doc = deserialize_body(self.body)
if api_doc: if api_doc:
fail_on_warnings = self._get_bool_param("failonwarnings") fail_on_warnings = self._get_bool_param("failonwarnings") or False
rest_api = self.backend.import_rest_api(api_doc, fail_on_warnings) rest_api = self.backend.import_rest_api(api_doc, fail_on_warnings)
return 200, {}, json.dumps(rest_api.to_dict()) return 200, {}, json.dumps(rest_api.to_dict())
@ -97,14 +100,16 @@ class APIGatewayResponse(BaseResponse):
return 200, {}, json.dumps(rest_api.to_dict()) return 200, {}, json.dumps(rest_api.to_dict())
def __validte_rest_patch_operations(self, patch_operations): def __validte_rest_patch_operations(self, patch_operations: List[Dict[str, str]]) -> RESPONSE_TYPE: # type: ignore[return]
for op in patch_operations: for op in patch_operations:
path = op["path"] path = op["path"]
if "apiKeySource" in path: if "apiKeySource" in path:
value = op["value"] value = op["value"]
return self.__validate_api_key_source(value) return self.__validate_api_key_source(value)
def restapis_individual(self, request, full_url, headers): def restapis_individual(
self, request: Any, full_url: str, headers: Dict[str, str]
) -> RESPONSE_TYPE:
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
function_id = self.path.replace("/restapis/", "", 1).split("/")[0] function_id = self.path.replace("/restapis/", "", 1).split("/")[0]
@ -114,12 +119,12 @@ class APIGatewayResponse(BaseResponse):
rest_api = self.backend.delete_rest_api(function_id) rest_api = self.backend.delete_rest_api(function_id)
elif self.method == "PUT": elif self.method == "PUT":
mode = self._get_param("mode", "merge") mode = self._get_param("mode", "merge")
fail_on_warnings = self._get_bool_param("failonwarnings", False) fail_on_warnings = self._get_bool_param("failonwarnings") or False
api_doc = deserialize_body(self.body) api_doc = deserialize_body(self.body)
rest_api = self.backend.put_rest_api( rest_api = self.backend.put_rest_api(
function_id, api_doc, mode, fail_on_warnings function_id, api_doc, mode=mode, fail_on_warnings=fail_on_warnings
) )
elif self.method == "PATCH": elif self.method == "PATCH":
patch_operations = self._get_param("patchOperations") patch_operations = self._get_param("patchOperations")
@ -130,7 +135,7 @@ class APIGatewayResponse(BaseResponse):
return 200, {}, json.dumps(rest_api.to_dict()) return 200, {}, json.dumps(rest_api.to_dict())
def resources(self, request, full_url, headers): def resources(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
function_id = self.path.replace("/restapis/", "", 1).split("/")[0] function_id = self.path.replace("/restapis/", "", 1).split("/")[0]
@ -142,7 +147,7 @@ class APIGatewayResponse(BaseResponse):
json.dumps({"item": [resource.to_dict() for resource in resources]}), json.dumps({"item": [resource.to_dict() for resource in resources]}),
) )
def gateway_response(self, request, full_url, headers): def gateway_response(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
if request.method == "PUT": if request.method == "PUT":
return self.put_gateway_response() return self.put_gateway_response()
@ -151,12 +156,12 @@ class APIGatewayResponse(BaseResponse):
elif request.method == "DELETE": elif request.method == "DELETE":
return self.delete_gateway_response() return self.delete_gateway_response()
def gateway_responses(self, request, full_url, headers): def gateway_responses(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
if request.method == "GET": if request.method == "GET":
return self.get_gateway_responses() return self.get_gateway_responses()
def resource_individual(self, request, full_url, headers): def resource_individual(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
function_id = self.path.replace("/restapis/", "", 1).split("/")[0] function_id = self.path.replace("/restapis/", "", 1).split("/")[0]
resource_id = self.path.split("/")[-1] resource_id = self.path.split("/")[-1]
@ -172,7 +177,9 @@ class APIGatewayResponse(BaseResponse):
resource = self.backend.delete_resource(function_id, resource_id) resource = self.backend.delete_resource(function_id, resource_id)
return 202, {}, json.dumps(resource.to_dict()) return 202, {}, json.dumps(resource.to_dict())
def resource_methods(self, request, full_url, headers): def resource_methods(
self, request: Any, full_url: str, headers: Dict[str, str]
) -> RESPONSE_TYPE:
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
function_id = url_path_parts[2] function_id = url_path_parts[2]
@ -210,15 +217,11 @@ class APIGatewayResponse(BaseResponse):
self.backend.delete_method(function_id, resource_id, method_type) self.backend.delete_method(function_id, resource_id, method_type)
return 204, {}, "" return 204, {}, ""
elif self.method == "PATCH":
patch_operations = self._get_param("patchOperations")
self.backend.update_method(
function_id, resource_id, method_type, patch_operations
)
return 200, {}, "" return 200, {}, ""
def resource_method_responses(self, request, full_url, headers): def resource_method_responses(
self, request: Any, full_url: str, headers: Dict[str, str]
) -> RESPONSE_TYPE:
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
function_id = url_path_parts[2] function_id = url_path_parts[2]
@ -248,15 +251,9 @@ class APIGatewayResponse(BaseResponse):
function_id, resource_id, method_type, response_code function_id, resource_id, method_type, response_code
) )
return 204, {}, json.dumps(method_response) return 204, {}, json.dumps(method_response)
elif self.method == "PATCH":
patch_operations = self._get_param("patchOperations")
method_response = self.backend.update_method_response(
function_id, resource_id, method_type, response_code, patch_operations
)
return 201, {}, json.dumps(method_response)
raise Exception('Unexpected HTTP method "%s"' % self.method) raise Exception('Unexpected HTTP method "%s"' % self.method)
def restapis_authorizers(self, request, full_url, headers): def restapis_authorizers(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
restapi_id = url_path_parts[2] restapi_id = url_path_parts[2]
@ -306,7 +303,7 @@ class APIGatewayResponse(BaseResponse):
authorizers = self.backend.get_authorizers(restapi_id) authorizers = self.backend.get_authorizers(restapi_id)
return 200, {}, json.dumps({"item": authorizers}) return 200, {}, json.dumps({"item": authorizers})
def request_validators(self, request, full_url, headers): def request_validators(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
restapi_id = url_path_parts[2] restapi_id = url_path_parts[2]
@ -326,7 +323,7 @@ class APIGatewayResponse(BaseResponse):
) )
return 201, {}, json.dumps(validator) return 201, {}, json.dumps(validator)
def request_validator_individual(self, request, full_url, headers): def request_validator_individual(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
restapi_id = url_path_parts[2] restapi_id = url_path_parts[2]
@ -345,7 +342,7 @@ class APIGatewayResponse(BaseResponse):
) )
return 200, {}, json.dumps(validator) return 200, {}, json.dumps(validator)
def authorizers(self, request, full_url, headers): def authorizers(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
restapi_id = url_path_parts[2] restapi_id = url_path_parts[2]
@ -364,7 +361,7 @@ class APIGatewayResponse(BaseResponse):
self.backend.delete_authorizer(restapi_id, authorizer_id) self.backend.delete_authorizer(restapi_id, authorizer_id)
return 202, {}, "{}" return 202, {}, "{}"
def restapis_stages(self, request, full_url, headers): def restapis_stages(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
function_id = url_path_parts[2] function_id = url_path_parts[2]
@ -395,7 +392,7 @@ class APIGatewayResponse(BaseResponse):
stages = self.backend.get_stages(function_id) stages = self.backend.get_stages(function_id)
return 200, {}, json.dumps({"item": stages}) return 200, {}, json.dumps({"item": stages})
def restapis_stages_tags(self, request, full_url, headers): def restapis_stages_tags(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
function_id = url_path_parts[4] function_id = url_path_parts[4]
@ -408,12 +405,12 @@ class APIGatewayResponse(BaseResponse):
return 200, {}, json.dumps({"item": tags}) return 200, {}, json.dumps({"item": tags})
if self.method == "DELETE": if self.method == "DELETE":
stage = self.backend.get_stage(function_id, stage_name) stage = self.backend.get_stage(function_id, stage_name)
for tag in stage.get("tags").copy(): for tag in stage.get("tags", {}).copy():
if tag in self.querystring.get("tagKeys"): if tag in (self.querystring.get("tagKeys") or {}):
stage["tags"].pop(tag, None) stage["tags"].pop(tag, None)
return 200, {}, json.dumps({"item": ""}) return 200, {}, json.dumps({"item": ""})
def stages(self, request, full_url, headers): def stages(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
function_id = url_path_parts[2] function_id = url_path_parts[2]
@ -432,15 +429,13 @@ class APIGatewayResponse(BaseResponse):
self.backend.delete_stage(function_id, stage_name) self.backend.delete_stage(function_id, stage_name)
return 202, {}, "{}" return 202, {}, "{}"
def integrations(self, request, full_url, headers): def integrations(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
function_id = url_path_parts[2] function_id = url_path_parts[2]
resource_id = url_path_parts[4] resource_id = url_path_parts[4]
method_type = url_path_parts[6] method_type = url_path_parts[6]
integration_response = {}
if self.method == "GET": if self.method == "GET":
integration_response = self.backend.get_integration( integration_response = self.backend.get_integration(
function_id, resource_id, method_type function_id, resource_id, method_type
@ -484,7 +479,7 @@ class APIGatewayResponse(BaseResponse):
) )
return 204, {}, json.dumps(integration_response) return 204, {}, json.dumps(integration_response)
def integration_responses(self, request, full_url, headers): def integration_responses(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
function_id = url_path_parts[2] function_id = url_path_parts[2]
@ -520,7 +515,7 @@ class APIGatewayResponse(BaseResponse):
) )
return 204, {}, json.dumps(integration_response) return 204, {}, json.dumps(integration_response)
def deployments(self, request, full_url, headers): def deployments(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
function_id = self.path.replace("/restapis/", "", 1).split("/")[0] function_id = self.path.replace("/restapis/", "", 1).split("/")[0]
@ -536,7 +531,7 @@ class APIGatewayResponse(BaseResponse):
) )
return 201, {}, json.dumps(deployment) return 201, {}, json.dumps(deployment)
def individual_deployment(self, request, full_url, headers): def individual_deployment(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
function_id = url_path_parts[2] function_id = url_path_parts[2]
@ -549,7 +544,7 @@ class APIGatewayResponse(BaseResponse):
deployment = self.backend.delete_deployment(function_id, deployment_id) deployment = self.backend.delete_deployment(function_id, deployment_id)
return 202, {}, json.dumps(deployment) return 202, {}, json.dumps(deployment)
def apikeys(self, request, full_url, headers): def apikeys(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
if self.method == "POST": if self.method == "POST":
@ -557,19 +552,20 @@ class APIGatewayResponse(BaseResponse):
return 201, {}, json.dumps(apikey_response) return 201, {}, json.dumps(apikey_response)
elif self.method == "GET": elif self.method == "GET":
include_values = self._get_bool_param("includeValues") include_values = self._get_bool_param("includeValues") or False
apikeys_response = self.backend.get_api_keys(include_values=include_values) apikeys_response = self.backend.get_api_keys(include_values=include_values)
return 200, {}, json.dumps({"item": apikeys_response}) return 200, {}, json.dumps({"item": apikeys_response})
def apikey_individual(self, request, full_url, headers): def apikey_individual(
self, request: Any, full_url: str, headers: Dict[str, str]
) -> RESPONSE_TYPE:
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
apikey = url_path_parts[2] apikey = url_path_parts[2]
status_code = 200
if self.method == "GET": if self.method == "GET":
include_value = self._get_bool_param("includeValue") include_value = self._get_bool_param("includeValue") or False
apikey_response = self.backend.get_api_key( apikey_response = self.backend.get_api_key(
apikey, include_value=include_value apikey, include_value=include_value
) )
@ -577,12 +573,12 @@ class APIGatewayResponse(BaseResponse):
patch_operations = self._get_param("patchOperations") patch_operations = self._get_param("patchOperations")
apikey_response = self.backend.update_api_key(apikey, patch_operations) apikey_response = self.backend.update_api_key(apikey, patch_operations)
elif self.method == "DELETE": elif self.method == "DELETE":
apikey_response = self.backend.delete_api_key(apikey) self.backend.delete_api_key(apikey)
status_code = 202 return 202, {}, "{}"
return status_code, {}, json.dumps(apikey_response) return 200, {}, json.dumps(apikey_response)
def usage_plans(self, request, full_url, headers): def usage_plans(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
if self.method == "POST": if self.method == "POST":
usage_plan_response = self.backend.create_usage_plan(json.loads(self.body)) usage_plan_response = self.backend.create_usage_plan(json.loads(self.body))
@ -592,7 +588,7 @@ class APIGatewayResponse(BaseResponse):
usage_plans_response = self.backend.get_usage_plans(api_key_id=api_key_id) usage_plans_response = self.backend.get_usage_plans(api_key_id=api_key_id)
return 200, {}, json.dumps({"item": usage_plans_response}) return 200, {}, json.dumps({"item": usage_plans_response})
def usage_plan_individual(self, request, full_url, headers): def usage_plan_individual(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
@ -602,8 +598,8 @@ class APIGatewayResponse(BaseResponse):
usage_plan_response = self.backend.get_usage_plan(usage_plan) usage_plan_response = self.backend.get_usage_plan(usage_plan)
return 200, {}, json.dumps(usage_plan_response) return 200, {}, json.dumps(usage_plan_response)
elif self.method == "DELETE": elif self.method == "DELETE":
usage_plan_response = self.backend.delete_usage_plan(usage_plan) self.backend.delete_usage_plan(usage_plan)
return 202, {}, json.dumps(usage_plan_response) return 202, {}, "{}"
elif self.method == "PATCH": elif self.method == "PATCH":
patch_operations = self._get_param("patchOperations") patch_operations = self._get_param("patchOperations")
usage_plan_response = self.backend.update_usage_plan( usage_plan_response = self.backend.update_usage_plan(
@ -611,7 +607,7 @@ class APIGatewayResponse(BaseResponse):
) )
return 200, {}, json.dumps(usage_plan_response) return 200, {}, json.dumps(usage_plan_response)
def usage_plan_keys(self, request, full_url, headers): def usage_plan_keys(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
@ -626,7 +622,7 @@ class APIGatewayResponse(BaseResponse):
usage_plans_response = self.backend.get_usage_plan_keys(usage_plan_id) usage_plans_response = self.backend.get_usage_plan_keys(usage_plan_id)
return 200, {}, json.dumps({"item": usage_plans_response}) return 200, {}, json.dumps({"item": usage_plans_response})
def usage_plan_key_individual(self, request, full_url, headers): def usage_plan_key_individual(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
@ -637,12 +633,10 @@ class APIGatewayResponse(BaseResponse):
usage_plan_response = self.backend.get_usage_plan_key(usage_plan_id, key_id) usage_plan_response = self.backend.get_usage_plan_key(usage_plan_id, key_id)
return 200, {}, json.dumps(usage_plan_response) return 200, {}, json.dumps(usage_plan_response)
elif self.method == "DELETE": elif self.method == "DELETE":
usage_plan_response = self.backend.delete_usage_plan_key( self.backend.delete_usage_plan_key(usage_plan_id, key_id)
usage_plan_id, key_id return 202, {}, "{}"
)
return 202, {}, json.dumps(usage_plan_response)
def domain_names(self, request, full_url, headers): def domain_names(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
if self.method == "GET": if self.method == "GET":
@ -661,7 +655,6 @@ class APIGatewayResponse(BaseResponse):
regional_certificate_arn = self._get_param("regionalCertificateArn") regional_certificate_arn = self._get_param("regionalCertificateArn")
endpoint_configuration = self._get_param("endpointConfiguration") endpoint_configuration = self._get_param("endpointConfiguration")
security_policy = self._get_param("securityPolicy") security_policy = self._get_param("securityPolicy")
generate_cli_skeleton = self._get_param("generateCliSkeleton")
domain_name_resp = self.backend.create_domain_name( domain_name_resp = self.backend.create_domain_name(
domain_name, domain_name,
certificate_name, certificate_name,
@ -674,35 +667,31 @@ class APIGatewayResponse(BaseResponse):
regional_certificate_arn, regional_certificate_arn,
endpoint_configuration, endpoint_configuration,
security_policy, security_policy,
generate_cli_skeleton,
) )
return 201, {}, json.dumps(domain_name_resp) return 201, {}, json.dumps(domain_name_resp)
def domain_name_induvidual(self, request, full_url, headers): def domain_name_induvidual(
self, request: Any, full_url: str, headers: Dict[str, str]
) -> RESPONSE_TYPE:
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
domain_name = url_path_parts[2] domain_name = url_path_parts[2]
domain_names = {}
if self.method == "GET": if self.method == "GET":
if domain_name is not None: if domain_name is not None:
domain_names = self.backend.get_domain_name(domain_name) domain_names = self.backend.get_domain_name(domain_name)
return 200, {}, json.dumps(domain_names) return 200, {}, json.dumps(domain_names)
return 200, {}, "{}"
elif self.method == "DELETE": elif self.method == "DELETE":
if domain_name is not None: if domain_name is not None:
self.backend.delete_domain_name(domain_name) self.backend.delete_domain_name(domain_name)
return 202, {}, json.dumps({}) return 202, {}, json.dumps({})
elif self.method == "PATCH":
if domain_name is not None:
patch_operations = self._get_param("patchOperations")
self.backend.update_domain_name(domain_name, patch_operations)
return 200, {}, json.dumps(domain_name)
else: else:
msg = 'Method "%s" for API GW domain names not implemented' % self.method msg = 'Method "%s" for API GW domain names not implemented' % self.method
return 404, {}, json.dumps({"error": msg}) return 404, {}, json.dumps({"error": msg})
def models(self, request, full_url, headers): def models(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
rest_api_id = self.path.replace("/restapis/", "", 1).split("/")[0] rest_api_id = self.path.replace("/restapis/", "", 1).split("/")[0]
@ -715,30 +704,29 @@ class APIGatewayResponse(BaseResponse):
description = self._get_param("description") description = self._get_param("description")
schema = self._get_param("schema") schema = self._get_param("schema")
content_type = self._get_param("contentType") content_type = self._get_param("contentType")
cli_input_json = self._get_param("cliInputJson")
generate_cli_skeleton = self._get_param("generateCliSkeleton")
model = self.backend.create_model( model = self.backend.create_model(
rest_api_id, rest_api_id,
name, name,
content_type, content_type,
description, description,
schema, schema,
cli_input_json,
generate_cli_skeleton,
) )
return 201, {}, json.dumps(model) return 201, {}, json.dumps(model)
def model_induvidual(self, request, full_url, headers): def model_induvidual(
self, request: Any, full_url: str, headers: Dict[str, str]
) -> RESPONSE_TYPE:
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
rest_api_id = url_path_parts[2] rest_api_id = url_path_parts[2]
model_name = url_path_parts[4] model_name = url_path_parts[4]
model_info = {}
if self.method == "GET": if self.method == "GET":
model_info = self.backend.get_model(rest_api_id, model_name) model_info = self.backend.get_model(rest_api_id, model_name)
return 200, {}, json.dumps(model_info) return 200, {}, json.dumps(model_info)
return 200, {}, "{}"
def base_path_mappings(self, request, full_url, headers): def base_path_mappings(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
@ -757,7 +745,7 @@ class APIGatewayResponse(BaseResponse):
) )
return 201, {}, json.dumps(base_path_mapping_resp) return 201, {}, json.dumps(base_path_mapping_resp)
def base_path_mapping_individual(self, request, full_url, headers): def base_path_mapping_individual(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
@ -780,7 +768,7 @@ class APIGatewayResponse(BaseResponse):
) )
return 200, {}, json.dumps(base_path_mapping) return 200, {}, json.dumps(base_path_mapping)
def vpc_link(self, request, full_url, headers): def vpc_link(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
url_path_parts = self.path.split("/") url_path_parts = self.path.split("/")
vpc_link_id = url_path_parts[-1] vpc_link_id = url_path_parts[-1]
@ -792,7 +780,7 @@ class APIGatewayResponse(BaseResponse):
vpc_link = self.backend.get_vpc_link(vpc_link_id=vpc_link_id) vpc_link = self.backend.get_vpc_link(vpc_link_id=vpc_link_id)
return 200, {}, json.dumps(vpc_link) return 200, {}, json.dumps(vpc_link)
def vpc_links(self, request, full_url, headers): def vpc_links(self, request: Any, full_url: str, headers: Dict[str, str]) -> RESPONSE_TYPE: # type: ignore[return]
self.setup_class(request, full_url, headers) self.setup_class(request, full_url, headers)
if self.method == "GET": if self.method == "GET":
@ -808,7 +796,7 @@ class APIGatewayResponse(BaseResponse):
) )
return 202, {}, json.dumps(vpc_link) return 202, {}, json.dumps(vpc_link)
def put_gateway_response(self): def put_gateway_response(self) -> RESPONSE_TYPE:
rest_api_id = self.path.split("/")[-3] rest_api_id = self.path.split("/")[-3]
response_type = self.path.split("/")[-1] response_type = self.path.split("/")[-1]
params = json.loads(self.body) params = json.loads(self.body)
@ -824,7 +812,7 @@ class APIGatewayResponse(BaseResponse):
) )
return 201, {}, json.dumps(response) return 201, {}, json.dumps(response)
def get_gateway_response(self): def get_gateway_response(self) -> RESPONSE_TYPE:
rest_api_id = self.path.split("/")[-3] rest_api_id = self.path.split("/")[-3]
response_type = self.path.split("/")[-1] response_type = self.path.split("/")[-1]
response = self.backend.get_gateway_response( response = self.backend.get_gateway_response(
@ -832,12 +820,12 @@ class APIGatewayResponse(BaseResponse):
) )
return 200, {}, json.dumps(response) return 200, {}, json.dumps(response)
def get_gateway_responses(self): def get_gateway_responses(self) -> RESPONSE_TYPE:
rest_api_id = self.path.split("/")[-2] rest_api_id = self.path.split("/")[-2]
responses = self.backend.get_gateway_responses(rest_api_id=rest_api_id) responses = self.backend.get_gateway_responses(rest_api_id=rest_api_id)
return 200, {}, json.dumps(dict(item=responses)) return 200, {}, json.dumps(dict(item=responses))
def delete_gateway_response(self): def delete_gateway_response(self) -> RESPONSE_TYPE:
rest_api_id = self.path.split("/")[-3] rest_api_id = self.path.split("/")[-3]
response_type = self.path.split("/")[-1] response_type = self.path.split("/")[-1]
self.backend.delete_gateway_response( self.backend.delete_gateway_response(

View File

@ -2,15 +2,16 @@ import string
import json import json
import yaml import yaml
from moto.moto_api._internal import mock_random as random from moto.moto_api._internal import mock_random as random
from typing import Any, Dict
def create_id(): def create_id() -> str:
size = 10 size = 10
chars = list(range(10)) + list(string.ascii_lowercase) chars = list(range(10)) + list(string.ascii_lowercase)
return "".join(str(random.choice(chars)) for x in range(size)) return "".join(str(random.choice(chars)) for x in range(size))
def deserialize_body(body): def deserialize_body(body: str) -> Dict[str, Any]:
try: try:
api_doc = json.loads(body) api_doc = json.loads(body)
except json.JSONDecodeError: except json.JSONDecodeError:
@ -19,8 +20,8 @@ def deserialize_body(body):
if "openapi" in api_doc or "swagger" in api_doc: if "openapi" in api_doc or "swagger" in api_doc:
return api_doc return api_doc
return None return {}
def to_path(prop): def to_path(prop: str) -> str:
return "/" + prop return "/" + prop

View File

@ -29,7 +29,7 @@ class CloudFormationModel(BaseModel):
@classmethod @classmethod
@abstractmethod @abstractmethod
def has_cfn_attr(cls, attr): def has_cfn_attr(cls, attr): # pylint: disable=unused-argument
# Used for validation # Used for validation
# If a template creates an Output for an attribute that does not exist, an error should be thrown # If a template creates an Output for an attribute that does not exist, an error should be thrown
return True return True

View File

@ -186,7 +186,7 @@ def unix_time_millis(dt=None):
return unix_time(dt) * 1000.0 return unix_time(dt) * 1000.0
def path_url(url): def path_url(url: str) -> str:
parsed_url = urlparse(url) parsed_url = urlparse(url)
path = parsed_url.path path = parsed_url.path
if not path: if not path:

View File

@ -2,8 +2,8 @@ import json
import hashlib import hashlib
import pkgutil import pkgutil
from collections.abc import MutableMapping from collections.abc import MutableMapping
from typing import Any, Dict
def str2bool(v): def str2bool(v):
@ -23,7 +23,7 @@ def load_resource(package, resource, as_json=True):
return json.loads(resource) if as_json else resource.decode("utf-8") return json.loads(resource) if as_json else resource.decode("utf-8")
def merge_multiple_dicts(*args): def merge_multiple_dicts(*args: Any) -> Dict[str, any]:
result = {} result = {}
for d in args: for d in args:
result.update(d) result.update(d)

View File

@ -18,9 +18,10 @@ disable = W,C,R,E
enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import
[mypy] [mypy]
exclude = tests files= moto/acm,moto/amp,moto/apigateway,moto/applicationautoscaling/
show_column_numbers=True show_column_numbers=True
show_error_codes = True show_error_codes = True
disable_error_code=abstract
disallow_any_unimported=False disallow_any_unimported=False
disallow_any_expr=False disallow_any_expr=False

View File

@ -842,9 +842,21 @@ def test_non_existent_authorizer():
response = client.create_rest_api(name="my_api", description="this is my api") response = client.create_rest_api(name="my_api", description="this is my api")
api_id = response["id"] api_id = response["id"]
client.get_authorizer.when.called_with( with pytest.raises(ClientError) as exc:
restApiId=api_id, authorizerId="xxx" client.get_authorizer(restApiId=api_id, authorizerId="xxx")
).should.throw(ClientError) err = exc.value.response["Error"]
err["Code"].should.equal("NotFoundException")
err["Message"].should.equal("Invalid Authorizer identifier specified")
with pytest.raises(ClientError) as exc:
client.update_authorizer(
restApiId=api_id,
authorizerId="xxx",
patchOperations=[{"op": "add", "path": "/type", "value": "sth"}],
)
err = exc.value.response["Error"]
err["Code"].should.equal("NotFoundException")
err["Message"].should.equal("Invalid Authorizer identifier specified")
@mock_apigateway @mock_apigateway
@ -1878,18 +1890,6 @@ def test_get_domain_name_unknown_domainname():
ex.value.response["Error"]["Code"].should.equal("NotFoundException") ex.value.response["Error"]["Code"].should.equal("NotFoundException")
@mock_apigateway
def test_update_domain_name_unknown_domainname():
client = boto3.client("apigateway", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.update_domain_name(domainName="www.google.fr", patchOperations=[])
ex.value.response["Error"]["Message"].should.equal(
"Invalid domain name identifier specified"
)
ex.value.response["Error"]["Code"].should.equal("NotFoundException")
@mock_apigateway @mock_apigateway
def test_delete_domain_name_unknown_domainname(): def test_delete_domain_name_unknown_domainname():
client = boto3.client("apigateway", region_name="us-east-1") client = boto3.client("apigateway", region_name="us-east-1")