TechDebt: MyPy AWSLambda (#5586)
This commit is contained in:
parent
6f710189ce
commit
8c88a93d7c
@ -51,19 +51,20 @@ class GraphqlSchema(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class GraphqlAPIKey(BaseModel):
|
class GraphqlAPIKey(BaseModel):
|
||||||
def __init__(self, description: str, expires: Optional[datetime]):
|
def __init__(self, description: str, expires: Optional[int]):
|
||||||
self.key_id = str(mock_random.uuid4())[0:6]
|
self.key_id = str(mock_random.uuid4())[0:6]
|
||||||
self.description = description
|
self.description = description
|
||||||
self.expires = expires
|
if not expires:
|
||||||
if not self.expires:
|
|
||||||
default_expiry = datetime.now(timezone.utc)
|
default_expiry = datetime.now(timezone.utc)
|
||||||
default_expiry = default_expiry.replace(
|
default_expiry = default_expiry.replace(
|
||||||
minute=0, second=0, microsecond=0, tzinfo=None
|
minute=0, second=0, microsecond=0, tzinfo=None
|
||||||
)
|
)
|
||||||
default_expiry = default_expiry + timedelta(days=7)
|
default_expiry = default_expiry + timedelta(days=7)
|
||||||
self.expires = unix_time(default_expiry)
|
self.expires = unix_time(default_expiry)
|
||||||
|
else:
|
||||||
|
self.expires = expires
|
||||||
|
|
||||||
def update(self, description: Optional[str], expires: Optional[datetime]) -> None:
|
def update(self, description: Optional[str], expires: Optional[int]) -> None:
|
||||||
if description:
|
if description:
|
||||||
self.description = description
|
self.description = description
|
||||||
if expires:
|
if expires:
|
||||||
@ -138,9 +139,7 @@ class GraphqlAPI(BaseModel):
|
|||||||
if xray_enabled is not None:
|
if xray_enabled is not None:
|
||||||
self.xray_enabled = xray_enabled
|
self.xray_enabled = xray_enabled
|
||||||
|
|
||||||
def create_api_key(
|
def create_api_key(self, description: str, expires: Optional[int]) -> GraphqlAPIKey:
|
||||||
self, description: str, expires: Optional[datetime]
|
|
||||||
) -> GraphqlAPIKey:
|
|
||||||
api_key = GraphqlAPIKey(description, expires)
|
api_key = GraphqlAPIKey(description, expires)
|
||||||
self.api_keys[api_key.key_id] = api_key
|
self.api_keys[api_key.key_id] = api_key
|
||||||
return api_key
|
return api_key
|
||||||
@ -152,7 +151,7 @@ class GraphqlAPI(BaseModel):
|
|||||||
self.api_keys.pop(api_key_id)
|
self.api_keys.pop(api_key_id)
|
||||||
|
|
||||||
def update_api_key(
|
def update_api_key(
|
||||||
self, api_key_id: str, description: str, expires: Optional[datetime]
|
self, api_key_id: str, description: str, expires: Optional[int]
|
||||||
) -> GraphqlAPIKey:
|
) -> GraphqlAPIKey:
|
||||||
api_key = self.api_keys[api_key_id]
|
api_key = self.api_keys[api_key_id]
|
||||||
api_key.update(description, expires)
|
api_key.update(description, expires)
|
||||||
@ -265,7 +264,7 @@ class AppSyncBackend(BaseBackend):
|
|||||||
return self.graphql_apis.values()
|
return self.graphql_apis.values()
|
||||||
|
|
||||||
def create_api_key(
|
def create_api_key(
|
||||||
self, api_id: str, description: str, expires: Optional[datetime]
|
self, api_id: str, description: str, expires: Optional[int]
|
||||||
) -> GraphqlAPIKey:
|
) -> GraphqlAPIKey:
|
||||||
return self.graphql_apis[api_id].create_api_key(description, expires)
|
return self.graphql_apis[api_id].create_api_key(description, expires)
|
||||||
|
|
||||||
@ -286,7 +285,7 @@ class AppSyncBackend(BaseBackend):
|
|||||||
api_id: str,
|
api_id: str,
|
||||||
api_key_id: str,
|
api_key_id: str,
|
||||||
description: str,
|
description: str,
|
||||||
expires: Optional[datetime],
|
expires: Optional[int],
|
||||||
) -> GraphqlAPIKey:
|
) -> GraphqlAPIKey:
|
||||||
return self.graphql_apis[api_id].update_api_key(
|
return self.graphql_apis[api_id].update_api_key(
|
||||||
api_key_id, description, expires
|
api_key_id, description, expires
|
||||||
|
@ -2,26 +2,26 @@ from moto.core.exceptions import JsonRESTError
|
|||||||
|
|
||||||
|
|
||||||
class LambdaClientError(JsonRESTError):
|
class LambdaClientError(JsonRESTError):
|
||||||
def __init__(self, error, message):
|
def __init__(self, error: str, message: str):
|
||||||
super().__init__(error, message)
|
super().__init__(error, message)
|
||||||
|
|
||||||
|
|
||||||
class CrossAccountNotAllowed(LambdaClientError):
|
class CrossAccountNotAllowed(LambdaClientError):
|
||||||
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 InvalidParameterValueException(LambdaClientError):
|
class InvalidParameterValueException(LambdaClientError):
|
||||||
def __init__(self, message):
|
def __init__(self, message: str):
|
||||||
super().__init__("InvalidParameterValueException", message)
|
super().__init__("InvalidParameterValueException", message)
|
||||||
|
|
||||||
|
|
||||||
class InvalidRoleFormat(LambdaClientError):
|
class InvalidRoleFormat(LambdaClientError):
|
||||||
pattern = r"arn:(aws[a-zA-Z-]*)?:iam::(\d{12}):role/?[a-zA-Z_0-9+=,.@\-_/]+"
|
pattern = r"arn:(aws[a-zA-Z-]*)?:iam::(\d{12}):role/?[a-zA-Z_0-9+=,.@\-_/]+"
|
||||||
|
|
||||||
def __init__(self, role):
|
def __init__(self, role: str):
|
||||||
message = "1 validation error detected: Value '{0}' at 'role' failed to satisfy constraint: Member must satisfy regular expression pattern: {1}".format(
|
message = "1 validation error detected: Value '{0}' at 'role' failed to satisfy constraint: Member must satisfy regular expression pattern: {1}".format(
|
||||||
role, InvalidRoleFormat.pattern
|
role, InvalidRoleFormat.pattern
|
||||||
)
|
)
|
||||||
@ -31,28 +31,28 @@ class InvalidRoleFormat(LambdaClientError):
|
|||||||
class PreconditionFailedException(JsonRESTError):
|
class PreconditionFailedException(JsonRESTError):
|
||||||
code = 412
|
code = 412
|
||||||
|
|
||||||
def __init__(self, message):
|
def __init__(self, message: str):
|
||||||
super().__init__("PreconditionFailedException", message)
|
super().__init__("PreconditionFailedException", message)
|
||||||
|
|
||||||
|
|
||||||
class UnknownAliasException(LambdaClientError):
|
class UnknownAliasException(LambdaClientError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self, arn):
|
def __init__(self, arn: str):
|
||||||
super().__init__("ResourceNotFoundException", f"Cannot find alias arn: {arn}")
|
super().__init__("ResourceNotFoundException", f"Cannot find alias arn: {arn}")
|
||||||
|
|
||||||
|
|
||||||
class UnknownFunctionException(LambdaClientError):
|
class UnknownFunctionException(LambdaClientError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self, arn):
|
def __init__(self, arn: str):
|
||||||
super().__init__("ResourceNotFoundException", f"Function not found: {arn}")
|
super().__init__("ResourceNotFoundException", f"Function not found: {arn}")
|
||||||
|
|
||||||
|
|
||||||
class FunctionUrlConfigNotFound(LambdaClientError):
|
class FunctionUrlConfigNotFound(LambdaClientError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"ResourceNotFoundException", "The resource you requested does not exist."
|
"ResourceNotFoundException", "The resource you requested does not exist."
|
||||||
)
|
)
|
||||||
@ -61,14 +61,14 @@ class FunctionUrlConfigNotFound(LambdaClientError):
|
|||||||
class UnknownLayerException(LambdaClientError):
|
class UnknownLayerException(LambdaClientError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__("ResourceNotFoundException", "Cannot find layer")
|
super().__init__("ResourceNotFoundException", "Cannot find layer")
|
||||||
|
|
||||||
|
|
||||||
class UnknownPolicyException(LambdaClientError):
|
class UnknownPolicyException(LambdaClientError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"ResourceNotFoundException",
|
"ResourceNotFoundException",
|
||||||
"No policy is associated with the given resource.",
|
"No policy is associated with the given resource.",
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,20 +5,24 @@ from moto.awslambda.exceptions import (
|
|||||||
UnknownPolicyException,
|
UnknownPolicyException,
|
||||||
)
|
)
|
||||||
from moto.moto_api._internal import mock_random
|
from moto.moto_api._internal import mock_random
|
||||||
|
from typing import Any, Callable, Dict, List, Optional, TypeVar
|
||||||
|
|
||||||
|
|
||||||
|
TYPE_IDENTITY = TypeVar("TYPE_IDENTITY")
|
||||||
|
|
||||||
|
|
||||||
class Policy:
|
class Policy:
|
||||||
def __init__(self, parent):
|
def __init__(self, parent: Any): # Parent should be a LambdaFunction
|
||||||
self.revision = str(mock_random.uuid4())
|
self.revision = str(mock_random.uuid4())
|
||||||
self.statements = []
|
self.statements: List[Dict[str, Any]] = []
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
||||||
def wire_format(self):
|
def wire_format(self) -> str:
|
||||||
p = self.get_policy()
|
p = self.get_policy()
|
||||||
p["Policy"] = json.dumps(p["Policy"])
|
p["Policy"] = json.dumps(p["Policy"])
|
||||||
return json.dumps(p)
|
return json.dumps(p)
|
||||||
|
|
||||||
def get_policy(self):
|
def get_policy(self) -> Dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
"Policy": {
|
"Policy": {
|
||||||
"Version": "2012-10-17",
|
"Version": "2012-10-17",
|
||||||
@ -29,7 +33,9 @@ class Policy:
|
|||||||
}
|
}
|
||||||
|
|
||||||
# adds the raw JSON statement to the policy
|
# adds the raw JSON statement to the policy
|
||||||
def add_statement(self, raw, qualifier=None):
|
def add_statement(
|
||||||
|
self, raw: str, qualifier: Optional[str] = None
|
||||||
|
) -> Dict[str, Any]:
|
||||||
policy = json.loads(raw, object_hook=self.decode_policy)
|
policy = json.loads(raw, object_hook=self.decode_policy)
|
||||||
if len(policy.revision) > 0 and self.revision != policy.revision:
|
if len(policy.revision) > 0 and self.revision != policy.revision:
|
||||||
raise PreconditionFailedException(
|
raise PreconditionFailedException(
|
||||||
@ -49,7 +55,7 @@ class Policy:
|
|||||||
return policy.statements[0]
|
return policy.statements[0]
|
||||||
|
|
||||||
# removes the statement that matches 'sid' from the policy
|
# removes the statement that matches 'sid' from the policy
|
||||||
def del_statement(self, sid, revision=""):
|
def del_statement(self, sid: str, revision: str = "") -> None:
|
||||||
if len(revision) > 0 and self.revision != revision:
|
if len(revision) > 0 and self.revision != revision:
|
||||||
raise PreconditionFailedException(
|
raise PreconditionFailedException(
|
||||||
"The RevisionId provided does not match the latest RevisionId"
|
"The RevisionId provided does not match the latest RevisionId"
|
||||||
@ -65,7 +71,7 @@ class Policy:
|
|||||||
|
|
||||||
# converts AddPermission request to PolicyStatement
|
# converts AddPermission request to PolicyStatement
|
||||||
# https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
|
# https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
|
||||||
def decode_policy(self, obj):
|
def decode_policy(self, obj: Dict[str, Any]) -> "Policy":
|
||||||
# import pydevd
|
# import pydevd
|
||||||
# pydevd.settrace("localhost", port=5678)
|
# pydevd.settrace("localhost", port=5678)
|
||||||
policy = Policy(self.parent)
|
policy = Policy(self.parent)
|
||||||
@ -101,14 +107,14 @@ class Policy:
|
|||||||
|
|
||||||
return policy
|
return policy
|
||||||
|
|
||||||
def nop_formatter(self, obj):
|
def nop_formatter(self, obj: TYPE_IDENTITY) -> TYPE_IDENTITY:
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def ensure_set(self, obj, key, value):
|
def ensure_set(self, obj: Dict[str, Any], key: str, value: Any) -> None:
|
||||||
if key not in obj:
|
if key not in obj:
|
||||||
obj[key] = value
|
obj[key] = value
|
||||||
|
|
||||||
def principal_formatter(self, obj):
|
def principal_formatter(self, obj: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
if isinstance(obj, str):
|
if isinstance(obj, str):
|
||||||
if obj.endswith(".amazonaws.com"):
|
if obj.endswith(".amazonaws.com"):
|
||||||
return {"Service": obj}
|
return {"Service": obj}
|
||||||
@ -116,27 +122,39 @@ class Policy:
|
|||||||
return {"AWS": obj}
|
return {"AWS": obj}
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def source_account_formatter(self, obj):
|
def source_account_formatter(
|
||||||
|
self, obj: TYPE_IDENTITY
|
||||||
|
) -> Dict[str, Dict[str, TYPE_IDENTITY]]:
|
||||||
return {"StringEquals": {"AWS:SourceAccount": obj}}
|
return {"StringEquals": {"AWS:SourceAccount": obj}}
|
||||||
|
|
||||||
def source_arn_formatter(self, obj):
|
def source_arn_formatter(
|
||||||
|
self, obj: TYPE_IDENTITY
|
||||||
|
) -> Dict[str, Dict[str, TYPE_IDENTITY]]:
|
||||||
return {"ArnLike": {"AWS:SourceArn": obj}}
|
return {"ArnLike": {"AWS:SourceArn": obj}}
|
||||||
|
|
||||||
def principal_org_id_formatter(self, obj):
|
def principal_org_id_formatter(
|
||||||
|
self, obj: TYPE_IDENTITY
|
||||||
|
) -> Dict[str, Dict[str, TYPE_IDENTITY]]:
|
||||||
return {"StringEquals": {"aws:PrincipalOrgID": obj}}
|
return {"StringEquals": {"aws:PrincipalOrgID": obj}}
|
||||||
|
|
||||||
def transform_property(self, obj, old_name, new_name, formatter):
|
def transform_property(
|
||||||
|
self,
|
||||||
|
obj: Dict[str, Any],
|
||||||
|
old_name: str,
|
||||||
|
new_name: str,
|
||||||
|
formatter: Callable[..., Any],
|
||||||
|
) -> None:
|
||||||
if old_name in obj:
|
if old_name in obj:
|
||||||
obj[new_name] = formatter(obj[old_name])
|
obj[new_name] = formatter(obj[old_name])
|
||||||
if new_name != old_name:
|
if new_name != old_name:
|
||||||
del obj[old_name]
|
del obj[old_name]
|
||||||
|
|
||||||
def remove_if_set(self, obj, keys):
|
def remove_if_set(self, obj: Dict[str, Any], keys: List[str]) -> None:
|
||||||
for key in keys:
|
for key in keys:
|
||||||
if key in obj:
|
if key in obj:
|
||||||
del obj[key]
|
del obj[key]
|
||||||
|
|
||||||
def condition_merge(self, obj):
|
def condition_merge(self, obj: Dict[str, Any]) -> None:
|
||||||
if "SourceArn" in obj:
|
if "SourceArn" in obj:
|
||||||
if "Condition" not in obj:
|
if "Condition" not in obj:
|
||||||
obj["Condition"] = {}
|
obj["Condition"] = {}
|
||||||
|
@ -1,31 +1,27 @@
|
|||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
|
from typing import Any, Dict, List, Tuple, Union
|
||||||
from urllib.parse import unquote
|
from urllib.parse import unquote
|
||||||
|
|
||||||
from moto.core.utils import path_url
|
from moto.core.utils import path_url
|
||||||
from moto.utilities.aws_headers import amz_crc32, amzn_request_id
|
from moto.utilities.aws_headers import amz_crc32, amzn_request_id
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse, TYPE_RESPONSE
|
||||||
from .models import lambda_backends
|
from .models import lambda_backends, LambdaBackend
|
||||||
|
|
||||||
|
|
||||||
class LambdaResponse(BaseResponse):
|
class LambdaResponse(BaseResponse):
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__(service_name="awslambda")
|
super().__init__(service_name="awslambda")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def json_body(self):
|
def json_body(self) -> Dict[str, Any]: # type: ignore[misc]
|
||||||
"""
|
|
||||||
:return: JSON
|
|
||||||
:rtype: dict
|
|
||||||
"""
|
|
||||||
return json.loads(self.body)
|
return json.loads(self.body)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def backend(self):
|
def backend(self) -> LambdaBackend:
|
||||||
return lambda_backends[self.current_account][self.region]
|
return lambda_backends[self.current_account][self.region]
|
||||||
|
|
||||||
def root(self, request, full_url, headers):
|
def root(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
return self._list_functions()
|
return self._list_functions()
|
||||||
@ -34,7 +30,9 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
def event_source_mappings(self, request, full_url, headers):
|
def event_source_mappings(
|
||||||
|
self, request: Any, full_url: str, headers: Any
|
||||||
|
) -> TYPE_RESPONSE:
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
querystring = self.querystring
|
querystring = self.querystring
|
||||||
@ -46,12 +44,12 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
def aliases(self, request, full_url, headers):
|
def aliases(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # type: ignore[return]
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
return self._create_alias()
|
return self._create_alias()
|
||||||
|
|
||||||
def alias(self, request, full_url, headers):
|
def alias(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # type: ignore[return]
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == "DELETE":
|
if request.method == "DELETE":
|
||||||
return self._delete_alias()
|
return self._delete_alias()
|
||||||
@ -60,7 +58,9 @@ class LambdaResponse(BaseResponse):
|
|||||||
elif request.method == "PUT":
|
elif request.method == "PUT":
|
||||||
return self._update_alias()
|
return self._update_alias()
|
||||||
|
|
||||||
def event_source_mapping(self, request, full_url, headers):
|
def event_source_mapping(
|
||||||
|
self, request: Any, full_url: str, headers: Any
|
||||||
|
) -> TYPE_RESPONSE:
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
path = request.path if hasattr(request, "path") else path_url(request.url)
|
path = request.path if hasattr(request, "path") else path_url(request.url)
|
||||||
uuid = path.split("/")[-1]
|
uuid = path.split("/")[-1]
|
||||||
@ -73,26 +73,26 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
def list_layers(self, request, full_url, headers):
|
def list_layers(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # 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._list_layers()
|
return self._list_layers()
|
||||||
|
|
||||||
def layers_version(self, request, full_url, headers):
|
def layers_version(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # type: ignore[return]
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == "DELETE":
|
if request.method == "DELETE":
|
||||||
return self._delete_layer_version()
|
return self._delete_layer_version()
|
||||||
elif request.method == "GET":
|
elif request.method == "GET":
|
||||||
return self._get_layer_version()
|
return self._get_layer_version()
|
||||||
|
|
||||||
def layers_versions(self, request, full_url, headers):
|
def layers_versions(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # 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_layer_versions()
|
return self._get_layer_versions()
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
return self._publish_layer_version()
|
return self._publish_layer_version()
|
||||||
|
|
||||||
def function(self, request, full_url, headers):
|
def function(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:
|
||||||
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_function()
|
return self._get_function()
|
||||||
@ -101,7 +101,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
def versions(self, request, full_url, headers):
|
def versions(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
# This is ListVersionByFunction
|
# This is ListVersionByFunction
|
||||||
@ -117,7 +117,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
|
|
||||||
@amz_crc32
|
@amz_crc32
|
||||||
@amzn_request_id
|
@amzn_request_id
|
||||||
def invoke(self, request, full_url, headers):
|
def invoke(self, request: Any, full_url: str, headers: Any) -> Tuple[int, Dict[str, str], Union[str, bytes]]: # type: ignore[misc]
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
return self._invoke(request)
|
return self._invoke(request)
|
||||||
@ -126,14 +126,14 @@ class LambdaResponse(BaseResponse):
|
|||||||
|
|
||||||
@amz_crc32
|
@amz_crc32
|
||||||
@amzn_request_id
|
@amzn_request_id
|
||||||
def invoke_async(self, request, full_url, headers):
|
def invoke_async(self, request: Any, full_url: str, headers: Any) -> Tuple[int, Dict[str, str], Union[str, bytes]]: # type: ignore[misc]
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
return self._invoke_async()
|
return self._invoke_async()
|
||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
def tag(self, request, full_url, headers):
|
def tag(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
return self._list_tags()
|
return self._list_tags()
|
||||||
@ -144,7 +144,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle {0} request".format(request.method))
|
raise ValueError("Cannot handle {0} request".format(request.method))
|
||||||
|
|
||||||
def policy(self, request, full_url, headers):
|
def policy(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:
|
||||||
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_policy(request)
|
return self._get_policy(request)
|
||||||
@ -155,7 +155,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle {0} request".format(request.method))
|
raise ValueError("Cannot handle {0} request".format(request.method))
|
||||||
|
|
||||||
def configuration(self, request, full_url, headers):
|
def configuration(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:
|
||||||
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_configuration()
|
return self._put_configuration()
|
||||||
@ -164,19 +164,21 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
def code(self, request, full_url, headers):
|
def code(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:
|
||||||
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_code()
|
return self._put_code()
|
||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
def code_signing_config(self, request, full_url, headers):
|
def code_signing_config(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # 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_code_signing_config()
|
return self._get_code_signing_config()
|
||||||
|
|
||||||
def function_concurrency(self, request, full_url, headers):
|
def function_concurrency(
|
||||||
|
self, request: Any, full_url: str, headers: Any
|
||||||
|
) -> TYPE_RESPONSE:
|
||||||
http_method = request.method
|
http_method = request.method
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
|
|
||||||
@ -189,7 +191,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
def function_url_config(self, request, full_url, headers):
|
def function_url_config(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # type: ignore[return]
|
||||||
http_method = request.method
|
http_method = request.method
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
|
|
||||||
@ -202,7 +204,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
elif http_method == "PUT":
|
elif http_method == "PUT":
|
||||||
return self._update_function_url_config()
|
return self._update_function_url_config()
|
||||||
|
|
||||||
def _add_policy(self, request):
|
def _add_policy(self, request: Any) -> TYPE_RESPONSE:
|
||||||
path = request.path if hasattr(request, "path") else path_url(request.url)
|
path = request.path if hasattr(request, "path") else path_url(request.url)
|
||||||
function_name = unquote(path.split("/")[-2])
|
function_name = unquote(path.split("/")[-2])
|
||||||
qualifier = self.querystring.get("Qualifier", [None])[0]
|
qualifier = self.querystring.get("Qualifier", [None])[0]
|
||||||
@ -210,13 +212,13 @@ class LambdaResponse(BaseResponse):
|
|||||||
statement = self.backend.add_permission(function_name, qualifier, statement)
|
statement = self.backend.add_permission(function_name, qualifier, statement)
|
||||||
return 200, {}, json.dumps({"Statement": json.dumps(statement)})
|
return 200, {}, json.dumps({"Statement": json.dumps(statement)})
|
||||||
|
|
||||||
def _get_policy(self, request):
|
def _get_policy(self, request: Any) -> TYPE_RESPONSE:
|
||||||
path = request.path if hasattr(request, "path") else path_url(request.url)
|
path = request.path if hasattr(request, "path") else path_url(request.url)
|
||||||
function_name = unquote(path.split("/")[-2])
|
function_name = unquote(path.split("/")[-2])
|
||||||
out = self.backend.get_policy(function_name)
|
out = self.backend.get_policy(function_name)
|
||||||
return 200, {}, out
|
return 200, {}, out
|
||||||
|
|
||||||
def _del_policy(self, request, querystring):
|
def _del_policy(self, request: Any, querystring: Dict[str, Any]) -> TYPE_RESPONSE:
|
||||||
path = request.path if hasattr(request, "path") else path_url(request.url)
|
path = request.path if hasattr(request, "path") else path_url(request.url)
|
||||||
function_name = unquote(path.split("/")[-3])
|
function_name = unquote(path.split("/")[-3])
|
||||||
statement_id = path.split("/")[-1].split("?")[0]
|
statement_id = path.split("/")[-1].split("?")[0]
|
||||||
@ -227,8 +229,8 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
return 404, {}, "{}"
|
return 404, {}, "{}"
|
||||||
|
|
||||||
def _invoke(self, request):
|
def _invoke(self, request: Any) -> Tuple[int, Dict[str, str], Union[str, bytes]]:
|
||||||
response_headers = {}
|
response_headers: Dict[str, str] = {}
|
||||||
|
|
||||||
# URL Decode in case it's a ARN:
|
# URL Decode in case it's a ARN:
|
||||||
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
||||||
@ -261,8 +263,8 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
return 404, response_headers, "{}"
|
return 404, response_headers, "{}"
|
||||||
|
|
||||||
def _invoke_async(self):
|
def _invoke_async(self) -> Tuple[int, Dict[str, str], Union[str, bytes]]:
|
||||||
response_headers = {}
|
response_headers: Dict[str, Any] = {}
|
||||||
|
|
||||||
function_name = unquote(self.path.rsplit("/", 3)[-3])
|
function_name = unquote(self.path.rsplit("/", 3)[-3])
|
||||||
|
|
||||||
@ -271,10 +273,10 @@ class LambdaResponse(BaseResponse):
|
|||||||
response_headers["Content-Length"] = str(len(payload))
|
response_headers["Content-Length"] = str(len(payload))
|
||||||
return 202, response_headers, payload
|
return 202, response_headers, payload
|
||||||
|
|
||||||
def _list_functions(self):
|
def _list_functions(self) -> TYPE_RESPONSE:
|
||||||
querystring = self.querystring
|
querystring = self.querystring
|
||||||
func_version = querystring.get("FunctionVersion", [None])[0]
|
func_version = querystring.get("FunctionVersion", [None])[0]
|
||||||
result = {"Functions": []}
|
result: Dict[str, List[Dict[str, Any]]] = {"Functions": []}
|
||||||
|
|
||||||
for fn in self.backend.list_functions(func_version):
|
for fn in self.backend.list_functions(func_version):
|
||||||
json_data = fn.get_configuration()
|
json_data = fn.get_configuration()
|
||||||
@ -282,67 +284,68 @@ class LambdaResponse(BaseResponse):
|
|||||||
|
|
||||||
return 200, {}, json.dumps(result)
|
return 200, {}, json.dumps(result)
|
||||||
|
|
||||||
def _list_versions_by_function(self, function_name):
|
def _list_versions_by_function(self, function_name: str) -> TYPE_RESPONSE:
|
||||||
result = {"Versions": []}
|
result: Dict[str, Any] = {"Versions": []}
|
||||||
|
|
||||||
functions = self.backend.list_versions_by_function(function_name)
|
functions = self.backend.list_versions_by_function(function_name)
|
||||||
if functions:
|
for fn in functions:
|
||||||
for fn in functions:
|
json_data = fn.get_configuration()
|
||||||
json_data = fn.get_configuration()
|
result["Versions"].append(json_data)
|
||||||
result["Versions"].append(json_data)
|
|
||||||
|
|
||||||
return 200, {}, json.dumps(result)
|
return 200, {}, json.dumps(result)
|
||||||
|
|
||||||
def _create_function(self):
|
def _create_function(self) -> TYPE_RESPONSE:
|
||||||
fn = self.backend.create_function(self.json_body)
|
fn = self.backend.create_function(self.json_body)
|
||||||
config = fn.get_configuration(on_create=True)
|
config = fn.get_configuration(on_create=True)
|
||||||
return 201, {}, json.dumps(config)
|
return 201, {}, json.dumps(config)
|
||||||
|
|
||||||
def _create_function_url_config(self):
|
def _create_function_url_config(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.split("/")[-2])
|
function_name = unquote(self.path.split("/")[-2])
|
||||||
config = self.backend.create_function_url_config(function_name, self.json_body)
|
config = self.backend.create_function_url_config(function_name, self.json_body)
|
||||||
return 201, {}, json.dumps(config.to_dict())
|
return 201, {}, json.dumps(config.to_dict())
|
||||||
|
|
||||||
def _delete_function_url_config(self):
|
def _delete_function_url_config(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.split("/")[-2])
|
function_name = unquote(self.path.split("/")[-2])
|
||||||
self.backend.delete_function_url_config(function_name)
|
self.backend.delete_function_url_config(function_name)
|
||||||
return 204, {}, "{}"
|
return 204, {}, "{}"
|
||||||
|
|
||||||
def _get_function_url_config(self):
|
def _get_function_url_config(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.split("/")[-2])
|
function_name = unquote(self.path.split("/")[-2])
|
||||||
config = self.backend.get_function_url_config(function_name)
|
config = self.backend.get_function_url_config(function_name)
|
||||||
return 201, {}, json.dumps(config.to_dict())
|
return 201, {}, json.dumps(config.to_dict())
|
||||||
|
|
||||||
def _update_function_url_config(self):
|
def _update_function_url_config(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.split("/")[-2])
|
function_name = unquote(self.path.split("/")[-2])
|
||||||
config = self.backend.update_function_url_config(function_name, self.json_body)
|
config = self.backend.update_function_url_config(function_name, self.json_body)
|
||||||
return 200, {}, json.dumps(config.to_dict())
|
return 200, {}, json.dumps(config.to_dict())
|
||||||
|
|
||||||
def _create_event_source_mapping(self):
|
def _create_event_source_mapping(self) -> TYPE_RESPONSE:
|
||||||
fn = self.backend.create_event_source_mapping(self.json_body)
|
fn = self.backend.create_event_source_mapping(self.json_body)
|
||||||
config = fn.get_configuration()
|
config = fn.get_configuration()
|
||||||
return 201, {}, json.dumps(config)
|
return 201, {}, json.dumps(config)
|
||||||
|
|
||||||
def _list_event_source_mappings(self, event_source_arn, function_name):
|
def _list_event_source_mappings(
|
||||||
|
self, event_source_arn: str, function_name: str
|
||||||
|
) -> TYPE_RESPONSE:
|
||||||
esms = self.backend.list_event_source_mappings(event_source_arn, function_name)
|
esms = self.backend.list_event_source_mappings(event_source_arn, function_name)
|
||||||
result = {"EventSourceMappings": [esm.get_configuration() for esm in esms]}
|
result = {"EventSourceMappings": [esm.get_configuration() for esm in esms]}
|
||||||
return 200, {}, json.dumps(result)
|
return 200, {}, json.dumps(result)
|
||||||
|
|
||||||
def _get_event_source_mapping(self, uuid):
|
def _get_event_source_mapping(self, uuid: str) -> TYPE_RESPONSE:
|
||||||
result = self.backend.get_event_source_mapping(uuid)
|
result = self.backend.get_event_source_mapping(uuid)
|
||||||
if result:
|
if result:
|
||||||
return 200, {}, json.dumps(result.get_configuration())
|
return 200, {}, json.dumps(result.get_configuration())
|
||||||
else:
|
else:
|
||||||
return 404, {}, "{}"
|
return 404, {}, "{}"
|
||||||
|
|
||||||
def _update_event_source_mapping(self, uuid):
|
def _update_event_source_mapping(self, uuid: str) -> TYPE_RESPONSE:
|
||||||
result = self.backend.update_event_source_mapping(uuid, self.json_body)
|
result = self.backend.update_event_source_mapping(uuid, self.json_body)
|
||||||
if result:
|
if result:
|
||||||
return 202, {}, json.dumps(result.get_configuration())
|
return 202, {}, json.dumps(result.get_configuration())
|
||||||
else:
|
else:
|
||||||
return 404, {}, "{}"
|
return 404, {}, "{}"
|
||||||
|
|
||||||
def _delete_event_source_mapping(self, uuid):
|
def _delete_event_source_mapping(self, uuid: str) -> TYPE_RESPONSE:
|
||||||
esm = self.backend.delete_event_source_mapping(uuid)
|
esm = self.backend.delete_event_source_mapping(uuid)
|
||||||
if esm:
|
if esm:
|
||||||
json_result = esm.get_configuration()
|
json_result = esm.get_configuration()
|
||||||
@ -351,15 +354,15 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
return 404, {}, "{}"
|
return 404, {}, "{}"
|
||||||
|
|
||||||
def _publish_function(self):
|
def _publish_function(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.split("/")[-2])
|
function_name = unquote(self.path.split("/")[-2])
|
||||||
description = self._get_param("Description")
|
description = self._get_param("Description")
|
||||||
|
|
||||||
fn = self.backend.publish_function(function_name, description)
|
fn = self.backend.publish_function(function_name, description)
|
||||||
config = fn.get_configuration()
|
config = fn.get_configuration() # type: ignore[union-attr]
|
||||||
return 201, {}, json.dumps(config)
|
return 201, {}, json.dumps(config)
|
||||||
|
|
||||||
def _delete_function(self):
|
def _delete_function(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.rsplit("/", 1)[-1])
|
function_name = unquote(self.path.rsplit("/", 1)[-1])
|
||||||
qualifier = self._get_param("Qualifier", None)
|
qualifier = self._get_param("Qualifier", None)
|
||||||
|
|
||||||
@ -367,14 +370,14 @@ class LambdaResponse(BaseResponse):
|
|||||||
return 204, {}, ""
|
return 204, {}, ""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _set_configuration_qualifier(configuration, qualifier):
|
def _set_configuration_qualifier(configuration: Dict[str, Any], qualifier: str) -> Dict[str, Any]: # type: ignore[misc]
|
||||||
if qualifier is None or qualifier == "$LATEST":
|
if qualifier is None or qualifier == "$LATEST":
|
||||||
configuration["Version"] = "$LATEST"
|
configuration["Version"] = "$LATEST"
|
||||||
if qualifier == "$LATEST":
|
if qualifier == "$LATEST":
|
||||||
configuration["FunctionArn"] += ":$LATEST"
|
configuration["FunctionArn"] += ":$LATEST"
|
||||||
return configuration
|
return configuration
|
||||||
|
|
||||||
def _get_function(self):
|
def _get_function(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.rsplit("/", 1)[-1])
|
function_name = unquote(self.path.rsplit("/", 1)[-1])
|
||||||
qualifier = self._get_param("Qualifier", None)
|
qualifier = self._get_param("Qualifier", None)
|
||||||
|
|
||||||
@ -386,7 +389,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
)
|
)
|
||||||
return 200, {}, json.dumps(code)
|
return 200, {}, json.dumps(code)
|
||||||
|
|
||||||
def _get_function_configuration(self):
|
def _get_function_configuration(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
||||||
qualifier = self._get_param("Qualifier", None)
|
qualifier = self._get_param("Qualifier", None)
|
||||||
|
|
||||||
@ -397,33 +400,33 @@ class LambdaResponse(BaseResponse):
|
|||||||
)
|
)
|
||||||
return 200, {}, json.dumps(configuration)
|
return 200, {}, json.dumps(configuration)
|
||||||
|
|
||||||
def _get_aws_region(self, full_url):
|
def _get_aws_region(self, full_url: str) -> str:
|
||||||
region = self.region_regex.search(full_url)
|
region = self.region_regex.search(full_url)
|
||||||
if region:
|
if region:
|
||||||
return region.group(1)
|
return region.group(1)
|
||||||
else:
|
else:
|
||||||
return self.default_region
|
return self.default_region
|
||||||
|
|
||||||
def _list_tags(self):
|
def _list_tags(self) -> TYPE_RESPONSE:
|
||||||
function_arn = unquote(self.path.rsplit("/", 1)[-1])
|
function_arn = unquote(self.path.rsplit("/", 1)[-1])
|
||||||
|
|
||||||
tags = self.backend.list_tags(function_arn)
|
tags = self.backend.list_tags(function_arn)
|
||||||
return 200, {}, json.dumps({"Tags": tags})
|
return 200, {}, json.dumps({"Tags": tags})
|
||||||
|
|
||||||
def _tag_resource(self):
|
def _tag_resource(self) -> TYPE_RESPONSE:
|
||||||
function_arn = unquote(self.path.rsplit("/", 1)[-1])
|
function_arn = unquote(self.path.rsplit("/", 1)[-1])
|
||||||
|
|
||||||
self.backend.tag_resource(function_arn, self.json_body["Tags"])
|
self.backend.tag_resource(function_arn, self.json_body["Tags"])
|
||||||
return 200, {}, "{}"
|
return 200, {}, "{}"
|
||||||
|
|
||||||
def _untag_resource(self):
|
def _untag_resource(self) -> TYPE_RESPONSE:
|
||||||
function_arn = unquote(self.path.rsplit("/", 1)[-1])
|
function_arn = unquote(self.path.rsplit("/", 1)[-1])
|
||||||
tag_keys = self.querystring["tagKeys"]
|
tag_keys = self.querystring["tagKeys"]
|
||||||
|
|
||||||
self.backend.untag_resource(function_arn, tag_keys)
|
self.backend.untag_resource(function_arn, tag_keys)
|
||||||
return 204, {}, "{}"
|
return 204, {}, "{}"
|
||||||
|
|
||||||
def _put_configuration(self):
|
def _put_configuration(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
||||||
qualifier = self._get_param("Qualifier", None)
|
qualifier = self._get_param("Qualifier", None)
|
||||||
resp = self.backend.update_function_configuration(
|
resp = self.backend.update_function_configuration(
|
||||||
@ -435,7 +438,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
return 404, {}, "{}"
|
return 404, {}, "{}"
|
||||||
|
|
||||||
def _put_code(self):
|
def _put_code(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
||||||
qualifier = self._get_param("Qualifier", None)
|
qualifier = self._get_param("Qualifier", None)
|
||||||
resp = self.backend.update_function_code(
|
resp = self.backend.update_function_code(
|
||||||
@ -447,12 +450,12 @@ class LambdaResponse(BaseResponse):
|
|||||||
else:
|
else:
|
||||||
return 404, {}, "{}"
|
return 404, {}, "{}"
|
||||||
|
|
||||||
def _get_code_signing_config(self):
|
def _get_code_signing_config(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
||||||
resp = self.backend.get_code_signing_config(function_name)
|
resp = self.backend.get_code_signing_config(function_name)
|
||||||
return 200, {}, json.dumps(resp)
|
return 200, {}, json.dumps(resp)
|
||||||
|
|
||||||
def _get_function_concurrency(self):
|
def _get_function_concurrency(self) -> TYPE_RESPONSE:
|
||||||
path_function_name = unquote(self.path.rsplit("/", 2)[-2])
|
path_function_name = unquote(self.path.rsplit("/", 2)[-2])
|
||||||
function_name = self.backend.get_function(path_function_name)
|
function_name = self.backend.get_function(path_function_name)
|
||||||
|
|
||||||
@ -462,7 +465,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
resp = self.backend.get_function_concurrency(path_function_name)
|
resp = self.backend.get_function_concurrency(path_function_name)
|
||||||
return 200, {}, json.dumps({"ReservedConcurrentExecutions": resp})
|
return 200, {}, json.dumps({"ReservedConcurrentExecutions": resp})
|
||||||
|
|
||||||
def _delete_function_concurrency(self):
|
def _delete_function_concurrency(self) -> TYPE_RESPONSE:
|
||||||
path_function_name = unquote(self.path.rsplit("/", 2)[-2])
|
path_function_name = unquote(self.path.rsplit("/", 2)[-2])
|
||||||
function_name = self.backend.get_function(path_function_name)
|
function_name = self.backend.get_function(path_function_name)
|
||||||
|
|
||||||
@ -473,7 +476,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
|
|
||||||
return 204, {}, "{}"
|
return 204, {}, "{}"
|
||||||
|
|
||||||
def _put_function_concurrency(self):
|
def _put_function_concurrency(self) -> TYPE_RESPONSE:
|
||||||
path_function_name = unquote(self.path.rsplit("/", 2)[-2])
|
path_function_name = unquote(self.path.rsplit("/", 2)[-2])
|
||||||
function = self.backend.get_function(path_function_name)
|
function = self.backend.get_function(path_function_name)
|
||||||
|
|
||||||
@ -485,25 +488,25 @@ class LambdaResponse(BaseResponse):
|
|||||||
|
|
||||||
return 200, {}, json.dumps({"ReservedConcurrentExecutions": resp})
|
return 200, {}, json.dumps({"ReservedConcurrentExecutions": resp})
|
||||||
|
|
||||||
def _list_layers(self):
|
def _list_layers(self) -> TYPE_RESPONSE:
|
||||||
layers = self.backend.list_layers()
|
layers = self.backend.list_layers()
|
||||||
return 200, {}, json.dumps({"Layers": layers})
|
return 200, {}, json.dumps({"Layers": layers})
|
||||||
|
|
||||||
def _delete_layer_version(self):
|
def _delete_layer_version(self) -> TYPE_RESPONSE:
|
||||||
layer_name = self.path.split("/")[-3]
|
layer_name = self.path.split("/")[-3]
|
||||||
layer_version = self.path.split("/")[-1]
|
layer_version = self.path.split("/")[-1]
|
||||||
|
|
||||||
self.backend.delete_layer_version(layer_name, layer_version)
|
self.backend.delete_layer_version(layer_name, layer_version)
|
||||||
return 200, {}, "{}"
|
return 200, {}, "{}"
|
||||||
|
|
||||||
def _get_layer_version(self):
|
def _get_layer_version(self) -> TYPE_RESPONSE:
|
||||||
layer_name = self.path.split("/")[-3]
|
layer_name = self.path.split("/")[-3]
|
||||||
layer_version = self.path.split("/")[-1]
|
layer_version = self.path.split("/")[-1]
|
||||||
|
|
||||||
layer = self.backend.get_layer_version(layer_name, layer_version)
|
layer = self.backend.get_layer_version(layer_name, layer_version)
|
||||||
return 200, {}, json.dumps(layer.get_layer_version())
|
return 200, {}, json.dumps(layer.get_layer_version())
|
||||||
|
|
||||||
def _get_layer_versions(self):
|
def _get_layer_versions(self) -> TYPE_RESPONSE:
|
||||||
layer_name = self.path.rsplit("/", 2)[-2]
|
layer_name = self.path.rsplit("/", 2)[-2]
|
||||||
layer_versions = self.backend.get_layer_versions(layer_name)
|
layer_versions = self.backend.get_layer_versions(layer_name)
|
||||||
return (
|
return (
|
||||||
@ -514,7 +517,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _publish_layer_version(self):
|
def _publish_layer_version(self) -> TYPE_RESPONSE:
|
||||||
spec = self.json_body
|
spec = self.json_body
|
||||||
if "LayerName" not in spec:
|
if "LayerName" not in spec:
|
||||||
spec["LayerName"] = self.path.rsplit("/", 2)[-2]
|
spec["LayerName"] = self.path.rsplit("/", 2)[-2]
|
||||||
@ -522,7 +525,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
config = layer_version.get_layer_version()
|
config = layer_version.get_layer_version()
|
||||||
return 201, {}, json.dumps(config)
|
return 201, {}, json.dumps(config)
|
||||||
|
|
||||||
def _create_alias(self):
|
def _create_alias(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
function_name = unquote(self.path.rsplit("/", 2)[-2])
|
||||||
params = json.loads(self.body)
|
params = json.loads(self.body)
|
||||||
alias_name = params.get("Name")
|
alias_name = params.get("Name")
|
||||||
@ -538,19 +541,19 @@ class LambdaResponse(BaseResponse):
|
|||||||
)
|
)
|
||||||
return 201, {}, json.dumps(alias.to_json())
|
return 201, {}, json.dumps(alias.to_json())
|
||||||
|
|
||||||
def _delete_alias(self):
|
def _delete_alias(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.rsplit("/")[-3])
|
function_name = unquote(self.path.rsplit("/")[-3])
|
||||||
alias_name = unquote(self.path.rsplit("/", 2)[-1])
|
alias_name = unquote(self.path.rsplit("/", 2)[-1])
|
||||||
self.backend.delete_alias(name=alias_name, function_name=function_name)
|
self.backend.delete_alias(name=alias_name, function_name=function_name)
|
||||||
return 201, {}, "{}"
|
return 201, {}, "{}"
|
||||||
|
|
||||||
def _get_alias(self):
|
def _get_alias(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.rsplit("/")[-3])
|
function_name = unquote(self.path.rsplit("/")[-3])
|
||||||
alias_name = unquote(self.path.rsplit("/", 2)[-1])
|
alias_name = unquote(self.path.rsplit("/", 2)[-1])
|
||||||
alias = self.backend.get_alias(name=alias_name, function_name=function_name)
|
alias = self.backend.get_alias(name=alias_name, function_name=function_name)
|
||||||
return 201, {}, json.dumps(alias.to_json())
|
return 201, {}, json.dumps(alias.to_json())
|
||||||
|
|
||||||
def _update_alias(self):
|
def _update_alias(self) -> TYPE_RESPONSE:
|
||||||
function_name = unquote(self.path.rsplit("/")[-3])
|
function_name = unquote(self.path.rsplit("/")[-3])
|
||||||
alias_name = unquote(self.path.rsplit("/", 2)[-1])
|
alias_name = unquote(self.path.rsplit("/", 2)[-1])
|
||||||
params = json.loads(self.body)
|
params = json.loads(self.body)
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
ARN = namedtuple("ARN", ["region", "account", "function_name", "version"])
|
ARN = namedtuple("ARN", ["region", "account", "function_name", "version"])
|
||||||
LAYER_ARN = namedtuple("LAYER_ARN", ["region", "account", "layer_name", "version"])
|
LAYER_ARN = namedtuple("LAYER_ARN", ["region", "account", "layer_name", "version"])
|
||||||
|
|
||||||
|
|
||||||
def make_arn(resource_type, region, account, name):
|
def make_arn(resource_type: str, region: str, account: str, name: str) -> str:
|
||||||
return "arn:aws:lambda:{0}:{1}:{2}:{3}".format(region, account, resource_type, name)
|
return "arn:aws:lambda:{0}:{1}:{2}:{3}".format(region, account, resource_type, name)
|
||||||
|
|
||||||
|
|
||||||
@ -13,7 +14,9 @@ make_function_arn = partial(make_arn, "function")
|
|||||||
make_layer_arn = partial(make_arn, "layer")
|
make_layer_arn = partial(make_arn, "layer")
|
||||||
|
|
||||||
|
|
||||||
def make_ver_arn(resource_type, region, account, name, version="1"):
|
def make_ver_arn(
|
||||||
|
resource_type: str, region: str, account: str, name: str, version: str = "1"
|
||||||
|
) -> str:
|
||||||
arn = make_arn(resource_type, region, account, name)
|
arn = make_arn(resource_type, region, account, name)
|
||||||
return "{0}:{1}".format(arn, version)
|
return "{0}:{1}".format(arn, version)
|
||||||
|
|
||||||
@ -22,7 +25,7 @@ make_function_ver_arn = partial(make_ver_arn, "function")
|
|||||||
make_layer_ver_arn = partial(make_ver_arn, "layer")
|
make_layer_ver_arn = partial(make_ver_arn, "layer")
|
||||||
|
|
||||||
|
|
||||||
def split_arn(arn_type, arn):
|
def split_arn(arn_type: Callable[[str, str, str, str], str], arn: str) -> Any:
|
||||||
arn = arn.replace("arn:aws:lambda:", "")
|
arn = arn.replace("arn:aws:lambda:", "")
|
||||||
|
|
||||||
region, account, _, name, version = arn.split(":")
|
region, account, _, name, version = arn.split(":")
|
||||||
|
@ -175,14 +175,14 @@ def str_to_rfc_1123_datetime(value):
|
|||||||
return datetime.datetime.strptime(value, RFC1123)
|
return datetime.datetime.strptime(value, RFC1123)
|
||||||
|
|
||||||
|
|
||||||
def unix_time(dt: datetime.datetime = None) -> datetime.datetime:
|
def unix_time(dt: datetime.datetime = None) -> int:
|
||||||
dt = dt or datetime.datetime.utcnow()
|
dt = dt or datetime.datetime.utcnow()
|
||||||
epoch = datetime.datetime.utcfromtimestamp(0)
|
epoch = datetime.datetime.utcfromtimestamp(0)
|
||||||
delta = dt - epoch
|
delta = dt - epoch
|
||||||
return (delta.days * 86400) + (delta.seconds + (delta.microseconds / 1e6))
|
return (delta.days * 86400) + (delta.seconds + (delta.microseconds / 1e6))
|
||||||
|
|
||||||
|
|
||||||
def unix_time_millis(dt=None):
|
def unix_time_millis(dt: datetime = None) -> int:
|
||||||
return unix_time(dt) * 1000.0
|
return unix_time(dt) * 1000.0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1917,7 +1917,7 @@ class IAMBackend(BaseBackend):
|
|||||||
return role
|
return role
|
||||||
raise IAMNotFoundException("Role {0} not found".format(role_name))
|
raise IAMNotFoundException("Role {0} not found".format(role_name))
|
||||||
|
|
||||||
def get_role_by_arn(self, arn):
|
def get_role_by_arn(self, arn: str) -> Role:
|
||||||
for role in self.get_roles():
|
for role in self.get_roles():
|
||||||
if role.arn == arn:
|
if role.arn == arn:
|
||||||
return role
|
return role
|
||||||
|
@ -68,37 +68,37 @@ def allow_unknown_region():
|
|||||||
return os.environ.get("MOTO_ALLOW_NONEXISTENT_REGION", "false").lower() == "true"
|
return os.environ.get("MOTO_ALLOW_NONEXISTENT_REGION", "false").lower() == "true"
|
||||||
|
|
||||||
|
|
||||||
def moto_server_port():
|
def moto_server_port() -> str:
|
||||||
return os.environ.get("MOTO_PORT") or "5000"
|
return os.environ.get("MOTO_PORT") or "5000"
|
||||||
|
|
||||||
|
|
||||||
@lru_cache()
|
@lru_cache()
|
||||||
def moto_server_host():
|
def moto_server_host() -> str:
|
||||||
if is_docker():
|
if is_docker():
|
||||||
return get_docker_host()
|
return get_docker_host()
|
||||||
else:
|
else:
|
||||||
return "http://host.docker.internal"
|
return "http://host.docker.internal"
|
||||||
|
|
||||||
|
|
||||||
def moto_lambda_image():
|
def moto_lambda_image() -> str:
|
||||||
return os.environ.get("MOTO_DOCKER_LAMBDA_IMAGE", "lambci/lambda")
|
return os.environ.get("MOTO_DOCKER_LAMBDA_IMAGE", "lambci/lambda")
|
||||||
|
|
||||||
|
|
||||||
def moto_network_name():
|
def moto_network_name() -> str:
|
||||||
return os.environ.get("MOTO_DOCKER_NETWORK_NAME")
|
return os.environ.get("MOTO_DOCKER_NETWORK_NAME")
|
||||||
|
|
||||||
|
|
||||||
def moto_network_mode():
|
def moto_network_mode() -> str:
|
||||||
return os.environ.get("MOTO_DOCKER_NETWORK_MODE")
|
return os.environ.get("MOTO_DOCKER_NETWORK_MODE")
|
||||||
|
|
||||||
|
|
||||||
def test_server_mode_endpoint():
|
def test_server_mode_endpoint() -> str:
|
||||||
return os.environ.get(
|
return os.environ.get(
|
||||||
"TEST_SERVER_MODE_ENDPOINT", f"http://localhost:{moto_server_port()}"
|
"TEST_SERVER_MODE_ENDPOINT", f"http://localhost:{moto_server_port()}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_docker():
|
def is_docker() -> bool:
|
||||||
path = pathlib.Path("/proc/self/cgroup")
|
path = pathlib.Path("/proc/self/cgroup")
|
||||||
return (
|
return (
|
||||||
os.path.exists("/.dockerenv")
|
os.path.exists("/.dockerenv")
|
||||||
@ -107,7 +107,7 @@ def is_docker():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_docker_host():
|
def get_docker_host() -> str:
|
||||||
try:
|
try:
|
||||||
cmd = "curl -s --unix-socket /run/docker.sock http://docker/containers/$HOSTNAME/json"
|
cmd = "curl -s --unix-socket /run/docker.sock http://docker/containers/$HOSTNAME/json"
|
||||||
container_info = os.popen(cmd).read()
|
container_info = os.popen(cmd).read()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import functools
|
import functools
|
||||||
import requests.adapters
|
import requests.adapters
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
from moto import settings
|
from moto import settings
|
||||||
|
|
||||||
@ -8,7 +9,7 @@ _orig_adapter_send = requests.adapters.HTTPAdapter.send
|
|||||||
|
|
||||||
|
|
||||||
class DockerModel:
|
class DockerModel:
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
self.__docker_client = None
|
self.__docker_client = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -36,7 +37,7 @@ class DockerModel:
|
|||||||
return self.__docker_client
|
return self.__docker_client
|
||||||
|
|
||||||
|
|
||||||
def parse_image_ref(image_name):
|
def parse_image_ref(image_name: str) -> Tuple[str, str]:
|
||||||
# podman does not support short container image name out of box - try to make a full name
|
# podman does not support short container image name out of box - try to make a full name
|
||||||
# See ParseDockerRef() in https://github.com/distribution/distribution/blob/main/reference/normalize.go
|
# See ParseDockerRef() in https://github.com/distribution/distribution/blob/main/reference/normalize.go
|
||||||
parts = image_name.split("/")
|
parts = image_name.split("/")
|
||||||
|
@ -18,7 +18,7 @@ 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]
|
||||||
files= moto/acm,moto/amp,moto/apigateway,moto/apigatewayv2,moto/applicationautoscaling/,moto/appsync,moto/athena,moto/autoscaling
|
files= moto/a*
|
||||||
show_column_numbers=True
|
show_column_numbers=True
|
||||||
show_error_codes = True
|
show_error_codes = True
|
||||||
disable_error_code=abstract
|
disable_error_code=abstract
|
||||||
|
Loading…
Reference in New Issue
Block a user