diff --git a/moto/acm/models.py b/moto/acm/models.py index a1cd531b2..360ac1a33 100644 --- a/moto/acm/models.py +++ b/moto/acm/models.py @@ -1,8 +1,7 @@ import base64 import re import datetime -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto import settings from typing import Any, Dict, List, Iterable, Optional, Tuple, Set diff --git a/moto/amp/models.py b/moto/amp/models.py index 0b7a3b8b0..b158dc015 100644 --- a/moto/amp/models.py +++ b/moto/amp/models.py @@ -1,7 +1,7 @@ """PrometheusServiceBackend class with methods for supported APIs.""" -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, unix_time +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from moto.moto_api._internal import mock_random from moto.utilities.paginator import paginate from moto.utilities.tagging_service import TaggingService diff --git a/moto/apigateway/models.py b/moto/apigateway/models.py index bed0c7b46..7f7a9e59c 100644 --- a/moto/apigateway/models.py +++ b/moto/apigateway/models.py @@ -15,9 +15,9 @@ try: except ImportError: # OpenAPI Spec Validator < 0.5.0 from openapi_spec_validator.exceptions import OpenAPIValidationError # type: ignore -from moto.core import BaseBackend, BaseModel, CloudFormationModel +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from .utils import create_id, to_path -from moto.core.utils import path_url, BackendDict +from moto.core.utils import path_url from .exceptions import ( ConflictException, DeploymentNotFoundException, diff --git a/moto/apigatewayv2/models.py b/moto/apigatewayv2/models.py index 4634e9cbd..bfbc6a8c3 100644 --- a/moto/apigatewayv2/models.py +++ b/moto/apigatewayv2/models.py @@ -3,8 +3,8 @@ import string import yaml from typing import Any, Dict, List, Optional -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, unix_time +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from moto.moto_api._internal import mock_random as random from moto.utilities.tagging_service import TaggingService diff --git a/moto/applicationautoscaling/models.py b/moto/applicationautoscaling/models.py index ff1f5ef66..67b9ad12c 100644 --- a/moto/applicationautoscaling/models.py +++ b/moto/applicationautoscaling/models.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.ecs import ecs_backends from moto.moto_api._internal import mock_random from .exceptions import AWSValidationException diff --git a/moto/appsync/models.py b/moto/appsync/models.py index f56b9fea3..819c659e2 100644 --- a/moto/appsync/models.py +++ b/moto/appsync/models.py @@ -1,8 +1,8 @@ import base64 from datetime import timedelta, datetime, timezone from typing import Any, Dict, Iterable, List, Optional, Tuple -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, unix_time +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService diff --git a/moto/athena/models.py b/moto/athena/models.py index 0c872d6af..c59c149ad 100644 --- a/moto/athena/models.py +++ b/moto/athena/models.py @@ -1,7 +1,6 @@ import time -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random from typing import Any, Dict, List, Optional diff --git a/moto/autoscaling/models.py b/moto/autoscaling/models.py index 1827131a5..74ccb03c5 100644 --- a/moto/autoscaling/models.py +++ b/moto/autoscaling/models.py @@ -8,8 +8,8 @@ from moto.packages.boto.ec2.blockdevicemapping import ( from moto.ec2.exceptions import InvalidInstanceIdError from collections import OrderedDict -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import camelcase_to_underscores, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel +from moto.core.utils import camelcase_to_underscores from moto.ec2 import ec2_backends from moto.ec2.models import EC2Backend from moto.ec2.models.instances import Instance @@ -398,7 +398,7 @@ class FakeAutoScalingGroup(CloudFormationModel): load_balancers: List[str], target_group_arns: List[str], placement_group: str, - termination_policies: str, + termination_policies: List[str], autoscaling_backend: "AutoScalingBackend", ec2_backend: EC2Backend, tags: List[Dict[str, str]], @@ -824,7 +824,7 @@ class AutoScalingBackend(BaseBackend): self.elbv2_backend: ELBv2Backend = elbv2_backends[self.account_id][region_name] @staticmethod - def default_vpc_endpoint_service(service_region: str, zones: List[Dict[str, Any]]) -> List[Dict[str, Any]]: # type: ignore[misc] + def default_vpc_endpoint_service(service_region: str, zones: List[str]) -> List[Dict[str, Any]]: # type: ignore[misc] """Default VPC endpoint service.""" return BaseBackend.default_vpc_endpoint_service_factory( service_region, zones, "autoscaling" @@ -980,7 +980,7 @@ class AutoScalingBackend(BaseBackend): load_balancers: List[str], target_group_arns: List[str], placement_group: str, - termination_policies: str, + termination_policies: List[str], tags: List[Dict[str, str]], capacity_rebalance: bool = False, new_instances_protected_from_scale_in: bool = False, @@ -1223,7 +1223,7 @@ class AutoScalingBackend(BaseBackend): return lifecycle_hook def describe_lifecycle_hooks( - self, as_name: str, lifecycle_hook_names: Optional[str] = None + self, as_name: str, lifecycle_hook_names: Optional[List[str]] = None ) -> List[FakeLifeCycleHook]: return [ lifecycle_hook diff --git a/moto/autoscaling/responses.py b/moto/autoscaling/responses.py index f3731272c..76c13e062 100644 --- a/moto/autoscaling/responses.py +++ b/moto/autoscaling/responses.py @@ -22,20 +22,20 @@ class AutoScalingResponse(BaseResponse): instance_monitoring = False params = self._get_params() self.autoscaling_backend.create_launch_configuration( - name=params.get("LaunchConfigurationName"), - image_id=params.get("ImageId"), + name=params.get("LaunchConfigurationName"), # type: ignore[arg-type] + image_id=params.get("ImageId"), # type: ignore[arg-type] key_name=params.get("KeyName"), - ramdisk_id=params.get("RamdiskId"), - kernel_id=params.get("KernelId"), + ramdisk_id=params.get("RamdiskId"), # type: ignore[arg-type] + kernel_id=params.get("KernelId"), # type: ignore[arg-type] security_groups=self._get_multi_param("SecurityGroups.member"), - user_data=params.get("UserData"), - instance_type=params.get("InstanceType"), + user_data=params.get("UserData"), # type: ignore[arg-type] + instance_type=params.get("InstanceType"), # type: ignore[arg-type] instance_monitoring=instance_monitoring, instance_profile_name=params.get("IamInstanceProfile"), spot_price=params.get("SpotPrice"), - ebs_optimized=params.get("EbsOptimized"), - associate_public_ip_address=params.get("AssociatePublicIpAddress"), - block_device_mappings=params.get("BlockDeviceMappings"), + ebs_optimized=params.get("EbsOptimized"), # type: ignore[arg-type] + associate_public_ip_address=params.get("AssociatePublicIpAddress"), # type: ignore[arg-type] + block_device_mappings=params.get("BlockDeviceMappings"), # type: ignore[arg-type] instance_id=params.get("InstanceId"), metadata_options=params.get("MetadataOptions"), classic_link_vpc_id=params.get("ClassicLinkVPCId"), @@ -311,17 +311,17 @@ class AutoScalingResponse(BaseResponse): def put_scaling_policy(self) -> str: params = self._get_params() policy = self.autoscaling_backend.put_scaling_policy( - name=params.get("PolicyName"), + name=params.get("PolicyName"), # type: ignore[arg-type] policy_type=params.get("PolicyType", "SimpleScaling"), - metric_aggregation_type=params.get("MetricAggregationType"), - adjustment_type=params.get("AdjustmentType"), - as_name=params.get("AutoScalingGroupName"), - min_adjustment_magnitude=params.get("MinAdjustmentMagnitude"), + metric_aggregation_type=params.get("MetricAggregationType"), # type: ignore[arg-type] + adjustment_type=params.get("AdjustmentType"), # type: ignore[arg-type] + as_name=params.get("AutoScalingGroupName"), # type: ignore[arg-type] + min_adjustment_magnitude=params.get("MinAdjustmentMagnitude"), # type: ignore[arg-type] scaling_adjustment=self._get_int_param("ScalingAdjustment"), cooldown=self._get_int_param("Cooldown"), target_tracking_config=params.get("TargetTrackingConfiguration", {}), step_adjustments=params.get("StepAdjustments", []), - estimated_instance_warmup=params.get("EstimatedInstanceWarmup"), + estimated_instance_warmup=params.get("EstimatedInstanceWarmup"), # type: ignore[arg-type] predictive_scaling_configuration=params.get( "PredictiveScalingConfiguration", {} ), @@ -480,7 +480,7 @@ class AutoScalingResponse(BaseResponse): def enable_metrics_collection(self) -> str: group_name = self._get_param("AutoScalingGroupName") metrics = self._get_params().get("Metrics") - self.autoscaling_backend.enable_metrics_collection(group_name, metrics) + self.autoscaling_backend.enable_metrics_collection(group_name, metrics) # type: ignore[arg-type] template = self.response_template(ENABLE_METRICS_COLLECTION_TEMPLATE) return template.render() diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index abe08753a..5a7adc9f8 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -23,9 +23,9 @@ import weakref import requests.exceptions from moto.awslambda.policy import Policy -from moto.core import BaseBackend, BaseModel, CloudFormationModel +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from moto.core.exceptions import RESTError -from moto.core.utils import unix_time_millis, BackendDict +from moto.core.utils import unix_time_millis from moto.iam.models import iam_backends from moto.iam.exceptions import IAMNotFoundException from moto.logs.models import logs_backends diff --git a/moto/backends.py b/moto/backends.py index c00331cf5..d6bb05670 100644 --- a/moto/backends.py +++ b/moto/backends.py @@ -1,7 +1,7 @@ import importlib import moto import sys -from moto.core.utils import BackendDict +from moto.core import BackendDict from typing import Iterable, Tuple diff --git a/moto/batch/models.py b/moto/batch/models.py index 2d4cfead5..62f095dd2 100644 --- a/moto/batch/models.py +++ b/moto/batch/models.py @@ -9,7 +9,7 @@ import threading import dateutil.parser from sys import platform -from moto.core import BaseBackend, BaseModel, CloudFormationModel +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from moto.iam.models import iam_backends, IAMBackend from moto.ec2.models import ec2_backends, EC2Backend from moto.ec2.models.instances import Instance @@ -28,7 +28,7 @@ from moto.ec2.exceptions import InvalidSubnetIdError from moto.ec2.models.instance_types import INSTANCE_TYPES as EC2_INSTANCE_TYPES from moto.ec2.models.instance_types import INSTANCE_FAMILIES as EC2_INSTANCE_FAMILIES from moto.iam.exceptions import IAMNotFoundException -from moto.core.utils import unix_time_millis, BackendDict +from moto.core.utils import unix_time_millis from moto.moto_api import state_manager from moto.moto_api._internal import mock_random from moto.moto_api._internal.managed_state_model import ManagedState diff --git a/moto/batch_simple/models.py b/moto/batch_simple/models.py index 1c752a7ad..dc8cd259f 100644 --- a/moto/batch_simple/models.py +++ b/moto/batch_simple/models.py @@ -5,7 +5,7 @@ from ..batch.models import ( ClientException, BatchBackend, ) -from ..core.utils import BackendDict +from ..core import BackendDict import datetime from typing import Any, Dict, List, Tuple, Optional diff --git a/moto/budgets/models.py b/moto/budgets/models.py index 89e010b08..d9d2388cc 100644 --- a/moto/budgets/models.py +++ b/moto/budgets/models.py @@ -1,8 +1,8 @@ from collections import defaultdict from copy import deepcopy from datetime import datetime -from moto.core import BaseBackend, BaseModel -from moto.core.utils import unix_time, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from typing import Any, Dict, Iterable, List from .exceptions import BudgetMissingLimit, DuplicateRecordException, NotFoundException diff --git a/moto/ce/models.py b/moto/ce/models.py index 9787c0ef3..2c2df6441 100644 --- a/moto/ce/models.py +++ b/moto/ce/models.py @@ -1,8 +1,7 @@ """CostExplorerBackend class with methods for supported APIs.""" from .exceptions import CostCategoryNotFound -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.utilities.tagging_service import TaggingService from moto.moto_api._internal import mock_random from typing import Any, Dict, List, Tuple diff --git a/moto/cloudformation/models.py b/moto/cloudformation/models.py index 7c8c030ad..883a0093e 100644 --- a/moto/cloudformation/models.py +++ b/moto/cloudformation/models.py @@ -7,11 +7,10 @@ from typing import Any, Dict, List, Optional, Iterable, Tuple, Union, Type from yaml.parser import ParserError # pylint:disable=c-extension-no-member from yaml.scanner import ScannerError # pylint:disable=c-extension-no-member -from moto.core import BaseBackend, BaseModel, CloudFormationModel +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from moto.core.utils import ( iso_8601_datetime_with_milliseconds, iso_8601_datetime_without_milliseconds, - BackendDict, ) from moto.moto_api._internal import mock_random from moto.sns.models import sns_backends @@ -117,7 +116,7 @@ class FakeStackSet(BaseModel): self.execution_role = execution_role or self.execution_role if accounts and regions: - self.update_instances(accounts, regions, self.parameters) + self.update_instances(accounts, regions, self.parameters) # type: ignore[arg-type] operation = self._create_operation( operation_id=operation_id, @@ -158,7 +157,7 @@ class FakeStackSet(BaseModel): ) def update_instances( - self, accounts: List[str], regions: List[str], parameters: Dict[str, str] + self, accounts: List[str], regions: List[str], parameters: List[Dict[str, Any]] ) -> Dict[str, Any]: operation_id = str(mock_random.uuid4()) @@ -208,7 +207,7 @@ class FakeStackInstances(BaseModel): self, accounts: List[str], regions: List[str], - parameters: Optional[Dict[str, str]], + parameters: Optional[List[Dict[str, Any]]], ) -> Any: for account in accounts: for region in regions: @@ -655,7 +654,7 @@ class CloudFormationBackend(BaseBackend): stackset_name: str, accounts: List[str], regions: List[str], - parameters: Dict[str, str], + parameters: List[Dict[str, Any]], ) -> Dict[str, Any]: stack_set = self.get_stack_set(stackset_name) return stack_set.update_instances(accounts, regions, parameters) diff --git a/moto/cloudfront/models.py b/moto/cloudfront/models.py index 09efe1690..ec763cbce 100644 --- a/moto/cloudfront/models.py +++ b/moto/cloudfront/models.py @@ -2,8 +2,8 @@ import string from datetime import datetime from typing import Any, Dict, Iterable, List, Tuple, Optional -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, iso_8601_datetime_with_milliseconds +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.moto_api import state_manager from moto.moto_api._internal.managed_state_model import ManagedState from moto.moto_api._internal import mock_random as random diff --git a/moto/cloudtrail/models.py b/moto/cloudtrail/models.py index 0e3343d83..cc9ebaca8 100644 --- a/moto/cloudtrail/models.py +++ b/moto/cloudtrail/models.py @@ -3,8 +3,8 @@ import time from datetime import datetime from typing import Any, Dict, List, Optional, Iterable, Tuple -from moto.core import BaseBackend, BaseModel -from moto.core.utils import iso_8601_datetime_without_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import iso_8601_datetime_without_milliseconds from moto.utilities.tagging_service import TaggingService from .exceptions import ( S3BucketDoesNotExistException, diff --git a/moto/cloudwatch/models.py b/moto/cloudwatch/models.py index d81d1ae48..0fbc3238a 100644 --- a/moto/cloudwatch/models.py +++ b/moto/cloudwatch/models.py @@ -1,11 +1,10 @@ import json import statistics -from moto.core import BaseBackend, BaseModel, CloudWatchMetricProvider +from moto.core import BaseBackend, BackendDict, BaseModel, CloudWatchMetricProvider from moto.core.utils import ( iso_8601_datetime_without_milliseconds, iso_8601_datetime_with_nanoseconds, - BackendDict, ) from moto.moto_api._internal import mock_random from datetime import datetime, timedelta diff --git a/moto/codebuild/models.py b/moto/codebuild/models.py index 5565ad294..248a81a46 100644 --- a/moto/codebuild/models.py +++ b/moto/codebuild/models.py @@ -1,5 +1,5 @@ -from moto.core import BaseBackend, BaseModel -from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.moto_api._internal import mock_random from collections import defaultdict from dateutil import parser diff --git a/moto/codecommit/models.py b/moto/codecommit/models.py index a7b260304..2d9aafcb9 100644 --- a/moto/codecommit/models.py +++ b/moto/codecommit/models.py @@ -1,5 +1,5 @@ -from moto.core import BaseBackend, BaseModel -from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.moto_api._internal import mock_random from datetime import datetime from typing import Dict, List, Optional diff --git a/moto/codepipeline/models.py b/moto/codepipeline/models.py index 861416972..6d3d7879c 100644 --- a/moto/codepipeline/models.py +++ b/moto/codepipeline/models.py @@ -1,7 +1,7 @@ import json from datetime import datetime from typing import Any, Dict, List, Tuple -from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.iam.exceptions import IAMNotFoundException from moto.iam.models import iam_backends, IAMBackend @@ -12,7 +12,7 @@ from moto.codepipeline.exceptions import ( InvalidTagsException, TooManyTagsException, ) -from moto.core import BaseBackend, BaseModel +from moto.core import BaseBackend, BackendDict, BaseModel class CodePipeline(BaseModel): diff --git a/moto/cognitoidentity/models.py b/moto/cognitoidentity/models.py index f9f2f0d99..f7c1920f7 100644 --- a/moto/cognitoidentity/models.py +++ b/moto/cognitoidentity/models.py @@ -4,8 +4,8 @@ import re from collections import OrderedDict from typing import Any, Dict, List, Optional -from moto.core import BaseBackend, BaseModel -from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import iso_8601_datetime_with_milliseconds from .exceptions import InvalidNameException, ResourceNotFoundError from .utils import get_random_identity_id diff --git a/moto/cognitoidp/models.py b/moto/cognitoidp/models.py index b7ee41e64..478e13efc 100644 --- a/moto/cognitoidp/models.py +++ b/moto/cognitoidp/models.py @@ -7,8 +7,7 @@ import enum from jose import jws from collections import OrderedDict from typing import Any, Dict, List, Tuple, Optional, Set -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random as random from .exceptions import ( GroupExistsException, diff --git a/moto/comprehend/models.py b/moto/comprehend/models.py index 3fc952fa2..c33b72b4c 100644 --- a/moto/comprehend/models.py +++ b/moto/comprehend/models.py @@ -1,7 +1,6 @@ """ComprehendBackend class with methods for supported APIs.""" -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.utilities.tagging_service import TaggingService from .exceptions import ResourceNotFound from typing import Any, Dict, List, Iterable diff --git a/moto/config/models.py b/moto/config/models.py index ac9786ce0..ea07ee655 100644 --- a/moto/config/models.py +++ b/moto/config/models.py @@ -48,10 +48,9 @@ from moto.config.exceptions import ( MissingRequiredConfigRuleParameterException, ) -from moto.core import BaseBackend, BaseModel +from moto.core import BaseBackend, BackendDict, BaseModel from moto.core.common_models import ConfigQueryModel from moto.core.responses import AWSServiceSpec -from moto.core.utils import BackendDict from moto.iam.config import role_config_query, policy_config_query from moto.moto_api._internal import mock_random as random from moto.s3.config import s3_config_query @@ -1382,7 +1381,7 @@ class ConfigBackend(BaseBackend): :param next_token: :return: """ - identifiers = [] + identifiers: List[Dict[str, Any]] = [] new_token = None limit = limit or DEFAULT_PAGE_SIZE @@ -1437,7 +1436,7 @@ class ConfigBackend(BaseBackend): resource_identifiers.append(item) - result = {"resourceIdentifiers": resource_identifiers} + result: Dict[str, Any] = {"resourceIdentifiers": resource_identifiers} if new_token: result["nextToken"] = new_token @@ -1469,7 +1468,7 @@ class ConfigBackend(BaseBackend): if not self.config_aggregators.get(aggregator_name): raise NoSuchConfigurationAggregatorException() - identifiers = [] + identifiers: List[Dict[str, Any]] = [] new_token = None filters = filters or {} diff --git a/moto/core/__init__.py b/moto/core/__init__.py index 6691a5b4e..140e82694 100644 --- a/moto/core/__init__.py +++ b/moto/core/__init__.py @@ -1,5 +1,5 @@ from .models import DEFAULT_ACCOUNT_ID # noqa -from .base_backend import BaseBackend # noqa +from .base_backend import BaseBackend, BackendDict # noqa from .common_models import BaseModel # noqa from .common_models import CloudFormationModel, CloudWatchMetricProvider # noqa from .models import patch_client, patch_resource # noqa diff --git a/moto/core/base_backend.py b/moto/core/base_backend.py index 04f31d028..840bfceef 100644 --- a/moto/core/base_backend.py +++ b/moto/core/base_backend.py @@ -1,15 +1,20 @@ +from boto3 import Session import re import string from collections import defaultdict -from typing import List, Dict +from functools import lru_cache +from threading import RLock +from typing import Any, List, Dict, Optional, ClassVar, TypeVar, Iterator +from uuid import uuid4 +from moto.settings import allow_unknown_region from .utils import convert_regex_to_flask_path -model_data = defaultdict(dict) +model_data: Dict[str, Dict[str, object]] = defaultdict(dict) class InstanceTrackerMeta(type): - def __new__(meta, name, bases, dct): + def __new__(meta, name: str, bases: Any, dct: Dict[str, Any]) -> type: cls = super(InstanceTrackerMeta, meta).__new__(meta, name, bases, dct) if name == "BaseModel": return cls @@ -17,30 +22,30 @@ class InstanceTrackerMeta(type): service = cls.__module__.split(".")[1] if name not in model_data[service]: model_data[service][name] = cls - cls.instances = [] + cls.instances: ClassVar[List[Any]] = [] # type: ignore return cls class BaseBackend: - def __init__(self, region_name, account_id=None) -> None: + def __init__(self, region_name: str, account_id: str): self.region_name = region_name self.account_id = account_id - def _reset_model_refs(self): + def _reset_model_refs(self) -> None: # Remove all references to the models stored for models in model_data.values(): for model in models.values(): - model.instances = [] + model.instances = [] # type: ignore[attr-defined] def reset(self) -> None: region_name = self.region_name account_id = self.account_id self._reset_model_refs() self.__dict__ = {} - self.__init__(region_name, account_id) + self.__init__(region_name, account_id) # type: ignore[misc] @property - def _url_module(self): + def _url_module(self) -> Any: # type: ignore[misc] backend_module = self.__class__.__module__ backend_urls_module_name = backend_module.replace("models", "urls") backend_urls_module = __import__( @@ -49,7 +54,7 @@ class BaseBackend: return backend_urls_module @property - def urls(self): + def urls(self) -> Dict[str, str]: """ A dictionary of the urls to be mocked with this service and the handlers that should be called in their place @@ -71,7 +76,7 @@ class BaseBackend: return urls @property - def url_paths(self): + def url_paths(self) -> Dict[str, str]: """ A dictionary of the paths of the urls to be mocked with this service and the handlers that should be called in their place @@ -86,14 +91,14 @@ class BaseBackend: return paths @property - def url_bases(self): + def url_bases(self) -> List[str]: """ A list containing the url_bases extracted from urls.py """ return self._url_module.url_bases @property - def flask_paths(self): + def flask_paths(self) -> Dict[str, str]: """ The url paths that will be used for the flask server """ @@ -106,29 +111,29 @@ class BaseBackend: @staticmethod def default_vpc_endpoint_service( - service_region, zones - ): # pylint: disable=unused-argument + service_region: str, zones: List[str] # pylint: disable=unused-argument + ) -> List[Dict[str, str]]: """Invoke the factory method for any VPC endpoint(s) services.""" - return None + return [] @staticmethod - def vpce_random_number(): + def vpce_random_number() -> str: from moto.moto_api._internal import mock_random as random """Return random number for a VPC endpoint service ID.""" return "".join([random.choice(string.hexdigits.lower()) for i in range(17)]) @staticmethod - def default_vpc_endpoint_service_factory( - service_region, - zones, - service="", - service_type="Interface", - private_dns_names=True, - special_service_name="", - policy_supported=True, - base_endpoint_dns_names=None, - ) -> List[Dict[str, str]]: # pylint: disable=too-many-arguments + def default_vpc_endpoint_service_factory( # type: ignore[misc] + service_region: str, + zones: List[str], + service: str = "", + service_type: str = "Interface", + private_dns_names: bool = True, + special_service_name: str = "", + policy_supported: bool = True, + base_endpoint_dns_names: Optional[List[str]] = None, + ) -> List[Dict[str, Any]]: # pylint: disable=too-many-arguments """List of dicts representing default VPC endpoints for this service.""" if special_service_name: service_name = f"com.amazonaws.{service_region}.{special_service_name}" @@ -166,3 +171,148 @@ class BaseBackend: # def list_config_service_resources(self, resource_ids, resource_name, limit, next_token): # """For AWS Config. This will list all of the resources of the given type and optional resource name and region""" # raise NotImplementedError() + + +backend_lock = RLock() +SERVICE_BACKEND = TypeVar("SERVICE_BACKEND", bound=BaseBackend) + + +class AccountSpecificBackend(Dict[str, SERVICE_BACKEND]): + """ + Dictionary storing the data for a service in a specific account. + Data access pattern: + account_specific_backend[region: str] = backend: BaseBackend + """ + + def __init__( + self, + service_name: str, + account_id: str, + backend: type, + use_boto3_regions: bool, + additional_regions: Optional[List[str]], + ): + self.service_name = service_name + self.account_id = account_id + self.backend = backend + self.regions = [] + if use_boto3_regions: + sess = Session() + self.regions.extend(sess.get_available_regions(service_name)) + self.regions.extend( + sess.get_available_regions(service_name, partition_name="aws-us-gov") + ) + self.regions.extend( + sess.get_available_regions(service_name, partition_name="aws-cn") + ) + self.regions.extend(additional_regions or []) + self._id = str(uuid4()) + + def __hash__(self) -> int: # type: ignore[override] + return hash(self._id) + + def __eq__(self, other: Any) -> bool: + return ( + other + and isinstance(other, AccountSpecificBackend) + and other._id == self._id + ) + + def __ne__(self, other: Any) -> bool: + return not self.__eq__(other) + + def reset(self) -> None: + for region_specific_backend in self.values(): + region_specific_backend.reset() + + def __contains__(self, region: str) -> bool: # type: ignore[override] + return region in self.regions or region in self.keys() + + def __delitem__(self, key: str) -> None: + super().__delitem__(key) + + def __iter__(self) -> Iterator[str]: + return super().__iter__() + + def __len__(self) -> int: + return super().__len__() + + def __setitem__(self, key: str, value: SERVICE_BACKEND) -> None: + super().__setitem__(key, value) + + @lru_cache() + def __getitem__(self, region_name: str) -> SERVICE_BACKEND: # type: ignore[override] + if region_name in self.keys(): + return super().__getitem__(region_name) + # Create the backend for a specific region + with backend_lock: + if region_name in self.regions and region_name not in self.keys(): + super().__setitem__( + region_name, self.backend(region_name, account_id=self.account_id) + ) + if region_name not in self.regions and allow_unknown_region(): + super().__setitem__( + region_name, self.backend(region_name, account_id=self.account_id) + ) + return super().__getitem__(region_name) + + +class BackendDict(Dict[str, AccountSpecificBackend]): # type: ignore[type-arg] + """ + Data Structure to store everything related to a specific service. + Format: + [account_id: str]: AccountSpecificBackend + [account_id: str][region: str] = BaseBackend + """ + + def __init__( + self, + backend: Any, + service_name: str, + use_boto3_regions: bool = True, + additional_regions: Optional[List[str]] = None, + ): + self.backend = backend + self.service_name = service_name + self._use_boto3_regions = use_boto3_regions + self._additional_regions = additional_regions + self._id = str(uuid4()) + + def __hash__(self) -> int: # type: ignore[override] + # Required for the LRUcache to work. + # service_name is enough to determine uniqueness - other properties are dependent + return hash(self._id) + + def __eq__(self, other: Any) -> bool: + return other and isinstance(other, BackendDict) and other._id == self._id + + def __ne__(self, other: Any) -> bool: + return not self.__eq__(other) + + @lru_cache() + def __getitem__(self, account_id: str) -> AccountSpecificBackend: # type: ignore + self._create_account_specific_backend(account_id) + return super().__getitem__(account_id) + + def __delitem__(self, key: str) -> None: + super().__delitem__(key) + + def __iter__(self) -> Iterator[str]: + return super().__iter__() + + def __len__(self) -> int: + return super().__len__() + + def __setitem__(self, key: str, value: AccountSpecificBackend) -> None: # type: ignore[type-arg] + super().__setitem__(key, value) + + def _create_account_specific_backend(self, account_id: str) -> None: + with backend_lock: + if account_id not in list(self.keys()): + self[account_id] = AccountSpecificBackend( + service_name=self.service_name, + account_id=account_id, + backend=self.backend, + use_boto3_regions=self._use_boto3_regions, + additional_regions=self._additional_regions, + ) diff --git a/moto/core/models.py b/moto/core/models.py index db400cd5a..862164b1e 100644 --- a/moto/core/models.py +++ b/moto/core/models.py @@ -14,7 +14,7 @@ from botocore.config import Config from botocore.handlers import BUILTIN_HANDLERS from moto import settings -from moto.core.utils import BackendDict +from moto.core.base_backend import BackendDict from .botocore_stubber import BotocoreStubber from .custom_responses_mock import ( get_response_mock, diff --git a/moto/core/utils.py b/moto/core/utils.py index 5eab94456..d803fb6d1 100644 --- a/moto/core/utils.py +++ b/moto/core/utils.py @@ -1,15 +1,9 @@ -from functools import lru_cache - import datetime import inspect import re from botocore.exceptions import ClientError -from boto3 import Session -from moto.settings import allow_unknown_region -from threading import RLock -from typing import Any, Optional, List +from typing import Optional from urllib.parse import urlparse -from uuid import uuid4 def camelcase_to_underscores(argument: Optional[str]) -> str: @@ -69,7 +63,7 @@ def method_names_from_class(clazz): return [x[0] for x in inspect.getmembers(clazz, predicate=predicate)] -def convert_regex_to_flask_path(url_path): +def convert_regex_to_flask_path(url_path: str) -> str: """ Converts a regex matching url to one that can be used with flask """ @@ -308,118 +302,3 @@ def extract_region_from_aws_authorization(string): if region == auth: return None return region - - -backend_lock = RLock() - - -class AccountSpecificBackend(dict): - """ - Dictionary storing the data for a service in a specific account. - Data access pattern: - account_specific_backend[region: str] = backend: BaseBackend - """ - - def __init__( - self, service_name, account_id, backend, use_boto3_regions, additional_regions - ): - self.service_name = service_name - self.account_id = account_id - self.backend = backend - self.regions = [] - if use_boto3_regions: - sess = Session() - self.regions.extend(sess.get_available_regions(service_name)) - self.regions.extend( - sess.get_available_regions(service_name, partition_name="aws-us-gov") - ) - self.regions.extend( - sess.get_available_regions(service_name, partition_name="aws-cn") - ) - self.regions.extend(additional_regions or []) - self._id = str(uuid4()) - - def __hash__(self): - return hash(self._id) - - def __eq__(self, other): - return ( - other - and isinstance(other, AccountSpecificBackend) - and other._id == self._id - ) - - def __ne__(self, other): - return not self.__eq__(other) - - def reset(self): - for region_specific_backend in self.values(): - region_specific_backend.reset() - - def __contains__(self, region): - return region in self.regions or region in self.keys() - - @lru_cache() - def __getitem__(self, region_name): - if region_name in self.keys(): - return super().__getitem__(region_name) - # Create the backend for a specific region - with backend_lock: - if region_name in self.regions and region_name not in self.keys(): - super().__setitem__( - region_name, self.backend(region_name, account_id=self.account_id) - ) - if region_name not in self.regions and allow_unknown_region(): - super().__setitem__( - region_name, self.backend(region_name, account_id=self.account_id) - ) - return super().__getitem__(region_name) - - -class BackendDict(dict): - """ - Data Structure to store everything related to a specific service. - Format: - [account_id: str]: AccountSpecificBackend - [account_id: str][region: str] = BaseBackend - """ - - def __init__( - self, - backend: Any, - service_name: str, - use_boto3_regions: bool = True, - additional_regions: Optional[List[str]] = None, - ): - self.backend = backend - self.service_name = service_name - self._use_boto3_regions = use_boto3_regions - self._additional_regions = additional_regions - self._id = str(uuid4()) - - def __hash__(self): - # Required for the LRUcache to work. - # service_name is enough to determine uniqueness - other properties are dependent - return hash(self._id) - - def __eq__(self, other): - return other and isinstance(other, BackendDict) and other._id == self._id - - def __ne__(self, other): - return not self.__eq__(other) - - @lru_cache() - def __getitem__(self, account_id) -> AccountSpecificBackend: - self._create_account_specific_backend(account_id) - return super().__getitem__(account_id) - - def _create_account_specific_backend(self, account_id) -> None: - with backend_lock: - if account_id not in self.keys(): - self[account_id] = AccountSpecificBackend( - service_name=self.service_name, - account_id=account_id, - backend=self.backend, - use_boto3_regions=self._use_boto3_regions, - additional_regions=self._additional_regions, - ) diff --git a/moto/databrew/models.py b/moto/databrew/models.py index 1138cc38a..de2d8cfe7 100644 --- a/moto/databrew/models.py +++ b/moto/databrew/models.py @@ -6,8 +6,7 @@ from copy import deepcopy import math from datetime import datetime -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.core.utils import underscores_to_camelcase from moto.core.utils import camelcase_to_pascal diff --git a/moto/datapipeline/models.py b/moto/datapipeline/models.py index 078ea861c..8b737be9e 100644 --- a/moto/datapipeline/models.py +++ b/moto/datapipeline/models.py @@ -1,8 +1,7 @@ import datetime from collections import OrderedDict -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from .utils import get_random_pipeline_id, remove_capitalization_of_dict_keys diff --git a/moto/datasync/models.py b/moto/datasync/models.py index 32135aa82..98313fff4 100644 --- a/moto/datasync/models.py +++ b/moto/datasync/models.py @@ -1,6 +1,5 @@ from collections import OrderedDict -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .exceptions import InvalidRequestException diff --git a/moto/dax/models.py b/moto/dax/models.py index 2fbd9e21a..a2b47fc34 100644 --- a/moto/dax/models.py +++ b/moto/dax/models.py @@ -1,6 +1,6 @@ """DAXBackend class with methods for supported APIs.""" -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, unix_time +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from moto.moto_api import state_manager from moto.moto_api._internal import mock_random as random from moto.moto_api._internal.managed_state_model import ManagedState diff --git a/moto/dms/models.py b/moto/dms/models.py index a5f0958f1..8456ab382 100644 --- a/moto/dms/models.py +++ b/moto/dms/models.py @@ -1,8 +1,7 @@ import json from datetime import datetime -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .exceptions import ( InvalidResourceStateFault, diff --git a/moto/ds/models.py b/moto/ds/models.py index c555e4123..13126cb69 100644 --- a/moto/ds/models.py +++ b/moto/ds/models.py @@ -1,8 +1,7 @@ """DirectoryServiceBackend class with methods for supported APIs.""" from datetime import datetime, timezone -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.ds.exceptions import ( ClientException, DirectoryLimitExceededException, diff --git a/moto/dynamodb/models/__init__.py b/moto/dynamodb/models/__init__.py index 830e833d8..febe9f3c5 100644 --- a/moto/dynamodb/models/__init__.py +++ b/moto/dynamodb/models/__init__.py @@ -6,8 +6,8 @@ import json import re from collections import OrderedDict -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import unix_time, unix_time_millis, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel +from moto.core.utils import unix_time, unix_time_millis from moto.core.exceptions import JsonRESTError from moto.dynamodb.comparisons import get_filter_expression from moto.dynamodb.comparisons import get_expected diff --git a/moto/dynamodb_v20111205/models.py b/moto/dynamodb_v20111205/models.py index c8ea16da1..15135324e 100644 --- a/moto/dynamodb_v20111205/models.py +++ b/moto/dynamodb_v20111205/models.py @@ -3,8 +3,8 @@ import datetime import json from collections import OrderedDict -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import unix_time, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel +from moto.core.utils import unix_time from .comparisons import get_comparison_func diff --git a/moto/dynamodbstreams/models.py b/moto/dynamodbstreams/models.py index 04f580ebe..fa237982e 100644 --- a/moto/dynamodbstreams/models.py +++ b/moto/dynamodbstreams/models.py @@ -2,8 +2,7 @@ import os import json import base64 -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.dynamodb.models import dynamodb_backends, DynamoJsonEncoder diff --git a/moto/ebs/models.py b/moto/ebs/models.py index aa0883294..58f05e313 100644 --- a/moto/ebs/models.py +++ b/moto/ebs/models.py @@ -1,7 +1,7 @@ """EBSBackend class with methods for supported APIs.""" -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, unix_time +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from moto.ec2 import ec2_backends from moto.ec2.models.elastic_block_store import Snapshot from moto.moto_api._internal import mock_random diff --git a/moto/ec2/models/__init__.py b/moto/ec2/models/__init__.py index addaadc02..ab040c81e 100644 --- a/moto/ec2/models/__init__.py +++ b/moto/ec2/models/__init__.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict from ..exceptions import ( EC2ClientError, InvalidID, diff --git a/moto/ec2instanceconnect/models.py b/moto/ec2instanceconnect/models.py index 6dc184d39..b79babaff 100644 --- a/moto/ec2instanceconnect/models.py +++ b/moto/ec2instanceconnect/models.py @@ -1,6 +1,5 @@ import json -from moto.core import BaseBackend -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict class Ec2InstanceConnectBackend(BaseBackend): diff --git a/moto/ecr/models.py b/moto/ecr/models.py index 097c6d627..6f1fd83c2 100644 --- a/moto/ecr/models.py +++ b/moto/ecr/models.py @@ -7,8 +7,8 @@ from typing import Dict, List from botocore.exceptions import ParamValidationError -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import iso_8601_datetime_without_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel +from moto.core.utils import iso_8601_datetime_without_milliseconds from moto.ecr.exceptions import ( ImageNotFoundException, RepositoryNotFoundException, diff --git a/moto/ecs/models.py b/moto/ecs/models.py index dfd6d921d..892cde847 100644 --- a/moto/ecs/models.py +++ b/moto/ecs/models.py @@ -5,14 +5,9 @@ from typing import Any import pytz from moto import settings -from moto.core import BaseBackend, BaseModel, CloudFormationModel +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from moto.core.exceptions import JsonRESTError -from moto.core.utils import ( - unix_time, - pascal_to_camelcase, - remap_nested_keys, - BackendDict, -) +from moto.core.utils import unix_time, pascal_to_camelcase, remap_nested_keys from ..ec2.utils import random_private_ip from moto.ec2 import ec2_backends diff --git a/moto/efs/models.py b/moto/efs/models.py index f1d170ce5..51f49aa46 100644 --- a/moto/efs/models.py +++ b/moto/efs/models.py @@ -8,12 +8,8 @@ import json import time from copy import deepcopy -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import ( - camelcase_to_underscores, - underscores_to_camelcase, - BackendDict, -) +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel +from moto.core.utils import camelcase_to_underscores, underscores_to_camelcase from moto.ec2 import ec2_backends from moto.ec2.exceptions import InvalidSubnetIdError from moto.efs.exceptions import ( diff --git a/moto/eks/models.py b/moto/eks/models.py index d9e842f58..98681a893 100644 --- a/moto/eks/models.py +++ b/moto/eks/models.py @@ -1,7 +1,7 @@ from datetime import datetime -from moto.core import BaseBackend -from moto.core.utils import iso_8601_datetime_without_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict +from moto.core.utils import iso_8601_datetime_without_milliseconds from moto.moto_api._internal import mock_random as random from .exceptions import ( diff --git a/moto/elasticache/models.py b/moto/elasticache/models.py index e1fdd0809..6b99ebab9 100644 --- a/moto/elasticache/models.py +++ b/moto/elasticache/models.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .exceptions import UserAlreadyExists, UserNotFound diff --git a/moto/elasticbeanstalk/models.py b/moto/elasticbeanstalk/models.py index ac4fe163d..52b8e37cd 100644 --- a/moto/elasticbeanstalk/models.py +++ b/moto/elasticbeanstalk/models.py @@ -1,7 +1,6 @@ import weakref -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .exceptions import InvalidParameterValueError, ResourceNotFoundException from .utils import make_arn diff --git a/moto/elastictranscoder/models.py b/moto/elastictranscoder/models.py index f0aadd1f1..1d3abea8c 100644 --- a/moto/elastictranscoder/models.py +++ b/moto/elastictranscoder/models.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random as random import string diff --git a/moto/elb/models.py b/moto/elb/models.py index 48b080de8..2b480c709 100644 --- a/moto/elb/models.py +++ b/moto/elb/models.py @@ -3,8 +3,7 @@ import pytz from collections import OrderedDict from typing import List, Iterable -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from moto.ec2.models import ec2_backends from moto.ec2.exceptions import InvalidInstanceIdError from moto.moto_api._internal import mock_random diff --git a/moto/elbv2/models.py b/moto/elbv2/models.py index 683a317fa..28f20c02d 100644 --- a/moto/elbv2/models.py +++ b/moto/elbv2/models.py @@ -5,11 +5,8 @@ from botocore.exceptions import ParamValidationError from collections import OrderedDict from typing import Any, List, Dict, Iterable, Optional from moto.core.exceptions import RESTError -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import ( - iso_8601_datetime_with_milliseconds, - BackendDict, -) +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.ec2.models import ec2_backends from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService diff --git a/moto/emr/models.py b/moto/emr/models.py index 1503bc941..89803a143 100644 --- a/moto/emr/models.py +++ b/moto/emr/models.py @@ -5,8 +5,7 @@ import warnings import pytz from dateutil.parser import parse as dtparse -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.emr.exceptions import ( InvalidRequestException, ValidationException, diff --git a/moto/emrcontainers/models.py b/moto/emrcontainers/models.py index bdf9d9ec0..98fd31937 100644 --- a/moto/emrcontainers/models.py +++ b/moto/emrcontainers/models.py @@ -2,8 +2,8 @@ import re from datetime import datetime -from moto.core import BaseBackend, BaseModel -from moto.core.utils import iso_8601_datetime_without_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import iso_8601_datetime_without_milliseconds from .utils import random_cluster_id, random_job_id, get_partition, paginated_list from .exceptions import ResourceNotFoundException diff --git a/moto/emrserverless/models.py b/moto/emrserverless/models.py index 4eed63442..d962f5097 100644 --- a/moto/emrserverless/models.py +++ b/moto/emrserverless/models.py @@ -3,8 +3,8 @@ import re from datetime import datetime import inspect -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, iso_8601_datetime_without_milliseconds +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import iso_8601_datetime_without_milliseconds from .utils import ( default_auto_start_configuration, default_auto_stop_configuration, diff --git a/moto/es/models.py b/moto/es/models.py index c7dbd5236..6c7e0c141 100644 --- a/moto/es/models.py +++ b/moto/es/models.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random from .exceptions import DomainNotFound diff --git a/moto/events/models.py b/moto/events/models.py index 77ec21f9a..e14addf71 100644 --- a/moto/events/models.py +++ b/moto/events/models.py @@ -12,12 +12,11 @@ from operator import lt, le, eq, ge, gt from collections import OrderedDict from moto.core.exceptions import JsonRESTError -from moto.core import BaseBackend, CloudFormationModel, BaseModel +from moto.core import BaseBackend, BackendDict, CloudFormationModel, BaseModel from moto.core.utils import ( unix_time, unix_time_millis, iso_8601_datetime_without_milliseconds, - BackendDict, ) from moto.events.exceptions import ( ValidationException, diff --git a/moto/firehose/models.py b/moto/firehose/models.py index 37bd35448..432eaf631 100644 --- a/moto/firehose/models.py +++ b/moto/firehose/models.py @@ -25,8 +25,7 @@ import warnings import requests -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.firehose.exceptions import ( ConcurrentModificationException, InvalidArgumentException, diff --git a/moto/forecast/models.py b/moto/forecast/models.py index e74b68e5f..b1773a480 100644 --- a/moto/forecast/models.py +++ b/moto/forecast/models.py @@ -1,8 +1,8 @@ import re from datetime import datetime -from moto.core import BaseBackend -from moto.core.utils import iso_8601_datetime_without_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict +from moto.core.utils import iso_8601_datetime_without_milliseconds from .exceptions import ( InvalidInputException, ResourceAlreadyExistsException, diff --git a/moto/glacier/models.py b/moto/glacier/models.py index 4067b6282..8d66e5f14 100644 --- a/moto/glacier/models.py +++ b/moto/glacier/models.py @@ -2,8 +2,7 @@ import hashlib import datetime -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.utilities.utils import md5_hash from .utils import get_job_id diff --git a/moto/glue/models.py b/moto/glue/models.py index 7f3b79d7d..738f741c9 100644 --- a/moto/glue/models.py +++ b/moto/glue/models.py @@ -4,8 +4,7 @@ from datetime import datetime import re from typing import List -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api import state_manager from moto.moto_api._internal import mock_random from moto.moto_api._internal.managed_state_model import ManagedState diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py index b653ec037..0508d3c92 100644 --- a/moto/greengrass/models.py +++ b/moto/greengrass/models.py @@ -3,8 +3,8 @@ from collections import OrderedDict from datetime import datetime import re -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, iso_8601_datetime_with_milliseconds +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.moto_api._internal import mock_random from .exceptions import ( GreengrassClientError, diff --git a/moto/guardduty/models.py b/moto/guardduty/models.py index afddd0403..f5056537c 100644 --- a/moto/guardduty/models.py +++ b/moto/guardduty/models.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random from datetime import datetime diff --git a/moto/iam/models.py b/moto/iam/models.py index 2f9d3cbf6..af0b6f6ce 100644 --- a/moto/iam/models.py +++ b/moto/iam/models.py @@ -13,11 +13,16 @@ from jinja2 import Template from typing import List, Mapping from urllib import parse from moto.core.exceptions import RESTError -from moto.core import DEFAULT_ACCOUNT_ID, BaseBackend, BaseModel, CloudFormationModel +from moto.core import ( + DEFAULT_ACCOUNT_ID, + BaseBackend, + BaseModel, + CloudFormationModel, + BackendDict, +) from moto.core.utils import ( iso_8601_datetime_without_milliseconds, iso_8601_datetime_with_milliseconds, - BackendDict, unix_time, ) from moto.iam.policy_validation import ( @@ -64,14 +69,16 @@ SERVICE_NAME_CONVERSION = { } -def get_account_id_from(access_key): +def get_account_id_from(access_key: str) -> str: for account_id, account in iam_backends.items(): if access_key in account["global"].access_keys: return account_id return DEFAULT_ACCOUNT_ID -def mark_account_as_visited(account_id, access_key, service, region): +def mark_account_as_visited( + account_id: str, access_key: str, service: str, region: str +) -> None: account = iam_backends[account_id] if access_key in account["global"].access_keys: account["global"].access_keys[access_key].last_used = AccessKeyLastUsed( @@ -3050,6 +3057,6 @@ class IAMBackend(BaseBackend): return True -iam_backends: Mapping[str, Mapping[str, IAMBackend]] = BackendDict( +iam_backends = BackendDict( IAMBackend, "iam", use_boto3_regions=False, additional_regions=["global"] ) diff --git a/moto/instance_metadata/models.py b/moto/instance_metadata/models.py index ee22e2fff..76e4b8dfe 100644 --- a/moto/instance_metadata/models.py +++ b/moto/instance_metadata/models.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict class InstanceMetadataBackend(BaseBackend): diff --git a/moto/iot/models.py b/moto/iot/models.py index a291aec34..91b51b39a 100644 --- a/moto/iot/models.py +++ b/moto/iot/models.py @@ -11,8 +11,7 @@ from datetime import datetime, timedelta from .utils import PAGINATION_MODEL -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random as random from moto.utilities.paginator import paginate from .exceptions import ( diff --git a/moto/iotdata/models.py b/moto/iotdata/models.py index 5164db52a..507284b09 100644 --- a/moto/iotdata/models.py +++ b/moto/iotdata/models.py @@ -2,8 +2,8 @@ import json import time import jsondiff -from moto.core import BaseBackend, BaseModel -from moto.core.utils import merge_dicts, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import merge_dicts from moto.iot import iot_backends from .exceptions import ( ConflictException, diff --git a/moto/kinesis/models.py b/moto/kinesis/models.py index f51a31267..b3850a77d 100644 --- a/moto/kinesis/models.py +++ b/moto/kinesis/models.py @@ -5,8 +5,8 @@ import itertools from operator import attrgetter -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import unix_time, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel +from moto.core.utils import unix_time from moto.utilities.paginator import paginate from moto.utilities.utils import md5_hash from .exceptions import ( diff --git a/moto/kinesisvideo/models.py b/moto/kinesisvideo/models.py index 221d7d1aa..95345d028 100644 --- a/moto/kinesisvideo/models.py +++ b/moto/kinesisvideo/models.py @@ -1,7 +1,6 @@ -from moto.core import BaseBackend, BaseModel +from moto.core import BaseBackend, BackendDict, BaseModel from datetime import datetime from .exceptions import ResourceNotFoundException, ResourceInUseException -from moto.core.utils import BackendDict from moto.moto_api._internal import mock_random as random diff --git a/moto/kinesisvideoarchivedmedia/models.py b/moto/kinesisvideoarchivedmedia/models.py index fdf9d5a4e..2d5a12dab 100644 --- a/moto/kinesisvideoarchivedmedia/models.py +++ b/moto/kinesisvideoarchivedmedia/models.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict from moto.kinesisvideo import kinesisvideo_backends from moto.sts.utils import random_session_token diff --git a/moto/kms/models.py b/moto/kms/models.py index 5953d4ae0..9067c3f3f 100644 --- a/moto/kms/models.py +++ b/moto/kms/models.py @@ -8,8 +8,8 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import unix_time, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel +from moto.core.utils import unix_time from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService from moto.core.exceptions import JsonRESTError diff --git a/moto/logs/models.py b/moto/logs/models.py index 7518d3a99..147c94646 100644 --- a/moto/logs/models.py +++ b/moto/logs/models.py @@ -1,8 +1,8 @@ from datetime import datetime, timedelta from typing import Any, Dict, List, Tuple, Optional -from moto.core import BaseBackend, BaseModel +from moto.core import BaseBackend, BackendDict, BaseModel from moto.core import CloudFormationModel -from moto.core.utils import unix_time_millis, BackendDict +from moto.core.utils import unix_time_millis from moto.logs.metric_filters import MetricFilters from moto.logs.exceptions import ( ResourceNotFoundException, diff --git a/moto/managedblockchain/models.py b/moto/managedblockchain/models.py index 9966f29fb..1a2ad0672 100644 --- a/moto/managedblockchain/models.py +++ b/moto/managedblockchain/models.py @@ -3,8 +3,7 @@ from __future__ import division import datetime import re -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .exceptions import ( BadRequestException, diff --git a/moto/mediaconnect/models.py b/moto/mediaconnect/models.py index 6e78adcd1..2aa945cbc 100644 --- a/moto/mediaconnect/models.py +++ b/moto/mediaconnect/models.py @@ -1,7 +1,6 @@ from collections import OrderedDict -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.mediaconnect.exceptions import NotFoundException from moto.moto_api._internal import mock_random as random diff --git a/moto/medialive/models.py b/moto/medialive/models.py index e75383b7e..46e8e50f4 100644 --- a/moto/medialive/models.py +++ b/moto/medialive/models.py @@ -1,7 +1,6 @@ from collections import OrderedDict -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random diff --git a/moto/mediapackage/models.py b/moto/mediapackage/models.py index 53b3347a5..c8bd3701c 100644 --- a/moto/mediapackage/models.py +++ b/moto/mediapackage/models.py @@ -1,7 +1,6 @@ from collections import OrderedDict -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .exceptions import ClientError diff --git a/moto/mediastore/models.py b/moto/mediastore/models.py index 938d8699b..5ca579c12 100644 --- a/moto/mediastore/models.py +++ b/moto/mediastore/models.py @@ -1,8 +1,7 @@ from collections import OrderedDict from datetime import date -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .exceptions import ( ContainerNotFoundException, ResourceNotFoundException, diff --git a/moto/mediastoredata/models.py b/moto/mediastoredata/models.py index 395faa1f9..0f964674b 100644 --- a/moto/mediastoredata/models.py +++ b/moto/mediastoredata/models.py @@ -1,8 +1,7 @@ import hashlib from collections import OrderedDict -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .exceptions import ClientError diff --git a/moto/meteringmarketplace/models.py b/moto/meteringmarketplace/models.py index b08bfcfa7..5d3933b84 100644 --- a/moto/meteringmarketplace/models.py +++ b/moto/meteringmarketplace/models.py @@ -1,7 +1,6 @@ import collections -from moto.core import BaseBackend, BaseModel +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random -from moto.core.utils import BackendDict class UsageRecord(BaseModel, dict): diff --git a/moto/moto_api/_internal/models.py b/moto/moto_api/_internal/models.py index 8002ef9eb..728b3c3eb 100644 --- a/moto/moto_api/_internal/models.py +++ b/moto/moto_api/_internal/models.py @@ -1,4 +1,4 @@ -from moto.core import BaseBackend +from moto.core import BaseBackend, DEFAULT_ACCOUNT_ID class MotoAPIBackend(BaseBackend): @@ -31,4 +31,4 @@ class MotoAPIBackend(BaseBackend): state_manager.unset_transition(model_name) -moto_api_backend = MotoAPIBackend(region_name="global") +moto_api_backend = MotoAPIBackend(region_name="global", account_id=DEFAULT_ACCOUNT_ID) diff --git a/moto/moto_api/_internal/recorder/models.py b/moto/moto_api/_internal/recorder/models.py index 2c053a56d..eb3a8b725 100644 --- a/moto/moto_api/_internal/recorder/models.py +++ b/moto/moto_api/_internal/recorder/models.py @@ -5,6 +5,7 @@ import os import requests from botocore.awsrequest import AWSPreparedRequest +from typing import Any, Optional from urllib.parse import urlparse @@ -14,7 +15,7 @@ class Recorder: self._os_enabled = bool(os.environ.get("MOTO_ENABLE_RECORDING", False)) self._user_enabled = self._os_enabled - def _record_request(self, request, body=None): + def _record_request(self, request: Any, body: Optional[bytes] = None) -> None: """ Record the current request """ diff --git a/moto/moto_server/werkzeug_app.py b/moto/moto_server/werkzeug_app.py index 343bfe640..fc98a046c 100644 --- a/moto/moto_server/werkzeug_app.py +++ b/moto/moto_server/werkzeug_app.py @@ -16,8 +16,8 @@ except ImportError: import moto.backends as backends import moto.backend_index as backend_index -from moto.core import DEFAULT_ACCOUNT_ID -from moto.core.utils import convert_to_flask_response, BackendDict +from moto.core import BackendDict, DEFAULT_ACCOUNT_ID +from moto.core.utils import convert_to_flask_response from .utilities import AWSTestHelper, RegexConverter diff --git a/moto/mq/models.py b/moto/mq/models.py index f80c9f76b..29491d9cf 100644 --- a/moto/mq/models.py +++ b/moto/mq/models.py @@ -1,8 +1,8 @@ import base64 import xmltodict -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, unix_time +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService diff --git a/moto/opsworks/models.py b/moto/opsworks/models.py index ea6500a93..54b816d06 100644 --- a/moto/opsworks/models.py +++ b/moto/opsworks/models.py @@ -1,6 +1,5 @@ -from moto.core import BaseBackend, BaseModel +from moto.core import BaseBackend, BackendDict, BaseModel from moto.ec2 import ec2_backends -from moto.core.utils import BackendDict from moto.moto_api._internal import mock_random as random import datetime diff --git a/moto/organizations/models.py b/moto/organizations/models.py index 2b51a8043..a2c615552 100644 --- a/moto/organizations/models.py +++ b/moto/organizations/models.py @@ -2,9 +2,9 @@ import datetime import re import json -from moto.core import BaseBackend, BaseModel +from moto.core import BaseBackend, BackendDict, BaseModel from moto.core.exceptions import RESTError -from moto.core.utils import unix_time, BackendDict +from moto.core.utils import unix_time from moto.organizations import utils from moto.organizations.exceptions import ( InvalidInputException, diff --git a/moto/personalize/models.py b/moto/personalize/models.py index 6a44257cf..410b685b5 100644 --- a/moto/personalize/models.py +++ b/moto/personalize/models.py @@ -1,8 +1,8 @@ """PersonalizeBackend class with methods for supported APIs.""" from .exceptions import ResourceNotFoundException -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, unix_time +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time class Schema(BaseModel): diff --git a/moto/pinpoint/models.py b/moto/pinpoint/models.py index 1ba47efa3..5cbdde16f 100644 --- a/moto/pinpoint/models.py +++ b/moto/pinpoint/models.py @@ -1,6 +1,6 @@ from datetime import datetime -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, unix_time +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService diff --git a/moto/polly/models.py b/moto/polly/models.py index 20455812a..d97399358 100644 --- a/moto/polly/models.py +++ b/moto/polly/models.py @@ -1,8 +1,7 @@ from xml.etree import ElementTree as ET import datetime -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .resources import VOICE_DATA from .utils import make_arn_for_lexicon diff --git a/moto/quicksight/models.py b/moto/quicksight/models.py index 03ba06918..495e67014 100644 --- a/moto/quicksight/models.py +++ b/moto/quicksight/models.py @@ -1,7 +1,6 @@ """QuickSightBackend class with methods for supported APIs.""" -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .exceptions import ResourceNotFoundException diff --git a/moto/ram/models.py b/moto/ram/models.py index 4b90304cf..3f8095829 100644 --- a/moto/ram/models.py +++ b/moto/ram/models.py @@ -2,8 +2,8 @@ import re import string from datetime import datetime -from moto.core import BaseBackend, BaseModel -from moto.core.utils import unix_time, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from moto.moto_api._internal import mock_random as random from moto.organizations import organizations_backends from moto.ram.exceptions import ( diff --git a/moto/rds/models.py b/moto/rds/models.py index 62e124738..f65382cc2 100644 --- a/moto/rds/models.py +++ b/moto/rds/models.py @@ -7,8 +7,8 @@ from collections import defaultdict from jinja2 import Template from re import compile as re_compile from collections import OrderedDict -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.ec2.models import ec2_backends from moto.moto_api._internal import mock_random as random from .exceptions import ( diff --git a/moto/redshift/models.py b/moto/redshift/models.py index a30c5fbf2..f084b6755 100644 --- a/moto/redshift/models.py +++ b/moto/redshift/models.py @@ -2,8 +2,8 @@ import copy import datetime from collections import OrderedDict -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.ec2 import ec2_backends from moto.moto_api._internal import mock_random from .exceptions import ( diff --git a/moto/redshiftdata/models.py b/moto/redshiftdata/models.py index abda501b7..0ebddde74 100644 --- a/moto/redshiftdata/models.py +++ b/moto/redshiftdata/models.py @@ -1,8 +1,8 @@ import re from datetime import datetime -from moto.core import BaseBackend -from moto.core.utils import BackendDict, iso_8601_datetime_without_milliseconds +from moto.core import BaseBackend, BackendDict +from moto.core.utils import iso_8601_datetime_without_milliseconds from moto.moto_api._internal import mock_random as random from moto.redshiftdata.exceptions import ValidationException, ResourceNotFoundException diff --git a/moto/rekognition/models.py b/moto/rekognition/models.py index d49155889..0b4ba7d08 100644 --- a/moto/rekognition/models.py +++ b/moto/rekognition/models.py @@ -2,8 +2,7 @@ import string -from moto.core import BaseBackend -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict from moto.moto_api._internal import mock_random as random diff --git a/moto/resourcegroups/models.py b/moto/resourcegroups/models.py index e17272538..a9722d367 100644 --- a/moto/resourcegroups/models.py +++ b/moto/resourcegroups/models.py @@ -3,8 +3,7 @@ from builtins import str import json import re -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from .exceptions import BadRequestException diff --git a/moto/resourcegroupstaggingapi/models.py b/moto/resourcegroupstaggingapi/models.py index 92d4a0cff..8f40f17e8 100644 --- a/moto/resourcegroupstaggingapi/models.py +++ b/moto/resourcegroupstaggingapi/models.py @@ -1,6 +1,5 @@ -from moto.core import BaseBackend +from moto.core import BaseBackend, BackendDict from moto.core.exceptions import RESTError -from moto.core.utils import BackendDict from moto.moto_api._internal import mock_random from moto.s3 import s3_backends diff --git a/moto/route53/models.py b/moto/route53/models.py index c854c166a..5e260b4bf 100644 --- a/moto/route53/models.py +++ b/moto/route53/models.py @@ -18,8 +18,7 @@ from moto.route53.exceptions import ( PublicZoneVPCAssociation, QueryLoggingConfigAlreadyExists, ) -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from moto.moto_api._internal import mock_random as random from moto.utilities.paginator import paginate from .utils import PAGINATION_MODEL diff --git a/moto/route53resolver/models.py b/moto/route53resolver/models.py index e6801008a..237aeb827 100644 --- a/moto/route53resolver/models.py +++ b/moto/route53resolver/models.py @@ -4,8 +4,7 @@ from datetime import datetime, timezone from ipaddress import ip_address, ip_network, IPv4Address import re -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.ec2 import ec2_backends from moto.ec2.exceptions import InvalidSubnetIdError from moto.ec2.exceptions import InvalidSecurityGroupNotFoundError diff --git a/moto/s3/models.py b/moto/s3/models.py index 458fc7d61..6671f7c6e 100644 --- a/moto/s3/models.py +++ b/moto/s3/models.py @@ -14,14 +14,13 @@ import urllib.parse from bisect import insort from importlib import reload -from moto.core import BaseBackend, BaseModel, CloudFormationModel +from moto.core import BaseBackend, BaseModel, BackendDict, CloudFormationModel from moto.core import CloudWatchMetricProvider from moto.core.utils import ( iso_8601_datetime_without_milliseconds_s3, rfc_1123_datetime, unix_time, unix_time_millis, - BackendDict, ) from moto.cloudwatch.models import MetricDatum from moto.moto_api import state_manager diff --git a/moto/s3control/models.py b/moto/s3control/models.py index ba573f4f4..9f1b398fd 100644 --- a/moto/s3control/models.py +++ b/moto/s3control/models.py @@ -1,7 +1,6 @@ from collections import defaultdict from datetime import datetime -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random from moto.s3.exceptions import ( WrongPublicAccessBlockAccountIdError, diff --git a/moto/sagemaker/models.py b/moto/sagemaker/models.py index 9325c3255..687b47c9f 100644 --- a/moto/sagemaker/models.py +++ b/moto/sagemaker/models.py @@ -1,8 +1,7 @@ import json import os from datetime import datetime -from moto.core import BaseBackend, BaseModel, CloudFormationModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from moto.sagemaker import validators from moto.utilities.paginator import paginate from .exceptions import ( diff --git a/moto/sdb/models.py b/moto/sdb/models.py index 6f1f1cffb..1831add4b 100644 --- a/moto/sdb/models.py +++ b/moto/sdb/models.py @@ -1,8 +1,7 @@ """SimpleDBBackend class with methods for supported APIs.""" import re from collections import defaultdict -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from threading import Lock from .exceptions import InvalidDomainName, UnknownDomainName diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py index 06743882b..82989a904 100644 --- a/moto/secretsmanager/models.py +++ b/moto/secretsmanager/models.py @@ -4,8 +4,7 @@ import datetime from typing import List, Tuple -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random from .exceptions import ( SecretNotFoundException, diff --git a/moto/servicediscovery/models.py b/moto/servicediscovery/models.py index 1c8a5ce7f..a97ab294a 100644 --- a/moto/servicediscovery/models.py +++ b/moto/servicediscovery/models.py @@ -1,7 +1,7 @@ import string -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, unix_time +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from moto.moto_api._internal import mock_random as random from moto.utilities.tagging_service import TaggingService diff --git a/moto/servicequotas/models.py b/moto/servicequotas/models.py index 1860a4734..2331ab2d1 100644 --- a/moto/servicequotas/models.py +++ b/moto/servicequotas/models.py @@ -1,7 +1,6 @@ """ServiceQuotasBackend class with methods for supported APIs.""" -from moto.core import BaseBackend -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict from typing import Any, Dict, List from .exceptions import NoSuchResource from .resources.default_quotas.vpc import VPC_DEFAULT_QUOTAS diff --git a/moto/ses/models.py b/moto/ses/models.py index b10bf450a..9a92d7961 100644 --- a/moto/ses/models.py +++ b/moto/ses/models.py @@ -8,8 +8,7 @@ from email.mime.multipart import MIMEMultipart from email.encoders import encode_7or8bit from typing import Mapping -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.sns.models import sns_backends from .exceptions import ( MessageRejectedError, diff --git a/moto/settings.py b/moto/settings.py index a7c52f8be..af28b7b9e 100644 --- a/moto/settings.py +++ b/moto/settings.py @@ -65,7 +65,7 @@ def ecs_new_arn_format(): return os.environ.get("MOTO_ECS_NEW_ARN", "true").lower() != "false" -def allow_unknown_region(): +def allow_unknown_region() -> bool: return os.environ.get("MOTO_ALLOW_NONEXISTENT_REGION", "false").lower() == "true" diff --git a/moto/signer/models.py b/moto/signer/models.py index 323c0320c..7289362f6 100644 --- a/moto/signer/models.py +++ b/moto/signer/models.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random diff --git a/moto/sns/models.py b/moto/sns/models.py index 2279f33d6..26141ea9a 100644 --- a/moto/sns/models.py +++ b/moto/sns/models.py @@ -5,11 +5,10 @@ import requests import re from collections import OrderedDict -from moto.core import BaseBackend, BaseModel, CloudFormationModel +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from moto.core.utils import ( iso_8601_datetime_with_milliseconds, camelcase_to_underscores, - BackendDict, ) from moto.moto_api._internal import mock_random from moto.sqs import sqs_backends diff --git a/moto/sqs/models.py b/moto/sqs/models.py index 9362b20a2..9dec73e63 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -11,13 +11,12 @@ from threading import Condition from xml.sax.saxutils import escape from moto.core.exceptions import RESTError -from moto.core import BaseBackend, BaseModel, CloudFormationModel +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from moto.core.utils import ( camelcase_to_underscores, unix_time, unix_time_millis, tags_from_cloudformation_tags_list, - BackendDict, ) from moto.moto_api._internal import mock_random as random from moto.utilities.utils import md5_hash diff --git a/moto/ssm/models.py b/moto/ssm/models.py index f492e4382..e10b969ff 100644 --- a/moto/ssm/models.py +++ b/moto/ssm/models.py @@ -4,9 +4,8 @@ from typing import Dict from collections import defaultdict -from moto.core import BaseBackend, BaseModel, CloudFormationModel +from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel from moto.core.exceptions import RESTError -from moto.core.utils import BackendDict from moto.ec2 import ec2_backends from moto.secretsmanager import secretsmanager_backends from moto.secretsmanager.exceptions import SecretsManagerClientError diff --git a/moto/ssoadmin/models.py b/moto/ssoadmin/models.py index abe79d11b..0aeba130c 100644 --- a/moto/ssoadmin/models.py +++ b/moto/ssoadmin/models.py @@ -1,7 +1,7 @@ from .exceptions import ResourceNotFound -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict, unix_time +from moto.core import BaseBackend, BackendDict, BaseModel +from moto.core.utils import unix_time from moto.moto_api._internal import mock_random as random from moto.utilities.paginator import paginate from .utils import PAGINATION_MODEL diff --git a/moto/stepfunctions/models.py b/moto/stepfunctions/models.py index 54da2cbf6..318713d45 100644 --- a/moto/stepfunctions/models.py +++ b/moto/stepfunctions/models.py @@ -3,8 +3,8 @@ import re from datetime import datetime from dateutil.tz import tzlocal -from moto.core import BaseBackend, CloudFormationModel -from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict +from moto.core import BaseBackend, BackendDict, CloudFormationModel +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.moto_api._internal import mock_random from .exceptions import ( ExecutionAlreadyExists, diff --git a/moto/sts/models.py b/moto/sts/models.py index fc492bc1c..d90b6ef50 100644 --- a/moto/sts/models.py +++ b/moto/sts/models.py @@ -2,8 +2,8 @@ from base64 import b64decode import datetime import re import xmltodict -from moto.core import BaseBackend, BaseModel -from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict +from moto.core import BaseBackend, BaseModel, BackendDict +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.iam import iam_backends from moto.sts.utils import ( random_session_token, diff --git a/moto/support/models.py b/moto/support/models.py index 6533e9add..037a95215 100644 --- a/moto/support/models.py +++ b/moto/support/models.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict from moto.moto_api import state_manager from moto.moto_api._internal.managed_state_model import ManagedState from moto.moto_api._internal import mock_random as random diff --git a/moto/swf/models/__init__.py b/moto/swf/models/__init__.py index a70a5403f..c728666aa 100644 --- a/moto/swf/models/__init__.py +++ b/moto/swf/models/__init__.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict from ..exceptions import ( SWFUnknownResourceFault, diff --git a/moto/textract/models.py b/moto/textract/models.py index 93e25a095..a7526ad16 100644 --- a/moto/textract/models.py +++ b/moto/textract/models.py @@ -2,8 +2,7 @@ from collections import defaultdict -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api._internal import mock_random from .exceptions import InvalidParameterException, InvalidJobIdException diff --git a/moto/timestreamwrite/models.py b/moto/timestreamwrite/models.py index c35c454ae..42b9d0f17 100644 --- a/moto/timestreamwrite/models.py +++ b/moto/timestreamwrite/models.py @@ -1,5 +1,4 @@ -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.utilities.tagging_service import TaggingService from .exceptions import ResourceNotFound diff --git a/moto/transcribe/models.py b/moto/transcribe/models.py index 7e44f6c81..729a20a6c 100644 --- a/moto/transcribe/models.py +++ b/moto/transcribe/models.py @@ -1,6 +1,5 @@ from datetime import datetime, timedelta -from moto.core import BaseBackend, BaseModel -from moto.core.utils import BackendDict +from moto.core import BaseBackend, BackendDict, BaseModel from moto.moto_api import state_manager from moto.moto_api._internal import mock_random from moto.moto_api._internal.managed_state_model import ManagedState diff --git a/moto/utilities/distutils_version.py b/moto/utilities/distutils_version.py index 7ad826151..280dff174 100644 --- a/moto/utilities/distutils_version.py +++ b/moto/utilities/distutils_version.py @@ -30,6 +30,7 @@ Every version number class implements the following interface: """ import re +from typing import Optional class Version: @@ -194,7 +195,7 @@ class LooseVersion(Version): component_re = re.compile(r"(\d+ | [a-z]+ | \.)", re.VERBOSE) - def __init__(self, vstring=None): + def __init__(self, vstring: Optional[str] = None): if vstring: self.parse(vstring) diff --git a/moto/utilities/utils.py b/moto/utilities/utils.py index f0d5118b0..ce75b988e 100644 --- a/moto/utilities/utils.py +++ b/moto/utilities/utils.py @@ -3,7 +3,7 @@ import hashlib import pkgutil from collections.abc import MutableMapping -from typing import Any, Dict, Union +from typing import Any, Dict def str2bool(v): @@ -13,9 +13,7 @@ def str2bool(v): return False -def load_resource( - package: str, resource: str, as_json: bool = True -) -> Union[Dict[str, Any], str]: +def load_resource(package: str, resource: str, as_json: bool = True) -> Dict[str, Any]: """ Open a file, and return the contents as JSON. Usage: diff --git a/moto/wafv2/models.py b/moto/wafv2/models.py index 652621057..788fc98cc 100644 --- a/moto/wafv2/models.py +++ b/moto/wafv2/models.py @@ -1,11 +1,11 @@ import datetime import re from typing import Dict -from moto.core import BaseBackend, BaseModel +from moto.core import BaseBackend, BackendDict, BaseModel from .utils import make_arn_for_wacl from .exceptions import WAFV2DuplicateItemException, WAFNonexistentItemException -from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict +from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService from collections import OrderedDict diff --git a/moto/xray/models.py b/moto/xray/models.py index 76218d128..a1eb40e49 100644 --- a/moto/xray/models.py +++ b/moto/xray/models.py @@ -2,9 +2,8 @@ import bisect import datetime from collections import defaultdict import json -from moto.core import BaseBackend, BaseModel +from moto.core import BaseBackend, BackendDict, BaseModel from moto.core.exceptions import AWSError -from moto.core.utils import BackendDict from .exceptions import BadSegmentException diff --git a/setup.cfg b/setup.cfg index a2a8fa254..f7cf76cbe 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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 [mypy] -files= moto/a*,moto/b*,moto/ce,moto/cloudformation,moto/cloudfront,moto/cloudtrail,moto/codebuild,moto/cloudwatch,moto/codepipeline,moto/codecommit,moto/cognito*,moto/comprehend,moto/config +files= moto/a*,moto/b*,moto/ce,moto/cloudformation,moto/cloudfront,moto/cloudtrail,moto/codebuild,moto/cloudwatch,moto/codepipeline,moto/codecommit,moto/cognito*,moto/comprehend,moto/config,moto/core/base_backend.py show_column_numbers=True show_error_codes = True disable_error_code=abstract diff --git a/tests/test_core/test_backenddict.py b/tests/test_core/test_backenddict.py index a49302375..f804dfa16 100644 --- a/tests/test_core/test_backenddict.py +++ b/tests/test_core/test_backenddict.py @@ -2,8 +2,8 @@ import random import time import pytest -from moto.core import BaseBackend, DEFAULT_ACCOUNT_ID -from moto.core.utils import AccountSpecificBackend, BackendDict +from moto.core import BaseBackend, BackendDict, DEFAULT_ACCOUNT_ID +from moto.core.base_backend import AccountSpecificBackend from moto.autoscaling.models import AutoScalingBackend from moto.ec2.models import EC2Backend