From 2515093ceea4b512d5fa99d50e9ccad6e9afe9e6 Mon Sep 17 00:00:00 2001 From: Steven Hoelscher Date: Wed, 22 May 2024 12:15:13 -0700 Subject: [PATCH 1/8] fix: POWERTOOLS_IDEMPOTENCY_DISABLED should respect truthy values --- aws_lambda_powertools/utilities/idempotency/idempotency.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/utilities/idempotency/idempotency.py b/aws_lambda_powertools/utilities/idempotency/idempotency.py index 9593655b3cd..8f10777b025 100644 --- a/aws_lambda_powertools/utilities/idempotency/idempotency.py +++ b/aws_lambda_powertools/utilities/idempotency/idempotency.py @@ -16,6 +16,7 @@ from aws_lambda_powertools.utilities.idempotency.persistence.base import ( BasePersistenceLayer, ) +from aws_lambda_powertools.shared.functions import strtobool from aws_lambda_powertools.utilities.idempotency.serialization.base import ( BaseIdempotencyModelSerializer, BaseIdempotencySerializer, @@ -66,7 +67,7 @@ def idempotent( >>> return {"StatusCode": 200} """ - if os.getenv(constants.IDEMPOTENCY_DISABLED_ENV): + if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "0")): return handler(event, context, **kwargs) config = config or IdempotencyConfig() @@ -150,7 +151,7 @@ def process_order(customer_id: str, order: dict, **kwargs): @functools.wraps(function) def decorate(*args, **kwargs): - if os.getenv(constants.IDEMPOTENCY_DISABLED_ENV): + if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "0")): return function(*args, **kwargs) if data_keyword_argument not in kwargs: From 44c19435e34d4ea50c13428254fcc1ef01a94bae Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Thu, 23 May 2024 00:09:01 +0100 Subject: [PATCH 2/8] Adding more tests --- .../utilities/idempotency/idempotency.py | 8 +++- .../idempotency/test_idempotency.py | 38 ++++++++++++++++++- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/aws_lambda_powertools/utilities/idempotency/idempotency.py b/aws_lambda_powertools/utilities/idempotency/idempotency.py index 8f10777b025..f7f28f27933 100644 --- a/aws_lambda_powertools/utilities/idempotency/idempotency.py +++ b/aws_lambda_powertools/utilities/idempotency/idempotency.py @@ -10,13 +10,13 @@ from aws_lambda_powertools.middleware_factory import lambda_handler_decorator from aws_lambda_powertools.shared import constants +from aws_lambda_powertools.shared.functions import strtobool from aws_lambda_powertools.shared.types import AnyCallableT from aws_lambda_powertools.utilities.idempotency.base import IdempotencyHandler from aws_lambda_powertools.utilities.idempotency.config import IdempotencyConfig from aws_lambda_powertools.utilities.idempotency.persistence.base import ( BasePersistenceLayer, ) -from aws_lambda_powertools.shared.functions import strtobool from aws_lambda_powertools.utilities.idempotency.serialization.base import ( BaseIdempotencyModelSerializer, BaseIdempotencySerializer, @@ -67,7 +67,9 @@ def idempotent( >>> return {"StatusCode": 200} """ - if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "0")): + # Check if the IDEMPOTENCY_DISABLED_ENV environment variable is set to True + # If IDEMPOTENCY_DISABLED_ENV is not set or set to any false value, the function will be idempotent by default + if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "false")): return handler(event, context, **kwargs) config = config or IdempotencyConfig() @@ -151,6 +153,8 @@ def process_order(customer_id: str, order: dict, **kwargs): @functools.wraps(function) def decorate(*args, **kwargs): + # Check if the IDEMPOTENCY_DISABLED_ENV environment variable is set to True + # If IDEMPOTENCY_DISABLED_ENV is not set or set to any false value, the function will be idempotent by default if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "0")): return function(*args, **kwargs) diff --git a/tests/functional/idempotency/test_idempotency.py b/tests/functional/idempotency/test_idempotency.py index d33469d680f..8d9cc10731c 100644 --- a/tests/functional/idempotency/test_idempotency.py +++ b/tests/functional/idempotency/test_idempotency.py @@ -1667,13 +1667,19 @@ def dummy(payload): dummy(payload=data_two) -def test_idempotency_disabled_envvar(monkeypatch, lambda_context, persistence_store: DynamoDBPersistenceLayer): +@pytest.mark.parametrize("idempotency_disabled_value", ["1", "y", "yes", "t", "true", "on"]) +def test_idempotency_enabled_envvar( + monkeypatch, + lambda_context, + persistence_store: DynamoDBPersistenceLayer, + idempotency_disabled_value, +): # Scenario to validate no requests sent to dynamodb table when 'POWERTOOLS_IDEMPOTENCY_DISABLED' is set mock_event = {"data": "value"} persistence_store.client = MagicMock() - monkeypatch.setenv("POWERTOOLS_IDEMPOTENCY_DISABLED", "1") + monkeypatch.setenv("POWERTOOLS_IDEMPOTENCY_DISABLED", str(idempotency_disabled_value)) @idempotent_function(data_keyword_argument="data", persistence_store=persistence_store) def dummy(data): @@ -1689,6 +1695,34 @@ def dummy_handler(event, context): assert len(persistence_store.client.method_calls) == 0 +@pytest.mark.parametrize("idempotency_disabled_value", ["0", "n", "no", "f", "false", "off"]) +def test_idempotency_disabled_envvar( + monkeypatch, + lambda_context, + persistence_store: DynamoDBPersistenceLayer, + idempotency_disabled_value, +): + # Scenario to validate no requests sent to dynamodb table when 'POWERTOOLS_IDEMPOTENCY_DISABLED' is false + mock_event = {"data": "value"} + + persistence_store.client = MagicMock() + + monkeypatch.setenv("POWERTOOLS_IDEMPOTENCY_DISABLED", str(idempotency_disabled_value)) + + @idempotent_function(data_keyword_argument="data", persistence_store=persistence_store) + def dummy(data): + return {"message": "hello"} + + @idempotent(persistence_store=persistence_store) + def dummy_handler(event, context): + return {"message": "hi"} + + dummy(data=mock_event) + dummy_handler(mock_event, lambda_context) + + assert len(persistence_store.client.method_calls) == 4 + + @pytest.mark.parametrize("idempotency_config", [{"use_local_cache": True}], indirect=True) def test_idempotent_function_duplicates( idempotency_config: IdempotencyConfig, From 1ee0a36abf3f8c731cfe20e6ea1dc8c9b57fcfd2 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Thu, 23 May 2024 14:23:35 +0100 Subject: [PATCH 3/8] Addressing Heitor's feedback --- .../shared/powertools_warnings.py | 18 ++++++++++ .../utilities/idempotency/idempotency.py | 28 ++++++++++++---- .../idempotency/test_idempotency.py | 33 ++++++++++++++++++- 3 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 aws_lambda_powertools/shared/powertools_warnings.py diff --git a/aws_lambda_powertools/shared/powertools_warnings.py b/aws_lambda_powertools/shared/powertools_warnings.py new file mode 100644 index 00000000000..2c8613ff336 --- /dev/null +++ b/aws_lambda_powertools/shared/powertools_warnings.py @@ -0,0 +1,18 @@ +class PowertoolsWarning(UserWarning): + """ + This class provides a custom Warning tailored for better clarity when certain situations occur. + It offers more informative and relevant warning messages, allowing customers to easily suppress + or handle this specific warning type as needed. + + Parameters + ---------- + message: str + The warning message to be displayed. + """ + + def __init__(self, message): + self.message = message + super().__init__(message) + + def __str__(self): + return self.message diff --git a/aws_lambda_powertools/utilities/idempotency/idempotency.py b/aws_lambda_powertools/utilities/idempotency/idempotency.py index f7f28f27933..ba894fe19e5 100644 --- a/aws_lambda_powertools/utilities/idempotency/idempotency.py +++ b/aws_lambda_powertools/utilities/idempotency/idempotency.py @@ -5,12 +5,14 @@ import functools import logging import os +import warnings from inspect import isclass from typing import Any, Callable, Dict, Optional, Type, Union, cast from aws_lambda_powertools.middleware_factory import lambda_handler_decorator from aws_lambda_powertools.shared import constants -from aws_lambda_powertools.shared.functions import strtobool +from aws_lambda_powertools.shared.functions import powertools_dev_is_set, strtobool +from aws_lambda_powertools.shared.powertools_warnings import PowertoolsWarning from aws_lambda_powertools.shared.types import AnyCallableT from aws_lambda_powertools.utilities.idempotency.base import IdempotencyHandler from aws_lambda_powertools.utilities.idempotency.config import IdempotencyConfig @@ -67,9 +69,16 @@ def idempotent( >>> return {"StatusCode": 200} """ - # Check if the IDEMPOTENCY_DISABLED_ENV environment variable is set to True - # If IDEMPOTENCY_DISABLED_ENV is not set or set to any false value, the function will be idempotent by default + # Skip idempotency controls when POWERTOOLS_IDEMPOTENCY_DISABLED has a truthy value + # Raises a warning if not running in development mode if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "false")): + if not powertools_dev_is_set(): + warnings.warn( + message="Disabling idempotency is intended for development environments only " + "and should not be used in production.", + category=PowertoolsWarning, + stacklevel=2, + ) return handler(event, context, **kwargs) config = config or IdempotencyConfig() @@ -153,9 +162,16 @@ def process_order(customer_id: str, order: dict, **kwargs): @functools.wraps(function) def decorate(*args, **kwargs): - # Check if the IDEMPOTENCY_DISABLED_ENV environment variable is set to True - # If IDEMPOTENCY_DISABLED_ENV is not set or set to any false value, the function will be idempotent by default - if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "0")): + # Skip idempotency controls when POWERTOOLS_IDEMPOTENCY_DISABLED has a truthy value + # Raises a warning if not running in development mode + if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "false")): + if not powertools_dev_is_set(): + warnings.warn( + message="Disabling idempotency is intended for development environments only " + "and should not be used in production.", + category=PowertoolsWarning, + stacklevel=2, + ) return function(*args, **kwargs) if data_keyword_argument not in kwargs: diff --git a/tests/functional/idempotency/test_idempotency.py b/tests/functional/idempotency/test_idempotency.py index 8d9cc10731c..9087f99608a 100644 --- a/tests/functional/idempotency/test_idempotency.py +++ b/tests/functional/idempotency/test_idempotency.py @@ -12,6 +12,7 @@ from pytest import FixtureRequest from pytest_mock import MockerFixture +from aws_lambda_powertools.shared.powertools_warnings import PowertoolsWarning from aws_lambda_powertools.utilities.data_classes import ( APIGatewayProxyEventV2, event_source, @@ -1668,7 +1669,7 @@ def dummy(payload): @pytest.mark.parametrize("idempotency_disabled_value", ["1", "y", "yes", "t", "true", "on"]) -def test_idempotency_enabled_envvar( +def test_idempotency_enabled_envvar_in_dev_environment( monkeypatch, lambda_context, persistence_store: DynamoDBPersistenceLayer, @@ -1680,6 +1681,7 @@ def test_idempotency_enabled_envvar( persistence_store.client = MagicMock() monkeypatch.setenv("POWERTOOLS_IDEMPOTENCY_DISABLED", str(idempotency_disabled_value)) + monkeypatch.setenv("POWERTOOLS_DEV", "true") @idempotent_function(data_keyword_argument="data", persistence_store=persistence_store) def dummy(data): @@ -1695,6 +1697,35 @@ def dummy_handler(event, context): assert len(persistence_store.client.method_calls) == 0 +@pytest.mark.parametrize("idempotency_disabled_value", ["1", "y", "yes", "t", "true", "on"]) +def test_idempotency_enabled_envvar_in_non_dev_environment( + monkeypatch, + lambda_context, + persistence_store: DynamoDBPersistenceLayer, + idempotency_disabled_value, +): + # Scenario to validate no requests sent to dynamodb table when 'POWERTOOLS_IDEMPOTENCY_DISABLED' is set + mock_event = {"data": "value"} + + persistence_store.client = MagicMock() + + monkeypatch.setenv("POWERTOOLS_IDEMPOTENCY_DISABLED", str(idempotency_disabled_value)) + + @idempotent_function(data_keyword_argument="data", persistence_store=persistence_store) + def dummy(data): + return {"message": "hello"} + + @idempotent(persistence_store=persistence_store) + def dummy_handler(event, context): + return {"message": "hi"} + + with pytest.warns(PowertoolsWarning, match="Disabling idempotency is intended for development environments*"): + dummy(data=mock_event) + dummy_handler(mock_event, lambda_context) + + assert len(persistence_store.client.method_calls) == 0 + + @pytest.mark.parametrize("idempotency_disabled_value", ["0", "n", "no", "f", "false", "off"]) def test_idempotency_disabled_envvar( monkeypatch, From eb67c59624a5779757b045428820fe98d8093239 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Fri, 31 May 2024 13:14:24 +0100 Subject: [PATCH 4/8] Moving exception files --- aws_lambda_powertools/exceptions/__init__.py | 2 +- aws_lambda_powertools/utilities/idempotency/idempotency.py | 2 +- .../{shared/powertools_warnings.py => warnings/__init__.py} | 3 +++ tests/functional/idempotency/test_idempotency.py | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) rename aws_lambda_powertools/{shared/powertools_warnings.py => warnings/__init__.py} (89%) diff --git a/aws_lambda_powertools/exceptions/__init__.py b/aws_lambda_powertools/exceptions/__init__.py index cb8724c4490..5e3433a249d 100644 --- a/aws_lambda_powertools/exceptions/__init__.py +++ b/aws_lambda_powertools/exceptions/__init__.py @@ -1,4 +1,4 @@ -"""Shared exceptions that don't belong to a single utility""" +"""Shared warnings that don't belong to a single utility""" class InvalidEnvelopeExpressionError(Exception): diff --git a/aws_lambda_powertools/utilities/idempotency/idempotency.py b/aws_lambda_powertools/utilities/idempotency/idempotency.py index ba894fe19e5..6aa9fffbe51 100644 --- a/aws_lambda_powertools/utilities/idempotency/idempotency.py +++ b/aws_lambda_powertools/utilities/idempotency/idempotency.py @@ -12,7 +12,6 @@ from aws_lambda_powertools.middleware_factory import lambda_handler_decorator from aws_lambda_powertools.shared import constants from aws_lambda_powertools.shared.functions import powertools_dev_is_set, strtobool -from aws_lambda_powertools.shared.powertools_warnings import PowertoolsWarning from aws_lambda_powertools.shared.types import AnyCallableT from aws_lambda_powertools.utilities.idempotency.base import IdempotencyHandler from aws_lambda_powertools.utilities.idempotency.config import IdempotencyConfig @@ -24,6 +23,7 @@ BaseIdempotencySerializer, ) from aws_lambda_powertools.utilities.typing import LambdaContext +from aws_lambda_powertools.warnings import PowertoolsWarning logger = logging.getLogger(__name__) diff --git a/aws_lambda_powertools/shared/powertools_warnings.py b/aws_lambda_powertools/warnings/__init__.py similarity index 89% rename from aws_lambda_powertools/shared/powertools_warnings.py rename to aws_lambda_powertools/warnings/__init__.py index 2c8613ff336..27957bd775e 100644 --- a/aws_lambda_powertools/shared/powertools_warnings.py +++ b/aws_lambda_powertools/warnings/__init__.py @@ -1,3 +1,6 @@ +"""Shared exceptions that don't belong to a single utility""" + + class PowertoolsWarning(UserWarning): """ This class provides a custom Warning tailored for better clarity when certain situations occur. diff --git a/tests/functional/idempotency/test_idempotency.py b/tests/functional/idempotency/test_idempotency.py index 9087f99608a..70421fd3242 100644 --- a/tests/functional/idempotency/test_idempotency.py +++ b/tests/functional/idempotency/test_idempotency.py @@ -12,7 +12,6 @@ from pytest import FixtureRequest from pytest_mock import MockerFixture -from aws_lambda_powertools.shared.powertools_warnings import PowertoolsWarning from aws_lambda_powertools.utilities.data_classes import ( APIGatewayProxyEventV2, event_source, @@ -52,6 +51,7 @@ PydanticSerializer, ) from aws_lambda_powertools.utilities.validation import envelopes, validator +from aws_lambda_powertools.warnings import PowertoolsWarning from tests.functional.idempotency.utils import ( build_idempotency_put_item_response_stub, build_idempotency_put_item_stub, From 058fbb9ba0cee7d87acde37d8ea63f94f240a029 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Fri, 31 May 2024 13:17:55 +0100 Subject: [PATCH 5/8] Typo --- aws_lambda_powertools/exceptions/__init__.py | 2 +- aws_lambda_powertools/warnings/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/exceptions/__init__.py b/aws_lambda_powertools/exceptions/__init__.py index 5e3433a249d..cb8724c4490 100644 --- a/aws_lambda_powertools/exceptions/__init__.py +++ b/aws_lambda_powertools/exceptions/__init__.py @@ -1,4 +1,4 @@ -"""Shared warnings that don't belong to a single utility""" +"""Shared exceptions that don't belong to a single utility""" class InvalidEnvelopeExpressionError(Exception): diff --git a/aws_lambda_powertools/warnings/__init__.py b/aws_lambda_powertools/warnings/__init__.py index 27957bd775e..1757ea9674a 100644 --- a/aws_lambda_powertools/warnings/__init__.py +++ b/aws_lambda_powertools/warnings/__init__.py @@ -1,4 +1,4 @@ -"""Shared exceptions that don't belong to a single utility""" +"""Shared warnings that don't belong to a single utility""" class PowertoolsWarning(UserWarning): From a0f12c9521637013626254cdf8a2565ac4bc3287 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 4 Jun 2024 08:20:18 +0100 Subject: [PATCH 6/8] Addressing Heitor's feedback --- aws_lambda_powertools/utilities/idempotency/idempotency.py | 6 +++--- aws_lambda_powertools/warnings/__init__.py | 2 +- tests/functional/idempotency/test_idempotency.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/aws_lambda_powertools/utilities/idempotency/idempotency.py b/aws_lambda_powertools/utilities/idempotency/idempotency.py index 6aa9fffbe51..08e9ae20788 100644 --- a/aws_lambda_powertools/utilities/idempotency/idempotency.py +++ b/aws_lambda_powertools/utilities/idempotency/idempotency.py @@ -23,7 +23,7 @@ BaseIdempotencySerializer, ) from aws_lambda_powertools.utilities.typing import LambdaContext -from aws_lambda_powertools.warnings import PowertoolsWarning +from aws_lambda_powertools.warnings import PowertoolsUserWarning logger = logging.getLogger(__name__) @@ -76,7 +76,7 @@ def idempotent( warnings.warn( message="Disabling idempotency is intended for development environments only " "and should not be used in production.", - category=PowertoolsWarning, + category=PowertoolsUserWarning, stacklevel=2, ) return handler(event, context, **kwargs) @@ -169,7 +169,7 @@ def decorate(*args, **kwargs): warnings.warn( message="Disabling idempotency is intended for development environments only " "and should not be used in production.", - category=PowertoolsWarning, + category=PowertoolsUserWarning, stacklevel=2, ) return function(*args, **kwargs) diff --git a/aws_lambda_powertools/warnings/__init__.py b/aws_lambda_powertools/warnings/__init__.py index 1757ea9674a..50426e2a14e 100644 --- a/aws_lambda_powertools/warnings/__init__.py +++ b/aws_lambda_powertools/warnings/__init__.py @@ -1,7 +1,7 @@ """Shared warnings that don't belong to a single utility""" -class PowertoolsWarning(UserWarning): +class PowertoolsUserWarning(UserWarning): """ This class provides a custom Warning tailored for better clarity when certain situations occur. It offers more informative and relevant warning messages, allowing customers to easily suppress diff --git a/tests/functional/idempotency/test_idempotency.py b/tests/functional/idempotency/test_idempotency.py index 70421fd3242..83ee16f328b 100644 --- a/tests/functional/idempotency/test_idempotency.py +++ b/tests/functional/idempotency/test_idempotency.py @@ -51,7 +51,7 @@ PydanticSerializer, ) from aws_lambda_powertools.utilities.validation import envelopes, validator -from aws_lambda_powertools.warnings import PowertoolsWarning +from aws_lambda_powertools.warnings import PowertoolsUserWarning from tests.functional.idempotency.utils import ( build_idempotency_put_item_response_stub, build_idempotency_put_item_stub, @@ -1719,7 +1719,7 @@ def dummy(data): def dummy_handler(event, context): return {"message": "hi"} - with pytest.warns(PowertoolsWarning, match="Disabling idempotency is intended for development environments*"): + with pytest.warns(PowertoolsUserWarning, match="Disabling idempotency is intended for development environments*"): dummy(data=mock_event) dummy_handler(mock_event, lambda_context) From a88f92077935a3fb2bfe05f4680013907f3c906d Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 4 Jun 2024 08:24:54 +0100 Subject: [PATCH 7/8] Addressing Heitor's feedback --- aws_lambda_powertools/warnings/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/warnings/__init__.py b/aws_lambda_powertools/warnings/__init__.py index 50426e2a14e..f6fcc85a988 100644 --- a/aws_lambda_powertools/warnings/__init__.py +++ b/aws_lambda_powertools/warnings/__init__.py @@ -4,8 +4,10 @@ class PowertoolsUserWarning(UserWarning): """ This class provides a custom Warning tailored for better clarity when certain situations occur. - It offers more informative and relevant warning messages, allowing customers to easily suppress - or handle this specific warning type as needed. + + Examples: + - Using development-only features in production environment. + - Potential performance or security issues due to misconfiguration. Parameters ---------- From ffe8e0000f010bbd60604d439d49fe57ae5abd18 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 4 Jun 2024 08:44:33 +0100 Subject: [PATCH 8/8] Addressing Heitor's feedback --- .../utilities/idempotency/idempotency.py | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/aws_lambda_powertools/utilities/idempotency/idempotency.py b/aws_lambda_powertools/utilities/idempotency/idempotency.py index 08e9ae20788..c6fa44aeac7 100644 --- a/aws_lambda_powertools/utilities/idempotency/idempotency.py +++ b/aws_lambda_powertools/utilities/idempotency/idempotency.py @@ -11,7 +11,7 @@ from aws_lambda_powertools.middleware_factory import lambda_handler_decorator from aws_lambda_powertools.shared import constants -from aws_lambda_powertools.shared.functions import powertools_dev_is_set, strtobool +from aws_lambda_powertools.shared.functions import strtobool from aws_lambda_powertools.shared.types import AnyCallableT from aws_lambda_powertools.utilities.idempotency.base import IdempotencyHandler from aws_lambda_powertools.utilities.idempotency.config import IdempotencyConfig @@ -72,13 +72,12 @@ def idempotent( # Skip idempotency controls when POWERTOOLS_IDEMPOTENCY_DISABLED has a truthy value # Raises a warning if not running in development mode if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "false")): - if not powertools_dev_is_set(): - warnings.warn( - message="Disabling idempotency is intended for development environments only " - "and should not be used in production.", - category=PowertoolsUserWarning, - stacklevel=2, - ) + warnings.warn( + message="Disabling idempotency is intended for development environments only " + "and should not be used in production.", + category=PowertoolsUserWarning, + stacklevel=2, + ) return handler(event, context, **kwargs) config = config or IdempotencyConfig() @@ -165,13 +164,12 @@ def decorate(*args, **kwargs): # Skip idempotency controls when POWERTOOLS_IDEMPOTENCY_DISABLED has a truthy value # Raises a warning if not running in development mode if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "false")): - if not powertools_dev_is_set(): - warnings.warn( - message="Disabling idempotency is intended for development environments only " - "and should not be used in production.", - category=PowertoolsUserWarning, - stacklevel=2, - ) + warnings.warn( + message="Disabling idempotency is intended for development environments only " + "and should not be used in production.", + category=PowertoolsUserWarning, + stacklevel=2, + ) return function(*args, **kwargs) if data_keyword_argument not in kwargs: