Techdebt: Hide private decorator-methods/attributes (#7216)
This commit is contained in:
parent
5aa3cc9d73
commit
0c8ccbb406
14
CHANGELOG.md
14
CHANGELOG.md
@ -40,6 +40,20 @@ Docker Digest for 4.2.14: _sha256:2fa10aa48e32f85c63c62a7d437b8a4b320a56a8494bc2
|
|||||||
* SNS: set_subscription_attributes() can now unset the FilterPolicy
|
* SNS: set_subscription_attributes() can now unset the FilterPolicy
|
||||||
|
|
||||||
|
|
||||||
|
5.0.0alpha2:
|
||||||
|
------------
|
||||||
|
|
||||||
|
General:
|
||||||
|
* It is now possible to configure methods/services which should reach out to AWS.
|
||||||
|
@mock_aws(
|
||||||
|
config={"core": {"mock_credentials": False, "passthrough": {"urls": [], "services": []}}}
|
||||||
|
)
|
||||||
|
* All requests now return a RequestId
|
||||||
|
|
||||||
|
Miscellaneous:
|
||||||
|
* S3: list_objects() now returns a hashed ContinuationToken
|
||||||
|
|
||||||
|
|
||||||
5.0.0alpha1:
|
5.0.0alpha1:
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
@ -1,41 +1,4 @@
|
|||||||
from typing import TYPE_CHECKING, Callable, Optional, TypeVar, Union, overload
|
from moto.core.decorator import mock_aws # noqa # pylint: disable=unused-import
|
||||||
|
|
||||||
from moto import settings
|
|
||||||
from moto.core.config import DefaultConfig
|
|
||||||
from moto.core.models import MockAWS, ProxyModeMockAWS, ServerModeMockAWS
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from typing_extensions import ParamSpec
|
|
||||||
|
|
||||||
P = ParamSpec("P")
|
|
||||||
|
|
||||||
T = TypeVar("T")
|
|
||||||
|
|
||||||
|
|
||||||
@overload
|
|
||||||
def mock_aws(func: "Callable[P, T]") -> "Callable[P, T]":
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
@overload
|
|
||||||
def mock_aws(func: None = None, config: Optional[DefaultConfig] = None) -> "MockAWS":
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
def mock_aws(
|
|
||||||
func: "Optional[Callable[P, T]]" = None,
|
|
||||||
config: Optional[DefaultConfig] = None,
|
|
||||||
) -> Union["MockAWS", "Callable[P, T]"]:
|
|
||||||
clss = (
|
|
||||||
ServerModeMockAWS
|
|
||||||
if settings.TEST_SERVER_MODE
|
|
||||||
else (ProxyModeMockAWS if settings.test_proxy_mode() else MockAWS)
|
|
||||||
)
|
|
||||||
if func is not None:
|
|
||||||
return clss().__call__(func=func)
|
|
||||||
else:
|
|
||||||
return clss(config)
|
|
||||||
|
|
||||||
|
|
||||||
__title__ = "moto"
|
__title__ = "moto"
|
||||||
__version__ = "4.2.15.dev"
|
__version__ = "4.2.15.dev"
|
||||||
|
@ -29,9 +29,6 @@ class BotocoreStubber:
|
|||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.enabled = False
|
self.enabled = False
|
||||||
|
|
||||||
def reset(self) -> None:
|
|
||||||
BackendDict.reset()
|
|
||||||
|
|
||||||
def __call__(
|
def __call__(
|
||||||
self, event_name: str, request: Any, **kwargs: Any
|
self, event_name: str, request: Any, **kwargs: Any
|
||||||
) -> Optional[AWSResponse]:
|
) -> Optional[AWSResponse]:
|
||||||
|
37
moto/core/decorator.py
Normal file
37
moto/core/decorator.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from typing import TYPE_CHECKING, Callable, Optional, TypeVar, Union, overload
|
||||||
|
|
||||||
|
from moto import settings
|
||||||
|
from moto.core.config import DefaultConfig
|
||||||
|
from moto.core.models import MockAWS, ProxyModeMockAWS, ServerModeMockAWS
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing_extensions import ParamSpec
|
||||||
|
|
||||||
|
P = ParamSpec("P")
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def mock_aws(func: "Callable[P, T]") -> "Callable[P, T]":
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def mock_aws(func: None = None, config: Optional[DefaultConfig] = None) -> "MockAWS":
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def mock_aws(
|
||||||
|
func: "Optional[Callable[P, T]]" = None,
|
||||||
|
config: Optional[DefaultConfig] = None,
|
||||||
|
) -> Union["MockAWS", "Callable[P, T]"]:
|
||||||
|
clss = (
|
||||||
|
ServerModeMockAWS
|
||||||
|
if settings.TEST_SERVER_MODE
|
||||||
|
else (ProxyModeMockAWS if settings.test_proxy_mode() else MockAWS)
|
||||||
|
)
|
||||||
|
if func is not None:
|
||||||
|
return clss().__call__(func=func)
|
||||||
|
else:
|
||||||
|
return clss(config)
|
@ -27,6 +27,7 @@ from botocore.handlers import BUILTIN_HANDLERS
|
|||||||
import moto.backend_index as backend_index
|
import moto.backend_index as backend_index
|
||||||
from moto import settings
|
from moto import settings
|
||||||
|
|
||||||
|
from .base_backend import BackendDict
|
||||||
from .botocore_stubber import BotocoreStubber
|
from .botocore_stubber import BotocoreStubber
|
||||||
from .config import DefaultConfig, default_user_config, mock_credentials
|
from .config import DefaultConfig, default_user_config, mock_credentials
|
||||||
from .custom_responses_mock import (
|
from .custom_responses_mock import (
|
||||||
@ -48,9 +49,9 @@ T = TypeVar("T")
|
|||||||
|
|
||||||
|
|
||||||
class MockAWS(ContextManager["MockAWS"]):
|
class MockAWS(ContextManager["MockAWS"]):
|
||||||
nested_count = 0
|
_nested_count = 0
|
||||||
mocks_active = False
|
_mocks_active = False
|
||||||
mock_init_lock = Lock()
|
_mock_init_lock = Lock()
|
||||||
|
|
||||||
def __init__(self, config: Optional[DefaultConfig] = None) -> None:
|
def __init__(self, config: Optional[DefaultConfig] = None) -> None:
|
||||||
self._fake_creds = {
|
self._fake_creds = {
|
||||||
@ -58,17 +59,17 @@ class MockAWS(ContextManager["MockAWS"]):
|
|||||||
"AWS_SECRET_ACCESS_KEY": "FOOBARSECRET",
|
"AWS_SECRET_ACCESS_KEY": "FOOBARSECRET",
|
||||||
}
|
}
|
||||||
self._orig_creds: Dict[str, Optional[str]] = {}
|
self._orig_creds: Dict[str, Optional[str]] = {}
|
||||||
self.default_session_mock = patch("boto3.DEFAULT_SESSION", None)
|
self._default_session_mock = patch("boto3.DEFAULT_SESSION", None)
|
||||||
current_user_config = default_user_config.copy()
|
current_user_config = default_user_config.copy()
|
||||||
current_user_config.update(config or {})
|
current_user_config.update(config or {})
|
||||||
self.user_config_mock = patch.dict(default_user_config, current_user_config)
|
self._user_config_mock = patch.dict(default_user_config, current_user_config)
|
||||||
|
|
||||||
def __call__(
|
def __call__(
|
||||||
self, func: "Callable[P, T]", reset: bool = True, remove_data: bool = True
|
self, func: "Callable[P, T]", reset: bool = True, remove_data: bool = True
|
||||||
) -> "Callable[P, T]":
|
) -> "Callable[P, T]":
|
||||||
if inspect.isclass(func):
|
if inspect.isclass(func):
|
||||||
return self.decorate_class(func)
|
return self._decorate_class(func)
|
||||||
return self.decorate_callable(func, reset, remove_data)
|
return self._decorate_callable(func, reset, remove_data)
|
||||||
|
|
||||||
def __enter__(self) -> "MockAWS":
|
def __enter__(self) -> "MockAWS":
|
||||||
self.start()
|
self.start()
|
||||||
@ -78,37 +79,37 @@ class MockAWS(ContextManager["MockAWS"]):
|
|||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
def start(self, reset: bool = True) -> None:
|
def start(self, reset: bool = True) -> None:
|
||||||
with MockAWS.mock_init_lock:
|
with MockAWS._mock_init_lock:
|
||||||
self.user_config_mock.start()
|
self._user_config_mock.start()
|
||||||
if mock_credentials():
|
if mock_credentials():
|
||||||
self.mock_env_variables()
|
self._mock_env_variables()
|
||||||
if not self.__class__.mocks_active:
|
if not self.__class__._mocks_active:
|
||||||
self.default_session_mock.start()
|
self._default_session_mock.start()
|
||||||
self.__class__.mocks_active = True
|
self.__class__._mocks_active = True
|
||||||
|
|
||||||
self.__class__.nested_count += 1
|
self.__class__._nested_count += 1
|
||||||
|
|
||||||
if self.__class__.nested_count == 1:
|
if self.__class__._nested_count == 1:
|
||||||
self.enable_patching(reset=reset)
|
self._enable_patching(reset=reset)
|
||||||
|
|
||||||
def stop(self, remove_data: bool = True) -> None:
|
def stop(self, remove_data: bool = True) -> None:
|
||||||
with MockAWS.mock_init_lock:
|
with MockAWS._mock_init_lock:
|
||||||
self.__class__.nested_count -= 1
|
self.__class__._nested_count -= 1
|
||||||
|
|
||||||
if self.__class__.nested_count < 0:
|
if self.__class__._nested_count < 0:
|
||||||
raise RuntimeError("Called stop() before start().")
|
raise RuntimeError("Called stop() before start().")
|
||||||
|
|
||||||
if mock_credentials():
|
if mock_credentials():
|
||||||
self.unmock_env_variables()
|
self._unmock_env_variables()
|
||||||
|
|
||||||
if self.__class__.nested_count == 0:
|
if self.__class__._nested_count == 0:
|
||||||
if self.__class__.mocks_active:
|
if self.__class__._mocks_active:
|
||||||
self.default_session_mock.stop()
|
self._default_session_mock.stop()
|
||||||
self.user_config_mock.stop()
|
self._user_config_mock.stop()
|
||||||
self.__class__.mocks_active = False
|
self.__class__._mocks_active = False
|
||||||
self.disable_patching(remove_data)
|
self._disable_patching(remove_data)
|
||||||
|
|
||||||
def decorate_callable(
|
def _decorate_callable(
|
||||||
self, func: "Callable[P, T]", reset: bool, remove_data: bool
|
self, func: "Callable[P, T]", reset: bool, remove_data: bool
|
||||||
) -> "Callable[P, T]":
|
) -> "Callable[P, T]":
|
||||||
def wrapper(*args: Any, **kwargs: Any) -> T:
|
def wrapper(*args: Any, **kwargs: Any) -> T:
|
||||||
@ -123,7 +124,7 @@ class MockAWS(ContextManager["MockAWS"]):
|
|||||||
wrapper.__wrapped__ = func # type: ignore[attr-defined]
|
wrapper.__wrapped__ = func # type: ignore[attr-defined]
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
def decorate_class(self, klass: "Callable[P, T]") -> "Callable[P, T]":
|
def _decorate_class(self, klass: "Callable[P, T]") -> "Callable[P, T]":
|
||||||
assert inspect.isclass(klass) # Keep mypy happy
|
assert inspect.isclass(klass) # Keep mypy happy
|
||||||
direct_methods = get_direct_methods_of(klass)
|
direct_methods = get_direct_methods_of(klass)
|
||||||
defined_classes = set(
|
defined_classes = set(
|
||||||
@ -191,13 +192,13 @@ class MockAWS(ContextManager["MockAWS"]):
|
|||||||
continue
|
continue
|
||||||
return klass
|
return klass
|
||||||
|
|
||||||
def mock_env_variables(self) -> None:
|
def _mock_env_variables(self) -> None:
|
||||||
# "Mock" the AWS credentials as they can't be mocked in Botocore currently
|
# "Mock" the AWS credentials as they can't be mocked in Botocore currently
|
||||||
for k, v in self._fake_creds.items():
|
for k, v in self._fake_creds.items():
|
||||||
self._orig_creds[k] = os.environ.get(k, None)
|
self._orig_creds[k] = os.environ.get(k, None)
|
||||||
os.environ[k] = v
|
os.environ[k] = v
|
||||||
|
|
||||||
def unmock_env_variables(self) -> None:
|
def _unmock_env_variables(self) -> None:
|
||||||
for k, v in self._orig_creds.items():
|
for k, v in self._orig_creds.items():
|
||||||
if v:
|
if v:
|
||||||
os.environ[k] = v
|
os.environ[k] = v
|
||||||
@ -205,12 +206,10 @@ class MockAWS(ContextManager["MockAWS"]):
|
|||||||
del os.environ[k]
|
del os.environ[k]
|
||||||
|
|
||||||
def reset(self) -> None:
|
def reset(self) -> None:
|
||||||
botocore_stubber.reset()
|
BackendDict.reset()
|
||||||
reset_responses_mock(responses_mock)
|
reset_responses_mock(responses_mock)
|
||||||
|
|
||||||
def enable_patching(
|
def _enable_patching(self, reset: bool = True) -> None:
|
||||||
self, reset: bool = True # pylint: disable=unused-argument
|
|
||||||
) -> None:
|
|
||||||
botocore_stubber.enabled = True
|
botocore_stubber.enabled = True
|
||||||
if reset:
|
if reset:
|
||||||
self.reset()
|
self.reset()
|
||||||
@ -233,7 +232,7 @@ class MockAWS(ContextManager["MockAWS"]):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def disable_patching(self, remove_data: bool) -> None:
|
def _disable_patching(self, remove_data: bool) -> None:
|
||||||
botocore_stubber.enabled = False
|
botocore_stubber.enabled = False
|
||||||
if remove_data:
|
if remove_data:
|
||||||
self.reset()
|
self.reset()
|
||||||
@ -337,24 +336,24 @@ def override_responses_real_send(user_mock: Optional[responses.RequestsMock]) ->
|
|||||||
|
|
||||||
|
|
||||||
class ServerModeMockAWS(MockAWS):
|
class ServerModeMockAWS(MockAWS):
|
||||||
RESET_IN_PROGRESS = False
|
_RESET_IN_PROGRESS = False
|
||||||
|
|
||||||
def __init__(self, *args: Any, **kwargs: Any):
|
def __init__(self, *args: Any, **kwargs: Any):
|
||||||
self.test_server_mode_endpoint = settings.test_server_mode_endpoint()
|
self._test_server_mode_endpoint = settings.test_server_mode_endpoint()
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def reset(self) -> None:
|
def reset(self) -> None:
|
||||||
call_reset_api = os.environ.get("MOTO_CALL_RESET_API")
|
call_reset_api = os.environ.get("MOTO_CALL_RESET_API")
|
||||||
if not call_reset_api or call_reset_api.lower() != "false":
|
if not call_reset_api or call_reset_api.lower() != "false":
|
||||||
if not ServerModeMockAWS.RESET_IN_PROGRESS:
|
if not ServerModeMockAWS._RESET_IN_PROGRESS:
|
||||||
ServerModeMockAWS.RESET_IN_PROGRESS = True
|
ServerModeMockAWS._RESET_IN_PROGRESS = True
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
requests.post(f"{self.test_server_mode_endpoint}/moto-api/reset")
|
requests.post(f"{self._test_server_mode_endpoint}/moto-api/reset")
|
||||||
ServerModeMockAWS.RESET_IN_PROGRESS = False
|
ServerModeMockAWS._RESET_IN_PROGRESS = False
|
||||||
|
|
||||||
def enable_patching(self, reset: bool = True) -> None:
|
def _enable_patching(self, reset: bool = True) -> None:
|
||||||
if self.__class__.nested_count == 1 and reset:
|
if self.__class__._nested_count == 1 and reset:
|
||||||
# Just started
|
# Just started
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
@ -373,12 +372,12 @@ class ServerModeMockAWS(MockAWS):
|
|||||||
config = Config(user_agent_extra="region/" + region)
|
config = Config(user_agent_extra="region/" + region)
|
||||||
kwargs["config"] = config
|
kwargs["config"] = config
|
||||||
if "endpoint_url" not in kwargs:
|
if "endpoint_url" not in kwargs:
|
||||||
kwargs["endpoint_url"] = self.test_server_mode_endpoint
|
kwargs["endpoint_url"] = self._test_server_mode_endpoint
|
||||||
return real_boto3_client(*args, **kwargs)
|
return real_boto3_client(*args, **kwargs)
|
||||||
|
|
||||||
def fake_boto3_resource(*args: Any, **kwargs: Any) -> Any:
|
def fake_boto3_resource(*args: Any, **kwargs: Any) -> Any:
|
||||||
if "endpoint_url" not in kwargs:
|
if "endpoint_url" not in kwargs:
|
||||||
kwargs["endpoint_url"] = self.test_server_mode_endpoint
|
kwargs["endpoint_url"] = self._test_server_mode_endpoint
|
||||||
return real_boto3_resource(*args, **kwargs)
|
return real_boto3_resource(*args, **kwargs)
|
||||||
|
|
||||||
self._client_patcher = patch("boto3.client", fake_boto3_client)
|
self._client_patcher = patch("boto3.client", fake_boto3_client)
|
||||||
@ -394,7 +393,7 @@ class ServerModeMockAWS(MockAWS):
|
|||||||
return region
|
return region
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def disable_patching(self, remove_data: bool) -> None:
|
def _disable_patching(self, remove_data: bool) -> None:
|
||||||
if self._client_patcher:
|
if self._client_patcher:
|
||||||
self._client_patcher.stop()
|
self._client_patcher.stop()
|
||||||
self._resource_patcher.stop()
|
self._resource_patcher.stop()
|
||||||
@ -404,24 +403,24 @@ class ServerModeMockAWS(MockAWS):
|
|||||||
|
|
||||||
class ProxyModeMockAWS(MockAWS):
|
class ProxyModeMockAWS(MockAWS):
|
||||||
|
|
||||||
RESET_IN_PROGRESS = False
|
_RESET_IN_PROGRESS = False
|
||||||
|
|
||||||
def __init__(self, *args: Any, **kwargs: Any):
|
def __init__(self, *args: Any, **kwargs: Any):
|
||||||
self.test_proxy_mode_endpoint = settings.test_proxy_mode_endpoint()
|
self._test_proxy_mode_endpoint = settings.test_proxy_mode_endpoint()
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def reset(self) -> None:
|
def reset(self) -> None:
|
||||||
call_reset_api = os.environ.get("MOTO_CALL_RESET_API")
|
call_reset_api = os.environ.get("MOTO_CALL_RESET_API")
|
||||||
if not call_reset_api or call_reset_api.lower() != "false":
|
if not call_reset_api or call_reset_api.lower() != "false":
|
||||||
if not ProxyModeMockAWS.RESET_IN_PROGRESS:
|
if not ProxyModeMockAWS._RESET_IN_PROGRESS:
|
||||||
ProxyModeMockAWS.RESET_IN_PROGRESS = True
|
ProxyModeMockAWS._RESET_IN_PROGRESS = True
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
requests.post(f"{self.test_proxy_mode_endpoint}/moto-api/reset")
|
requests.post(f"{self._test_proxy_mode_endpoint}/moto-api/reset")
|
||||||
ProxyModeMockAWS.RESET_IN_PROGRESS = False
|
ProxyModeMockAWS._RESET_IN_PROGRESS = False
|
||||||
|
|
||||||
def enable_patching(self, reset: bool = True) -> None:
|
def _enable_patching(self, reset: bool = True) -> None:
|
||||||
if self.__class__.nested_count == 1 and reset:
|
if self.__class__._nested_count == 1 and reset:
|
||||||
# Just started
|
# Just started
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
@ -460,7 +459,7 @@ class ProxyModeMockAWS(MockAWS):
|
|||||||
self._client_patcher.start()
|
self._client_patcher.start()
|
||||||
self._resource_patcher.start()
|
self._resource_patcher.start()
|
||||||
|
|
||||||
def disable_patching(self, remove_data: bool) -> None:
|
def _disable_patching(self, remove_data: bool) -> None:
|
||||||
if self._client_patcher:
|
if self._client_patcher:
|
||||||
self._client_patcher.stop()
|
self._client_patcher.stop()
|
||||||
self._resource_patcher.stop()
|
self._resource_patcher.stop()
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
|
import inspect
|
||||||
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest import SkipTest
|
from unittest import SkipTest, mock
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
import pytest
|
import pytest
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
|
|
||||||
from moto import mock_aws, settings
|
from moto import mock_aws, settings
|
||||||
|
from moto.core.decorator import ProxyModeMockAWS, ServerModeMockAWS
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Test the different ways that the decorator can be used
|
Test the different ways that the decorator can be used
|
||||||
@ -44,15 +47,29 @@ def test_context_manager(aws_credentials: Any) -> None: # type: ignore[misc] #
|
|||||||
assert client.describe_addresses()["Addresses"] == []
|
assert client.describe_addresses()["Addresses"] == []
|
||||||
|
|
||||||
|
|
||||||
|
@mock.patch.dict(os.environ, {"MOTO_CALL_RESET_API": "false"})
|
||||||
|
@pytest.mark.parametrize("mock_class", [mock_aws, ServerModeMockAWS, ProxyModeMockAWS])
|
||||||
|
def test_context_decorator_exposes_bare_essentials(mock_class: Any) -> None: # type: ignore
|
||||||
|
|
||||||
|
# Verify we're only exposing the necessary methods
|
||||||
|
with mock_class() as m:
|
||||||
|
exposed_attributes = [a for a in m.__dict__.keys() if not a.startswith("_")]
|
||||||
|
assert exposed_attributes == []
|
||||||
|
|
||||||
|
# Methods + Static attributes
|
||||||
|
exposed_methods = [n for n, _ in inspect.getmembers(m) if not n.startswith("_")]
|
||||||
|
assert sorted(exposed_methods) == ["reset", "start", "stop"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.network
|
@pytest.mark.network
|
||||||
def test_decorator_start_and_stop() -> None:
|
def test_decorator_start_and_stop() -> None:
|
||||||
if settings.TEST_SERVER_MODE:
|
if settings.TEST_SERVER_MODE:
|
||||||
raise SkipTest("Authentication always works in ServerMode")
|
raise SkipTest("Authentication always works in ServerMode")
|
||||||
mock = mock_aws()
|
my_mock = mock_aws()
|
||||||
mock.start()
|
my_mock.start()
|
||||||
client = boto3.client("ec2", region_name="us-west-1")
|
client = boto3.client("ec2", region_name="us-west-1")
|
||||||
assert client.describe_addresses()["Addresses"] == []
|
assert client.describe_addresses()["Addresses"] == []
|
||||||
mock.stop()
|
my_mock.stop()
|
||||||
|
|
||||||
with pytest.raises(ClientError) as exc:
|
with pytest.raises(ClientError) as exc:
|
||||||
client.describe_addresses()
|
client.describe_addresses()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import boto3
|
import boto3
|
||||||
|
|
||||||
from moto import MockAWS, mock_aws
|
from moto import mock_aws
|
||||||
|
from moto.core.decorator import MockAWS
|
||||||
|
|
||||||
|
|
||||||
@mock_aws
|
@mock_aws
|
||||||
|
Loading…
Reference in New Issue
Block a user