Techdebt: Improve type annotations (#7124)

This commit is contained in:
Bert Blommers 2023-12-14 20:35:36 -01:00 committed by GitHub
parent 43d3f14d08
commit 9c58c689ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 211 additions and 184 deletions

View File

@ -6,6 +6,7 @@ import os
import re import re
from collections import OrderedDict, defaultdict from collections import OrderedDict, defaultdict
from typing import ( from typing import (
TYPE_CHECKING,
Any, Any,
Callable, Callable,
ClassVar, ClassVar,
@ -41,6 +42,13 @@ log = logging.getLogger(__name__)
JINJA_ENVS: Dict[type, Environment] = {} JINJA_ENVS: Dict[type, Environment] = {}
if TYPE_CHECKING:
from typing_extensions import ParamSpec
P = ParamSpec("P")
T = TypeVar("T")
ResponseShape = TypeVar("ResponseShape", bound="BaseResponse") ResponseShape = TypeVar("ResponseShape", bound="BaseResponse")
@ -173,13 +181,13 @@ class ActionAuthenticatorMixin(object):
self._authenticate_and_authorize_action(S3IAMRequest, resource) self._authenticate_and_authorize_action(S3IAMRequest, resource)
@staticmethod @staticmethod
def set_initial_no_auth_action_count(initial_no_auth_action_count: int) -> Callable[..., Callable[..., TYPE_RESPONSE]]: # type: ignore[misc] def set_initial_no_auth_action_count(
initial_no_auth_action_count: int,
) -> "Callable[[Callable[P, T]], Callable[P, T]]":
_test_server_mode_endpoint = settings.test_server_mode_endpoint() _test_server_mode_endpoint = settings.test_server_mode_endpoint()
def decorator( def decorator(function: "Callable[P, T]") -> "Callable[P, T]":
function: Callable[..., TYPE_RESPONSE] def wrapper(*args: "P.args", **kwargs: "P.kwargs") -> T:
) -> Callable[..., TYPE_RESPONSE]:
def wrapper(*args: Any, **kwargs: Any) -> TYPE_RESPONSE:
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
response = requests.post( response = requests.post(
f"{_test_server_mode_endpoint}/moto-api/reset-auth", f"{_test_server_mode_endpoint}/moto-api/reset-auth",

View File

@ -277,7 +277,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, tests/test_core/test_mock_all.py, tests/test_core/test_decorator_calls.py, tests/test_core/test_responses_module.py, tests/test_core/test_mypy.py files= moto, tests/test_core/
show_column_numbers=True show_column_numbers=True
show_error_codes = True show_error_codes = True
disable_error_code=abstract disable_error_code=abstract

View File

@ -1,4 +1,5 @@
import os import os
from typing import Dict, Optional
from unittest import SkipTest from unittest import SkipTest
import requests import requests
@ -13,7 +14,7 @@ BASE_URL = f"http://localhost:{SERVER_PORT}/"
class TestAccountIdResolution: class TestAccountIdResolution:
def setup_method(self): def setup_method(self) -> None:
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest( raise SkipTest(
"No point in testing this in ServerMode, as we already start our own server" "No point in testing this in ServerMode, as we already start our own server"
@ -21,10 +22,10 @@ class TestAccountIdResolution:
self.server = ThreadedMotoServer(port=SERVER_PORT, verbose=False) self.server = ThreadedMotoServer(port=SERVER_PORT, verbose=False)
self.server.start() self.server.start()
def teardown_method(self): def teardown_method(self) -> None:
self.server.stop() self.server.stop()
def test_environment_variable_takes_precedence(self): def test_environment_variable_takes_precedence(self) -> None:
# Verify ACCOUNT ID is standard # Verify ACCOUNT ID is standard
resp = self._get_caller_identity() resp = self._get_caller_identity()
assert self._get_account_id(resp) == ACCOUNT_ID assert self._get_account_id(resp) == ACCOUNT_ID
@ -51,7 +52,9 @@ class TestAccountIdResolution:
resp = self._get_caller_identity() resp = self._get_caller_identity()
assert self._get_account_id(resp) == ACCOUNT_ID assert self._get_account_id(resp) == ACCOUNT_ID
def _get_caller_identity(self, extra_headers=None): def _get_caller_identity(
self, extra_headers: Optional[Dict[str, str]] = None
) -> requests.Response:
data = "Action=GetCallerIdentity&Version=2011-06-15" data = "Action=GetCallerIdentity&Version=2011-06-15"
headers = { headers = {
"Authorization": "AWS4-HMAC-SHA256 Credential=abcd/20010101/us-east-2/sts/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=...", "Authorization": "AWS4-HMAC-SHA256 Credential=abcd/20010101/us-east-2/sts/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=...",
@ -61,6 +64,6 @@ class TestAccountIdResolution:
headers.update(extra_headers or {}) headers.update(extra_headers or {})
return requests.post(f"{BASE_URL}", headers=headers, data=data) return requests.post(f"{BASE_URL}", headers=headers, data=data)
def _get_account_id(self, resp): def _get_account_id(self, resp: requests.Response) -> str:
data = xmltodict.parse(resp.content) data = xmltodict.parse(resp.content)
return data["GetCallerIdentityResponse"]["GetCallerIdentityResult"]["Account"] return data["GetCallerIdentityResponse"]["GetCallerIdentityResult"]["Account"]

View File

@ -1,4 +1,5 @@
import json import json
from typing import Any, Dict, Optional
from uuid import uuid4 from uuid import uuid4
import boto3 import boto3
@ -11,16 +12,16 @@ from moto.core import set_initial_no_auth_action_count
@mock_iam @mock_iam
def create_user_with_access_key(user_name="test-user"): def create_user_with_access_key(user_name: str = "test-user") -> Dict[str, str]:
client = boto3.client("iam", region_name="us-east-1") client = boto3.client("iam", region_name="us-east-1")
client.create_user(UserName=user_name) client.create_user(UserName=user_name)
return client.create_access_key(UserName=user_name)["AccessKey"] return client.create_access_key(UserName=user_name)["AccessKey"]
@mock_iam @mock_iam
def create_user_with_access_key_and_inline_policy( def create_user_with_access_key_and_inline_policy( # type: ignore[misc]
user_name, policy_document, policy_name="policy1" user_name: str, policy_document: Dict[str, Any], policy_name: str = "policy1"
): ) -> Dict[str, str]:
client = boto3.client("iam", region_name="us-east-1") client = boto3.client("iam", region_name="us-east-1")
client.create_user(UserName=user_name) client.create_user(UserName=user_name)
client.put_user_policy( client.put_user_policy(
@ -32,9 +33,9 @@ def create_user_with_access_key_and_inline_policy(
@mock_iam @mock_iam
def create_user_with_access_key_and_attached_policy( def create_user_with_access_key_and_attached_policy( # type: ignore[misc]
user_name, policy_document, policy_name="policy1" user_name: str, policy_document: Dict[str, Any], policy_name: str = "policy1"
): ) -> Dict[str, str]:
client = boto3.client("iam", region_name="us-east-1") client = boto3.client("iam", region_name="us-east-1")
client.create_user(UserName=user_name) client.create_user(UserName=user_name)
policy_arn = client.create_policy( policy_arn = client.create_policy(
@ -45,13 +46,13 @@ def create_user_with_access_key_and_attached_policy(
@mock_iam @mock_iam
def create_user_with_access_key_and_multiple_policies( def create_user_with_access_key_and_multiple_policies( # type: ignore[misc]
user_name, user_name: str,
inline_policy_document, inline_policy_document: Dict[str, Any],
attached_policy_document, attached_policy_document: Dict[str, Any],
inline_policy_name="policy1", inline_policy_name: str = "policy1",
attached_policy_name="policy1", attached_policy_name: str = "policy1",
): ) -> Dict[str, str]:
client = boto3.client("iam", region_name="us-east-1") client = boto3.client("iam", region_name="us-east-1")
client.create_user(UserName=user_name) client.create_user(UserName=user_name)
policy_arn = client.create_policy( policy_arn = client.create_policy(
@ -68,8 +69,11 @@ def create_user_with_access_key_and_multiple_policies(
def create_group_with_attached_policy_and_add_user( def create_group_with_attached_policy_and_add_user(
user_name, policy_document, group_name="test-group", policy_name=None user_name: str,
): policy_document: Dict[str, Any],
group_name: str = "test-group",
policy_name: Optional[str] = None,
) -> None:
if not policy_name: if not policy_name:
policy_name = str(uuid4()) policy_name = str(uuid4())
client = boto3.client("iam", region_name="us-east-1") client = boto3.client("iam", region_name="us-east-1")
@ -82,8 +86,11 @@ def create_group_with_attached_policy_and_add_user(
def create_group_with_inline_policy_and_add_user( def create_group_with_inline_policy_and_add_user(
user_name, policy_document, group_name="test-group", policy_name="policy1" user_name: str,
): policy_document: Dict[str, Any],
group_name: str = "test-group",
policy_name: str = "policy1",
) -> None:
client = boto3.client("iam", region_name="us-east-1") client = boto3.client("iam", region_name="us-east-1")
client.create_group(GroupName=group_name) client.create_group(GroupName=group_name)
client.put_group_policy( client.put_group_policy(
@ -95,13 +102,13 @@ def create_group_with_inline_policy_and_add_user(
def create_group_with_multiple_policies_and_add_user( def create_group_with_multiple_policies_and_add_user(
user_name, user_name: str,
inline_policy_document, inline_policy_document: Dict[str, Any],
attached_policy_document, attached_policy_document: Dict[str, Any],
group_name="test-group", group_name: str = "test-group",
inline_policy_name="policy1", inline_policy_name: str = "policy1",
attached_policy_name=None, attached_policy_name: Optional[str] = None,
): ) -> None:
if not attached_policy_name: if not attached_policy_name:
attached_policy_name = str(uuid4()) attached_policy_name = str(uuid4())
client = boto3.client("iam", region_name="us-east-1") client = boto3.client("iam", region_name="us-east-1")
@ -121,13 +128,13 @@ def create_group_with_multiple_policies_and_add_user(
@mock_iam @mock_iam
@mock_sts @mock_sts
def create_role_with_attached_policy_and_assume_it( def create_role_with_attached_policy_and_assume_it( # type: ignore[misc]
role_name, role_name: str,
trust_policy_document, trust_policy_document: Dict[str, Any],
policy_document, policy_document: Dict[str, Any],
session_name="session1", session_name: str = "session1",
policy_name="policy1", policy_name: str = "policy1",
): ) -> Dict[str, str]:
iam_client = boto3.client("iam", region_name="us-east-1") iam_client = boto3.client("iam", region_name="us-east-1")
sts_client = boto3.client("sts", region_name="us-east-1") sts_client = boto3.client("sts", region_name="us-east-1")
role_arn = iam_client.create_role( role_arn = iam_client.create_role(
@ -144,13 +151,13 @@ def create_role_with_attached_policy_and_assume_it(
@mock_iam @mock_iam
@mock_sts @mock_sts
def create_role_with_inline_policy_and_assume_it( def create_role_with_inline_policy_and_assume_it( # type: ignore[misc]
role_name, role_name: str,
trust_policy_document, trust_policy_document: Dict[str, Any],
policy_document, policy_document: Dict[str, Any],
session_name="session1", session_name: str = "session1",
policy_name="policy1", policy_name: str = "policy1",
): ) -> Dict[str, str]:
iam_client = boto3.client("iam", region_name="us-east-1") iam_client = boto3.client("iam", region_name="us-east-1")
sts_client = boto3.client("sts", region_name="us-east-1") sts_client = boto3.client("sts", region_name="us-east-1")
role_arn = iam_client.create_role( role_arn = iam_client.create_role(
@ -168,7 +175,7 @@ def create_role_with_inline_policy_and_assume_it(
@set_initial_no_auth_action_count(0) @set_initial_no_auth_action_count(0)
@mock_iam @mock_iam
def test_invalid_client_token_id(): def test_invalid_client_token_id() -> None:
client = boto3.client( client = boto3.client(
"iam", "iam",
region_name="us-east-1", region_name="us-east-1",
@ -185,7 +192,7 @@ def test_invalid_client_token_id():
@set_initial_no_auth_action_count(0) @set_initial_no_auth_action_count(0)
@mock_ec2 @mock_ec2
def test_auth_failure(): def test_auth_failure() -> None:
client = boto3.client( client = boto3.client(
"ec2", "ec2",
region_name="us-east-1", region_name="us-east-1",
@ -204,7 +211,7 @@ def test_auth_failure():
@set_initial_no_auth_action_count(2) @set_initial_no_auth_action_count(2)
@mock_iam @mock_iam
def test_signature_does_not_match(): def test_signature_does_not_match() -> None:
access_key = create_user_with_access_key() access_key = create_user_with_access_key()
client = boto3.client( client = boto3.client(
"iam", "iam",
@ -224,7 +231,7 @@ def test_signature_does_not_match():
@set_initial_no_auth_action_count(2) @set_initial_no_auth_action_count(2)
@mock_ec2 @mock_ec2
def test_auth_failure_with_valid_access_key_id(): def test_auth_failure_with_valid_access_key_id() -> None:
access_key = create_user_with_access_key() access_key = create_user_with_access_key()
client = boto3.client( client = boto3.client(
"ec2", "ec2",
@ -244,7 +251,7 @@ def test_auth_failure_with_valid_access_key_id():
@set_initial_no_auth_action_count(2) @set_initial_no_auth_action_count(2)
@mock_ec2 @mock_ec2
def test_access_denied_with_no_policy(): def test_access_denied_with_no_policy() -> None:
user_name = "test-user" user_name = "test-user"
access_key = create_user_with_access_key(user_name) access_key = create_user_with_access_key(user_name)
client = boto3.client( client = boto3.client(
@ -265,7 +272,7 @@ def test_access_denied_with_no_policy():
@set_initial_no_auth_action_count(3) @set_initial_no_auth_action_count(3)
@mock_ec2 @mock_ec2
def test_access_denied_with_not_allowing_policy(): def test_access_denied_with_not_allowing_policy() -> None:
user_name = "test-user" user_name = "test-user"
inline_policy_document = { inline_policy_document = {
"Version": "2012-10-17", "Version": "2012-10-17",
@ -292,7 +299,7 @@ def test_access_denied_with_not_allowing_policy():
@set_initial_no_auth_action_count(3) @set_initial_no_auth_action_count(3)
@mock_sts @mock_sts
def test_access_denied_explicitly_on_specific_resource(): def test_access_denied_explicitly_on_specific_resource() -> None:
user_name = "test-user" user_name = "test-user"
forbidden_role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/forbidden_explicitly" forbidden_role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/forbidden_explicitly"
allowed_role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/allowed_implictly" allowed_role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/allowed_implictly"
@ -333,7 +340,7 @@ def test_access_denied_explicitly_on_specific_resource():
@set_initial_no_auth_action_count(3) @set_initial_no_auth_action_count(3)
@mock_ec2 @mock_ec2
def test_access_denied_for_run_instances(): def test_access_denied_for_run_instances() -> None:
# https://github.com/getmoto/moto/issues/2774 # https://github.com/getmoto/moto/issues/2774
# The run-instances method was broken between botocore versions 1.15.8 and 1.15.12 # The run-instances method was broken between botocore versions 1.15.8 and 1.15.12
# This was due to the inclusion of '"idempotencyToken":true' in the response, somehow altering the signature and breaking the authentication # This was due to the inclusion of '"idempotencyToken":true' in the response, somehow altering the signature and breaking the authentication
@ -366,7 +373,7 @@ def test_access_denied_for_run_instances():
@set_initial_no_auth_action_count(3) @set_initial_no_auth_action_count(3)
@mock_ec2 @mock_ec2
def test_access_denied_with_denying_policy(): def test_access_denied_with_denying_policy() -> None:
user_name = "test-user" user_name = "test-user"
inline_policy_document = { inline_policy_document = {
"Version": "2012-10-17", "Version": "2012-10-17",
@ -396,7 +403,7 @@ def test_access_denied_with_denying_policy():
@set_initial_no_auth_action_count(3) @set_initial_no_auth_action_count(3)
@mock_sts @mock_sts
def test_get_caller_identity_allowed_with_denying_policy(): def test_get_caller_identity_allowed_with_denying_policy() -> None:
user_name = "test-user" user_name = "test-user"
inline_policy_document = { inline_policy_document = {
"Version": "2012-10-17", "Version": "2012-10-17",
@ -421,7 +428,7 @@ def test_get_caller_identity_allowed_with_denying_policy():
@set_initial_no_auth_action_count(3) @set_initial_no_auth_action_count(3)
@mock_ec2 @mock_ec2
def test_allowed_with_wildcard_action(): def test_allowed_with_wildcard_action() -> None:
user_name = "test-user" user_name = "test-user"
inline_policy_document = { inline_policy_document = {
"Version": "2012-10-17", "Version": "2012-10-17",
@ -441,7 +448,7 @@ def test_allowed_with_wildcard_action():
@set_initial_no_auth_action_count(4) @set_initial_no_auth_action_count(4)
@mock_iam @mock_iam
def test_allowed_with_explicit_action_in_attached_policy(): def test_allowed_with_explicit_action_in_attached_policy() -> None:
user_name = "test-user" user_name = "test-user"
attached_policy_document = { attached_policy_document = {
"Version": "2012-10-17", "Version": "2012-10-17",
@ -462,7 +469,7 @@ def test_allowed_with_explicit_action_in_attached_policy():
@set_initial_no_auth_action_count(8) @set_initial_no_auth_action_count(8)
@mock_s3 @mock_s3
@mock_iam @mock_iam
def test_s3_access_denied_with_denying_attached_group_policy(): def test_s3_access_denied_with_denying_attached_group_policy() -> None:
user_name = "test-user" user_name = "test-user"
attached_policy_document = { attached_policy_document = {
"Version": "2012-10-17", "Version": "2012-10-17",
@ -496,7 +503,7 @@ def test_s3_access_denied_with_denying_attached_group_policy():
@set_initial_no_auth_action_count(6) @set_initial_no_auth_action_count(6)
@mock_s3 @mock_s3
@mock_iam @mock_iam
def test_s3_access_denied_with_denying_inline_group_policy(): def test_s3_access_denied_with_denying_inline_group_policy() -> None:
user_name = "test-user" user_name = "test-user"
bucket_name = "test-bucket" bucket_name = "test-bucket"
inline_policy_document = { inline_policy_document = {
@ -530,7 +537,7 @@ def test_s3_access_denied_with_denying_inline_group_policy():
@set_initial_no_auth_action_count(10) @set_initial_no_auth_action_count(10)
@mock_iam @mock_iam
@mock_ec2 @mock_ec2
def test_access_denied_with_many_irrelevant_policies(): def test_access_denied_with_many_irrelevant_policies() -> None:
user_name = "test-user" user_name = "test-user"
inline_policy_document = { inline_policy_document = {
"Version": "2012-10-17", "Version": "2012-10-17",
@ -581,7 +588,7 @@ def test_access_denied_with_many_irrelevant_policies():
@mock_sts @mock_sts
@mock_ec2 @mock_ec2
@mock_elbv2 @mock_elbv2
def test_allowed_with_temporary_credentials(): def test_allowed_with_temporary_credentials() -> None:
role_name = "test-role" role_name = "test-role"
trust_policy_document = { trust_policy_document = {
"Version": "2012-10-17", "Version": "2012-10-17",
@ -632,7 +639,7 @@ def test_allowed_with_temporary_credentials():
@mock_iam @mock_iam
@mock_sts @mock_sts
@mock_rds @mock_rds
def test_access_denied_with_temporary_credentials(): def test_access_denied_with_temporary_credentials() -> None:
role_name = "test-role" role_name = "test-role"
session_name = "test-session" session_name = "test-session"
trust_policy_document = { trust_policy_document = {
@ -675,7 +682,7 @@ def test_access_denied_with_temporary_credentials():
@set_initial_no_auth_action_count(3) @set_initial_no_auth_action_count(3)
@mock_iam @mock_iam
def test_get_user_from_credentials(): def test_get_user_from_credentials() -> None:
user_name = "new-test-user" user_name = "new-test-user"
inline_policy_document = { inline_policy_document = {
"Version": "2012-10-17", "Version": "2012-10-17",
@ -695,7 +702,7 @@ def test_get_user_from_credentials():
@set_initial_no_auth_action_count(0) @set_initial_no_auth_action_count(0)
@mock_s3 @mock_s3
def test_s3_invalid_access_key_id(): def test_s3_invalid_access_key_id() -> None:
client = boto3.client( client = boto3.client(
"s3", "s3",
region_name="us-east-1", region_name="us-east-1",
@ -715,7 +722,7 @@ def test_s3_invalid_access_key_id():
@set_initial_no_auth_action_count(3) @set_initial_no_auth_action_count(3)
@mock_s3 @mock_s3
@mock_iam @mock_iam
def test_s3_signature_does_not_match(): def test_s3_signature_does_not_match() -> None:
bucket_name = "test-bucket" bucket_name = "test-bucket"
access_key = create_user_with_access_key() access_key = create_user_with_access_key()
client = boto3.client( client = boto3.client(
@ -738,7 +745,7 @@ def test_s3_signature_does_not_match():
@set_initial_no_auth_action_count(7) @set_initial_no_auth_action_count(7)
@mock_s3 @mock_s3
@mock_iam @mock_iam
def test_s3_access_denied_not_action(): def test_s3_access_denied_not_action() -> None:
user_name = "test-user" user_name = "test-user"
bucket_name = "test-bucket" bucket_name = "test-bucket"
inline_policy_document = { inline_policy_document = {
@ -773,7 +780,7 @@ def test_s3_access_denied_not_action():
@mock_iam @mock_iam
@mock_sts @mock_sts
@mock_s3 @mock_s3
def test_s3_invalid_token_with_temporary_credentials(): def test_s3_invalid_token_with_temporary_credentials() -> None:
role_name = "test-role" role_name = "test-role"
session_name = "test-session" session_name = "test-session"
bucket_name = "test-bucket-888" bucket_name = "test-bucket-888"
@ -876,17 +883,11 @@ def test_allow_key_access_using_resource_arn() -> None:
@set_initial_no_auth_action_count(3) @set_initial_no_auth_action_count(3)
@mock_ssm @mock_ssm
@mock_iam @mock_iam
def test_ssm_service(): def test_ssm_service() -> None:
user_name = "test-user" user_name = "test-user"
policy_doc = { policy_doc = {
"Version": "2012-10-17", "Version": "2012-10-17",
"Statement": [ "Statement": [{"Action": ["ssm:*"], "Effect": "Allow", "Resource": ["*"]}],
{
"Action": ["ssm:*"],
"Effect": "Allow",
"Resource": ["*"],
},
],
} }
access_key = create_user_with_access_key_and_inline_policy(user_name, policy_doc) access_key = create_user_with_access_key_and_inline_policy(user_name, policy_doc)

View File

@ -1,6 +1,7 @@
import random import random
import time import time
from threading import Thread from threading import Thread
from typing import Any, List, Optional
import pytest import pytest
@ -12,32 +13,32 @@ from moto.elbv2.models import ELBv2Backend
class ExampleBackend(BaseBackend): class ExampleBackend(BaseBackend):
def __init__(self, region_name, account_id): def __init__(self, region_name: str, account_id: str):
super().__init__(region_name, account_id) super().__init__(region_name, account_id)
def test_backend_dict_returns_nothing_by_default(): def test_backend_dict_returns_nothing_by_default() -> None:
backend_dict = BackendDict(ExampleBackend, "ebs") backend_dict = BackendDict(ExampleBackend, "ebs")
assert list(backend_dict.items()) == [] assert list(backend_dict.items()) == []
def test_account_specific_dict_contains_known_regions(): def test_account_specific_dict_contains_known_regions() -> None:
backend_dict = BackendDict(ExampleBackend, "ec2") backend_dict = BackendDict(ExampleBackend, "ec2")
assert isinstance(backend_dict["account"]["eu-north-1"], ExampleBackend) assert isinstance(backend_dict["account"]["eu-north-1"], ExampleBackend)
def test_backend_dict_does_not_contain_unknown_regions(): def test_backend_dict_does_not_contain_unknown_regions() -> None:
backend_dict = BackendDict(ExampleBackend, "ec2") backend_dict = BackendDict(ExampleBackend, "ec2")
assert "mars-south-1" not in backend_dict["account"] assert "mars-south-1" not in backend_dict["account"]
def test_backend_dict_fails_when_retrieving_unknown_regions(): def test_backend_dict_fails_when_retrieving_unknown_regions() -> None:
backend_dict = BackendDict(ExampleBackend, "ec2") backend_dict = BackendDict(ExampleBackend, "ec2")
with pytest.raises(KeyError): with pytest.raises(KeyError):
backend_dict["account"]["mars-south-1"] # pylint: disable=pointless-statement backend_dict["account"]["mars-south-1"] # pylint: disable=pointless-statement
def test_backend_dict_can_retrieve_for_specific_account(): def test_backend_dict_can_retrieve_for_specific_account() -> None:
backend_dict = BackendDict(ExampleBackend, "ec2") backend_dict = BackendDict(ExampleBackend, "ec2")
# Random account does not exist # Random account does not exist
@ -55,12 +56,12 @@ def test_backend_dict_can_retrieve_for_specific_account():
assert regional_backend.account_id == "012345" assert regional_backend.account_id == "012345"
def test_backend_dict_can_ignore_boto3_regions(): def test_backend_dict_can_ignore_boto3_regions() -> None:
backend_dict = BackendDict(ExampleBackend, "ec2", use_boto3_regions=False) backend_dict = BackendDict(ExampleBackend, "ec2", use_boto3_regions=False)
assert backend_dict["account"].get("us-east-1") is None assert backend_dict["account"].get("us-east-1") is None
def test_backend_dict_can_specify_additional_regions(): def test_backend_dict_can_specify_additional_regions() -> None:
backend_dict = BackendDict( backend_dict = BackendDict(
ExampleBackend, "ec2", additional_regions=["region1", "global"] ExampleBackend, "ec2", additional_regions=["region1", "global"]
)["123456"] )["123456"]
@ -74,15 +75,15 @@ def test_backend_dict_can_specify_additional_regions():
class TestMultiThreadedAccess: class TestMultiThreadedAccess:
class SlowExampleBackend(BaseBackend): class SlowExampleBackend(BaseBackend):
def __init__(self, region_name, account_id): def __init__(self, region_name: str, account_id: str):
super().__init__(region_name, account_id) super().__init__(region_name, account_id)
time.sleep(0.1) time.sleep(0.1)
self.data = [] self.data: List[int] = []
def setup_method(self): def setup_method(self) -> None:
self.backend = BackendDict(TestMultiThreadedAccess.SlowExampleBackend, "ec2") self.backend = BackendDict(TestMultiThreadedAccess.SlowExampleBackend, "ec2")
def test_access_a_slow_backend_concurrently(self): def test_access_a_slow_backend_concurrently(self) -> None:
"""None """None
Usecase that we want to avoid: Usecase that we want to avoid:
@ -103,7 +104,7 @@ class TestMultiThreadedAccess:
Thread 2 adds a new value to the list Thread 2 adds a new value to the list
""" """
def access(random_number): def access(random_number: int) -> None:
self.backend["123456789012"]["us-east-1"].data.append(random_number) self.backend["123456789012"]["us-east-1"].data.append(random_number)
threads = [] threads = []
@ -119,7 +120,7 @@ class TestMultiThreadedAccess:
assert len(self.backend["123456789012"]["us-east-1"].data) == 15 assert len(self.backend["123456789012"]["us-east-1"].data) == 15
def test_backend_dict_can_be_hashed(): def test_backend_dict_can_be_hashed() -> None:
hashes = [] hashes = []
for backend in [ExampleBackend, set, list, BaseBackend]: for backend in [ExampleBackend, set, list, BaseBackend]:
hashes.append(BackendDict(backend, "n/a").__hash__()) hashes.append(BackendDict(backend, "n/a").__hash__())
@ -127,7 +128,7 @@ def test_backend_dict_can_be_hashed():
assert len(set(hashes)) == 4 assert len(set(hashes)) == 4
def test_account_specific_dict_can_be_hashed(): def test_account_specific_dict_can_be_hashed() -> None:
hashes = [] hashes = []
ids = ["01234567912", "01234567911", "01234567913", "000000000000", "0"] ids = ["01234567912", "01234567911", "01234567913", "000000000000", "0"]
for accnt_id in ids: for accnt_id in ids:
@ -137,7 +138,12 @@ def test_account_specific_dict_can_be_hashed():
assert len(set(hashes)) == 5 assert len(set(hashes)) == 5
def _create_asb(account_id, backend=None, use_boto3_regions=False, regions=None): def _create_asb(
account_id: str,
backend: Any = None,
use_boto3_regions: bool = False,
regions: Optional[List[str]] = None,
) -> Any:
return AccountSpecificBackend( return AccountSpecificBackend(
service_name="ec2", service_name="ec2",
account_id=account_id, account_id=account_id,
@ -147,7 +153,7 @@ def _create_asb(account_id, backend=None, use_boto3_regions=False, regions=None)
) )
def test_multiple_backends_cache_behaviour(): def test_multiple_backends_cache_behaviour() -> None:
ec2 = BackendDict(EC2Backend, "ec2") ec2 = BackendDict(EC2Backend, "ec2")
ec2_useast1 = ec2[DEFAULT_ACCOUNT_ID]["us-east-1"] ec2_useast1 = ec2[DEFAULT_ACCOUNT_ID]["us-east-1"]
assert type(ec2_useast1) == EC2Backend assert type(ec2_useast1) == EC2Backend
@ -172,7 +178,7 @@ def test_multiple_backends_cache_behaviour():
assert type(as_1) == AutoScalingBackend assert type(as_1) == AutoScalingBackend
def test_backenddict_cache_hits_and_misses(): def test_backenddict_cache_hits_and_misses() -> None:
backend = BackendDict(ExampleBackend, "ebs") backend = BackendDict(ExampleBackend, "ebs")
backend.__getitem__.cache_clear() backend.__getitem__.cache_clear()
@ -213,7 +219,7 @@ def test_backenddict_cache_hits_and_misses():
assert backend.__getitem__.cache_info().currsize == 2 assert backend.__getitem__.cache_info().currsize == 2
def test_asb_cache_hits_and_misses(): def test_asb_cache_hits_and_misses() -> None:
backend = BackendDict(ExampleBackend, "ebs") backend = BackendDict(ExampleBackend, "ebs")
acb = backend["accnt_id"] acb = backend["accnt_id"]
acb.__getitem__.cache_clear() acb.__getitem__.cache_clear()

View File

@ -4,11 +4,11 @@ from moto import mock_sqs, settings
from tests import DEFAULT_ACCOUNT_ID from tests import DEFAULT_ACCOUNT_ID
def test_context_manager_returns_mock(): def test_context_manager_returns_mock() -> None:
with mock_sqs() as sqs_mock: with mock_sqs() as sqs_mock:
conn = boto3.client("sqs", region_name="us-west-1") conn = boto3.client("sqs", region_name="us-west-1")
conn.create_queue(QueueName="queue1") conn.create_queue(QueueName="queue1")
if not settings.TEST_SERVER_MODE: if not settings.TEST_SERVER_MODE:
backend = sqs_mock.backends[DEFAULT_ACCOUNT_ID]["us-west-1"] backend = sqs_mock.backends[DEFAULT_ACCOUNT_ID]["us-west-1"]
assert list(backend.queues.keys()) == ["queue1"] assert list(backend.queues.keys()) == ["queue1"] # type: ignore[attr-defined]

View File

@ -9,7 +9,7 @@ logger = logging.getLogger(__name__)
@requires_docker @requires_docker
@pytest.mark.order(0) @pytest.mark.order(0)
def test_docker_package_is_available(): def test_docker_package_is_available() -> None:
try: try:
import docker # noqa: F401 # pylint: disable=unused-import import docker # noqa: F401 # pylint: disable=unused-import
except ImportError as err: except ImportError as err:
@ -22,7 +22,7 @@ def test_docker_package_is_available():
@requires_docker @requires_docker
@pytest.mark.order(0) @pytest.mark.order(0)
def test_docker_is_running_and_available(): def test_docker_is_running_and_available() -> None:
import docker import docker
from docker.errors import DockerException from docker.errors import DockerException

View File

@ -11,7 +11,7 @@ from moto import mock_ec2
@mock_ec2 @mock_ec2
def test_describe_vpc_endpoint_services_bad_args(): def test_describe_vpc_endpoint_services_bad_args() -> None:
"""Verify exceptions are raised for bad arguments.""" """Verify exceptions are raised for bad arguments."""
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
@ -47,7 +47,7 @@ def test_describe_vpc_endpoint_services_bad_args():
@mock_ec2 @mock_ec2
def test_describe_vpc_default_endpoint_services(): def test_describe_vpc_default_endpoint_services() -> None:
"""Test successfull calls as well as the next_token arg.""" """Test successfull calls as well as the next_token arg."""
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")

View File

@ -5,13 +5,13 @@ from moto import mock_ec2, mock_s3
KEY = "AWS_ACCESS_KEY_ID" KEY = "AWS_ACCESS_KEY_ID"
def test_aws_keys_are_patched(): def test_aws_keys_are_patched() -> None:
with mock_ec2(): with mock_ec2():
patched_value = os.environ[KEY] patched_value = os.environ[KEY]
assert patched_value == "FOOBARKEY" assert patched_value == "FOOBARKEY"
def test_aws_keys_can_be_none(): def test_aws_keys_can_be_none() -> None:
""" """
Verify that the os.environ[KEY] can be None Verify that the os.environ[KEY] can be None
Patching the None-value shouldn't be an issue Patching the None-value shouldn't be an issue

View File

@ -1,3 +1,4 @@
from typing import Any, List
from unittest import SkipTest from unittest import SkipTest
import boto3 import boto3
@ -7,7 +8,7 @@ from moto import mock_s3, settings
@pytest.fixture(scope="function", name="aws_credentials") @pytest.fixture(scope="function", name="aws_credentials")
def fixture_aws_credentials(monkeypatch): def fixture_aws_credentials(monkeypatch: Any) -> None: # type: ignore[misc]
"""Mocked AWS Credentials for moto.""" """Mocked AWS Credentials for moto."""
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest("No point in testing this in ServerMode.") raise SkipTest("No point in testing this in ServerMode.")
@ -18,8 +19,8 @@ def fixture_aws_credentials(monkeypatch):
def test_mock_works_with_client_created_inside( def test_mock_works_with_client_created_inside(
aws_credentials, aws_credentials: Any, # pylint: disable=unused-argument
): # pylint: disable=unused-argument ) -> None:
m = mock_s3() m = mock_s3()
m.start() m.start()
client = boto3.client("s3", region_name="us-east-1") client = boto3.client("s3", region_name="us-east-1")
@ -30,8 +31,8 @@ def test_mock_works_with_client_created_inside(
def test_mock_works_with_client_created_outside( def test_mock_works_with_client_created_outside(
aws_credentials, aws_credentials: Any, # pylint: disable=unused-argument
): # pylint: disable=unused-argument ) -> None:
# Create the boto3 client first # Create the boto3 client first
outside_client = boto3.client("s3", region_name="us-east-1") outside_client = boto3.client("s3", region_name="us-east-1")
@ -50,8 +51,8 @@ def test_mock_works_with_client_created_outside(
def test_mock_works_with_resource_created_outside( def test_mock_works_with_resource_created_outside(
aws_credentials, aws_credentials: Any, # pylint: disable=unused-argument
): # pylint: disable=unused-argument ) -> None:
# Create the boto3 client first # Create the boto3 client first
outside_resource = boto3.resource("s3", region_name="us-east-1") outside_resource = boto3.resource("s3", region_name="us-east-1")
@ -68,7 +69,7 @@ def test_mock_works_with_resource_created_outside(
m.stop() m.stop()
def test_patch_can_be_called_on_a_mocked_client(): def test_patch_can_be_called_on_a_mocked_client() -> None:
# start S3 after the mock, ensuring that the client contains our event-handler # start S3 after the mock, ensuring that the client contains our event-handler
m = mock_s3() m = mock_s3()
m.start() m.start()
@ -90,14 +91,14 @@ def test_patch_can_be_called_on_a_mocked_client():
m.stop() m.stop()
def test_patch_client_does_not_work_for_random_parameters(): def test_patch_client_does_not_work_for_random_parameters() -> None:
from moto.core import patch_client from moto.core import patch_client
with pytest.raises(Exception, match="Argument sth should be of type boto3.client"): with pytest.raises(Exception, match="Argument sth should be of type boto3.client"):
patch_client("sth") patch_client("sth") # type: ignore[arg-type]
def test_patch_resource_does_not_work_for_random_parameters(): def test_patch_resource_does_not_work_for_random_parameters() -> None:
from moto.core import patch_resource from moto.core import patch_resource
with pytest.raises( with pytest.raises(
@ -107,16 +108,16 @@ def test_patch_resource_does_not_work_for_random_parameters():
class ImportantBusinessLogic: class ImportantBusinessLogic:
def __init__(self): def __init__(self) -> None:
self._s3 = boto3.client("s3", region_name="us-east-1") self._s3 = boto3.client("s3", region_name="us-east-1")
def do_important_things(self): def do_important_things(self) -> List[str]:
return self._s3.list_buckets()["Buckets"] return self._s3.list_buckets()["Buckets"]
def test_mock_works_when_replacing_client( def test_mock_works_when_replacing_client(
aws_credentials, aws_credentials: Any, # pylint: disable=unused-argument
): # pylint: disable=unused-argument ) -> None:
logic = ImportantBusinessLogic() logic = ImportantBusinessLogic()
m = mock_s3() m = mock_s3()

View File

@ -9,13 +9,13 @@ else:
@mock_ec2 @mock_ec2
def test_latest_meta_data(): def test_latest_meta_data() -> None:
res = requests.get(f"{BASE_URL}/latest/meta-data/") res = requests.get(f"{BASE_URL}/latest/meta-data/")
assert res.content == b"iam" assert res.content == b"iam"
@mock_ec2 @mock_ec2
def test_meta_data_iam(): def test_meta_data_iam() -> None:
res = requests.get(f"{BASE_URL}/latest/meta-data/iam") res = requests.get(f"{BASE_URL}/latest/meta-data/iam")
json_response = res.json() json_response = res.json()
default_role = json_response["security-credentials"]["default-role"] default_role = json_response["security-credentials"]["default-role"]
@ -26,13 +26,13 @@ def test_meta_data_iam():
@mock_ec2 @mock_ec2
def test_meta_data_security_credentials(): def test_meta_data_security_credentials() -> None:
res = requests.get(f"{BASE_URL}/latest/meta-data/iam/security-credentials/") res = requests.get(f"{BASE_URL}/latest/meta-data/iam/security-credentials/")
assert res.content == b"default-role" assert res.content == b"default-role"
@mock_ec2 @mock_ec2
def test_meta_data_default_role(): def test_meta_data_default_role() -> None:
res = requests.get( res = requests.get(
f"{BASE_URL}/latest/meta-data/iam/security-credentials/default-role" f"{BASE_URL}/latest/meta-data/iam/security-credentials/default-role"
) )

View File

@ -8,7 +8,7 @@ from moto import mock_dynamodb, mock_sns, settings
@mock_sns @mock_sns
def test_use_invalid_region(): def test_use_invalid_region() -> None:
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode will throw different errors") raise SkipTest("ServerMode will throw different errors")
client = boto3.client("sns", region_name="any-region") client = boto3.client("sns", region_name="any-region")
@ -19,14 +19,14 @@ def test_use_invalid_region():
@mock_sns @mock_sns
@mock.patch.dict(os.environ, {"AWS_DEFAULT_REGION": "us-east-2"}) @mock.patch.dict(os.environ, {"AWS_DEFAULT_REGION": "us-east-2"})
def test_use_region_from_env(): def test_use_region_from_env() -> None: # type: ignore[misc]
client = boto3.client("sns") client = boto3.client("sns")
assert client.list_platform_applications()["PlatformApplications"] == [] assert client.list_platform_applications()["PlatformApplications"] == []
@mock_sns @mock_sns
@mock.patch.dict(os.environ, {"AWS_DEFAULT_REGION": "any-region"}) @mock.patch.dict(os.environ, {"AWS_DEFAULT_REGION": "any-region"})
def test_use_unknown_region_from_env(): def test_use_unknown_region_from_env() -> None: # type: ignore[misc]
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest("Cannot set environemnt variables in ServerMode") raise SkipTest("Cannot set environemnt variables in ServerMode")
client = boto3.client("sns") client = boto3.client("sns")
@ -38,7 +38,7 @@ def test_use_unknown_region_from_env():
@mock_sns @mock_sns
@mock.patch.dict(os.environ, {"AWS_DEFAULT_REGION": "any-region"}) @mock.patch.dict(os.environ, {"AWS_DEFAULT_REGION": "any-region"})
@mock.patch.dict(os.environ, {"MOTO_ALLOW_NONEXISTENT_REGION": "trUe"}) @mock.patch.dict(os.environ, {"MOTO_ALLOW_NONEXISTENT_REGION": "trUe"})
def test_use_unknown_region_from_env_but_allow_it(): def test_use_unknown_region_from_env_but_allow_it() -> None: # type: ignore[misc]
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest("Cannot set environemnt variables in ServerMode") raise SkipTest("Cannot set environemnt variables in ServerMode")
client = boto3.client("sns") client = boto3.client("sns")
@ -47,7 +47,7 @@ def test_use_unknown_region_from_env_but_allow_it():
@mock_dynamodb @mock_dynamodb
@mock.patch.dict(os.environ, {"MOTO_ALLOW_NONEXISTENT_REGION": "trUe"}) @mock.patch.dict(os.environ, {"MOTO_ALLOW_NONEXISTENT_REGION": "trUe"})
def test_use_unknown_region_from_env_but_allow_it__dynamo(): def test_use_unknown_region_from_env_but_allow_it__dynamo() -> None: # type: ignore[misc]
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest("Cannot set environemnt variables in ServerMode") raise SkipTest("Cannot set environemnt variables in ServerMode")
dynamo_db = boto3.resource("dynamodb", region_name="test") dynamo_db = boto3.resource("dynamodb", region_name="test")

View File

@ -18,7 +18,7 @@ data_url = f"{base_url}/moto-api/data.json"
@mock_sqs @mock_sqs
def test_reset_api(): def test_reset_api() -> None:
conn = boto3.client("sqs", region_name="us-west-1") conn = boto3.client("sqs", region_name="us-west-1")
conn.create_queue(QueueName="queue1") conn.create_queue(QueueName="queue1")
assert len(conn.list_queues()["QueueUrls"]) == 1 assert len(conn.list_queues()["QueueUrls"]) == 1
@ -30,7 +30,7 @@ def test_reset_api():
@mock_sqs @mock_sqs
def test_data_api(): def test_data_api() -> None:
conn = boto3.client("sqs", region_name="us-west-1") conn = boto3.client("sqs", region_name="us-west-1")
conn.create_queue(QueueName="queue1") conn.create_queue(QueueName="queue1")
@ -41,7 +41,7 @@ def test_data_api():
@mock_s3 @mock_s3
def test_overwriting_s3_object_still_returns_data(): def test_overwriting_s3_object_still_returns_data() -> None:
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest("No point in testing this behaves the same in ServerMode") raise SkipTest("No point in testing this behaves the same in ServerMode")
s3 = boto3.client("s3", region_name="us-east-1") s3 = boto3.client("s3", region_name="us-east-1")
@ -53,7 +53,7 @@ def test_overwriting_s3_object_still_returns_data():
@mock_autoscaling @mock_autoscaling
def test_creation_error__data_api_still_returns_thing(): def test_creation_error__data_api_still_returns_thing() -> None:
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest("No point in testing this behaves the same in ServerMode") raise SkipTest("No point in testing this behaves the same in ServerMode")
# Timeline: # Timeline:
@ -78,7 +78,7 @@ def test_creation_error__data_api_still_returns_thing():
from moto.moto_api._internal.urls import response_instance from moto.moto_api._internal.urls import response_instance
_, _, x = response_instance.model_data(None, None, None) _, _, x = response_instance.model_data(None, "None", None)
as_objects = json.loads(x)["autoscaling"] as_objects = json.loads(x)["autoscaling"]
assert len(as_objects["FakeAutoScalingGroup"]) >= 1 assert len(as_objects["FakeAutoScalingGroup"]) >= 1
@ -87,7 +87,7 @@ def test_creation_error__data_api_still_returns_thing():
assert "test_asg" in names assert "test_asg" in names
def test_model_data_is_emptied_as_necessary(): def test_model_data_is_emptied_as_necessary() -> None:
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest("We're only interested in the decorator performance here") raise SkipTest("We're only interested in the decorator performance here")
@ -97,24 +97,24 @@ def test_model_data_is_emptied_as_necessary():
# No instances exist, because we have just reset it # No instances exist, because we have just reset it
for classes_per_service in model_data.values(): for classes_per_service in model_data.values():
for _class in classes_per_service.values(): for _class in classes_per_service.values():
assert _class.instances == [] assert _class.instances == [] # type: ignore[attr-defined]
with mock_sqs(): with mock_sqs():
# When just starting a mock, it is empty # When just starting a mock, it is empty
for classes_per_service in model_data.values(): for classes_per_service in model_data.values():
for _class in classes_per_service.values(): for _class in classes_per_service.values():
assert _class.instances == [] assert _class.instances == [] # type: ignore[attr-defined]
# After creating a queue, some data will be present # After creating a queue, some data will be present
conn = boto3.client("sqs", region_name="us-west-1") conn = boto3.client("sqs", region_name="us-west-1")
conn.create_queue(QueueName="queue1") conn.create_queue(QueueName="queue1")
assert len(model_data["sqs"]["Queue"].instances) == 1 assert len(model_data["sqs"]["Queue"].instances) == 1 # type: ignore[attr-defined]
# But after the mock ends, it is empty again # But after the mock ends, it is empty again
for classes_per_service in model_data.values(): for classes_per_service in model_data.values():
for _class in classes_per_service.values(): for _class in classes_per_service.values():
assert _class.instances == [] assert _class.instances == [] # type: ignore[attr-defined]
# When we have multiple/nested mocks, the data should still be present after the first mock ends # When we have multiple/nested mocks, the data should still be present after the first mock ends
with mock_sqs(): with mock_sqs():
@ -122,24 +122,24 @@ def test_model_data_is_emptied_as_necessary():
conn.create_queue(QueueName="queue1") conn.create_queue(QueueName="queue1")
with mock_s3(): with mock_s3():
# The data should still be here - instances should not reset if another mock is still active # The data should still be here - instances should not reset if another mock is still active
assert len(model_data["sqs"]["Queue"].instances) == 1 assert len(model_data["sqs"]["Queue"].instances) == 1 # type: ignore[attr-defined]
# The data should still be here - the inner mock has exited, but the outer mock is still active # The data should still be here - the inner mock has exited, but the outer mock is still active
assert len(model_data["sqs"]["Queue"].instances) == 1 assert len(model_data["sqs"]["Queue"].instances) == 1 # type: ignore[attr-defined]
@mock_sqs @mock_sqs
class TestModelDataResetForClassDecorator(TestCase): class TestModelDataResetForClassDecorator(TestCase):
def setUp(self): def setUp(self) -> None:
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest("We're only interested in the decorator performance here") raise SkipTest("We're only interested in the decorator performance here")
# No data is present at the beginning # No data is present at the beginning
for classes_per_service in model_data.values(): for classes_per_service in model_data.values():
for _class in classes_per_service.values(): for _class in classes_per_service.values():
assert _class.instances == [] assert _class.instances == [] # type: ignore[attr-defined]
conn = boto3.client("sqs", region_name="us-west-1") conn = boto3.client("sqs", region_name="us-west-1")
conn.create_queue(QueueName="queue1") conn.create_queue(QueueName="queue1")
def test_should_find_bucket(self): def test_should_find_bucket(self) -> None:
assert len(model_data["sqs"]["Queue"].instances) == 1 assert len(model_data["sqs"]["Queue"].instances) == 1 # type: ignore[attr-defined]

View File

@ -8,7 +8,7 @@ from tests import EXAMPLE_AMI_ID
class TestNestedDecoratorsBoto3(unittest.TestCase): class TestNestedDecoratorsBoto3(unittest.TestCase):
@mock_sqs @mock_sqs
def setup_sqs_queue(self): def setup_sqs_queue(self) -> None:
conn = boto3.resource("sqs", region_name="us-east-1") conn = boto3.resource("sqs", region_name="us-east-1")
queue = conn.create_queue(QueueName="some-queue") queue = conn.create_queue(QueueName="some-queue")
@ -18,7 +18,7 @@ class TestNestedDecoratorsBoto3(unittest.TestCase):
assert queue.attributes["ApproximateNumberOfMessages"] == "1" assert queue.attributes["ApproximateNumberOfMessages"] == "1"
@mock_ec2 @mock_ec2
def test_nested(self): def test_nested(self) -> None:
self.setup_sqs_queue() self.setup_sqs_queue()
conn = boto3.client("ec2", region_name="us-west-2") conn = boto3.client("ec2", region_name="us-west-2")

View File

@ -1,9 +1,10 @@
import datetime import datetime
from collections import OrderedDict from collections import OrderedDict
from gzip import compress as gzip_compress from gzip import compress as gzip_compress
from typing import Any, Dict
from unittest import SkipTest, mock from unittest import SkipTest, mock
from botocore.awsrequest import AWSPreparedRequest from botocore.awsrequest import AWSPreparedRequest, HTTPHeaders
from freezegun import freeze_time from freezegun import freeze_time
from moto import settings from moto import settings
@ -11,10 +12,10 @@ from moto.core.responses import AWSServiceSpec, BaseResponse, flatten_json_reque
from moto.s3.responses import S3Response from moto.s3.responses import S3Response
def test_flatten_json_request_body(): def test_flatten_json_request_body() -> None:
spec = AWSServiceSpec("data/emr/2009-03-31/service-2.json").input_spec("RunJobFlow") spec = AWSServiceSpec("data/emr/2009-03-31/service-2.json").input_spec("RunJobFlow")
body = { body: Dict[str, Any] = {
"Name": "cluster", "Name": "cluster",
"Instances": { "Instances": {
"Ec2KeyName": "ec2key", "Ec2KeyName": "ec2key",
@ -93,13 +94,15 @@ def test_flatten_json_request_body():
assert props == body["Configurations"][idx]["Properties"] assert props == body["Configurations"][idx]["Properties"]
def test_parse_qs_unicode_decode_error(): def test_parse_qs_unicode_decode_error() -> None:
body = b'{"key": "%D0"}, "C": "#0 = :0"}' body = b'{"key": "%D0"}, "C": "#0 = :0"}'
request = AWSPreparedRequest("GET", "http://request", {"foo": "bar"}, body, False) headers = HTTPHeaders()
headers["foo"] = "bar"
request = AWSPreparedRequest("GET", "http://request", headers, body, False)
BaseResponse().setup_class(request, request.url, request.headers) BaseResponse().setup_class(request, request.url, request.headers)
def test_get_params(): def test_get_params() -> None:
subject = BaseResponse() subject = BaseResponse()
subject.querystring = OrderedDict( subject.querystring = OrderedDict(
[ [
@ -150,7 +153,7 @@ def test_get_params():
} }
def test_get_dict_list_params(): def test_get_dict_list_params() -> None:
subject = BaseResponse() subject = BaseResponse()
subject.querystring = OrderedDict( subject.querystring = OrderedDict(
[ [
@ -168,7 +171,7 @@ def test_get_dict_list_params():
assert result == {"VpcSecurityGroupId": ["sg-123", "sg-456", "sg-789"]} assert result == {"VpcSecurityGroupId": ["sg-123", "sg-456", "sg-789"]}
def test_response_environment_preserved_by_type(): def test_response_environment_preserved_by_type() -> None:
"""Ensure Jinja environment is cached by response type.""" """Ensure Jinja environment is cached by response type."""
class ResponseA(BaseResponse): class ResponseA(BaseResponse):
@ -214,7 +217,7 @@ def test_response_environment_preserved_by_type():
"moto.core.responses.settings.PRETTIFY_RESPONSES", "moto.core.responses.settings.PRETTIFY_RESPONSES",
new_callable=mock.PropertyMock(return_value=True), new_callable=mock.PropertyMock(return_value=True),
) )
def test_jinja_render_prettify(m_env_var): def test_jinja_render_prettify(m_env_var: Any) -> None: # type: ignore[misc]
if settings.TEST_SERVER_MODE: if settings.TEST_SERVER_MODE:
raise SkipTest( raise SkipTest(
"It is not possible to set the environment variable in server mode" "It is not possible to set the environment variable in server mode"
@ -228,12 +231,12 @@ def test_jinja_render_prettify(m_env_var):
assert m_env_var assert m_env_var
def test_response_metadata(): def test_response_metadata() -> None:
# Setup # Setup
frozen_time = datetime.datetime( frozen_time = datetime.datetime(
2023, 5, 20, 10, 20, 30, tzinfo=datetime.timezone.utc 2023, 5, 20, 10, 20, 30, tzinfo=datetime.timezone.utc
) )
request = AWSPreparedRequest("GET", "http://request", {}, None, False) request = AWSPreparedRequest("GET", "http://request", HTTPHeaders(), None, False)
# Execute # Execute
with freeze_time(frozen_time): with freeze_time(frozen_time):
@ -246,12 +249,14 @@ def test_response_metadata():
assert bc.response_headers["date"] == "Sat, 20 May 2023 10:20:30 GMT" assert bc.response_headers["date"] == "Sat, 20 May 2023 10:20:30 GMT"
def test_compression_gzip(): def test_compression_gzip() -> None:
body = '{"key": "%D0"}, "C": "#0 = :0"}' body = '{"key": "%D0"}, "C": "#0 = :0"}'
headers = HTTPHeaders()
headers["Content-Encoding"] = "gzip"
request = AWSPreparedRequest( request = AWSPreparedRequest(
"GET", "GET",
url="http://request", url="http://request",
headers={"Content-Encoding": "gzip"}, headers=headers,
body=_gzip_compress_body(body), body=_gzip_compress_body(body),
stream_output=False, stream_output=False,
) )
@ -261,12 +266,14 @@ def test_compression_gzip():
assert body == response.body assert body == response.body
def test_compression_gzip_in_s3(): def test_compression_gzip_in_s3() -> None:
body = b"some random data" body = b"some random data"
headers = HTTPHeaders()
headers["Content-Encoding"] = "gzip"
request = AWSPreparedRequest( request = AWSPreparedRequest(
"GET", "GET",
url="http://request", url="http://request",
headers={"Content-Encoding": "gzip"}, headers=headers,
body=body, body=body,
stream_output=False, stream_output=False,
) )
@ -276,6 +283,6 @@ def test_compression_gzip_in_s3():
assert body == response.body.encode("utf-8") assert body == response.body.encode("utf-8")
def _gzip_compress_body(body: str): def _gzip_compress_body(body: str) -> bytes:
assert isinstance(body, str) assert isinstance(body, str)
return gzip_compress(data=body.encode("utf-8")) return gzip_compress(data=body.encode("utf-8"))

View File

@ -1,9 +1,10 @@
from typing import Any
from unittest.mock import patch from unittest.mock import patch
from moto.server import DomainDispatcherApplication, create_backend_app, main from moto.server import DomainDispatcherApplication, create_backend_app, main
def test_wrong_arguments(): def test_wrong_arguments() -> None:
try: try:
main(["name", "test1", "test2", "test3"]) main(["name", "test1", "test2", "test3"])
assert False, ( assert False, (
@ -15,7 +16,7 @@ def test_wrong_arguments():
@patch("moto.server.run_simple") @patch("moto.server.run_simple")
def test_right_arguments(run_simple): def test_right_arguments(run_simple: Any) -> None: # type: ignore[misc]
main(["s3"]) main(["s3"])
func_call = run_simple.call_args[0] func_call = run_simple.call_args[0]
assert func_call[0] == "127.0.0.1" assert func_call[0] == "127.0.0.1"
@ -23,14 +24,14 @@ def test_right_arguments(run_simple):
@patch("moto.server.run_simple") @patch("moto.server.run_simple")
def test_port_argument(run_simple): def test_port_argument(run_simple: Any) -> None: # type: ignore[misc]
main(["s3", "--port", "8080"]) main(["s3", "--port", "8080"])
func_call = run_simple.call_args[0] func_call = run_simple.call_args[0]
assert func_call[0] == "127.0.0.1" assert func_call[0] == "127.0.0.1"
assert func_call[1] == 8080 assert func_call[1] == 8080
def test_domain_dispatched(): def test_domain_dispatched() -> None:
dispatcher = DomainDispatcherApplication(create_backend_app) dispatcher = DomainDispatcherApplication(create_backend_app)
backend_app = dispatcher.get_application( backend_app = dispatcher.get_application(
{"HTTP_HOST": "email.us-east1.amazonaws.com"} {"HTTP_HOST": "email.us-east1.amazonaws.com"}
@ -39,7 +40,7 @@ def test_domain_dispatched():
assert keys[0] == "EmailResponse.dispatch" assert keys[0] == "EmailResponse.dispatch"
def test_domain_dispatched_with_service(): def test_domain_dispatched_with_service() -> None:
# If we pass a particular service, always return that. # If we pass a particular service, always return that.
dispatcher = DomainDispatcherApplication(create_backend_app, service="s3") dispatcher = DomainDispatcherApplication(create_backend_app, service="s3")
backend_app = dispatcher.get_application({"HTTP_HOST": "s3.us-east1.amazonaws.com"}) backend_app = dispatcher.get_application({"HTTP_HOST": "s3.us-east1.amazonaws.com"})

View File

@ -10,17 +10,17 @@ Sanity checks for interpretation of the MOTO_ECS_NEW_ARN-variable
""" """
def test_default_is_true(): def test_default_is_true() -> None:
assert settings.ecs_new_arn_format() is True assert settings.ecs_new_arn_format() is True
@pytest.mark.parametrize("value", ["TrUe", "true", "invalid", "0", "1"]) @pytest.mark.parametrize("value", ["TrUe", "true", "invalid", "0", "1"])
def test_anything_but_false_is_true(value): def test_anything_but_false_is_true(value: str) -> None:
with mock.patch.dict(os.environ, {"MOTO_ECS_NEW_ARN": value}): with mock.patch.dict(os.environ, {"MOTO_ECS_NEW_ARN": value}):
assert settings.ecs_new_arn_format() is True assert settings.ecs_new_arn_format() is True
@pytest.mark.parametrize("value", ["False", "false", "faLse"]) @pytest.mark.parametrize("value", ["False", "false", "faLse"])
def test_only_false_is_false(value): def test_only_false_is_false(value: str) -> None:
with mock.patch.dict(os.environ, {"MOTO_ECS_NEW_ARN": value}): with mock.patch.dict(os.environ, {"MOTO_ECS_NEW_ARN": value}):
assert settings.ecs_new_arn_format() is False assert settings.ecs_new_arn_format() is False

View File

@ -6,7 +6,7 @@ from moto import mock_dynamodb
class TestSocketPair(unittest.TestCase): class TestSocketPair(unittest.TestCase):
@mock_dynamodb @mock_dynamodb
def test_socket_pair(self): def test_socket_pair(self) -> None:
a, b = socket.socketpair() a, b = socket.socketpair()
self.assertIsNotNone(a) self.assertIsNotNone(a)
self.assertIsNotNone(b) self.assertIsNotNone(b)

View File

@ -5,7 +5,7 @@ import moto
from moto import mock_s3 from moto import mock_s3
service_names = [ service_names = [
(d[5:], "") d[5:]
for d in dir(moto) for d in dir(moto)
if d.startswith("mock_") and not d == "mock_xray_client" and not d == "mock_all" if d.startswith("mock_") and not d == "mock_xray_client" and not d == "mock_all"
] ]
@ -16,8 +16,8 @@ class TestMockBucketStartingWithServiceName:
https://github.com/getmoto/moto/issues/4099 https://github.com/getmoto/moto/issues/4099
""" """
@pytest.mark.parametrize("service_name,decorator", service_names) @pytest.mark.parametrize("service_name", service_names)
def test_bucketname_starting_with_service_name(self, service_name, decorator): def test_bucketname_starting_with_service_name(self, service_name: str) -> None:
decorator = getattr(moto, f"mock_{service_name}") decorator = getattr(moto, f"mock_{service_name}")
with decorator(): with decorator():
with mock_s3(): with mock_s3():

View File

@ -1,7 +1,7 @@
from moto.core.utils import convert_regex_to_flask_path from moto.core.utils import convert_regex_to_flask_path
def test_flask_path_converting_simple(): def test_flask_path_converting_simple() -> None:
assert convert_regex_to_flask_path("/") == "/" assert convert_regex_to_flask_path("/") == "/"
assert convert_regex_to_flask_path("/$") == "/" assert convert_regex_to_flask_path("/$") == "/"
@ -10,7 +10,7 @@ def test_flask_path_converting_simple():
assert convert_regex_to_flask_path("/foo/bar/") == "/foo/bar/" assert convert_regex_to_flask_path("/foo/bar/") == "/foo/bar/"
def test_flask_path_converting_regex(): def test_flask_path_converting_regex() -> None:
assert ( assert (
convert_regex_to_flask_path(r"/(?P<key_name>[a-zA-Z0-9\-_]+)") convert_regex_to_flask_path(r"/(?P<key_name>[a-zA-Z0-9\-_]+)")
== r'/<regex("[a-zA-Z0-9\-_]+"):key_name>' == r'/<regex("[a-zA-Z0-9\-_]+"):key_name>'

View File

@ -19,7 +19,7 @@ from moto.core.utils import (
("ListMFADevices", "list_mfa_devices"), ("ListMFADevices", "list_mfa_devices"),
], ],
) )
def test_camelcase_to_underscores(_input, expected): def test_camelcase_to_underscores(_input: str, expected: str) -> None:
assert camelcase_to_underscores(_input) == expected assert camelcase_to_underscores(_input) == expected
@ -27,7 +27,7 @@ def test_camelcase_to_underscores(_input, expected):
"_input,expected", "_input,expected",
[("the_new_attribute", "theNewAttribute"), ("attribute", "attribute")], [("the_new_attribute", "theNewAttribute"), ("attribute", "attribute")],
) )
def test_underscores_to_camelcase(_input, expected): def test_underscores_to_camelcase(_input: str, expected: str) -> None:
assert underscores_to_camelcase(_input) == expected assert underscores_to_camelcase(_input) == expected
@ -35,7 +35,7 @@ def test_underscores_to_camelcase(_input, expected):
"_input,expected", "_input,expected",
[("TheNewAttribute", "theNewAttribute"), ("Attribute", "attribute")], [("TheNewAttribute", "theNewAttribute"), ("Attribute", "attribute")],
) )
def test_pascal_to_camelcase(_input, expected): def test_pascal_to_camelcase(_input: str, expected: str) -> None:
assert pascal_to_camelcase(_input) == expected assert pascal_to_camelcase(_input) == expected
@ -43,10 +43,10 @@ def test_pascal_to_camelcase(_input, expected):
"_input,expected", "_input,expected",
[("theNewAttribute", "TheNewAttribute"), ("attribute", "Attribute")], [("theNewAttribute", "TheNewAttribute"), ("attribute", "Attribute")],
) )
def test_camelcase_to_pascal(_input, expected): def test_camelcase_to_pascal(_input: str, expected: str) -> None:
assert camelcase_to_pascal(_input) == expected assert camelcase_to_pascal(_input) == expected
@freeze_time("2015-01-01 12:00:00") @freeze_time("2015-01-01 12:00:00")
def test_unix_time(): def test_unix_time() -> None: # type: ignore[misc]
assert unix_time() == 1420113600.0 assert unix_time() == 1420113600.0