diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index 7d7dedf8dc8..1db45b80ebd 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -209,7 +209,13 @@ class Route: """Internally used Route Configuration""" def __init__( - self, method: str, rule: Pattern, func: Callable, cors: bool, compress: bool, cache_control: Optional[str] + self, + method: str, + rule: Pattern, + func: Callable, + cors: bool, + compress: bool, + cache_control: Optional[str], ): self.method = method.upper() self.rule = rule @@ -237,7 +243,9 @@ def _add_cache_control(self, cache_control: str): @staticmethod def _has_compression_enabled( - route_compression: bool, response_compression: Optional[bool], event: BaseProxyEvent + route_compression: bool, + response_compression: Optional[bool], + event: BaseProxyEvent, ) -> bool: """ Checks if compression is enabled. @@ -285,7 +293,9 @@ def _route(self, event: BaseProxyEvent, cors: Optional[CORSConfig]): if self.route.cache_control: self._add_cache_control(self.route.cache_control) if self._has_compression_enabled( - route_compression=self.route.compress, response_compression=self.response.compress, event=event + route_compression=self.route.compress, + response_compression=self.response.compress, + event=event, ): self._compress() @@ -400,7 +410,11 @@ def lambda_handler(event, context): return self.route(rule, "PUT", cors, compress, cache_control) def delete( - self, rule: str, cors: Optional[bool] = None, compress: bool = False, cache_control: Optional[str] = None + self, + rule: str, + cors: Optional[bool] = None, + compress: bool = False, + cache_control: Optional[str] = None, ): """Delete route decorator with DELETE `method` @@ -427,7 +441,11 @@ def lambda_handler(event, context): return self.route(rule, "DELETE", cors, compress, cache_control) def patch( - self, rule: str, cors: Optional[bool] = None, compress: bool = False, cache_control: Optional[str] = None + self, + rule: str, + cors: Optional[bool] = None, + compress: bool = False, + cache_control: Optional[str] = None, ): """Patch route decorator with PATCH `method` @@ -566,7 +584,8 @@ def register_resolver(func: Callable): route_key = item + rule if route_key in self._route_keys: warnings.warn( - f"A route like this was already registered. method: '{item}' rule: '{rule}'", stacklevel=2 + f"A route like this was already registered. method: '{item}' rule: '{rule}'", + stacklevel=2, ) self._route_keys.append(route_key) if cors_enabled: @@ -725,7 +744,7 @@ def _not_found(self, method: str) -> ResponseBuilder: content_type=content_types.APPLICATION_JSON, headers=headers, body=self._json_dump({"statusCode": HTTPStatus.NOT_FOUND.value, "message": "Not found"}), - ) + ), ) def _call_route(self, route: Route, args: Dict[str, str]) -> ResponseBuilder: diff --git a/aws_lambda_powertools/event_handler/appsync.py b/aws_lambda_powertools/event_handler/appsync.py index 316792e4119..fba5681ef6a 100644 --- a/aws_lambda_powertools/event_handler/appsync.py +++ b/aws_lambda_powertools/event_handler/appsync.py @@ -80,7 +80,10 @@ def __init__(self): self.context = {} # early init as customers might add context before event resolution def resolve( - self, event: dict, context: LambdaContext, data_model: Type[AppSyncResolverEvent] = AppSyncResolverEvent + self, + event: dict, + context: LambdaContext, + data_model: Type[AppSyncResolverEvent] = AppSyncResolverEvent, ) -> Any: """Resolve field_name @@ -183,7 +186,10 @@ def _get_resolver(self, type_name: str, field_name: str) -> Callable: return resolver["func"] def __call__( - self, event: dict, context: LambdaContext, data_model: Type[AppSyncResolverEvent] = AppSyncResolverEvent + self, + event: dict, + context: LambdaContext, + data_model: Type[AppSyncResolverEvent] = AppSyncResolverEvent, ) -> Any: """Implicit lambda handler which internally calls `resolve`""" return self.resolve(event, context, data_model) diff --git a/aws_lambda_powertools/logging/formatter.py b/aws_lambda_powertools/logging/formatter.py index 03bb4211f49..03b290fde64 100644 --- a/aws_lambda_powertools/logging/formatter.py +++ b/aws_lambda_powertools/logging/formatter.py @@ -127,7 +127,10 @@ def __init__( constants.PRETTY_INDENT if powertools_dev_is_set() else constants.COMPACT_INDENT ) # indented json serialization when in AWS SAM Local self.json_serializer = json_serializer or partial( - json.dumps, default=self.json_default, separators=(",", ":"), indent=self.json_indent + json.dumps, + default=self.json_default, + separators=(",", ":"), + indent=self.json_indent, ) self.datefmt = datefmt diff --git a/aws_lambda_powertools/logging/logger.py b/aws_lambda_powertools/logging/logger.py index f1d4729c5d2..31405ff4e26 100644 --- a/aws_lambda_powertools/logging/logger.py +++ b/aws_lambda_powertools/logging/logger.py @@ -223,10 +223,12 @@ def __init__( **kwargs, ): self.service = resolve_env_var_choice( - choice=service, env=os.getenv(constants.SERVICE_NAME_ENV, "service_undefined") + choice=service, + env=os.getenv(constants.SERVICE_NAME_ENV, "service_undefined"), ) self.sampling_rate = resolve_env_var_choice( - choice=sampling_rate, env=os.getenv(constants.LOGGER_LOG_SAMPLING_RATE) + choice=sampling_rate, + env=os.getenv(constants.LOGGER_LOG_SAMPLING_RATE), ) self.child = child self.logger_formatter = logger_formatter @@ -234,7 +236,7 @@ def __init__( self.log_uncaught_exceptions = log_uncaught_exceptions self._is_deduplication_disabled = resolve_truthy_env_var_choice( - env=os.getenv(constants.LOGGER_LOG_DEDUPLICATION_ENV, "false") + env=os.getenv(constants.LOGGER_LOG_DEDUPLICATION_ENV, "false"), ) self._default_log_keys = {"service": self.service, "sampling_rate": self.sampling_rate} self._logger = self._get_logger() @@ -327,7 +329,7 @@ def _configure_sampling(self): except ValueError: raise InvalidLoggerSamplingRateError( f"Expected a float value ranging 0 to 1, but received {self.sampling_rate} instead." - f"Please review POWERTOOLS_LOGGER_SAMPLE_RATE environment variable." + f"Please review POWERTOOLS_LOGGER_SAMPLE_RATE environment variable.", ) @overload @@ -415,7 +417,8 @@ def handler(event, context): ) log_event = resolve_truthy_env_var_choice( - env=os.getenv(constants.LOGGER_LOG_EVENT_ENV, "false"), choice=log_event + env=os.getenv(constants.LOGGER_LOG_EVENT_ENV, "false"), + choice=log_event, ) @functools.wraps(lambda_handler) @@ -456,7 +459,12 @@ def info( if sys.version_info < (3, 8): # pragma: no cover return self._logger.info(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) return self._logger.info( - msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + msg, + *args, + exc_info=exc_info, + stack_info=stack_info, + stacklevel=stacklevel, + extra=extra, ) def error( @@ -476,7 +484,12 @@ def error( if sys.version_info < (3, 8): # pragma: no cover return self._logger.error(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) return self._logger.error( - msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + msg, + *args, + exc_info=exc_info, + stack_info=stack_info, + stacklevel=stacklevel, + extra=extra, ) def exception( @@ -496,7 +509,12 @@ def exception( if sys.version_info < (3, 8): # pragma: no cover return self._logger.exception(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) return self._logger.exception( - msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + msg, + *args, + exc_info=exc_info, + stack_info=stack_info, + stacklevel=stacklevel, + extra=extra, ) def critical( @@ -516,7 +534,12 @@ def critical( if sys.version_info < (3, 8): # pragma: no cover return self._logger.critical(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) return self._logger.critical( - msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + msg, + *args, + exc_info=exc_info, + stack_info=stack_info, + stacklevel=stacklevel, + extra=extra, ) def warning( @@ -536,7 +559,12 @@ def warning( if sys.version_info < (3, 8): # pragma: no cover return self._logger.warning(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) return self._logger.warning( - msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + msg, + *args, + exc_info=exc_info, + stack_info=stack_info, + stacklevel=stacklevel, + extra=extra, ) def debug( @@ -556,7 +584,12 @@ def debug( if sys.version_info < (3, 8): # pragma: no cover return self._logger.debug(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) return self._logger.debug( - msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + msg, + *args, + exc_info=exc_info, + stack_info=stack_info, + stacklevel=stacklevel, + extra=extra, ) def append_keys(self, **additional_keys): diff --git a/aws_lambda_powertools/logging/utils.py b/aws_lambda_powertools/logging/utils.py index 4066011f7f2..eb299c888a2 100644 --- a/aws_lambda_powertools/logging/utils.py +++ b/aws_lambda_powertools/logging/utils.py @@ -68,7 +68,9 @@ def _exclude_registered_loggers_filter(loggers: Set[str]) -> List[logging.Logger def _find_registered_loggers( - source_logger: Logger, loggers: Set[str], filter_func: Callable[[Set[str]], List[logging.Logger]] + source_logger: Logger, + loggers: Set[str], + filter_func: Callable[[Set[str]], List[logging.Logger]], ) -> List[logging.Logger]: """Filter root loggers based on provided parameters.""" root_loggers = filter_func(loggers) diff --git a/aws_lambda_powertools/metrics/base.py b/aws_lambda_powertools/metrics/base.py index 7013f9620c5..6a5e7282392 100644 --- a/aws_lambda_powertools/metrics/base.py +++ b/aws_lambda_powertools/metrics/base.py @@ -172,7 +172,10 @@ def add_metric( self.metric_set.clear() def serialize_metric_set( - self, metrics: Optional[Dict] = None, dimensions: Optional[Dict] = None, metadata: Optional[Dict] = None + self, + metrics: Optional[Dict] = None, + dimensions: Optional[Dict] = None, + metadata: Optional[Dict] = None, ) -> Dict: """Serializes metric and dimensions set @@ -256,7 +259,7 @@ def serialize_metric_set( "Namespace": self.namespace, # "test_namespace" "Dimensions": [list(dimensions.keys())], # [ "service" ] "Metrics": metric_definition, - } + }, ], }, **dimensions, # "service": "test_service" @@ -283,7 +286,7 @@ def add_dimension(self, name: str, value: str) -> None: logger.debug(f"Adding dimension: {name}:{value}") if len(self.dimension_set) == MAX_DIMENSIONS: raise SchemaValidationError( - f"Maximum number of dimensions exceeded ({MAX_DIMENSIONS}): Unable to add dimension {name}." + f"Maximum number of dimensions exceeded ({MAX_DIMENSIONS}): Unable to add dimension {name}.", ) # Cast value to str according to EMF spec # Majority of values are expected to be string already, so @@ -443,7 +446,7 @@ def _extract_metric_resolution_value(self, resolution: Union[int, MetricResoluti return resolution raise MetricResolutionError( - f"Invalid metric resolution '{resolution}', expected either option: {self._metric_resolutions}" # noqa: E501 + f"Invalid metric resolution '{resolution}', expected either option: {self._metric_resolutions}", # noqa: E501 ) def _extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str: @@ -471,7 +474,7 @@ def _extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str: if unit not in self._metric_units: raise MetricUnitError( - f"Invalid metric unit '{unit}', expected either option: {self._metric_unit_valid_options}" + f"Invalid metric unit '{unit}', expected either option: {self._metric_unit_valid_options}", ) if isinstance(unit, MetricUnit): diff --git a/aws_lambda_powertools/middleware_factory/factory.py b/aws_lambda_powertools/middleware_factory/factory.py index 850983728c2..55874c56eff 100644 --- a/aws_lambda_powertools/middleware_factory/factory.py +++ b/aws_lambda_powertools/middleware_factory/factory.py @@ -107,7 +107,8 @@ def lambda_handler(event, context): return functools.partial(lambda_handler_decorator, trace_execution=trace_execution) trace_execution = resolve_truthy_env_var_choice( - env=os.getenv(constants.MIDDLEWARE_FACTORY_TRACE_ENV, "false"), choice=trace_execution + env=os.getenv(constants.MIDDLEWARE_FACTORY_TRACE_ENV, "false"), + choice=trace_execution, ) @functools.wraps(decorator) @@ -119,7 +120,7 @@ def final_decorator(func: Optional[Callable] = None, **kwargs: Any): if not inspect.isfunction(func): # @custom_middleware(True) vs @custom_middleware(log_event=True) raise MiddlewareInvalidArgumentError( - f"Only keyword arguments is supported for middlewares: {decorator.__qualname__} received {func}" # type: ignore # noqa: E501 + f"Only keyword arguments is supported for middlewares: {decorator.__qualname__} received {func}", # type: ignore # noqa: E501 ) @functools.wraps(func) diff --git a/aws_lambda_powertools/shared/functions.py b/aws_lambda_powertools/shared/functions.py index 20a4994e9be..82ea7dad8d8 100644 --- a/aws_lambda_powertools/shared/functions.py +++ b/aws_lambda_powertools/shared/functions.py @@ -72,7 +72,8 @@ def resolve_env_var_choice(env: Optional[str], choice: Optional[str]) -> str: def resolve_env_var_choice( - env: Optional[str] = None, choice: Optional[Union[str, float]] = None + env: Optional[str] = None, + choice: Optional[Union[str, float]] = None, ) -> Optional[Union[str, float]]: """Pick explicit choice over env, if available, otherwise return env value received @@ -112,7 +113,8 @@ def powertools_dev_is_set() -> bool: is_on = strtobool(os.getenv(constants.POWERTOOLS_DEV_ENV, "0")) if is_on: warnings.warn( - "POWERTOOLS_DEV environment variable is enabled. Increasing verbosity across utilities.", stacklevel=2 + "POWERTOOLS_DEV environment variable is enabled. Increasing verbosity across utilities.", + stacklevel=2, ) return True diff --git a/aws_lambda_powertools/tracing/tracer.py b/aws_lambda_powertools/tracing/tracer.py index 589108a1a21..3004e5505c8 100644 --- a/aws_lambda_powertools/tracing/tracer.py +++ b/aws_lambda_powertools/tracing/tracer.py @@ -153,7 +153,11 @@ def __init__( provider: Optional[BaseProvider] = None, ): self.__build_config( - service=service, disabled=disabled, auto_patch=auto_patch, patch_modules=patch_modules, provider=provider + service=service, + disabled=disabled, + auto_patch=auto_patch, + patch_modules=patch_modules, + provider=provider, ) self.provider: BaseProvider = self._config["provider"] self.disabled = self._config["disabled"] @@ -286,15 +290,19 @@ def handler(event, context): if lambda_handler is None: logger.debug("Decorator called with parameters") return functools.partial( - self.capture_lambda_handler, capture_response=capture_response, capture_error=capture_error + self.capture_lambda_handler, + capture_response=capture_response, + capture_error=capture_error, ) lambda_handler_name = lambda_handler.__name__ capture_response = resolve_truthy_env_var_choice( - env=os.getenv(constants.TRACER_CAPTURE_RESPONSE_ENV, "true"), choice=capture_response + env=os.getenv(constants.TRACER_CAPTURE_RESPONSE_ENV, "true"), + choice=capture_response, ) capture_error = resolve_truthy_env_var_choice( - env=os.getenv(constants.TRACER_CAPTURE_ERROR_ENV, "true"), choice=capture_error + env=os.getenv(constants.TRACER_CAPTURE_ERROR_ENV, "true"), + choice=capture_error, ) @functools.wraps(lambda_handler) @@ -313,7 +321,10 @@ def decorate(event, context, **kwargs): except Exception as err: logger.exception(f"Exception received from {lambda_handler_name}") self._add_full_exception_as_metadata( - method_name=lambda_handler_name, error=err, subsegment=subsegment, capture_error=capture_error + method_name=lambda_handler_name, + error=err, + subsegment=subsegment, + capture_error=capture_error, ) raise @@ -514,28 +525,42 @@ async def async_tasks(): method_name = f"{method.__module__}.{method.__qualname__}" capture_response = resolve_truthy_env_var_choice( - env=os.getenv(constants.TRACER_CAPTURE_RESPONSE_ENV, "true"), choice=capture_response + env=os.getenv(constants.TRACER_CAPTURE_RESPONSE_ENV, "true"), + choice=capture_response, ) capture_error = resolve_truthy_env_var_choice( - env=os.getenv(constants.TRACER_CAPTURE_ERROR_ENV, "true"), choice=capture_error + env=os.getenv(constants.TRACER_CAPTURE_ERROR_ENV, "true"), + choice=capture_error, ) # Maintenance: Need a factory/builder here to simplify this now if inspect.iscoroutinefunction(method): return self._decorate_async_function( - method=method, capture_response=capture_response, capture_error=capture_error, method_name=method_name + method=method, + capture_response=capture_response, + capture_error=capture_error, + method_name=method_name, ) elif inspect.isgeneratorfunction(method): return self._decorate_generator_function( - method=method, capture_response=capture_response, capture_error=capture_error, method_name=method_name + method=method, + capture_response=capture_response, + capture_error=capture_error, + method_name=method_name, ) elif hasattr(method, "__wrapped__") and inspect.isgeneratorfunction(method.__wrapped__): return self._decorate_generator_function_with_context_manager( - method=method, capture_response=capture_response, capture_error=capture_error, method_name=method_name + method=method, + capture_response=capture_response, + capture_error=capture_error, + method_name=method_name, ) else: return self._decorate_sync_function( - method=method, capture_response=capture_response, capture_error=capture_error, method_name=method_name + method=method, + capture_response=capture_response, + capture_error=capture_error, + method_name=method_name, ) def _decorate_async_function( @@ -552,12 +577,18 @@ async def decorate(*args, **kwargs): logger.debug(f"Calling method: {method_name}") response = await method(*args, **kwargs) self._add_response_as_metadata( - method_name=method_name, data=response, subsegment=subsegment, capture_response=capture_response + method_name=method_name, + data=response, + subsegment=subsegment, + capture_response=capture_response, ) except Exception as err: logger.exception(f"Exception received from '{method_name}' method") self._add_full_exception_as_metadata( - method_name=method_name, error=err, subsegment=subsegment, capture_error=capture_error + method_name=method_name, + error=err, + subsegment=subsegment, + capture_error=capture_error, ) raise @@ -579,12 +610,18 @@ def decorate(*args, **kwargs): logger.debug(f"Calling method: {method_name}") result = yield from method(*args, **kwargs) self._add_response_as_metadata( - method_name=method_name, data=result, subsegment=subsegment, capture_response=capture_response + method_name=method_name, + data=result, + subsegment=subsegment, + capture_response=capture_response, ) except Exception as err: logger.exception(f"Exception received from '{method_name}' method") self._add_full_exception_as_metadata( - method_name=method_name, error=err, subsegment=subsegment, capture_error=capture_error + method_name=method_name, + error=err, + subsegment=subsegment, + capture_error=capture_error, ) raise @@ -609,12 +646,18 @@ def decorate(*args, **kwargs): result = return_val yield result self._add_response_as_metadata( - method_name=method_name, data=result, subsegment=subsegment, capture_response=capture_response + method_name=method_name, + data=result, + subsegment=subsegment, + capture_response=capture_response, ) except Exception as err: logger.exception(f"Exception received from '{method_name}' method") self._add_full_exception_as_metadata( - method_name=method_name, error=err, subsegment=subsegment, capture_error=capture_error + method_name=method_name, + error=err, + subsegment=subsegment, + capture_error=capture_error, ) raise @@ -642,7 +685,10 @@ def decorate(*args, **kwargs): except Exception as err: logger.exception(f"Exception received from '{method_name}' method") self._add_full_exception_as_metadata( - method_name=method_name, error=err, subsegment=subsegment, capture_error=capture_error + method_name=method_name, + error=err, + subsegment=subsegment, + capture_error=capture_error, ) raise diff --git a/aws_lambda_powertools/utilities/batch/decorators.py b/aws_lambda_powertools/utilities/batch/decorators.py index 356342fb83f..ad4c93f8863 100644 --- a/aws_lambda_powertools/utilities/batch/decorators.py +++ b/aws_lambda_powertools/utilities/batch/decorators.py @@ -71,7 +71,11 @@ def async_batch_processor( @lambda_handler_decorator def batch_processor( - handler: Callable, event: Dict, context: LambdaContext, record_handler: Callable, processor: BatchProcessor + handler: Callable, + event: Dict, + context: LambdaContext, + record_handler: Callable, + processor: BatchProcessor, ): """ Middleware to handle batch event processing @@ -176,7 +180,7 @@ def handler(event, context): docs = "https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/#processing-messages-from-sqs" # noqa: E501 # long-line raise ValueError( f"Invalid event format. Please ensure batch event is a valid {processor.event_type.value} event. \n" - f"See sample events in our documentation for either {event_types}: \n {docs}" + f"See sample events in our documentation for either {event_types}: \n {docs}", ) with processor(records, record_handler, context): @@ -240,7 +244,7 @@ def handler(event, context): docs = "https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/#processing-messages-from-sqs" # noqa: E501 # long-line raise ValueError( f"Invalid event format. Please ensure batch event is a valid {processor.event_type.value} event. \n" - f"See sample events in our documentation for either {event_types}: \n {docs}" + f"See sample events in our documentation for either {event_types}: \n {docs}", ) with processor(records, record_handler, context): diff --git a/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py b/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py index a8897cce5b0..32d933ecf27 100644 --- a/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py +++ b/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py @@ -163,7 +163,10 @@ def request_context(self) -> BaseRequestContext: return BaseRequestContext(self._data) def get_header_value( - self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False + self, + name: str, + default_value: Optional[str] = None, + case_sensitive: Optional[bool] = False, ) -> Optional[str]: """Get header value by name @@ -265,7 +268,10 @@ def stage_variables(self) -> Optional[Dict[str, str]]: return self.get("stageVariables") def get_header_value( - self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False + self, + name: str, + default_value: Optional[str] = None, + case_sensitive: Optional[bool] = False, ) -> Optional[str]: """Get header value by name @@ -343,7 +349,7 @@ class HttpVerb(enum.Enum): "Action": "execute-api:Invoke", "Effect": "Deny", "Resource": ["*"], - } + }, ], }, } @@ -452,7 +458,13 @@ def _add_route(self, effect: str, http_method: str, resource: str, conditions: O raise ValueError(f"Invalid resource path: {resource}. Path should match {self.path_regex}") resource_arn = APIGatewayRouteArn( - self.region, self.aws_account_id, self.api_id, self.stage, http_method, resource, self.partition + self.region, + self.aws_account_id, + self.api_id, + self.stage, + http_method, + resource, + self.partition, ).arn route = {"resourceArn": resource_arn, "conditions": conditions} diff --git a/aws_lambda_powertools/utilities/data_classes/appsync_resolver_event.py b/aws_lambda_powertools/utilities/data_classes/appsync_resolver_event.py index fc54f334cab..14973009fb9 100644 --- a/aws_lambda_powertools/utilities/data_classes/appsync_resolver_event.py +++ b/aws_lambda_powertools/utilities/data_classes/appsync_resolver_event.py @@ -215,7 +215,10 @@ def stash(self) -> Optional[dict]: return self.get("stash") def get_header_value( - self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False + self, + name: str, + default_value: Optional[str] = None, + case_sensitive: Optional[bool] = False, ) -> Optional[str]: """Get header value by name diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py index c778040906d..7eb14c38de4 100644 --- a/aws_lambda_powertools/utilities/data_classes/common.py +++ b/aws_lambda_powertools/utilities/data_classes/common.py @@ -151,12 +151,17 @@ def get_query_string_value(self, name: str, default_value: Optional[str] = None) Query string parameter value """ return get_query_string_value( - query_string_parameters=self.query_string_parameters, name=name, default_value=default_value + query_string_parameters=self.query_string_parameters, + name=name, + default_value=default_value, ) # Maintenance: missing @overload to ensure return type is a str when default_value is set def get_header_value( - self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False + self, + name: str, + default_value: Optional[str] = None, + case_sensitive: Optional[bool] = False, ) -> Optional[str]: """Get header value by name @@ -174,7 +179,10 @@ def get_header_value( Header value """ return get_header_value( - headers=self.headers, name=name, default_value=default_value, case_sensitive=case_sensitive + headers=self.headers, + name=name, + default_value=default_value, + case_sensitive=case_sensitive, ) def header_serializer(self) -> BaseHeadersSerializer: diff --git a/aws_lambda_powertools/utilities/data_classes/kafka_event.py b/aws_lambda_powertools/utilities/data_classes/kafka_event.py index a79232b6d5d..f54f979bace 100644 --- a/aws_lambda_powertools/utilities/data_classes/kafka_event.py +++ b/aws_lambda_powertools/utilities/data_classes/kafka_event.py @@ -71,11 +71,17 @@ def decoded_headers(self) -> Dict[str, bytes]: return {k: bytes(v) for chunk in self.headers for k, v in chunk.items()} def get_header_value( - self, name: str, default_value: Optional[Any] = None, case_sensitive: bool = True + self, + name: str, + default_value: Optional[Any] = None, + case_sensitive: bool = True, ) -> Optional[str]: """Get a decoded header value by name.""" return get_header_value( - headers=self.decoded_headers, name=name, default_value=default_value, case_sensitive=case_sensitive + headers=self.decoded_headers, + name=name, + default_value=default_value, + case_sensitive=case_sensitive, ) diff --git a/aws_lambda_powertools/utilities/data_classes/s3_object_event.py b/aws_lambda_powertools/utilities/data_classes/s3_object_event.py index 8cff4cfd59a..a7953c32c59 100644 --- a/aws_lambda_powertools/utilities/data_classes/s3_object_event.py +++ b/aws_lambda_powertools/utilities/data_classes/s3_object_event.py @@ -74,7 +74,10 @@ def headers(self) -> Dict[str, str]: return self["headers"] def get_header_value( - self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False + self, + name: str, + default_value: Optional[str] = None, + case_sensitive: Optional[bool] = False, ) -> Optional[str]: """Get header value by name diff --git a/aws_lambda_powertools/utilities/data_classes/shared_functions.py b/aws_lambda_powertools/utilities/data_classes/shared_functions.py index fe5108b2b20..594ea35bea7 100644 --- a/aws_lambda_powertools/utilities/data_classes/shared_functions.py +++ b/aws_lambda_powertools/utilities/data_classes/shared_functions.py @@ -22,7 +22,10 @@ def base64_decode(value: str) -> str: def get_header_value( - headers: dict[str, Any], name: str, default_value: str | None, case_sensitive: bool | None + headers: dict[str, Any], + name: str, + default_value: str | None, + case_sensitive: bool | None, ) -> str | None: """ Get the value of a header by its name. @@ -60,7 +63,9 @@ def get_header_value( def get_query_string_value( - query_string_parameters: dict[str, str] | None, name: str, default_value: str | None = None + query_string_parameters: dict[str, str] | None, + name: str, + default_value: str | None = None, ) -> str | None: """ Retrieves the value of a query string parameter specified by the given name. diff --git a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py index e5e126d2702..ca9df29776a 100644 --- a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py +++ b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py @@ -69,11 +69,16 @@ def get_query_string_value(self, name: str, default_value: Optional[str] = None) Query string parameter value """ return get_query_string_value( - query_string_parameters=self.query_string_parameters, name=name, default_value=default_value + query_string_parameters=self.query_string_parameters, + name=name, + default_value=default_value, ) def get_header_value( - self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False + self, + name: str, + default_value: Optional[str] = None, + case_sensitive: Optional[bool] = False, ) -> Optional[str]: """Get header value by name @@ -91,5 +96,8 @@ def get_header_value( Header value """ return get_header_value( - headers=self.headers, name=name, default_value=default_value, case_sensitive=case_sensitive + headers=self.headers, + name=name, + default_value=default_value, + case_sensitive=case_sensitive, ) diff --git a/aws_lambda_powertools/utilities/feature_flags/appconfig.py b/aws_lambda_powertools/utilities/feature_flags/appconfig.py index 8695c1fd8c9..1fb7e8d62af 100644 --- a/aws_lambda_powertools/utilities/feature_flags/appconfig.py +++ b/aws_lambda_powertools/utilities/feature_flags/appconfig.py @@ -66,7 +66,8 @@ def get_raw_configuration(self) -> Dict[str, Any]: try: # parse result conf as JSON, keep in cache for self.max_age seconds self.logger.debug( - "Fetching configuration from the store", extra={"param_name": self.name, "max_age": self.cache_seconds} + "Fetching configuration from the store", + extra={"param_name": self.name, "max_age": self.cache_seconds}, ) return cast( dict, @@ -103,7 +104,9 @@ def get_configuration(self) -> Dict[str, Any]: if self.envelope: self.logger.debug("Envelope enabled; extracting data from config", extra={"envelope": self.envelope}) config = jmespath_utils.extract_data_from_envelope( - data=config, envelope=self.envelope, jmespath_options=self.jmespath_options + data=config, + envelope=self.envelope, + jmespath_options=self.jmespath_options, ) return config diff --git a/aws_lambda_powertools/utilities/feature_flags/feature_flags.py b/aws_lambda_powertools/utilities/feature_flags/feature_flags.py index 4849dd450ac..8610d68a8f6 100644 --- a/aws_lambda_powertools/utilities/feature_flags/feature_flags.py +++ b/aws_lambda_powertools/utilities/feature_flags/feature_flags.py @@ -77,7 +77,11 @@ def _match_by_action(self, action: str, condition_value: Any, context_value: Any return False def _evaluate_conditions( - self, rule_name: str, feature_name: str, rule: Dict[str, Any], context: Dict[str, Any] + self, + rule_name: str, + feature_name: str, + rule: Dict[str, Any], + context: Dict[str, Any], ) -> bool: """Evaluates whether context matches conditions, return False otherwise""" rule_match_value = rule.get(schema.RULE_MATCH_VALUE) @@ -86,7 +90,7 @@ def _evaluate_conditions( if not conditions: self.logger.debug( f"rule did not match, no conditions to match, rule_name={rule_name}, rule_value={rule_match_value}, " - f"name={feature_name} " + f"name={feature_name} ", ) return False @@ -106,7 +110,7 @@ def _evaluate_conditions( if not self._match_by_action(action=cond_action, condition_value=cond_value, context_value=context_value): self.logger.debug( f"rule did not match action, rule_name={rule_name}, rule_value={rule_match_value}, " - f"name={feature_name}, context_value={str(context_value)} " + f"name={feature_name}, context_value={str(context_value)} ", ) return False # context doesn't match condition @@ -128,7 +132,7 @@ def _evaluate_rules( # Context might contain PII data; do not log its value self.logger.debug( - f"Evaluating rule matching, rule={rule_name}, feature={feature_name}, default={str(feat_default)}, boolean_feature={boolean_feature}" # noqa: E501 + f"Evaluating rule matching, rule={rule_name}, feature={feature_name}, default={str(feat_default)}, boolean_feature={boolean_feature}", # noqa: E501 ) if self._evaluate_conditions(rule_name=rule_name, feature_name=feature_name, rule=rule, context=context): # Maintenance: Revisit before going GA. @@ -136,7 +140,7 @@ def _evaluate_rules( # no rule matched, return default value of feature self.logger.debug( - f"no rule matched, returning feature default, default={str(feat_default)}, name={feature_name}, boolean_feature={boolean_feature}" # noqa: E501 + f"no rule matched, returning feature default, default={str(feat_default)}, name={feature_name}, boolean_feature={boolean_feature}", # noqa: E501 ) return feat_default @@ -243,21 +247,26 @@ def evaluate(self, *, name: str, context: Optional[Dict[str, Any]] = None, defau # get_enabled_features. We can minimize breaking change, despite Beta label, by having a new # method `get_matching_features` returning Dict[feature_name, feature_value] boolean_feature = feature.get( - schema.FEATURE_DEFAULT_VAL_TYPE_KEY, True + schema.FEATURE_DEFAULT_VAL_TYPE_KEY, + True, ) # backwards compatibility, assume feature flag if not rules: self.logger.debug( - f"no rules found, returning feature default, name={name}, default={str(feat_default)}, boolean_feature={boolean_feature}" # noqa: E501 + f"no rules found, returning feature default, name={name}, default={str(feat_default)}, boolean_feature={boolean_feature}", # noqa: E501 ) # Maintenance: Revisit before going GA. We might to simplify customers on-boarding by not requiring it # for non-boolean flags. return bool(feat_default) if boolean_feature else feat_default self.logger.debug( - f"looking for rule match, name={name}, default={str(feat_default)}, boolean_feature={boolean_feature}" # noqa: E501 + f"looking for rule match, name={name}, default={str(feat_default)}, boolean_feature={boolean_feature}", # noqa: E501 ) return self._evaluate_rules( - feature_name=name, context=context, feat_default=feat_default, rules=rules, boolean_feature=boolean_feature + feature_name=name, + context=context, + feat_default=feat_default, + rules=rules, + boolean_feature=boolean_feature, ) def get_enabled_features(self, *, context: Optional[Dict[str, Any]] = None) -> List[str]: @@ -302,7 +311,8 @@ def get_enabled_features(self, *, context: Optional[Dict[str, Any]] = None) -> L rules = feature.get(schema.RULES_KEY, {}) feature_default_value = feature.get(schema.FEATURE_DEFAULT_VAL_KEY) boolean_feature = feature.get( - schema.FEATURE_DEFAULT_VAL_TYPE_KEY, True + schema.FEATURE_DEFAULT_VAL_TYPE_KEY, + True, ) # backwards compatibility, assume feature flag if feature_default_value and not rules: diff --git a/aws_lambda_powertools/utilities/feature_flags/schema.py b/aws_lambda_powertools/utilities/feature_flags/schema.py index 0ada75c238d..0dc5e8d56bc 100644 --- a/aws_lambda_powertools/utilities/feature_flags/schema.py +++ b/aws_lambda_powertools/utilities/feature_flags/schema.py @@ -231,7 +231,10 @@ class RulesValidator(BaseValidator): """Validates each rule and calls ConditionsValidator to validate each rule's conditions""" def __init__( - self, feature: Dict[str, Any], boolean_feature: bool, logger: Optional[Union[logging.Logger, Logger]] = None + self, + feature: Dict[str, Any], + boolean_feature: bool, + logger: Optional[Union[logging.Logger, Logger]] = None, ): self.feature = feature self.feature_name = next(iter(self.feature)) @@ -251,7 +254,10 @@ def validate(self): for rule_name, rule in self.rules.items(): self.logger.debug(f"Attempting to validate rule={rule_name} and feature={self.feature_name}") self.validate_rule( - rule=rule, rule_name=rule_name, feature_name=self.feature_name, boolean_feature=self.boolean_feature + rule=rule, + rule_name=rule_name, + feature_name=self.feature_name, + boolean_feature=self.boolean_feature, ) conditions = ConditionsValidator(rule=rule, rule_name=rule_name, logger=self.logger) conditions.validate() @@ -307,7 +313,7 @@ def validate_condition_action(condition: Dict[str, Any], rule_name: str): if action not in RuleAction.__members__: allowed_values = [_action.value for _action in RuleAction] raise SchemaValidationError( - f"'action' value must be either {allowed_values}, rule_name={rule_name}, action={action}" + f"'action' value must be either {allowed_values}, rule_name={rule_name}, action={action}", ) @staticmethod @@ -323,15 +329,15 @@ def validate_condition_key(condition: Dict[str, Any], rule_name: str): action = condition.get(CONDITION_ACTION, "") if action == RuleAction.SCHEDULE_BETWEEN_TIME_RANGE.value and key != TimeKeys.CURRENT_TIME.value: raise SchemaValidationError( - f"'condition with a 'SCHEDULE_BETWEEN_TIME_RANGE' action must have a 'CURRENT_TIME' condition key, rule={rule_name}" # noqa: E501 + f"'condition with a 'SCHEDULE_BETWEEN_TIME_RANGE' action must have a 'CURRENT_TIME' condition key, rule={rule_name}", # noqa: E501 ) if action == RuleAction.SCHEDULE_BETWEEN_DATETIME_RANGE.value and key != TimeKeys.CURRENT_DATETIME.value: raise SchemaValidationError( - f"'condition with a 'SCHEDULE_BETWEEN_DATETIME_RANGE' action must have a 'CURRENT_DATETIME' condition key, rule={rule_name}" # noqa: E501 + f"'condition with a 'SCHEDULE_BETWEEN_DATETIME_RANGE' action must have a 'CURRENT_DATETIME' condition key, rule={rule_name}", # noqa: E501 ) if action == RuleAction.SCHEDULE_BETWEEN_DAYS_OF_WEEK.value and key != TimeKeys.CURRENT_DAY_OF_WEEK.value: raise SchemaValidationError( - f"'condition with a 'SCHEDULE_BETWEEN_DAYS_OF_WEEK' action must have a 'CURRENT_DAY_OF_WEEK' condition key, rule={rule_name}" # noqa: E501 + f"'condition with a 'SCHEDULE_BETWEEN_DAYS_OF_WEEK' action must have a 'CURRENT_DAY_OF_WEEK' condition key, rule={rule_name}", # noqa: E501 ) @staticmethod @@ -344,11 +350,17 @@ def validate_condition_value(condition: Dict[str, Any], rule_name: str): # time actions need to be parsed to make sure date and time format is valid and timezone is recognized if action == RuleAction.SCHEDULE_BETWEEN_TIME_RANGE.value: ConditionsValidator._validate_schedule_between_time_and_datetime_ranges( - value, rule_name, action, ConditionsValidator._validate_time_value + value, + rule_name, + action, + ConditionsValidator._validate_time_value, ) elif action == RuleAction.SCHEDULE_BETWEEN_DATETIME_RANGE.value: ConditionsValidator._validate_schedule_between_time_and_datetime_ranges( - value, rule_name, action, ConditionsValidator._validate_datetime_value + value, + rule_name, + action, + ConditionsValidator._validate_datetime_value, ) elif action == RuleAction.SCHEDULE_BETWEEN_DAYS_OF_WEEK.value: ConditionsValidator._validate_schedule_between_days_of_week(value, rule_name) @@ -379,7 +391,7 @@ def _validate_datetime_value(datetime_str: str, rule_name: str): if date.tzinfo is not None: raise SchemaValidationError( "'START' and 'END' must not include timezone information. Set the timezone using the 'TIMEZONE' " - f"field, rule={rule_name} " + f"field, rule={rule_name} ", ) @staticmethod @@ -389,7 +401,7 @@ def _validate_time_value(time: str, rule_name: str): if not match: raise SchemaValidationError( - f"'START' and 'END' must be a valid time format, time_format={TIME_RANGE_FORMAT}, rule={rule_name}" + f"'START' and 'END' must be a valid time format, time_format={TIME_RANGE_FORMAT}, rule={rule_name}", ) @staticmethod @@ -412,7 +424,7 @@ def _validate_schedule_between_days_of_week(value: Any, rule_name: str): TimeValues.SUNDAY.value, ]: raise SchemaValidationError( - f"condition value DAYS must represent a day of the week in 'TimeValues' enum, rule={rule_name}" + f"condition value DAYS must represent a day of the week in 'TimeValues' enum, rule={rule_name}", ) timezone = value.get(TimeValues.TIMEZONE.value, "UTC") @@ -425,7 +437,10 @@ def _validate_schedule_between_days_of_week(value: Any, rule_name: str): @staticmethod def _validate_schedule_between_time_and_datetime_ranges( - value: Any, rule_name: str, action_name: str, validator: Callable[[str, str], None] + value: Any, + rule_name: str, + action_name: str, + validator: Callable[[str, str], None], ): error_str = f"condition with a '{action_name}' action must have a condition value type dictionary with 'START' and 'END' keys, rule={rule_name}" # noqa: E501 if not isinstance(value, dict): @@ -465,5 +480,5 @@ def _validate_modulo_range(value: Any, rule_name: str): if not 0 <= start <= end <= base - 1: raise SchemaValidationError( - f"condition with 'MODULO_RANGE' action must satisfy 0 <= START <= END <= BASE-1, rule={rule_name}" + f"condition with 'MODULO_RANGE' action must satisfy 0 <= START <= END <= BASE-1, rule={rule_name}", ) diff --git a/aws_lambda_powertools/utilities/idempotency/base.py b/aws_lambda_powertools/utilities/idempotency/base.py index db303084375..46aa5ef8962 100644 --- a/aws_lambda_powertools/utilities/idempotency/base.py +++ b/aws_lambda_powertools/utilities/idempotency/base.py @@ -104,7 +104,8 @@ def _process_idempotency(self): # We call save_inprogress first as an optimization for the most common case where no idempotent record # already exists. If it succeeds, there's no need to call get_record. self.persistence_store.save_inprogress( - data=self.data, remaining_time_in_millis=self._get_remaining_time_in_millis() + data=self.data, + remaining_time_in_millis=self._get_remaining_time_in_millis(), ) except IdempotencyKeyError: raise @@ -115,7 +116,8 @@ def _process_idempotency(self): return self._handle_for_status(record) except Exception as exc: raise IdempotencyPersistenceLayerError( - "Failed to save in progress record to idempotency store", exc + "Failed to save in progress record to idempotency store", + exc, ) from exc return self._get_function_response() @@ -153,7 +155,7 @@ def _get_idempotency_record(self) -> Optional[DataRecord]: except IdempotencyItemNotFoundError: # This code path will only be triggered if the record is removed between save_inprogress and get_record. logger.debug( - f"An existing idempotency record was deleted before we could fetch it. Proceeding with {self.function}" + f"An existing idempotency record was deleted before we could fetch it. Proceeding with {self.function}", ) raise IdempotencyInconsistentStateError("save_inprogress and get_record return inconsistent results.") @@ -194,15 +196,15 @@ def _handle_for_status(self, data_record: DataRecord) -> Optional[Dict[Any, Any] if data_record.status == STATUS_CONSTANTS["INPROGRESS"]: if data_record.in_progress_expiry_timestamp is not None and data_record.in_progress_expiry_timestamp < int( - datetime.datetime.now().timestamp() * 1000 + datetime.datetime.now().timestamp() * 1000, ): raise IdempotencyInconsistentStateError( - "item should have been expired in-progress because it already time-outed." + "item should have been expired in-progress because it already time-outed.", ) raise IdempotencyAlreadyInProgressError( f"Execution already in progress with idempotency key: " - f"{self.persistence_store.event_key_jmespath}={data_record.idempotency_key}" + f"{self.persistence_store.event_key_jmespath}={data_record.idempotency_key}", ) return data_record.response_json_as_dict() @@ -217,7 +219,8 @@ def _get_function_response(self): self.persistence_store.delete_record(data=self.data, exception=handler_exception) except Exception as delete_exception: raise IdempotencyPersistenceLayerError( - "Failed to delete record from idempotency store", delete_exception + "Failed to delete record from idempotency store", + delete_exception, ) from delete_exception raise @@ -226,7 +229,8 @@ def _get_function_response(self): self.persistence_store.save_success(data=self.data, result=response) except Exception as save_exception: raise IdempotencyPersistenceLayerError( - "Failed to update record state to success in idempotency store", save_exception + "Failed to update record state to success in idempotency store", + save_exception, ) from save_exception return response diff --git a/aws_lambda_powertools/utilities/idempotency/idempotency.py b/aws_lambda_powertools/utilities/idempotency/idempotency.py index 14fd3bfe5af..76d353d205e 100644 --- a/aws_lambda_powertools/utilities/idempotency/idempotency.py +++ b/aws_lambda_powertools/utilities/idempotency/idempotency.py @@ -137,7 +137,7 @@ def decorate(*args, **kwargs): if data_keyword_argument not in kwargs: raise RuntimeError( f"Unable to extract '{data_keyword_argument}' from keyword arguments." - f" Ensure this exists in your function's signature as well as the caller used it as a keyword argument" + f" Ensure this exists in your function's signature as well as the caller used it as a keyword argument", ) payload = kwargs.get(data_keyword_argument) diff --git a/aws_lambda_powertools/utilities/idempotency/persistence/base.py b/aws_lambda_powertools/utilities/idempotency/persistence/base.py index 4a23fd47276..eaea36127c1 100644 --- a/aws_lambda_powertools/utilities/idempotency/persistence/base.py +++ b/aws_lambda_powertools/utilities/idempotency/persistence/base.py @@ -339,7 +339,7 @@ def save_success(self, data: Dict[str, Any], result: dict) -> None: ) logger.debug( f"Function successfully executed. Saving record to persistence store with " - f"idempotency key: {data_record.idempotency_key}" + f"idempotency key: {data_record.idempotency_key}", ) self._update_record(data_record=data_record) @@ -412,7 +412,7 @@ def delete_record(self, data: Dict[str, Any], exception: Exception): logger.debug( f"Function raised an exception ({type(exception).__name__}). Clearing in progress record in persistence " - f"store for idempotency key: {data_record.idempotency_key}" + f"store for idempotency key: {data_record.idempotency_key}", ) self._delete_record(data_record=data_record) diff --git a/aws_lambda_powertools/utilities/idempotency/persistence/dynamodb.py b/aws_lambda_powertools/utilities/idempotency/persistence/dynamodb.py index d69e42f9287..5fcc3039ec6 100644 --- a/aws_lambda_powertools/utilities/idempotency/persistence/dynamodb.py +++ b/aws_lambda_powertools/utilities/idempotency/persistence/dynamodb.py @@ -163,7 +163,9 @@ def _item_to_data_record(self, item: Dict[str, Any]) -> DataRecord: def _get_record(self, idempotency_key) -> DataRecord: response = self.client.get_item( - TableName=self.table_name, Key=self._get_key(idempotency_key), ConsistentRead=True + TableName=self.table_name, + Key=self._get_key(idempotency_key), + ConsistentRead=True, ) try: item = response["Item"] @@ -211,7 +213,7 @@ def _put_record(self, data_record: DataRecord) -> None: "#status = :inprogress", "attribute_exists(#in_progress_expiry)", "#in_progress_expiry < :now_in_millis", - ] + ], ) condition_expression = ( @@ -237,7 +239,7 @@ def _put_record(self, data_record: DataRecord) -> None: error_code = exc.response.get("Error", {}).get("Code") if error_code == "ConditionalCheckFailedException": logger.debug( - f"Failed to put record for already existing idempotency key: {data_record.idempotency_key}" + f"Failed to put record for already existing idempotency key: {data_record.idempotency_key}", ) raise IdempotencyItemAlreadyExistsError from exc else: diff --git a/aws_lambda_powertools/utilities/parameters/appconfig.py b/aws_lambda_powertools/utilities/parameters/appconfig.py index 7fc4bcc7cbb..87c6f5077b2 100644 --- a/aws_lambda_powertools/utilities/parameters/appconfig.py +++ b/aws_lambda_powertools/utilities/parameters/appconfig.py @@ -85,11 +85,15 @@ def __init__( super().__init__() self.client: "AppConfigDataClient" = self._build_boto3_client( - service_name="appconfigdata", client=boto3_client, session=boto3_session, config=config + service_name="appconfigdata", + client=boto3_client, + session=boto3_session, + config=config, ) self.application = resolve_env_var_choice( - choice=application, env=os.getenv(constants.SERVICE_NAME_ENV, "service_undefined") + choice=application, + env=os.getenv(constants.SERVICE_NAME_ENV, "service_undefined"), ) self.environment = environment self.current_version = "" @@ -141,7 +145,7 @@ def get_app_config( transform: TransformOptions = None, force_fetch: bool = False, max_age: Optional[int] = None, - **sdk_options + **sdk_options, ) -> Union[str, list, dict, bytes]: """ Retrieve a configuration value from AWS App Config. @@ -199,5 +203,9 @@ def get_app_config( DEFAULT_PROVIDERS["appconfig"] = AppConfigProvider(environment=environment, application=application) return DEFAULT_PROVIDERS["appconfig"].get( - name, max_age=max_age, transform=transform, force_fetch=force_fetch, **sdk_options + name, + max_age=max_age, + transform=transform, + force_fetch=force_fetch, + **sdk_options, ) diff --git a/aws_lambda_powertools/utilities/parameters/secrets.py b/aws_lambda_powertools/utilities/parameters/secrets.py index b11cb472012..dc7bc2b0053 100644 --- a/aws_lambda_powertools/utilities/parameters/secrets.py +++ b/aws_lambda_powertools/utilities/parameters/secrets.py @@ -82,7 +82,10 @@ def __init__( super().__init__() self.client: "SecretsManagerClient" = self._build_boto3_client( - service_name="secretsmanager", client=boto3_client, session=boto3_session, config=config + service_name="secretsmanager", + client=boto3_client, + session=boto3_session, + config=config, ) def _get(self, name: str, **sdk_options) -> str: @@ -115,7 +118,11 @@ def _get_multiple(self, path: str, **sdk_options) -> Dict[str, str]: def get_secret( - name: str, transform: Optional[str] = None, force_fetch: bool = False, max_age: Optional[int] = None, **sdk_options + name: str, + transform: Optional[str] = None, + force_fetch: bool = False, + max_age: Optional[int] = None, + **sdk_options, ) -> Union[str, dict, bytes]: """ Retrieve a parameter value from AWS Secrets Manager @@ -170,5 +177,9 @@ def get_secret( DEFAULT_PROVIDERS["secrets"] = SecretsProvider() return DEFAULT_PROVIDERS["secrets"].get( - name, max_age=max_age, transform=transform, force_fetch=force_fetch, **sdk_options + name, + max_age=max_age, + transform=transform, + force_fetch=force_fetch, + **sdk_options, ) diff --git a/aws_lambda_powertools/utilities/parameters/ssm.py b/aws_lambda_powertools/utilities/parameters/ssm.py index 4a341ff0318..e03eea9e31c 100644 --- a/aws_lambda_powertools/utilities/parameters/ssm.py +++ b/aws_lambda_powertools/utilities/parameters/ssm.py @@ -108,7 +108,10 @@ def __init__( super().__init__() self.client: "SSMClient" = self._build_boto3_client( - service_name="ssm", client=boto3_client, session=boto3_session, config=config + service_name="ssm", + client=boto3_client, + session=boto3_session, + config=config, ) # We break Liskov substitution principle due to differences in signatures of this method and superclass get method @@ -156,7 +159,8 @@ def get( # type: ignore[override] # If decrypt is not set, resolve it from the environment variable, defaulting to False decrypt = resolve_truthy_env_var_choice( - env=os.getenv(constants.PARAMETERS_SSM_DECRYPT_ENV, "false"), choice=decrypt + env=os.getenv(constants.PARAMETERS_SSM_DECRYPT_ENV, "false"), + choice=decrypt, ) # Add to `decrypt` sdk_options to we can have an explicit option for this @@ -279,7 +283,8 @@ def get_parameters_by_name( # If decrypt is not set, resolve it from the environment variable, defaulting to False decrypt = resolve_truthy_env_var_choice( - env=os.getenv(constants.PARAMETERS_SSM_DECRYPT_ENV, "false"), choice=decrypt + env=os.getenv(constants.PARAMETERS_SSM_DECRYPT_ENV, "false"), + choice=decrypt, ) # Init potential batch/decrypt batch responses and errors @@ -313,7 +318,9 @@ def get_parameters_by_name( return {**response, **batch_ret, **decrypt_ret} def _get_parameters_by_name_with_decrypt_option( - self, batch: Dict[str, Dict], raise_on_error: bool + self, + batch: Dict[str, Dict], + raise_on_error: bool, ) -> Tuple[Dict, List]: response: Dict[str, Any] = {} errors: List[str] = [] @@ -332,7 +339,10 @@ def _get_parameters_by_name_with_decrypt_option( return response, errors def _get_parameters_batch_by_name( - self, batch: Dict[str, Dict], raise_on_error: bool = True, decrypt: bool = False + self, + batch: Dict[str, Dict], + raise_on_error: bool = True, + decrypt: bool = False, ) -> Tuple[Dict, List]: """Slice batch and fetch parameters using GetParameters by max permitted""" errors: List[str] = [] @@ -358,7 +368,11 @@ def _get_parameters_by_name_from_cache(self, batch: Dict[str, Dict]) -> Dict[str return cache def _get_parameters_by_name_in_chunks( - self, batch: Dict[str, Dict], cache: Dict[str, Any], raise_on_error: bool, decrypt: bool = False + self, + batch: Dict[str, Dict], + cache: Dict[str, Any], + raise_on_error: bool, + decrypt: bool = False, ) -> Tuple[Dict, List]: """Take out differences from cache and batch, slice it and fetch from SSM""" response: Dict[str, Any] = {} @@ -368,7 +382,9 @@ def _get_parameters_by_name_in_chunks( for chunk in slice_dictionary(data=diff, chunk_size=self._MAX_GET_PARAMETERS_ITEM): response, possible_errors = self._get_parameters_by_name( - parameters=chunk, raise_on_error=raise_on_error, decrypt=decrypt + parameters=chunk, + raise_on_error=raise_on_error, + decrypt=decrypt, ) response.update(response) errors.extend(possible_errors) @@ -376,7 +392,10 @@ def _get_parameters_by_name_in_chunks( return response, errors def _get_parameters_by_name( - self, parameters: Dict[str, Dict], raise_on_error: bool = True, decrypt: bool = False + self, + parameters: Dict[str, Dict], + raise_on_error: bool = True, + decrypt: bool = False, ) -> Tuple[Dict[str, Any], List[str]]: """Use SSM GetParameters to fetch parameters, hydrate cache, and handle partial failure @@ -418,7 +437,10 @@ def _get_parameters_by_name( return transformed_params, batch_errors def _transform_and_cache_get_parameters_response( - self, api_response: GetParametersResultTypeDef, parameters: Dict[str, Any], raise_on_error: bool = True + self, + api_response: GetParametersResultTypeDef, + parameters: Dict[str, Any], + raise_on_error: bool = True, ) -> Dict[str, Any]: response: Dict[str, Any] = {} @@ -441,7 +463,8 @@ def _transform_and_cache_get_parameters_response( @staticmethod def _handle_any_invalid_get_parameter_errors( - api_response: GetParametersResultTypeDef, raise_on_error: bool = True + api_response: GetParametersResultTypeDef, + raise_on_error: bool = True, ) -> List[str]: """GetParameters is non-atomic. Failures don't always reflect in exceptions so we need to collect.""" failed_parameters = api_response["InvalidParameters"] @@ -455,7 +478,10 @@ def _handle_any_invalid_get_parameter_errors( @staticmethod def _split_batch_and_decrypt_parameters( - parameters: Dict[str, Dict], transform: TransformOptions, max_age: int, decrypt: bool + parameters: Dict[str, Dict], + transform: TransformOptions, + max_age: int, + decrypt: bool, ) -> Tuple[Dict[str, Dict], Dict[str, Dict]]: """Split parameters that can be fetched by GetParameters vs GetParameter @@ -503,7 +529,7 @@ def _raise_if_errors_key_is_present(parameters: Dict, reserved_parameter: str, r """Raise GetParameterError if fail-fast is disabled and '_errors' key is in parameters batch""" if not raise_on_error and reserved_parameter in parameters: raise GetParameterError( - f"You cannot fetch a parameter named '{reserved_parameter}' in graceful error mode." + f"You cannot fetch a parameter named '{reserved_parameter}' in graceful error mode.", ) @@ -571,14 +597,19 @@ def get_parameter( # If decrypt is not set, resolve it from the environment variable, defaulting to False decrypt = resolve_truthy_env_var_choice( - env=os.getenv(constants.PARAMETERS_SSM_DECRYPT_ENV, "false"), choice=decrypt + env=os.getenv(constants.PARAMETERS_SSM_DECRYPT_ENV, "false"), + choice=decrypt, ) # Add to `decrypt` sdk_options to we can have an explicit option for this sdk_options["decrypt"] = decrypt return DEFAULT_PROVIDERS["ssm"].get( - name, max_age=max_age, transform=transform, force_fetch=force_fetch, **sdk_options + name, + max_age=max_age, + transform=transform, + force_fetch=force_fetch, + **sdk_options, ) @@ -653,7 +684,8 @@ def get_parameters( # If decrypt is not set, resolve it from the environment variable, defaulting to False decrypt = resolve_truthy_env_var_choice( - env=os.getenv(constants.PARAMETERS_SSM_DECRYPT_ENV, "false"), choice=decrypt + env=os.getenv(constants.PARAMETERS_SSM_DECRYPT_ENV, "false"), + choice=decrypt, ) sdk_options["recursive"] = recursive @@ -776,7 +808,8 @@ def get_parameters_by_name( # If decrypt is not set, resolve it from the environment variable, defaulting to False decrypt = resolve_truthy_env_var_choice( - env=os.getenv(constants.PARAMETERS_SSM_DECRYPT_ENV, "false"), choice=decrypt + env=os.getenv(constants.PARAMETERS_SSM_DECRYPT_ENV, "false"), + choice=decrypt, ) # Only create the provider if this function is called at least once @@ -784,5 +817,9 @@ def get_parameters_by_name( DEFAULT_PROVIDERS["ssm"] = SSMProvider() return DEFAULT_PROVIDERS["ssm"].get_parameters_by_name( - parameters=parameters, max_age=max_age, transform=transform, decrypt=decrypt, raise_on_error=raise_on_error + parameters=parameters, + max_age=max_age, + transform=transform, + decrypt=decrypt, + raise_on_error=raise_on_error, ) diff --git a/aws_lambda_powertools/utilities/streaming/_s3_seekable_io.py b/aws_lambda_powertools/utilities/streaming/_s3_seekable_io.py index de9b77410a3..96e567185ae 100644 --- a/aws_lambda_powertools/utilities/streaming/_s3_seekable_io.py +++ b/aws_lambda_powertools/utilities/streaming/_s3_seekable_io.py @@ -48,7 +48,12 @@ class _S3SeekableIO(IO[bytes]): """ def __init__( - self, bucket: str, key: str, version_id: Optional[str] = None, boto3_client=Optional["Client"], **sdk_options + self, + bucket: str, + key: str, + version_id: Optional[str] = None, + boto3_client=Optional["Client"], + **sdk_options, ): self.bucket = bucket self.key = key diff --git a/aws_lambda_powertools/utilities/streaming/s3_object.py b/aws_lambda_powertools/utilities/streaming/s3_object.py index 3c19740cc29..7f0ce17b4ae 100644 --- a/aws_lambda_powertools/utilities/streaming/s3_object.py +++ b/aws_lambda_powertools/utilities/streaming/s3_object.py @@ -87,7 +87,11 @@ def __init__( # The underlying seekable IO, where all the magic happens self.raw_stream = _S3SeekableIO( - bucket=bucket, key=key, version_id=version_id, boto3_client=boto3_client, **sdk_options + bucket=bucket, + key=key, + version_id=version_id, + boto3_client=boto3_client, + **sdk_options, ) # Stores the list of data transformations @@ -136,7 +140,9 @@ def transform(self, transformations: BaseTransform[T] | Sequence[BaseTransform[T @overload def transform( - self, transformations: BaseTransform[T] | Sequence[BaseTransform[T]], in_place: Literal[False] + self, + transformations: BaseTransform[T] | Sequence[BaseTransform[T]], + in_place: Literal[False], ) -> None: pass @@ -145,7 +151,9 @@ def transform(self, transformations: BaseTransform[T] | Sequence[BaseTransform[T pass def transform( - self, transformations: BaseTransform[T] | Sequence[BaseTransform[T]], in_place: Optional[bool] = False + self, + transformations: BaseTransform[T] | Sequence[BaseTransform[T]], + in_place: Optional[bool] = False, ) -> Optional[T]: """ Applies one or more data transformations to the stream. diff --git a/aws_lambda_powertools/utilities/validation/validator.py b/aws_lambda_powertools/utilities/validation/validator.py index da459ea69cd..fdd92de3687 100644 --- a/aws_lambda_powertools/utilities/validation/validator.py +++ b/aws_lambda_powertools/utilities/validation/validator.py @@ -119,7 +119,9 @@ def handler(event, context): """ # noqa: E501 if envelope: event = jmespath_utils.extract_data_from_envelope( - data=event, envelope=envelope, jmespath_options=jmespath_options + data=event, + envelope=envelope, + jmespath_options=jmespath_options, ) if inbound_schema: @@ -221,7 +223,9 @@ def handler(event, context): """ # noqa: E501 if envelope: event = jmespath_utils.extract_data_from_envelope( - data=event, envelope=envelope, jmespath_options=jmespath_options + data=event, + envelope=envelope, + jmespath_options=jmespath_options, ) validate_data_against_schema(data=event, schema=schema, formats=formats) diff --git a/examples/batch_processing/src/getting_started_async.py b/examples/batch_processing/src/getting_started_async.py index 304c01795bb..7c4ce6705ae 100644 --- a/examples/batch_processing/src/getting_started_async.py +++ b/examples/batch_processing/src/getting_started_async.py @@ -22,5 +22,8 @@ async def async_record_handler(record: SQSRecord): def lambda_handler(event, context: LambdaContext): return async_process_partial_response( - event=event, record_handler=async_record_handler, processor=processor, context=context + event=event, + record_handler=async_record_handler, + processor=processor, + context=context, ) diff --git a/examples/feature_flags/src/extracting_envelope.py b/examples/feature_flags/src/extracting_envelope.py index 3c3194c0c1a..74111157704 100644 --- a/examples/feature_flags/src/extracting_envelope.py +++ b/examples/feature_flags/src/extracting_envelope.py @@ -4,7 +4,10 @@ from aws_lambda_powertools.utilities.typing import LambdaContext app_config = AppConfigStore( - environment="dev", application="product-catalogue", name="features", envelope="feature_flags" + environment="dev", + application="product-catalogue", + name="features", + envelope="feature_flags", ) feature_flags = FeatureFlags(store=app_config) diff --git a/examples/feature_flags/src/getting_started_with_tests.py b/examples/feature_flags/src/getting_started_with_tests.py index 81152dca104..a8f877667d2 100644 --- a/examples/feature_flags/src/getting_started_with_tests.py +++ b/examples/feature_flags/src/getting_started_with_tests.py @@ -36,11 +36,11 @@ def test_flags_condition_match(mocker): "action": RuleAction.EQUALS.value, "key": "tenant_id", "value": "12345", - } + }, ], - } + }, }, - } + }, } # WHEN diff --git a/examples/feature_flags/src/getting_stored_features.py b/examples/feature_flags/src/getting_stored_features.py index 07f115375a6..aa1a1516ce5 100644 --- a/examples/feature_flags/src/getting_stored_features.py +++ b/examples/feature_flags/src/getting_stored_features.py @@ -1,7 +1,10 @@ from aws_lambda_powertools.utilities.feature_flags import AppConfigStore, FeatureFlags app_config = AppConfigStore( - environment="dev", application="product-catalogue", name="configuration", envelope="feature_flags" + environment="dev", + application="product-catalogue", + name="configuration", + envelope="feature_flags", ) feature_flags = FeatureFlags(store=app_config) diff --git a/examples/idempotency/src/working_with_exceptions.py b/examples/idempotency/src/working_with_exceptions.py index 9b495c01ce4..ff282d5a601 100644 --- a/examples/idempotency/src/working_with_exceptions.py +++ b/examples/idempotency/src/working_with_exceptions.py @@ -31,6 +31,7 @@ def lambda_handler(event: dict, context: LambdaContext): @idempotent_function(data_keyword_argument="data", config=config, persistence_store=persistence_layer) def call_external_service(data: dict): result: requests.Response = requests.post( - "https://jsonplaceholder.typicode.com/comments/", json={"user": data["user"], "transaction_id": data["id"]} + "https://jsonplaceholder.typicode.com/comments/", + json={"user": data["user"], "transaction_id": data["id"]}, ) return result.json() diff --git a/examples/idempotency/templates/cdk.py b/examples/idempotency/templates/cdk.py index 4b22656defe..1203d17a8d3 100644 --- a/examples/idempotency/templates/cdk.py +++ b/examples/idempotency/templates/cdk.py @@ -17,5 +17,9 @@ def __init__(self, scope: Construct, name: str, lambda_role: iam.Role) -> None: point_in_time_recovery=True, ) self.idempotency_table.grant( - lambda_role, "dynamodb:PutItem", "dynamodb:GetItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem" + lambda_role, + "dynamodb:PutItem", + "dynamodb:GetItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", ) diff --git a/examples/jmespath_functions/src/powertools_base64_gzip_jmespath_schema.py b/examples/jmespath_functions/src/powertools_base64_gzip_jmespath_schema.py index 0ba02934928..d95a295df69 100644 --- a/examples/jmespath_functions/src/powertools_base64_gzip_jmespath_schema.py +++ b/examples/jmespath_functions/src/powertools_base64_gzip_jmespath_schema.py @@ -10,7 +10,7 @@ "logGroup": "/aws/lambda/powertools-example", "logStream": "2022/08/07/[$LATEST]d3a8dcaffc7f4de2b8db132e3e106660", "logEvents": {}, - } + }, ], "required": ["owner", "logGroup", "logStream", "logEvents"], "properties": { diff --git a/examples/jmespath_functions/src/powertools_base64_jmespath_function.py b/examples/jmespath_functions/src/powertools_base64_jmespath_function.py index ba7208298a0..a870d62c5f9 100644 --- a/examples/jmespath_functions/src/powertools_base64_jmespath_function.py +++ b/examples/jmespath_functions/src/powertools_base64_jmespath_function.py @@ -31,7 +31,6 @@ def default(self, obj): def lambda_handler(event, context: LambdaContext) -> dict: - # Try to validate the schema try: validate(event=event, schema=schemas.INPUT, envelope="powertools_json(powertools_base64(payload))") @@ -48,7 +47,7 @@ def lambda_handler(event, context: LambdaContext) -> dict: } except JMESPathTypeError: return return_error_message( - "The powertools_json(powertools_base64()) envelope function must match a valid path." + "The powertools_json(powertools_base64()) envelope function must match a valid path.", ) except binascii.Error: return return_error_message("Payload must be a valid base64 encoded string") diff --git a/examples/jmespath_functions/src/powertools_custom_jmespath_function.py b/examples/jmespath_functions/src/powertools_custom_jmespath_function.py index cd7b85b8115..20ff9fa1763 100644 --- a/examples/jmespath_functions/src/powertools_custom_jmespath_function.py +++ b/examples/jmespath_functions/src/powertools_custom_jmespath_function.py @@ -24,7 +24,6 @@ def _func_decode_snappy_compression(self, payload: str): def lambda_handler(event, context) -> dict: - try: logs = [] logs.append( @@ -33,7 +32,7 @@ def lambda_handler(event, context) -> dict: # NOTE: Use the prefix `_func_` before the name of the function envelope="Records[*].decode_snappy_compression(log)", jmespath_options=custom_jmespath_options, - ) + ), ) return {"logs": logs, "message": "Extracted messages", "success": True} except JMESPathTypeError: diff --git a/examples/logger/src/bring_your_own_formatter_from_scratch.py b/examples/logger/src/bring_your_own_formatter_from_scratch.py index 9b616595824..b7e7761b562 100644 --- a/examples/logger/src/bring_your_own_formatter_from_scratch.py +++ b/examples/logger/src/bring_your_own_formatter_from_scratch.py @@ -31,7 +31,7 @@ def format(self, record: logging.LogRecord) -> str: # noqa: A003 "timestamp": self.formatTime(record), "my_default_key": "test", **self.log_format, - } + }, ) diff --git a/examples/logger/src/bring_your_own_json_serializer.py b/examples/logger/src/bring_your_own_json_serializer.py index 204e131fb87..7954cb3eb90 100644 --- a/examples/logger/src/bring_your_own_json_serializer.py +++ b/examples/logger/src/bring_your_own_json_serializer.py @@ -13,5 +13,7 @@ custom_serializer_with_parameters = functools.partial(orjson.dumps, option=orjson.OPT_SERIALIZE_NUMPY) logger_two = Logger( - service="payment", json_serializer=custom_serializer_with_parameters, json_deserializer=custom_deserializer + service="payment", + json_serializer=custom_serializer_with_parameters, + json_deserializer=custom_deserializer, ) diff --git a/examples/metrics/src/single_metric_default_dimensions.py b/examples/metrics/src/single_metric_default_dimensions.py index 3ed6c5e9035..96ca475314c 100644 --- a/examples/metrics/src/single_metric_default_dimensions.py +++ b/examples/metrics/src/single_metric_default_dimensions.py @@ -9,6 +9,9 @@ def lambda_handler(event: dict, context: LambdaContext): with single_metric( - name="RecordsCount", unit=MetricUnit.Count, value=10, default_dimensions={"environment": STAGE} + name="RecordsCount", + unit=MetricUnit.Count, + value=10, + default_dimensions={"environment": STAGE}, ) as metric: metric.add_dimension(name="TableName", value="Users") diff --git a/examples/metrics/src/single_metric_default_dimensions_inherit.py b/examples/metrics/src/single_metric_default_dimensions_inherit.py index 92a27d6e0d3..f187cea0aa5 100644 --- a/examples/metrics/src/single_metric_default_dimensions_inherit.py +++ b/examples/metrics/src/single_metric_default_dimensions_inherit.py @@ -12,6 +12,9 @@ def lambda_handler(event: dict, context: LambdaContext): with single_metric( - name="RecordsCount", unit=MetricUnit.Count, value=10, default_dimensions=metrics.default_dimensions + name="RecordsCount", + unit=MetricUnit.Count, + value=10, + default_dimensions=metrics.default_dimensions, ) as metric: metric.add_dimension(name="TableName", value="Users") diff --git a/examples/middleware_factory/src/combining_powertools_utilities_function.py b/examples/middleware_factory/src/combining_powertools_utilities_function.py index 6f4935ec9c3..164a8d44dc9 100644 --- a/examples/middleware_factory/src/combining_powertools_utilities_function.py +++ b/examples/middleware_factory/src/combining_powertools_utilities_function.py @@ -80,7 +80,7 @@ def save_api_execution_history(path: str, headers: dict, request_context: dict) "request_time": request_context.get("requestTime"), "source_ip": request_context.get("identity", {}).get("sourceIp"), "http_method": request_context.get("httpMethod"), - } + }, ) return None diff --git a/examples/middleware_factory/src/combining_powertools_utilities_schema.py b/examples/middleware_factory/src/combining_powertools_utilities_schema.py index 7a1978a71a3..a63768204c7 100644 --- a/examples/middleware_factory/src/combining_powertools_utilities_schema.py +++ b/examples/middleware_factory/src/combining_powertools_utilities_schema.py @@ -18,8 +18,8 @@ "default": "", "examples": ["1"], "pattern": "^.*$", - } + }, }, - } + }, }, } diff --git a/examples/parameters/src/appconfig_force_fetch.py b/examples/parameters/src/appconfig_force_fetch.py index 3cf5cbda6fd..101f2d09148 100644 --- a/examples/parameters/src/appconfig_force_fetch.py +++ b/examples/parameters/src/appconfig_force_fetch.py @@ -10,7 +10,10 @@ def lambda_handler(event: dict, context: LambdaContext): try: # Retrieve a single parameter endpoint_comments: Any = parameters.get_app_config( - name="config", environment="dev", application="comments", force_fetch=True + name="config", + environment="dev", + application="comments", + force_fetch=True, ) # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ diff --git a/examples/parameters/src/appconfig_with_cache.py b/examples/parameters/src/appconfig_with_cache.py index 55514e12ea7..6822d9a03cf 100644 --- a/examples/parameters/src/appconfig_with_cache.py +++ b/examples/parameters/src/appconfig_with_cache.py @@ -10,7 +10,10 @@ def lambda_handler(event: dict, context: LambdaContext): try: # Retrieve a single parameter endpoint_comments: Any = parameters.get_app_config( - name="config", environment="dev", application="comments", max_age=20 + name="config", + environment="dev", + application="comments", + max_age=20, ) # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ diff --git a/examples/parameters/src/builtin_provider_dynamodb_custom_fields.py b/examples/parameters/src/builtin_provider_dynamodb_custom_fields.py index 6936f7f0a19..6058b24651f 100644 --- a/examples/parameters/src/builtin_provider_dynamodb_custom_fields.py +++ b/examples/parameters/src/builtin_provider_dynamodb_custom_fields.py @@ -6,12 +6,14 @@ from aws_lambda_powertools.utilities.typing import LambdaContext dynamodb_provider = parameters.DynamoDBProvider( - table_name="ParameterTable", key_attr="IdKeyAttr", sort_attr="SkKeyAttr", value_attr="ValueAttr" + table_name="ParameterTable", + key_attr="IdKeyAttr", + sort_attr="SkKeyAttr", + value_attr="ValueAttr", ) def lambda_handler(event: dict, context: LambdaContext): - try: # Usually an endpoint is not sensitive data, so we store it in DynamoDB Table endpoint_comments: Any = dynamodb_provider.get("comments_endpoint") diff --git a/examples/parameters/src/builtin_provider_ssm_recursive_parameter.py b/examples/parameters/src/builtin_provider_ssm_recursive_parameter.py index ae6c6a29a87..33912c179c3 100644 --- a/examples/parameters/src/builtin_provider_ssm_recursive_parameter.py +++ b/examples/parameters/src/builtin_provider_ssm_recursive_parameter.py @@ -10,7 +10,8 @@ # see: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html sts_client = boto3.client("sts") assumed_role_object = sts_client.assume_role( - RoleArn="arn:aws:iam::account-of-role-to-assume:role/name-of-role", RoleSessionName="RoleAssume1" + RoleArn="arn:aws:iam::account-of-role-to-assume:role/name-of-role", + RoleSessionName="RoleAssume1", ) credentials = assumed_role_object["Credentials"] @@ -32,7 +33,6 @@ def lambda_handler(event: dict, context: LambdaContext): endpoint_comments = "https://jsonplaceholder.typicode.com/noexists/" for parameter, value in all_parameters.items(): - if parameter == "endpoint_comments": endpoint_comments = value diff --git a/examples/parameters/src/builtin_provider_ssm_with_decrypt.py b/examples/parameters/src/builtin_provider_ssm_with_decrypt.py index 1bb4444726a..d44c812851c 100644 --- a/examples/parameters/src/builtin_provider_ssm_with_decrypt.py +++ b/examples/parameters/src/builtin_provider_ssm_with_decrypt.py @@ -20,7 +20,11 @@ def lambda_handler(event: dict, context: LambdaContext): ec2.import_key_pair(KeyName=name_key_pair, PublicKeyMaterial=ec2_pem) ec2.create_instances( - ImageId="ami-026b57f3c383c2eec", InstanceType="t2.micro", MinCount=1, MaxCount=1, KeyName=name_key_pair + ImageId="ami-026b57f3c383c2eec", + InstanceType="t2.micro", + MinCount=1, + MaxCount=1, + KeyName=name_key_pair, ) return {"message": "EC2 created", "success": True} diff --git a/examples/streaming/src/assert_transformation.py b/examples/streaming/src/assert_transformation.py index fe96509a10c..a982c7f2c33 100644 --- a/examples/streaming/src/assert_transformation.py +++ b/examples/streaming/src/assert_transformation.py @@ -23,7 +23,8 @@ def test_s3_object_with_upper_transform(): s3_client = boto3.client("s3") s3_stub = stub.Stubber(s3_client) s3_stub.add_response( - "get_object", {"Body": PowertoolsStreamingBody(raw_stream=io.BytesIO(payload), content_length=len(payload))} + "get_object", + {"Body": PowertoolsStreamingBody(raw_stream=io.BytesIO(payload), content_length=len(payload))}, ) s3_stub.activate() diff --git a/examples/typing/src/working_with_context_function.py b/examples/typing/src/working_with_context_function.py index bfe610efa38..3175593a8de 100644 --- a/examples/typing/src/working_with_context_function.py +++ b/examples/typing/src/working_with_context_function.py @@ -9,12 +9,10 @@ def lambda_handler(event, context: LambdaContext) -> dict: - limit_execution: int = 1000 # milliseconds # scrape website and exit before lambda timeout while context.get_remaining_time_in_millis() > limit_execution: - comments: requests.Response = requests.get("https://jsonplaceholder.typicode.com/comments") # add logic here and save the results of the request to an S3 bucket, for example. @@ -24,7 +22,7 @@ def lambda_handler(event, context: LambdaContext) -> dict: "request_id": context.aws_request_id, "remaining_time": context.get_remaining_time_in_millis(), "comments": comments.json()[:2], - } + }, ) sleep(1) diff --git a/examples/validation/src/getting_started_validator_unwrapping_schema.py b/examples/validation/src/getting_started_validator_unwrapping_schema.py index 2db9b8a4ab9..02b0128d971 100644 --- a/examples/validation/src/getting_started_validator_unwrapping_schema.py +++ b/examples/validation/src/getting_started_validator_unwrapping_schema.py @@ -11,8 +11,8 @@ "s3_key": "event.txt", "file_size": 200, "file_type": "text/plain", - } - } + }, + }, ], "required": ["data"], "properties": { @@ -54,6 +54,6 @@ "pattern": "^.*$", }, }, - } + }, }, } diff --git a/ruff.toml b/ruff.toml index c44950a577e..3ed70837a33 100644 --- a/ruff.toml +++ b/ruff.toml @@ -35,7 +35,6 @@ ignore = [ "PLW0603", #https://beta.ruff.rs/docs/rules/global-statement/ "B904", # raise-without-from-inside-except - disabled temporarily "B018", # useless-expression - disabled temporarily - "COM812", # Trailing comma missing - disabled temporarily "PLC1901", # Compare-to-empty-string - disabled temporarily "ISC", # flake8-implicit-str-concat - disabled temporarily "I001", # isort - disabled temporarily diff --git a/tests/e2e/event_handler/test_cors.py b/tests/e2e/event_handler/test_cors.py index 5d2f140715f..921a227e944 100644 --- a/tests/e2e/event_handler/test_cors.py +++ b/tests/e2e/event_handler/test_cors.py @@ -80,7 +80,7 @@ def test_api_gateway_http_cors_with_correct_origin(apigw_http_endpoint): headers=headers, json={}, auth=build_iam_auth(url=url, aws_service="execute-api"), - ) + ), ) # THEN response has CORS headers @@ -101,7 +101,7 @@ def test_api_gateway_http_cors_with_correct_alternative_origin(apigw_http_endpoi headers=headers, json={}, auth=build_iam_auth(url=url, aws_service="execute-api"), - ) + ), ) # THEN response has CORS headers @@ -122,7 +122,7 @@ def test_api_gateway_http_cors_with_unknown_origin(apigw_http_endpoint): headers=headers, json={}, auth=build_iam_auth(url=url, aws_service="execute-api"), - ) + ), ) # THEN response does NOT have CORS headers @@ -142,7 +142,7 @@ def test_api_gateway_rest_cors_with_correct_origin(apigw_rest_endpoint): url=url, headers=headers, json={}, - ) + ), ) # THEN response has CORS headers @@ -162,7 +162,7 @@ def test_api_gateway_rest_cors_with_correct_alternative_origin(apigw_rest_endpoi url=url, headers=headers, json={}, - ) + ), ) # THEN response has CORS headers @@ -182,7 +182,7 @@ def test_api_gateway_rest_cors_with_unknown_origin(apigw_rest_endpoint): url=url, headers=headers, json={}, - ) + ), ) # THEN response does NOT have CORS headers @@ -203,7 +203,7 @@ def test_lambda_function_url_cors_with_correct_origin(lambda_function_url_endpoi headers=headers, json={}, auth=build_iam_auth(url=url, aws_service="lambda"), - ) + ), ) # THEN response has CORS headers @@ -224,7 +224,7 @@ def test_lambda_function_url_cors_with_correct_alternative_origin(lambda_functio headers=headers, json={}, auth=build_iam_auth(url=url, aws_service="lambda"), - ) + ), ) # THEN response has CORS headers @@ -245,7 +245,7 @@ def test_lambda_function_url_cors_with_unknown_origin(lambda_function_url_endpoi headers=headers, json={}, auth=build_iam_auth(url=url, aws_service="lambda"), - ) + ), ) # THEN response does NOT have CORS headers diff --git a/tests/e2e/event_handler/test_header_serializer.py b/tests/e2e/event_handler/test_header_serializer.py index 7189c349666..6eb9c6d0fd7 100644 --- a/tests/e2e/event_handler/test_header_serializer.py +++ b/tests/e2e/event_handler/test_header_serializer.py @@ -56,7 +56,7 @@ def test_alb_headers_serializer(alb_basic_listener_endpoint): method="POST", url=url, json={"body": body, "status_code": status_code, "headers": headers, "cookies": list(map(str, cookies))}, - ) + ), ) # THEN @@ -94,7 +94,7 @@ def test_alb_multi_value_headers_serializer(alb_multi_value_header_listener_endp method="POST", url=url, json={"body": body, "status_code": status_code, "headers": headers, "cookies": list(map(str, cookies))}, - ) + ), ) # THEN @@ -133,7 +133,7 @@ def test_api_gateway_rest_headers_serializer(apigw_rest_endpoint): method="POST", url=url, json={"body": body, "status_code": status_code, "headers": headers, "cookies": list(map(str, cookies))}, - ) + ), ) # THEN @@ -170,7 +170,7 @@ def test_api_gateway_http_headers_serializer(apigw_http_endpoint): url=url, json={"body": body, "status_code": status_code, "headers": headers, "cookies": list(map(str, cookies))}, auth=build_iam_auth(url=url, aws_service="execute-api"), - ) + ), ) # THEN @@ -207,7 +207,7 @@ def test_lambda_function_url_headers_serializer(lambda_function_url_endpoint): url=url, json={"body": body, "status_code": status_code, "headers": headers, "cookies": list(map(str, cookies))}, auth=build_iam_auth(url=url, aws_service="lambda"), - ) + ), ) # THEN diff --git a/tests/e2e/event_handler/test_paths_ending_with_slash.py b/tests/e2e/event_handler/test_paths_ending_with_slash.py index d871edbb98e..efbc02cf1ac 100644 --- a/tests/e2e/event_handler/test_paths_ending_with_slash.py +++ b/tests/e2e/event_handler/test_paths_ending_with_slash.py @@ -47,7 +47,7 @@ def test_api_gateway_rest_trailing_slash(apigw_rest_endpoint): url=url, json={"body": body}, auth=build_iam_auth(url=url, aws_service="lambda"), - ) + ), ) # THEN expect a HTTP 200 response @@ -68,7 +68,7 @@ def test_api_gateway_http_trailing_slash(apigw_http_endpoint): url=url, json={"body": body}, auth=build_iam_auth(url=url, aws_service="lambda"), - ) + ), ) @@ -86,7 +86,7 @@ def test_lambda_function_url_trailing_slash(lambda_function_url_endpoint): url=url, json={"body": body}, auth=build_iam_auth(url=url, aws_service="lambda"), - ) + ), ) @@ -104,5 +104,5 @@ def test_alb_url_trailing_slash(alb_multi_value_header_listener_endpoint): url=url, json={"body": body}, auth=build_iam_auth(url=url, aws_service="lambda"), - ) + ), ) diff --git a/tests/e2e/idempotency/test_idempotency_dynamodb.py b/tests/e2e/idempotency/test_idempotency_dynamodb.py index e5d3eb4aeb3..a374f763bd4 100644 --- a/tests/e2e/idempotency/test_idempotency_dynamodb.py +++ b/tests/e2e/idempotency/test_idempotency_dynamodb.py @@ -45,20 +45,23 @@ def test_ttl_caching_expiration_idempotency(ttl_cache_expiration_handler_fn_arn: # WHEN # first execution first_execution, _ = data_fetcher.get_lambda_response( - lambda_arn=ttl_cache_expiration_handler_fn_arn, payload=payload + lambda_arn=ttl_cache_expiration_handler_fn_arn, + payload=payload, ) first_execution_response = first_execution["Payload"].read().decode("utf-8") # the second execution should return the same response as the first execution second_execution, _ = data_fetcher.get_lambda_response( - lambda_arn=ttl_cache_expiration_handler_fn_arn, payload=payload + lambda_arn=ttl_cache_expiration_handler_fn_arn, + payload=payload, ) second_execution_response = second_execution["Payload"].read().decode("utf-8") # wait 8s to expire ttl and execute again, this should return a new response value sleep(8) third_execution, _ = data_fetcher.get_lambda_response( - lambda_arn=ttl_cache_expiration_handler_fn_arn, payload=payload + lambda_arn=ttl_cache_expiration_handler_fn_arn, + payload=payload, ) third_execution_response = third_execution["Payload"].read().decode("utf-8") @@ -76,13 +79,15 @@ def test_ttl_caching_timeout_idempotency(ttl_cache_timeout_handler_fn_arn: str): # WHEN # first call should fail due to timeout execution_with_timeout, _ = data_fetcher.get_lambda_response( - lambda_arn=ttl_cache_timeout_handler_fn_arn, payload=payload_timeout_execution + lambda_arn=ttl_cache_timeout_handler_fn_arn, + payload=payload_timeout_execution, ) execution_with_timeout_response = execution_with_timeout["Payload"].read().decode("utf-8") # the second call should work and return the payload execution_working, _ = data_fetcher.get_lambda_response( - lambda_arn=ttl_cache_timeout_handler_fn_arn, payload=payload_working_execution + lambda_arn=ttl_cache_timeout_handler_fn_arn, + payload=payload_working_execution, ) execution_working_response = execution_working["Payload"].read().decode("utf-8") @@ -117,13 +122,15 @@ def test_idempotent_function_thread_safety(function_thread_safety_handler_fn_arn # WHEN # first execution first_execution, _ = data_fetcher.get_lambda_response( - lambda_arn=function_thread_safety_handler_fn_arn, payload=payload + lambda_arn=function_thread_safety_handler_fn_arn, + payload=payload, ) first_execution_response = first_execution["Payload"].read().decode("utf-8") # the second execution should return the same response as the first execution second_execution, _ = data_fetcher.get_lambda_response( - lambda_arn=function_thread_safety_handler_fn_arn, payload=payload + lambda_arn=function_thread_safety_handler_fn_arn, + payload=payload, ) second_execution_response = second_execution["Payload"].read().decode("utf-8") @@ -152,12 +159,14 @@ def test_optional_idempotency_key(optional_idempotency_key_fn_arn: str): # and two others without the idempotency key second_execution, _ = data_fetcher.get_lambda_response( - lambda_arn=optional_idempotency_key_fn_arn, payload=payload_without + lambda_arn=optional_idempotency_key_fn_arn, + payload=payload_without, ) second_execution_response = second_execution["Payload"].read().decode("utf-8") third_execution, _ = data_fetcher.get_lambda_response( - lambda_arn=optional_idempotency_key_fn_arn, payload=payload_without + lambda_arn=optional_idempotency_key_fn_arn, + payload=payload_without, ) third_execution_response = third_execution["Payload"].read().decode("utf-8") diff --git a/tests/e2e/metrics/test_metrics.py b/tests/e2e/metrics/test_metrics.py index 192cbcc25af..4285d011524 100644 --- a/tests/e2e/metrics/test_metrics.py +++ b/tests/e2e/metrics/test_metrics.py @@ -41,7 +41,10 @@ def test_basic_lambda_metric_is_visible(basic_handler_fn: str, basic_handler_fn_ _, execution_time = data_fetcher.get_lambda_response(lambda_arn=basic_handler_fn_arn, payload=event) metric_values = data_fetcher.get_metrics( - namespace=METRIC_NAMESPACE, start_date=execution_time, metric_name=metric_name, dimensions=dimensions + namespace=METRIC_NAMESPACE, + start_date=execution_time, + metric_name=metric_name, + dimensions=dimensions, ) # THEN @@ -62,7 +65,10 @@ def test_cold_start_metric(cold_start_fn_arn: str, cold_start_fn: str): data_fetcher.get_lambda_response(lambda_arn=cold_start_fn_arn, payload=event) metric_values = data_fetcher.get_metrics( - namespace=METRIC_NAMESPACE, start_date=execution_time, metric_name=metric_name, dimensions=dimensions + namespace=METRIC_NAMESPACE, + start_date=execution_time, + metric_name=metric_name, + dimensions=dimensions, ) # THEN diff --git a/tests/e2e/parameters/handlers/parameter_appconfig_freeform_handler.py b/tests/e2e/parameters/handlers/parameter_appconfig_freeform_handler.py index 51b56eba95a..7c73273102e 100644 --- a/tests/e2e/parameters/handlers/parameter_appconfig_freeform_handler.py +++ b/tests/e2e/parameters/handlers/parameter_appconfig_freeform_handler.py @@ -5,7 +5,9 @@ def lambda_handler(event: dict, context: LambdaContext): # Retrieve a single configuration, latest version value: bytes = parameters.get_app_config( - name=event.get("name"), environment=event.get("environment"), application=event.get("application") + name=event.get("name"), + environment=event.get("environment"), + application=event.get("application"), ) return value diff --git a/tests/e2e/parameters/infrastructure.py b/tests/e2e/parameters/infrastructure.py index db76a68def3..810e0f101d4 100644 --- a/tests/e2e/parameters/infrastructure.py +++ b/tests/e2e/parameters/infrastructure.py @@ -17,7 +17,7 @@ def create_resources(self): env_vars = {"parameters": json.dumps(parameters)} functions = self.create_lambda_functions( - function_props={"environment": env_vars, "timeout": Duration.seconds(30)} + function_props={"environment": env_vars, "timeout": Duration.seconds(30)}, ) self._create_app_config(function=functions["ParameterAppconfigFreeformHandler"]) @@ -30,7 +30,7 @@ def create_resources(self): "ssm:GetParameters", ], resources=[f"arn:aws:ssm:{self.region}:{self.account_id}:parameter/powertools/e2e/parameters/*"], - ) + ), ) def _create_app_config(self, function: Function): @@ -122,7 +122,7 @@ def _create_app_config_freeform( "appconfig:StartConfigurationSession", ], resources=["*"], - ) + ), ) def _create_ssm_parameters(self) -> List[str]: diff --git a/tests/e2e/parameters/test_appconfig.py b/tests/e2e/parameters/test_appconfig.py index 7cf6f87067f..28f50a653f4 100644 --- a/tests/e2e/parameters/test_appconfig.py +++ b/tests/e2e/parameters/test_appconfig.py @@ -49,13 +49,14 @@ def test_get_parameter_appconfig_freeform( "name": parameter_appconfig_freeform_profile, "environment": parameter_appconfig_freeform_environment, "application": parameter_appconfig_freeform_application, - } + }, ) expected_return = parameter_appconfig_freeform_value # WHEN parameter_execution, _ = data_fetcher.get_lambda_response( - lambda_arn=parameter_appconfig_freeform_handler_fn_arn, payload=payload + lambda_arn=parameter_appconfig_freeform_handler_fn_arn, + payload=payload, ) parameter_value = parameter_execution["Payload"].read().decode("utf-8") diff --git a/tests/e2e/streaming/test_s3_object.py b/tests/e2e/streaming/test_s3_object.py index fe4fd638b10..4a16c58b2b6 100644 --- a/tests/e2e/streaming/test_s3_object.py +++ b/tests/e2e/streaming/test_s3_object.py @@ -38,7 +38,8 @@ def get_object_version(bucket, key) -> str: def get_lambda_result_payload(s3_object_handler_fn_arn: str, payload: dict) -> dict: handler_result, _ = data_fetcher.get_lambda_response( - lambda_arn=s3_object_handler_fn_arn, payload=json.dumps(payload) + lambda_arn=s3_object_handler_fn_arn, + payload=json.dumps(payload), ) return json.loads(handler_result["Payload"].read()) diff --git a/tests/e2e/utils/data_builder/metrics.py b/tests/e2e/utils/data_builder/metrics.py index d14f4ae3567..55d728c3b31 100644 --- a/tests/e2e/utils/data_builder/metrics.py +++ b/tests/e2e/utils/data_builder/metrics.py @@ -43,7 +43,7 @@ def build_metric_query_data( "Stat": stat, }, "ReturnData": True, - } + }, ] if dimensions: @@ -73,7 +73,10 @@ def build_add_metric_input(metric_name: str, value: float, unit: str = MetricUni def build_multiple_add_metric_input( - metric_name: str, value: float, unit: str = MetricUnit.Count.value, quantity: int = 1 + metric_name: str, + value: float, + unit: str = MetricUnit.Count.value, + quantity: int = 1, ) -> List[Dict]: """Create list of metrics input to be used with Metrics.add_metric() diff --git a/tests/e2e/utils/data_fetcher/common.py b/tests/e2e/utils/data_fetcher/common.py index b2f0724afba..3bbdaa24e6a 100644 --- a/tests/e2e/utils/data_fetcher/common.py +++ b/tests/e2e/utils/data_fetcher/common.py @@ -11,7 +11,9 @@ def get_lambda_response( - lambda_arn: str, payload: Optional[str] = None, client: Optional[LambdaClient] = None + lambda_arn: str, + payload: Optional[str] = None, + client: Optional[LambdaClient] = None, ) -> Tuple[InvocationResponseTypeDef, datetime]: client = client or boto3.client("lambda") payload = payload or "" diff --git a/tests/e2e/utils/data_fetcher/logs.py b/tests/e2e/utils/data_fetcher/logs.py index c81bd1bca7d..8adc9381cab 100644 --- a/tests/e2e/utils/data_fetcher/logs.py +++ b/tests/e2e/utils/data_fetcher/logs.py @@ -118,7 +118,7 @@ def _get_logs(self) -> List[Log]: if len(filtered_logs) < self.minimum_log_entries: raise ValueError( - f"Number of log entries found doesn't meet minimum required ({self.minimum_log_entries}). Repeating..." + f"Number of log entries found doesn't meet minimum required ({self.minimum_log_entries}). Repeating...", ) return filtered_logs diff --git a/tests/e2e/utils/data_fetcher/metrics.py b/tests/e2e/utils/data_fetcher/metrics.py index 18023b18336..a7b415cb97d 100644 --- a/tests/e2e/utils/data_fetcher/metrics.py +++ b/tests/e2e/utils/data_fetcher/metrics.py @@ -57,7 +57,11 @@ def get_metrics( end_date = end_date or start_date + timedelta(minutes=2) metric_query = build_metric_query_data( - namespace=namespace, metric_name=metric_name, period=period, stat=stat, dimensions=dimensions + namespace=namespace, + metric_name=metric_name, + period=period, + stat=stat, + dimensions=dimensions, ) response = cw_client.get_metric_data( diff --git a/tests/e2e/utils/data_fetcher/traces.py b/tests/e2e/utils/data_fetcher/traces.py index 827109112df..09499499517 100644 --- a/tests/e2e/utils/data_fetcher/traces.py +++ b/tests/e2e/utils/data_fetcher/traces.py @@ -194,7 +194,7 @@ def _get_trace_ids(self, pages: PageIterator) -> List[str]: trace_ids = [trace["Id"] for trace in summaries[0]] # type: ignore[index] # TypedDict not being recognized if len(trace_ids) < self.minimum_traces: raise ValueError( - f"Number of traces found doesn't meet minimum required ({self.minimum_traces}). Repeating..." + f"Number of traces found doesn't meet minimum required ({self.minimum_traces}). Repeating...", ) return trace_ids diff --git a/tests/e2e/utils/functions.py b/tests/e2e/utils/functions.py index db70f4ab6b9..64135c96aa3 100644 --- a/tests/e2e/utils/functions.py +++ b/tests/e2e/utils/functions.py @@ -21,7 +21,7 @@ def execute_lambdas_in_parallel(function_name: str, lambdas_arn: list, arguments function_name, arn, arguments, - ) + ), ) executor.shutdown(wait=True) diff --git a/tests/e2e/utils/infrastructure.py b/tests/e2e/utils/infrastructure.py index e827841c52c..e49b3446aaf 100644 --- a/tests/e2e/utils/infrastructure.py +++ b/tests/e2e/utils/infrastructure.py @@ -61,11 +61,13 @@ def __init__(self) -> None: if not self._feature_infra_file.exists(): raise FileNotFoundError( - "You must have your infrastructure defined in 'tests/e2e//infrastructure.py'." + "You must have your infrastructure defined in 'tests/e2e//infrastructure.py'.", ) def create_lambda_functions( - self, function_props: Optional[Dict] = None, architecture: Architecture = Architecture.X86_64 + self, + function_props: Optional[Dict] = None, + architecture: Architecture = Architecture.X86_64, ) -> Dict[str, Function]: """Create Lambda functions available under handlers_dir diff --git a/tests/functional/feature_flags/test_feature_flags.py b/tests/functional/feature_flags/test_feature_flags.py index 4dea0e65aca..12adaa4525b 100644 --- a/tests/functional/feature_flags/test_feature_flags.py +++ b/tests/functional/feature_flags/test_feature_flags.py @@ -31,7 +31,11 @@ def config(): def init_feature_flags( - mocker, mock_schema: Dict, config: Config, envelope: str = "", jmespath_options: Optional[Dict] = None + mocker, + mock_schema: Dict, + config: Config, + envelope: str = "", + jmespath_options: Optional[Dict] = None, ) -> FeatureFlags: mocked_get_conf = mocker.patch("aws_lambda_powertools.utilities.parameters.AppConfigProvider.get") mocked_get_conf.return_value = mock_schema @@ -76,11 +80,11 @@ def test_flags_rule_does_not_match(mocker, config): "action": RuleAction.EQUALS.value, "key": "tenant_id", "value": "345345435", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) @@ -123,11 +127,11 @@ def test_flags_conditions_no_match(mocker, config): "action": RuleAction.EQUALS.value, "key": "tenant_id", "value": "345345435", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False) @@ -157,9 +161,9 @@ def test_flags_conditions_rule_not_match_multiple_conditions_match_only_one_cond "value": "bbb", }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -195,9 +199,9 @@ def test_flags_conditions_rule_match_equal_multiple_conditions(mocker, config): "value": username_val, }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -235,9 +239,9 @@ def test_flags_conditions_no_rule_match_equal_multiple_conditions(mocker, config "value": "a", }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False) @@ -290,7 +294,7 @@ def test_flags_conditions_rule_match_multiple_actions_multiple_rules_multiple_co ], }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) @@ -302,7 +306,9 @@ def test_flags_conditions_rule_match_multiple_actions_multiple_rules_multiple_co assert toggle == expected_value_second_check # match no rule toggle = feature_flags.evaluate( - name="my_feature", context={"tenant_id": "11114446", "username": "ab"}, default=False + name="my_feature", + context={"tenant_id": "11114446", "username": "ab"}, + default=False, ) assert toggle == expected_value_third_check # feature doesn't exist @@ -331,11 +337,11 @@ def test_flags_match_rule_with_in_action(mocker, config): "action": RuleAction.IN.value, "key": "tenant_id", "value": ["6", "2"], - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False) @@ -355,11 +361,11 @@ def test_flags_no_match_rule_with_in_action(mocker, config): "action": RuleAction.IN.value, "key": "tenant_id", "value": ["8", "2"], - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False) @@ -379,11 +385,11 @@ def test_flags_match_rule_with_not_in_action(mocker, config): "action": RuleAction.NOT_IN.value, "key": "tenant_id", "value": ["10", "4"], - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False) @@ -403,11 +409,11 @@ def test_flags_no_match_rule_with_not_in_action(mocker, config): "action": RuleAction.NOT_IN.value, "key": "tenant_id", "value": ["6", "4"], - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False) @@ -427,11 +433,11 @@ def test_flags_match_rule_with_key_in_value_action(mocker, config): "action": RuleAction.KEY_IN_VALUE.value, "key": "tenant_id", "value": ["6", "2"], - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False) @@ -451,11 +457,11 @@ def test_flags_no_match_rule_with_key_in_value_action(mocker, config): "action": RuleAction.KEY_IN_VALUE.value, "key": "tenant_id", "value": ["8", "2"], - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False) @@ -475,11 +481,11 @@ def test_flags_match_rule_with_key_not_in_value_action(mocker, config): "action": RuleAction.KEY_NOT_IN_VALUE.value, "key": "tenant_id", "value": ["10", "4"], - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False) @@ -499,11 +505,11 @@ def test_flags_no_match_rule_with_key_not_in_value_action(mocker, config): "action": RuleAction.KEY_NOT_IN_VALUE.value, "key": "tenant_id", "value": ["6", "4"], - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False) @@ -523,15 +529,17 @@ def test_flags_match_rule_with_value_in_key_action(mocker, config): "action": RuleAction.VALUE_IN_KEY.value, "key": "groups", "value": "SYSADMIN", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( - name="my_feature", context={"tenant_id": "6", "username": "a", "groups": ["SYSADMIN", "IT"]}, default=False + name="my_feature", + context={"tenant_id": "6", "username": "a", "groups": ["SYSADMIN", "IT"]}, + default=False, ) assert toggle == expected_value @@ -549,15 +557,17 @@ def test_flags_no_match_rule_with_value_in_key_action(mocker, config): "action": RuleAction.VALUE_IN_KEY.value, "key": "groups", "value": "GUEST", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( - name="my_feature", context={"tenant_id": "6", "username": "a", "groups": ["SYSADMIN", "IT"]}, default=False + name="my_feature", + context={"tenant_id": "6", "username": "a", "groups": ["SYSADMIN", "IT"]}, + default=False, ) assert toggle == expected_value @@ -575,15 +585,17 @@ def test_flags_match_rule_with_value_not_in_key_action(mocker, config): "action": RuleAction.VALUE_NOT_IN_KEY.value, "key": "groups", "value": "GUEST", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( - name="my_feature", context={"tenant_id": "6", "username": "a", "groups": ["SYSADMIN", "IT"]}, default=False + name="my_feature", + context={"tenant_id": "6", "username": "a", "groups": ["SYSADMIN", "IT"]}, + default=False, ) assert toggle == expected_value @@ -601,15 +613,17 @@ def test_flags_no_match_rule_with_value_not_in_key_action(mocker, config): "action": RuleAction.VALUE_NOT_IN_KEY.value, "key": "groups", "value": "SYSADMIN", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( - name="my_feature", context={"tenant_id": "6", "username": "a", "groups": ["SYSADMIN", "IT"]}, default=False + name="my_feature", + context={"tenant_id": "6", "username": "a", "groups": ["SYSADMIN", "IT"]}, + default=False, ) assert toggle == expected_value @@ -628,9 +642,9 @@ def test_multiple_features_enabled(mocker, config): "action": RuleAction.IN.value, "key": "tenant_id", "value": ["6", "2"], - } + }, ], - } + }, }, }, "my_feature2": { @@ -707,7 +721,10 @@ def test_is_rule_matched_no_matches(mocker, config): # WHEN calling _evaluate_conditions result = feature_flags._evaluate_conditions( - rule_name="dummy", feature_name="dummy", rule=rule, context=rules_context + rule_name="dummy", + feature_name="dummy", + rule=rule, + context=rules_context, ) # THEN return False @@ -736,11 +753,11 @@ def test_match_condition_with_dict_value(mocker, config): "action": RuleAction.EQUALS.value, "key": "tenant", "value": {"tenant_id": "6", "username": "lessa"}, - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) ctx = {"tenant": {"tenant_id": "6", "username": "lessa"}} @@ -792,15 +809,17 @@ def test_flags_not_equal_no_match(mocker, config): "action": RuleAction.NOT_EQUALS.value, "key": "tenant_id", "value": "345345435", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( - name="my_feature", context={"tenant_id": "345345435", "username": "a"}, default=False + name="my_feature", + context={"tenant_id": "345345435", "username": "a"}, + default=False, ) assert toggle == expected_value @@ -818,11 +837,11 @@ def test_flags_not_equal_match(mocker, config): "action": RuleAction.NOT_EQUALS.value, "key": "tenant_id", "value": "345345435", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "", "username": "a"}, default=False) @@ -843,11 +862,11 @@ def test_flags_less_than_no_match_1(mocker, config): "action": RuleAction.KEY_LESS_THAN_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -871,11 +890,11 @@ def test_flags_less_than_no_match_2(mocker, config): "action": RuleAction.KEY_LESS_THAN_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -899,11 +918,11 @@ def test_flags_less_than_match(mocker, config): "action": RuleAction.KEY_LESS_THAN_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -928,11 +947,11 @@ def test_flags_less_than_or_equal_no_match(mocker, config): "action": RuleAction.KEY_LESS_THAN_OR_EQUAL_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -956,11 +975,11 @@ def test_flags_less_than_or_equal_match_1(mocker, config): "action": RuleAction.KEY_LESS_THAN_OR_EQUAL_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -984,11 +1003,11 @@ def test_flags_less_than_or_equal_match_2(mocker, config): "action": RuleAction.KEY_LESS_THAN_OR_EQUAL_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -1013,11 +1032,11 @@ def test_flags_greater_than_no_match_1(mocker, config): "action": RuleAction.KEY_GREATER_THAN_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -1041,11 +1060,11 @@ def test_flags_greater_than_no_match_2(mocker, config): "action": RuleAction.KEY_GREATER_THAN_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -1069,11 +1088,11 @@ def test_flags_greater_than_match(mocker, config): "action": RuleAction.KEY_GREATER_THAN_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -1098,11 +1117,11 @@ def test_flags_greater_than_or_equal_no_match(mocker, config): "action": RuleAction.KEY_GREATER_THAN_OR_EQUAL_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -1126,11 +1145,11 @@ def test_flags_greater_than_or_equal_match_1(mocker, config): "action": RuleAction.KEY_GREATER_THAN_OR_EQUAL_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -1154,11 +1173,11 @@ def test_flags_greater_than_or_equal_match_2(mocker, config): "action": RuleAction.KEY_GREATER_THAN_OR_EQUAL_VALUE.value, "key": "current_date", "value": "2021.10.31", - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -1187,11 +1206,11 @@ def test_flags_modulo_range_no_match(mocker, config): ModuloRangeValues.START.value: 0, ModuloRangeValues.END.value: 29, }, - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -1219,11 +1238,11 @@ def test_flags_modulo_range_match_1(mocker, config): ModuloRangeValues.START.value: 0, ModuloRangeValues.END.value: 39, }, - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -1251,11 +1270,11 @@ def test_flags_modulo_range_match_2(mocker, config): ModuloRangeValues.START.value: 10, ModuloRangeValues.END.value: 35, }, - } + }, ], - } + }, }, - } + }, } feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config) toggle = feature_flags.evaluate( @@ -1281,11 +1300,11 @@ def test_non_boolean_feature_match(mocker, config): CONDITION_ACTION: RuleAction.EQUALS.value, CONDITION_KEY: "tenant_id", CONDITION_VALUE: "345345435", - } + }, ], - } + }, }, - } + }, } # WHEN @@ -1299,7 +1318,7 @@ def test_non_boolean_feature_with_no_rules(mocker, config): expected_value = ["value1"] # GIVEN mocked_app_config_schema = { - "my_feature": {FEATURE_DEFAULT_VAL_KEY: expected_value, FEATURE_DEFAULT_VAL_TYPE_KEY: False} + "my_feature": {FEATURE_DEFAULT_VAL_KEY: expected_value, FEATURE_DEFAULT_VAL_TYPE_KEY: False}, } # WHEN features = init_feature_flags(mocker, mocked_app_config_schema, config) @@ -1322,11 +1341,11 @@ def test_non_boolean_feature_with_no_rule_match(mocker, config): CONDITION_ACTION: RuleAction.EQUALS.value, CONDITION_KEY: "tenant_id", CONDITION_VALUE: "345345435", - } + }, ], - } + }, }, - } + }, } features = init_feature_flags(mocker, mocked_app_config_schema, config) @@ -1347,9 +1366,9 @@ def test_get_all_enabled_features_boolean_and_non_boolean(mocker, config): CONDITION_ACTION: RuleAction.IN.value, CONDITION_KEY: "tenant_id", CONDITION_VALUE: ["6", "2"], - } + }, ], - } + }, }, }, "my_feature2": { @@ -1369,7 +1388,7 @@ def test_get_all_enabled_features_boolean_and_non_boolean(mocker, config): CONDITION_ACTION: RuleAction.EQUALS.value, CONDITION_KEY: "username", CONDITION_VALUE: "a", - } + }, ], }, }, diff --git a/tests/functional/feature_flags/test_schema_validation.py b/tests/functional/feature_flags/test_schema_validation.py index 86cba07bbd8..654cfbcab40 100644 --- a/tests/functional/feature_flags/test_schema_validation.py +++ b/tests/functional/feature_flags/test_schema_validation.py @@ -85,7 +85,7 @@ def test_invalid_rule(): "a", "b", ], - } + }, } validator = SchemaValidator(schema) with pytest.raises(SchemaValidationError): @@ -98,9 +98,9 @@ def test_invalid_rule(): RULES_KEY: { "tenant id equals 345345435": { RULE_MATCH_VALUE: "False", - } + }, }, - } + }, } validator = SchemaValidator(schema) with pytest.raises(SchemaValidationError): @@ -113,9 +113,9 @@ def test_invalid_rule(): RULES_KEY: { "tenant id equals 345345435": { RULE_MATCH_VALUE: False, - } + }, }, - } + }, } validator = SchemaValidator(schema) with pytest.raises(SchemaValidationError): @@ -128,7 +128,7 @@ def test_invalid_rule(): RULES_KEY: { "tenant id equals 345345435": {RULE_MATCH_VALUE: False, CONDITIONS_KEY: []}, }, - } + }, } validator = SchemaValidator(schema) with pytest.raises(SchemaValidationError): @@ -141,7 +141,7 @@ def test_invalid_rule(): RULES_KEY: { "tenant id equals 345345435": {RULE_MATCH_VALUE: False, CONDITIONS_KEY: {}}, }, - } + }, } validator = SchemaValidator(schema) with pytest.raises(SchemaValidationError): @@ -157,9 +157,9 @@ def test_invalid_condition(): "tenant id equals 345345435": { RULE_MATCH_VALUE: False, CONDITIONS_KEY: {CONDITION_ACTION: "stuff", CONDITION_KEY: "a", CONDITION_VALUE: "a"}, - } + }, }, - } + }, } validator = SchemaValidator(schema) with pytest.raises(SchemaValidationError): @@ -173,9 +173,9 @@ def test_invalid_condition(): "tenant id equals 345345435": { RULE_MATCH_VALUE: False, CONDITIONS_KEY: {CONDITION_ACTION: RuleAction.EQUALS.value}, - } + }, }, - } + }, } validator = SchemaValidator(schema) with pytest.raises(SchemaValidationError): @@ -193,9 +193,9 @@ def test_invalid_condition(): CONDITION_KEY: 5, CONDITION_VALUE: "a", }, - } + }, }, - } + }, } validator = SchemaValidator(schema) with pytest.raises(SchemaValidationError): @@ -256,9 +256,9 @@ def test_valid_condition_all_actions(): CONDITION_VALUE: "GUEST", }, ], - } + }, }, - } + }, } validator = SchemaValidator(schema) validator.validate() diff --git a/tests/functional/feature_flags/test_time_based_actions.py b/tests/functional/feature_flags/test_time_based_actions.py index 20d95a35580..8b850d52fc3 100644 --- a/tests/functional/feature_flags/test_time_based_actions.py +++ b/tests/functional/feature_flags/test_time_based_actions.py @@ -38,7 +38,14 @@ def evaluate_mocked_schema( year, month, day, hour, minute, second, timezone = mocked_time time = mocker.patch("aws_lambda_powertools.utilities.feature_flags.comparators._get_now_from_timezone") time.return_value = datetime.datetime( - year=year, month=month, day=day, hour=hour, minute=minute, second=second, microsecond=0, tzinfo=timezone + year=year, + month=month, + day=day, + hour=hour, + minute=minute, + second=second, + microsecond=0, + tzinfo=timezone, ) # Mock the returned data from AppConfig @@ -47,7 +54,7 @@ def evaluate_mocked_schema( "my_feature": { FEATURE_DEFAULT_VAL_KEY: False, RULES_KEY: rules, - } + }, } # Create a dummy AppConfigStore that returns our mocked FeatureFlag @@ -82,7 +89,7 @@ def test_time_based_utc_in_between_time_range_rule_match(mocker): CONDITION_VALUE: {TimeValues.START.value: "11:11", TimeValues.END.value: "23:59"}, }, ], - } + }, }, mocked_time=(2022, 2, 15, 11, 12, 0, datetime.timezone.utc), ) @@ -101,7 +108,7 @@ def test_time_based_utc_in_between_time_range_no_rule_match(mocker): CONDITION_VALUE: {TimeValues.START.value: "11:11", TimeValues.END.value: "23:59"}, }, ], - } + }, }, mocked_time=(2022, 2, 15, 7, 12, 0, datetime.timezone.utc), # no rule match 7:12 am ) @@ -120,7 +127,7 @@ def test_time_based_utc_in_between_time_range_full_hour_rule_match(mocker): CONDITION_VALUE: {TimeValues.START.value: "20:00", TimeValues.END.value: "23:00"}, }, ], - } + }, }, mocked_time=(2022, 2, 15, 21, 12, 0, datetime.timezone.utc), # rule match 21:12 ) @@ -139,7 +146,7 @@ def test_time_based_utc_in_between_time_range_between_days_rule_match(mocker): CONDITION_VALUE: {TimeValues.START.value: "23:00", TimeValues.END.value: "04:00"}, }, ], - } + }, }, mocked_time=(2022, 2, 15, 2, 3, 0, datetime.timezone.utc), # rule match 2:03 am ) @@ -158,7 +165,7 @@ def test_time_based_utc_in_between_time_range_between_days_rule_no_match(mocker) CONDITION_VALUE: {TimeValues.START.value: "23:00", TimeValues.END.value: "04:00"}, }, ], - } + }, }, mocked_time=(2022, 2, 15, 5, 0, 0, datetime.timezone.utc), # rule no match 5:00 am ) @@ -183,7 +190,7 @@ def test_time_based_between_time_range_rule_timezone_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 2, 15, 11, 11, 0, gettz(timezone_name)), # rule match 11:11 am, Europe/Copenhagen ) @@ -208,7 +215,7 @@ def test_time_based_between_time_range_rule_timezone_no_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 2, 15, 10, 11, 0, gettz(timezone_name)), # no rule match 10:11 am, Europe/Copenhagen ) @@ -230,7 +237,7 @@ def test_time_based_utc_in_between_full_time_range_rule_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 10, 7, 10, 0, 0, datetime.timezone.utc), # will match rule ) @@ -255,7 +262,7 @@ def test_time_based_utc_in_between_full_time_range_no_rule_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 9, 7, 10, 0, 0, gettz(timezone_name)), # will not rule match ) @@ -278,7 +285,7 @@ def test_time_based_utc_in_between_full_time_range_timezone_no_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 10, 10, 12, 15, 0, gettz("America/New_York")), # will not rule match, it's too late ) @@ -302,7 +309,7 @@ def test_time_based_multiple_conditions_utc_in_between_time_range_rule_match(moc CONDITION_VALUE: "ran", }, ], - } + }, }, mocked_time=(2022, 10, 7, 10, 0, 0, datetime.timezone.utc), # will rule match context={"username": "ran"}, @@ -327,7 +334,7 @@ def test_time_based_multiple_conditions_utc_in_between_time_range_no_rule_match( CONDITION_VALUE: "ran", }, ], - } + }, }, mocked_time=(2022, 10, 7, 7, 0, 0, datetime.timezone.utc), # will cause no rule match, 7:00 context={"username": "ran"}, @@ -355,7 +362,7 @@ def test_time_based_utc_days_range_rule_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 11, 18, 10, 0, 0, datetime.timezone.utc), # friday ) @@ -382,7 +389,7 @@ def test_time_based_utc_days_range_no_rule_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 11, 20, 10, 0, 0, datetime.timezone.utc), # sunday, no match ) @@ -403,7 +410,7 @@ def test_time_based_utc_only_weekend_rule_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 11, 19, 10, 0, 0, datetime.timezone.utc), # saturday ) @@ -427,7 +434,7 @@ def test_time_based_utc_only_weekend_with_timezone_rule_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 11, 19, 10, 0, 0, gettz(timezone_name)), # saturday ) @@ -451,7 +458,7 @@ def test_time_based_utc_only_weekend_with_timezone_rule_no_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 11, 21, 0, 0, 0, gettz("Europe/Copenhagen")), # monday, 00:00 ) @@ -472,7 +479,7 @@ def test_time_based_utc_only_weekend_no_rule_match(mocker): }, }, ], - } + }, }, mocked_time=(2022, 11, 18, 10, 0, 0, datetime.timezone.utc), # friday, no match ) @@ -496,7 +503,7 @@ def test_time_based_multiple_conditions_utc_days_range_and_certain_hours_rule_ma CONDITION_VALUE: {TimeValues.DAYS.value: [TimeValues.MONDAY.value, TimeValues.THURSDAY.value]}, }, ], - } + }, }, mocked_time=(2022, 11, 17, 16, 0, 0, datetime.timezone.utc), # thursday 16:00 ) @@ -519,11 +526,11 @@ def evaluate(mocked_time: Tuple[int, int, int, int, int, int, datetime.tzinfo]): CONDITION_ACTION: RuleAction.SCHEDULE_BETWEEN_DAYS_OF_WEEK.value, CONDITION_KEY: TimeKeys.CURRENT_DAY_OF_WEEK.value, CONDITION_VALUE: { - TimeValues.DAYS.value: [TimeValues.MONDAY.value, TimeValues.THURSDAY.value] + TimeValues.DAYS.value: [TimeValues.MONDAY.value, TimeValues.THURSDAY.value], }, }, ], - } + }, }, mocked_time=mocked_time, ) diff --git a/tests/functional/idempotency/conftest.py b/tests/functional/idempotency/conftest.py index 75834f76688..5dda24b9460 100644 --- a/tests/functional/idempotency/conftest.py +++ b/tests/functional/idempotency/conftest.py @@ -97,7 +97,9 @@ def expected_params_update_item(serialized_lambda_response, hashed_idempotency_k @pytest.fixture def expected_params_update_item_with_validation( - serialized_lambda_response, hashed_idempotency_key, hashed_validation_key + serialized_lambda_response, + hashed_idempotency_key, + hashed_validation_key, ): return { "ExpressionAttributeNames": { @@ -192,7 +194,9 @@ def hashed_idempotency_key(request, lambda_apigw_event, default_jmespath, lambda @pytest.fixture def hashed_idempotency_key_with_envelope(request, lambda_apigw_event): event = extract_data_from_envelope( - data=lambda_apigw_event, envelope=envelopes.API_GATEWAY_HTTP, jmespath_options={} + data=lambda_apigw_event, + envelope=envelopes.API_GATEWAY_HTTP, + jmespath_options={}, ) return ( f"test-func.{request.function.__module__}.{request.function.__qualname__}..lambda_handler#" @@ -218,7 +222,11 @@ def persistence_store_compound(config): @pytest.fixture def persistence_store_compound_static_pk_value(config, static_pk_value): return DynamoDBPersistenceLayer( - table_name=TABLE_NAME, boto_config=config, key_attr="id", sort_key_attr="sk", static_pk_value=static_pk_value + table_name=TABLE_NAME, + boto_config=config, + key_attr="id", + sort_key_attr="sk", + static_pk_value=static_pk_value, ) @@ -262,7 +270,9 @@ def static_pk_value(): @pytest.fixture def expected_params_update_item_compound_key_static_pk_value( - expected_params_update_item, hashed_idempotency_key, static_pk_value + expected_params_update_item, + hashed_idempotency_key, + static_pk_value, ): return { # same as in any update_item transaction except the `Key` due to composite key value @@ -273,7 +283,9 @@ def expected_params_update_item_compound_key_static_pk_value( @pytest.fixture def expected_params_put_item_compound_key_static_pk_value( - expected_params_put_item, hashed_idempotency_key, static_pk_value + expected_params_put_item, + hashed_idempotency_key, + static_pk_value, ): return { # same as in any put_item transaction except the `Item` due to composite key value diff --git a/tests/functional/idempotency/test_idempotency.py b/tests/functional/idempotency/test_idempotency.py index 9722a1e9841..47b24744665 100644 --- a/tests/functional/idempotency/test_idempotency.py +++ b/tests/functional/idempotency/test_idempotency.py @@ -82,7 +82,7 @@ def test_idempotent_lambda_already_completed( "expiration": {"N": timestamp_future}, "data": {"S": serialized_lambda_response}, "status": {"S": "COMPLETED"}, - } + }, } expected_params = { @@ -131,7 +131,7 @@ def test_idempotent_lambda_in_progress( "id": {"S": hashed_idempotency_key}, "expiration": {"N": timestamp_future}, "status": {"S": "INPROGRESS"}, - } + }, } stubber.add_client_error("put_item", "ConditionalCheckFailedException") @@ -183,7 +183,7 @@ def test_idempotent_lambda_in_progress_with_cache( "id": {"S": hashed_idempotency_key}, "expiration": {"N": timestamp_future}, "status": {"S": "INPROGRESS"}, - } + }, } stubber.add_client_error("put_item", "ConditionalCheckFailedException") @@ -434,7 +434,7 @@ def test_idempotent_lambda_already_completed_with_validation_bad_payload( "data": {"S": '{"message": "test", "statusCode": 200}'}, "status": {"S": "COMPLETED"}, "validation": {"S": hashed_validation_key}, - } + }, } expected_params = {"TableName": TABLE_NAME, "Key": {"id": {"S": hashed_idempotency_key}}, "ConsistentRead": True} @@ -478,7 +478,7 @@ def test_idempotent_lambda_expired_during_request( "expiration": {"N": timestamp_expired}, "data": {"S": '{"message": "test", "statusCode": 200}'}, "status": {"S": "INPROGRESS"}, - } + }, } ddb_response_get_item_missing = {} expected_params_get_item = { @@ -642,7 +642,9 @@ def lambda_handler(event, context): @pytest.mark.parametrize( - "config_without_jmespath", [{"use_local_cache": False}, {"use_local_cache": True}], indirect=True + "config_without_jmespath", + [{"use_local_cache": False}, {"use_local_cache": True}], + indirect=True, ) def test_idempotent_lambda_with_validator_util( config_without_jmespath: IdempotencyConfig, @@ -667,7 +669,7 @@ def test_idempotent_lambda_with_validator_util( "expiration": {"N": timestamp_future}, "data": {"S": serialized_lambda_response}, "status": {"S": "COMPLETED"}, - } + }, } expected_params = { @@ -723,7 +725,7 @@ def test_idempotent_lambda_expires_in_progress_before_expire( "in_progress_expiration": {"N": str(timestamp_expires_in_progress)}, "data": {"S": '{"message": "test", "statusCode": 200'}, "status": {"S": "INPROGRESS"}, - } + }, } stubber.add_response("get_item", ddb_response_get_item, expected_params_get_item) @@ -768,7 +770,7 @@ def test_idempotent_lambda_expires_in_progress_after_expire( "in_progress_expiration": {"N": str(int(one_second_ago.timestamp() * 1000))}, "data": {"S": '{"message": "test", "statusCode": 200'}, "status": {"S": "INPROGRESS"}, - } + }, } stubber.add_response("get_item", ddb_response_get_item, expected_params_get_item) @@ -816,7 +818,9 @@ def test_data_record_invalid_status_value(): def test_data_record_json_to_dict_mapping(): # GIVEN a data record with status "INPROGRESS" and provided response data data_record = DataRecord( - "key", status="INPROGRESS", response_data='{"body": "execution finished","statusCode": "200"}' + "key", + status="INPROGRESS", + response_data='{"body": "execution finished","statusCode": "200"}', ) # WHEN translating response data to dictionary @@ -838,7 +842,8 @@ def test_data_record_json_to_dict_mapping_when_response_data_none(): @pytest.mark.parametrize("idempotency_config", [{"use_local_cache": True}], indirect=True) def test_handler_for_status_expired_data_record( - idempotency_config: IdempotencyConfig, persistence_store: DynamoDBPersistenceLayer + idempotency_config: IdempotencyConfig, + persistence_store: DynamoDBPersistenceLayer, ): idempotency_handler = IdempotencyHandler( function=lambda a: a, @@ -854,7 +859,8 @@ def test_handler_for_status_expired_data_record( @pytest.mark.parametrize("idempotency_config", [{"use_local_cache": True}], indirect=True) def test_handler_for_status_inprogress_data_record_inconsistent( - idempotency_config: IdempotencyConfig, persistence_store: DynamoDBPersistenceLayer + idempotency_config: IdempotencyConfig, + persistence_store: DynamoDBPersistenceLayer, ): idempotency_handler = IdempotencyHandler( function=lambda a: a, @@ -874,7 +880,8 @@ def test_handler_for_status_inprogress_data_record_inconsistent( @pytest.mark.parametrize("idempotency_config", [{"use_local_cache": True}], indirect=True) def test_handler_for_status_inprogress_data_record_consistent( - idempotency_config: IdempotencyConfig, persistence_store: DynamoDBPersistenceLayer + idempotency_config: IdempotencyConfig, + persistence_store: DynamoDBPersistenceLayer, ): idempotency_handler = IdempotencyHandler( function=lambda a: a, @@ -894,7 +901,8 @@ def test_handler_for_status_inprogress_data_record_consistent( @pytest.mark.parametrize("idempotency_config", [{"use_local_cache": True}], indirect=True) def test_in_progress_never_saved_to_cache( - idempotency_config: IdempotencyConfig, persistence_store: DynamoDBPersistenceLayer + idempotency_config: IdempotencyConfig, + persistence_store: DynamoDBPersistenceLayer, ): # GIVEN a data record with status "INPROGRESS" # and persistence_store has use_local_cache = True @@ -930,7 +938,8 @@ def test_user_local_disabled(idempotency_config: IdempotencyConfig, persistence_ @pytest.mark.parametrize("idempotency_config", [{"use_local_cache": True}], indirect=True) def test_delete_from_cache_when_empty( - idempotency_config: IdempotencyConfig, persistence_store: DynamoDBPersistenceLayer + idempotency_config: IdempotencyConfig, + persistence_store: DynamoDBPersistenceLayer, ): # GIVEN use_local_cache is True AND the local cache is empty persistence_store.configure(idempotency_config) @@ -982,10 +991,13 @@ def test_is_missing_idempotency_key(): @pytest.mark.parametrize( - "idempotency_config", [{"use_local_cache": False, "event_key_jmespath": "body"}], indirect=True + "idempotency_config", + [{"use_local_cache": False, "event_key_jmespath": "body"}], + indirect=True, ) def test_default_no_raise_on_missing_idempotency_key( - idempotency_config: IdempotencyConfig, persistence_store: DynamoDBPersistenceLayer + idempotency_config: IdempotencyConfig, + persistence_store: DynamoDBPersistenceLayer, ): # GIVEN a persistence_store with use_local_cache = False and event_key_jmespath = "body" function_name = "foo" @@ -1008,7 +1020,8 @@ def test_default_no_raise_on_missing_idempotency_key( indirect=True, ) def test_raise_on_no_idempotency_key( - idempotency_config: IdempotencyConfig, persistence_store: DynamoDBPersistenceLayer + idempotency_config: IdempotencyConfig, + persistence_store: DynamoDBPersistenceLayer, ): # GIVEN a persistence_store with raise_on_no_idempotency_key and no idempotency key in the request persistence_store.configure(idempotency_config) @@ -1035,7 +1048,8 @@ def test_raise_on_no_idempotency_key( indirect=True, ) def test_jmespath_with_powertools_json( - idempotency_config: IdempotencyConfig, persistence_store: DynamoDBPersistenceLayer + idempotency_config: IdempotencyConfig, + persistence_store: DynamoDBPersistenceLayer, ): # GIVEN an event_key_jmespath with powertools_json custom function persistence_store.configure(idempotency_config, "handler") @@ -1056,7 +1070,8 @@ def test_jmespath_with_powertools_json( @pytest.mark.parametrize("config_with_jmespath_options", ["powertools_json(data).payload"], indirect=True) def test_custom_jmespath_function_overrides_builtin_functions( - config_with_jmespath_options: IdempotencyConfig, persistence_store: DynamoDBPersistenceLayer + config_with_jmespath_options: IdempotencyConfig, + persistence_store: DynamoDBPersistenceLayer, ): # GIVEN a persistence store with a custom jmespath_options # AND use a builtin Powertools for AWS Lambda (Python) custom function @@ -1288,7 +1303,8 @@ def record_handler(record): @pytest.mark.parametrize("data", [None, 0, False]) def test_idempotent_function_falsy_values_with_raise_on_no_idempotency_key( - data, persistence_store: DynamoDBPersistenceLayer + data, + persistence_store: DynamoDBPersistenceLayer, ): # GIVEN raise_on_no_idempotency_key is True idempotency_config = IdempotencyConfig(event_key_jmespath="idemKey", raise_on_no_idempotency_key=True) @@ -1348,7 +1364,8 @@ def dummy_handler(event, context): @pytest.mark.parametrize("idempotency_config", [{"use_local_cache": True}], indirect=True) def test_idempotent_function_duplicates( - idempotency_config: IdempotencyConfig, persistence_store: DynamoDBPersistenceLayer + idempotency_config: IdempotencyConfig, + persistence_store: DynamoDBPersistenceLayer, ): # Scenario to validate the both methods are called mock_event = {"data": "value"} @@ -1371,7 +1388,10 @@ def test_invalid_dynamodb_persistence_layer(): # Scenario constructing a DynamoDBPersistenceLayer with a key_attr matching sort_key_attr should fail with pytest.raises(ValueError) as ve: DynamoDBPersistenceLayer( - table_name="Foo", key_attr="id", sort_key_attr="id", boto_config=Config(region_name="eu-west-1") + table_name="Foo", + key_attr="id", + sort_key_attr="id", + boto_config=Config(region_name="eu-west-1"), ) # and raise a ValueError assert str(ve.value) == "key_attr [id] and sort_key_attr [id] cannot be the same!" @@ -1485,7 +1505,7 @@ def test_idempotent_lambda_compound_already_completed( "expiration": {"N": timestamp_future}, "data": {"S": serialized_lambda_response}, "status": {"S": "COMPLETED"}, - } + }, } expected_params = { "TableName": TABLE_NAME, diff --git a/tests/functional/parser/test_kinesis.py b/tests/functional/parser/test_kinesis.py index 6b23bd214a6..151102c34c8 100644 --- a/tests/functional/parser/test_kinesis.py +++ b/tests/functional/parser/test_kinesis.py @@ -72,8 +72,8 @@ def test_kinesis_trigger_event(): "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role", "awsRegion": "us-east-2", "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream", - } - ] + }, + ], } handle_kinesis(event_dict, LambdaContext()) @@ -97,8 +97,8 @@ def test_kinesis_trigger_bad_base64_event(): "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role", "awsRegion": "us-east-2", "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream", - } - ] + }, + ], } with pytest.raises(ValidationError): handle_kinesis_no_envelope(event_dict, LambdaContext()) diff --git a/tests/functional/parser/test_parser.py b/tests/functional/parser/test_parser.py index d2a77f10998..c439134071c 100644 --- a/tests/functional/parser/test_parser.py +++ b/tests/functional/parser/test_parser.py @@ -22,7 +22,8 @@ def handle_no_envelope(event: Dict, _: LambdaContext): @pytest.mark.parametrize( - "invalid_envelope,expected", [(True, ""), (["dummy"], ""), (object, exceptions.InvalidEnvelopeError)] + "invalid_envelope,expected", + [(True, ""), (["dummy"], ""), (object, exceptions.InvalidEnvelopeError)], ) def test_parser_invalid_envelope_type(dummy_event, dummy_schema, invalid_envelope, expected): @event_parser(model=dummy_schema, envelope=invalid_envelope) diff --git a/tests/functional/parser/test_s3.py b/tests/functional/parser/test_s3.py index f6ed3a5422e..4037790efc5 100644 --- a/tests/functional/parser/test_s3.py +++ b/tests/functional/parser/test_s3.py @@ -79,7 +79,7 @@ def handle_s3_glacier(event: S3Model, _: LambdaContext): assert s3.object.sequencer == "0C0F6F405D6ED209E1" assert record.glacierEventData is not None convert_time = int( - round(record.glacierEventData.restoreEventData.lifecycleRestorationExpiryTime.timestamp() * 1000) + round(record.glacierEventData.restoreEventData.lifecycleRestorationExpiryTime.timestamp() * 1000), ) assert convert_time == 60000 assert record.glacierEventData.restoreEventData.lifecycleRestoreStorageClass == "standard" diff --git a/tests/functional/parser/test_sns.py b/tests/functional/parser/test_sns.py index 10674c88ef5..617de487748 100644 --- a/tests/functional/parser/test_sns.py +++ b/tests/functional/parser/test_sns.py @@ -52,8 +52,8 @@ def test_validate_event_does_not_conform_user_json_string_with_model(): "TopicArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda", "Subject": "TestInvoke", }, - } - ] + }, + ], } with pytest.raises(ValidationError): diff --git a/tests/functional/parser/test_sqs.py b/tests/functional/parser/test_sqs.py index cd86c68a4aa..4f547ad4bcc 100644 --- a/tests/functional/parser/test_sqs.py +++ b/tests/functional/parser/test_sqs.py @@ -45,14 +45,14 @@ def test_validate_event_does_not_conform_user_json_string_with_model(): "ApproximateFirstReceiveTimestamp": "1545082649185", }, "messageAttributes": { - "testAttr": {"stringValue": "100", "binaryValue": "base64Str", "dataType": "Number"} + "testAttr": {"stringValue": "100", "binaryValue": "base64Str", "dataType": "Number"}, }, "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", "eventSource": "aws:sqs", "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue", "awsRegion": "us-east-2", - } - ] + }, + ], } with pytest.raises(ValidationError): diff --git a/tests/functional/test_logger.py b/tests/functional/test_logger.py index f732e41e533..feb034b5e46 100644 --- a/tests/functional/test_logger.py +++ b/tests/functional/test_logger.py @@ -145,7 +145,11 @@ def handler(event, context): def test_inject_lambda_context_log_event_request_env_var( - monkeypatch, lambda_context, stdout, lambda_event, service_name + monkeypatch, + lambda_context, + stdout, + lambda_event, + service_name, ): # GIVEN Logger is initialized monkeypatch.setenv("POWERTOOLS_LOGGER_LOG_EVENT", "true") @@ -165,7 +169,11 @@ def handler(event, context): def test_inject_lambda_context_log_no_request_by_default( - monkeypatch, lambda_context, stdout, lambda_event, service_name + monkeypatch, + lambda_context, + stdout, + lambda_event, + service_name, ): # GIVEN Logger is initialized logger = Logger(service=service_name, stream=stdout) @@ -590,7 +598,7 @@ def format(self, record: logging.LogRecord) -> str: # noqa: A003 "timestamp": self.formatTime(record), "my_default_key": "test", **self.custom_format, - } + }, ) custom_formatter = CustomFormatter() @@ -842,7 +850,8 @@ def test_use_datetime(stdout, service_name, utc): expected_tz = datetime.now().astimezone(timezone.utc if utc else None).strftime("%z") assert re.fullmatch( - f"custom timestamp: milliseconds=[0-9]+ microseconds=[0-9]+ timezone={re.escape(expected_tz)}", log["timestamp"] + f"custom timestamp: milliseconds=[0-9]+ microseconds=[0-9]+ timezone={re.escape(expected_tz)}", + log["timestamp"], ) diff --git a/tests/functional/test_logger_utils.py b/tests/functional/test_logger_utils.py index 23796b74e6c..7ca9e1198ac 100644 --- a/tests/functional/test_logger_utils.py +++ b/tests/functional/test_logger_utils.py @@ -130,7 +130,9 @@ def test_copy_config_to_ext_loggers_include_exclude(stdout, logger, log_level): # WHEN configuration copied from Powertools for AWS Lambda (Python) logger to INCLUDED external loggers # AND external logger_1 is also in EXCLUDE list utils.copy_config_to_registered_loggers( - source_logger=powertools_logger, include={logger_1.name, logger_2.name}, exclude={logger_1.name} + source_logger=powertools_logger, + include={logger_1.name, logger_2.name}, + exclude={logger_1.name}, ) msg = "test message3" logger_2.info(msg) @@ -172,7 +174,9 @@ def test_copy_config_to_ext_loggers_custom_log_level(stdout, logger, log_level, # WHEN configuration copied from Powertools for AWS Lambda (Python) logger to INCLUDED external logger # AND external logger used with custom log_level utils.copy_config_to_registered_loggers( - source_logger=powertools_logger, include={logger.name}, log_level=level_to_set + source_logger=powertools_logger, + include={logger.name}, + log_level=level_to_set, ) msg = "test message4" logger.warning(msg) diff --git a/tests/functional/test_metrics.py b/tests/functional/test_metrics.py index 964af99ce6e..d7063f88744 100644 --- a/tests/functional/test_metrics.py +++ b/tests/functional/test_metrics.py @@ -104,7 +104,10 @@ def a_hundred_metric_values() -> List[Dict[str, str]]: def serialize_metrics( - metrics: List[Dict], dimensions: List[Dict], namespace: str, metadatas: List[Dict] = None + metrics: List[Dict], + dimensions: List[Dict], + namespace: str, + metadatas: List[Dict] = None, ) -> Dict: """Helper function to build EMF object from a list of metrics, dimensions""" my_metrics = MetricManager(namespace=namespace) @@ -833,7 +836,11 @@ def lambda_handler(evt, ctx): def test_serialize_high_resolution_metric_set_metric_definition( - metric_with_resolution, dimension, namespace, service, metadata + metric_with_resolution, + dimension, + namespace, + service, + metadata, ): expected_metric_definition = { "single_metric": [1.0], @@ -844,7 +851,7 @@ def test_serialize_high_resolution_metric_set_metric_definition( "Namespace": "test_namespace", "Dimensions": [["test_dimension", "service"]], "Metrics": [{"Name": "single_metric", "Unit": "Count", "StorageResolution": 1}], - } + }, ], }, "service": "test_service", @@ -877,7 +884,7 @@ def test_serialize_metric_set_metric_definition(metric, dimension, namespace, se "Namespace": "test_namespace", "Dimensions": [["test_dimension", "service"]], "Metrics": [{"Name": "single_metric", "Unit": "Count"}], - } + }, ], }, "service": "test_service", @@ -960,7 +967,11 @@ def lambda_handler(evt, ctx): def test_serialize_metric_set_metric_definition_multiple_values( - metrics_same_name, dimension, namespace, service, metadata + metrics_same_name, + dimension, + namespace, + service, + metadata, ): expected_metric_definition = { "metric_one": [1.0, 5.0], @@ -971,7 +982,7 @@ def test_serialize_metric_set_metric_definition_multiple_values( "Namespace": "test_namespace", "Dimensions": [["test_dimension", "service"]], "Metrics": [{"Name": "metric_one", "Unit": "Count"}], - } + }, ], }, "service": "test_service", diff --git a/tests/functional/test_utilities_batch.py b/tests/functional/test_utilities_batch.py index 4ad33b290bd..1831ef973d9 100644 --- a/tests/functional/test_utilities_batch.py +++ b/tests/functional/test_utilities_batch.py @@ -300,7 +300,7 @@ def test_batch_processor_context_with_failure(sqs_event_factory, record_handler) assert processed_messages[1] == ("success", second_record.body, second_record.raw_event) assert len(batch.fail_messages) == 2 assert batch.response() == { - "batchItemFailures": [{"itemIdentifier": first_record.message_id}, {"itemIdentifier": third_record.message_id}] + "batchItemFailures": [{"itemIdentifier": first_record.message_id}, {"itemIdentifier": third_record.message_id}], } @@ -345,7 +345,7 @@ def test_batch_processor_kinesis_context_with_failure(kinesis_event_factory, kin "batchItemFailures": [ {"itemIdentifier": first_record.kinesis.sequence_number}, {"itemIdentifier": third_record.kinesis.sequence_number}, - ] + ], } @@ -408,7 +408,7 @@ def test_batch_processor_dynamodb_context_with_failure(dynamodb_event_factory, d "batchItemFailures": [ {"itemIdentifier": first_record["dynamodb"]["SequenceNumber"]}, {"itemIdentifier": third_record["dynamodb"]["SequenceNumber"]}, - ] + ], } @@ -482,7 +482,7 @@ def record_handler(record: OrderSqs): "batchItemFailures": [ {"itemIdentifier": first_record["messageId"]}, {"itemIdentifier": third_record["messageId"]}, - ] + ], } @@ -574,12 +574,14 @@ def record_handler(record: OrderDynamoDBRecord): "batchItemFailures": [ {"itemIdentifier": first_record["dynamodb"]["SequenceNumber"]}, {"itemIdentifier": third_record["dynamodb"]["SequenceNumber"]}, - ] + ], } def test_batch_processor_kinesis_context_parser_model( - kinesis_record_handler_model: Callable, kinesis_event_factory, order_event_factory + kinesis_record_handler_model: Callable, + kinesis_event_factory, + order_event_factory, ): # GIVEN order_event = order_event_factory({"type": "success"}) @@ -603,7 +605,9 @@ def test_batch_processor_kinesis_context_parser_model( def test_batch_processor_kinesis_context_parser_model_with_failure( - kinesis_record_handler_model: Callable, kinesis_event_factory, order_event_factory + kinesis_record_handler_model: Callable, + kinesis_event_factory, + order_event_factory, ): # GIVEN order_event = order_event_factory({"type": "success"}) @@ -625,7 +629,7 @@ def test_batch_processor_kinesis_context_parser_model_with_failure( "batchItemFailures": [ {"itemIdentifier": first_record["kinesis"]["sequenceNumber"]}, {"itemIdentifier": third_record["kinesis"]["sequenceNumber"]}, - ] + ], } @@ -773,7 +777,7 @@ def test_async_batch_processor_context_with_failure(sqs_event_factory, async_rec assert processed_messages[1] == ("success", second_record.body, second_record.raw_event) assert len(batch.fail_messages) == 2 assert batch.response() == { - "batchItemFailures": [{"itemIdentifier": first_record.message_id}, {"itemIdentifier": third_record.message_id}] + "batchItemFailures": [{"itemIdentifier": first_record.message_id}, {"itemIdentifier": third_record.message_id}], } @@ -842,7 +846,9 @@ def test_async_process_partial_response_invalid_input(async_record_handler: Call def test_batch_processor_model_with_partial_validation_error( - record_handler_model: Callable, sqs_event_factory, order_event_factory + record_handler_model: Callable, + sqs_event_factory, + order_event_factory, ): # GIVEN order_event = order_event_factory({"type": "success"}) @@ -861,12 +867,14 @@ def test_batch_processor_model_with_partial_validation_error( assert batch.response() == { "batchItemFailures": [ {"itemIdentifier": malformed_record["messageId"]}, - ] + ], } def test_batch_processor_dynamodb_context_model_with_partial_validation_error( - dynamodb_record_handler_model: Callable, dynamodb_event_factory, order_event_factory + dynamodb_record_handler_model: Callable, + dynamodb_event_factory, + order_event_factory, ): # GIVEN order_event = order_event_factory({"type": "success"}) @@ -885,12 +893,14 @@ def test_batch_processor_dynamodb_context_model_with_partial_validation_error( assert batch.response() == { "batchItemFailures": [ {"itemIdentifier": malformed_record["dynamodb"]["SequenceNumber"]}, - ] + ], } def test_batch_processor_kinesis_context_parser_model_with_partial_validation_error( - kinesis_record_handler_model: Callable, kinesis_event_factory, order_event_factory + kinesis_record_handler_model: Callable, + kinesis_event_factory, + order_event_factory, ): # GIVEN order_event = order_event_factory({"type": "success"}) @@ -909,12 +919,14 @@ def test_batch_processor_kinesis_context_parser_model_with_partial_validation_er assert batch.response() == { "batchItemFailures": [ {"itemIdentifier": malformed_record["kinesis"]["sequenceNumber"]}, - ] + ], } def test_async_batch_processor_model_with_partial_validation_error( - async_record_handler_model: Callable, sqs_event_factory, order_event_factory + async_record_handler_model: Callable, + sqs_event_factory, + order_event_factory, ): # GIVEN order_event = order_event_factory({"type": "success"}) @@ -933,12 +945,14 @@ def test_async_batch_processor_model_with_partial_validation_error( assert batch.response() == { "batchItemFailures": [ {"itemIdentifier": malformed_record["messageId"]}, - ] + ], } def test_async_batch_processor_dynamodb_context_model_with_partial_validation_error( - async_dynamodb_record_handler: Callable, dynamodb_event_factory, order_event_factory + async_dynamodb_record_handler: Callable, + dynamodb_event_factory, + order_event_factory, ): # GIVEN order_event = order_event_factory({"type": "success"}) @@ -957,12 +971,14 @@ def test_async_batch_processor_dynamodb_context_model_with_partial_validation_er assert batch.response() == { "batchItemFailures": [ {"itemIdentifier": malformed_record["dynamodb"]["SequenceNumber"]}, - ] + ], } def test_async_batch_processor_kinesis_context_parser_model_with_partial_validation_error( - async_kinesis_record_handler_model: Callable, kinesis_event_factory, order_event_factory + async_kinesis_record_handler_model: Callable, + kinesis_event_factory, + order_event_factory, ): # GIVEN order_event = order_event_factory({"type": "success"}) @@ -981,5 +997,5 @@ def test_async_batch_processor_kinesis_context_parser_model_with_partial_validat assert batch.response() == { "batchItemFailures": [ {"itemIdentifier": malformed_record["kinesis"]["sequenceNumber"]}, - ] + ], } diff --git a/tests/functional/test_utilities_parameters.py b/tests/functional/test_utilities_parameters.py index c03a20cdab8..f151c1cd781 100644 --- a/tests/functional/test_utilities_parameters.py +++ b/tests/functional/test_utilities_parameters.py @@ -282,7 +282,7 @@ def test_dynamodb_provider_get_multiple(mock_name, mock_value, config): "Items": [ {"id": {"S": mock_name}, "sk": {"S": name}, "value": {"S": f"{mock_value}/{name}"}} for name in mock_param_names - ] + ], } expected_params = {"TableName": table_name, "KeyConditionExpression": Key("id").eq(mock_name)} stubber.add_response("query", response, expected_params) @@ -319,7 +319,7 @@ def test_dynamodb_provider_get_multiple_auto(mock_name, mock_value, config): response = { "Items": [ {"id": {"S": mock_name}, "sk": {"S": name}, "value": {"S": value}} for (name, value) in mock_params.items() - ] + ], } expected_params = {"TableName": table_name, "KeyConditionExpression": Key("id").eq(mock_name)} stubber.add_response("query", response, expected_params) @@ -373,7 +373,7 @@ def test_dynamodb_provider_get_multiple_next_token(mock_name, mock_value, config "Items": [ {"id": {"S": mock_name}, "sk": {"S": name}, "value": {"S": f"{mock_value}/{name}"}} for name in mock_param_names[1:] - ] + ], } expected_params = { "TableName": table_name, @@ -413,7 +413,7 @@ def test_dynamodb_provider_get_multiple_sdk_options(mock_name, mock_value, confi "Items": [ {"id": {"S": mock_name}, "sk": {"S": name}, "value": {"S": f"{mock_value}/{name}"}} for name in mock_param_names - ] + ], } expected_params = { "TableName": table_name, @@ -453,7 +453,7 @@ def test_dynamodb_provider_get_multiple_sdk_options_overwrite(mock_name, mock_va "Items": [ {"id": {"S": mock_name}, "sk": {"S": name}, "value": {"S": f"{mock_value}/{name}"}} for name in mock_param_names - ] + ], } expected_params = { "TableName": table_name, @@ -495,7 +495,7 @@ def test_ssm_provider_get(mock_name, mock_value, mock_version, config): "SourceResult": "string", "LastModifiedDate": datetime(2015, 1, 1), "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}", - } + }, } expected_params = {"Name": mock_name, "WithDecryption": False} stubber.add_response("get_parameter", response, expected_params) @@ -532,7 +532,7 @@ def test_ssm_provider_get_with_custom_client(mock_name, mock_value, mock_version "SourceResult": "string", "LastModifiedDate": datetime(2015, 1, 1), "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}", - } + }, } expected_params = {"Name": mock_name, "WithDecryption": False} stubber.add_response("get_parameter", response, expected_params) @@ -570,7 +570,7 @@ def test_ssm_provider_get_with_decrypt_environment_variable(monkeypatch, mock_na "SourceResult": "string", "LastModifiedDate": datetime(2015, 1, 1), "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}", - } + }, } expected_params = {"Name": mock_name, "WithDecryption": True} stubber.add_response("get_parameter", response, expected_params) @@ -607,7 +607,7 @@ def test_ssm_provider_get_default_config(monkeypatch, mock_name, mock_value, moc "SourceResult": "string", "LastModifiedDate": datetime(2015, 1, 1), "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}", - } + }, } expected_params = {"Name": mock_name, "WithDecryption": False} stubber.add_response("get_parameter", response, expected_params) @@ -764,7 +764,9 @@ def test_ssm_provider_get_parameters_by_name_do_not_raise_on_failure_with_decryp def test_ssm_provider_get_parameters_by_name_do_not_raise_on_failure_batch_decrypt_combined( - mock_value, mock_version, config + mock_value, + mock_version, + config, ): # GIVEN three parameters are requested # one requires decryption, two can be batched @@ -776,7 +778,8 @@ def test_ssm_provider_get_parameters_by_name_do_not_raise_on_failure_batch_decry expected_stub_params = {"Names": [success, fail]} expected_stub_response = build_get_parameters_stub( - params={fail: mock_value, success: mock_value}, invalid_parameters=[fail] + params={fail: mock_value, success: mock_value}, + invalid_parameters=[fail], ) provider = parameters.SSMProvider(config=config) @@ -905,7 +908,7 @@ def test_ssm_provider_get_expired(mock_name, mock_value, mock_version, config): "SourceResult": "string", "LastModifiedDate": datetime(2015, 1, 1), "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}", - } + }, } expected_params = {"Name": mock_name, "WithDecryption": False} stubber.add_response("get_parameter", response, expected_params) @@ -940,7 +943,7 @@ def test_ssm_provider_get_sdk_options_overwrite(mock_name, mock_value, mock_vers "SourceResult": "string", "LastModifiedDate": datetime(2015, 1, 1), "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}", - } + }, } expected_params = {"Name": mock_name, "WithDecryption": False} stubber.add_response("get_parameter", response, expected_params) @@ -980,7 +983,7 @@ def test_ssm_provider_get_multiple(mock_name, mock_value, mock_version, config): "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}/{name}", } for name in mock_param_names - ] + ], } expected_params = {"Path": mock_name, "Recursive": False, "WithDecryption": False} stubber.add_response("get_parameters_by_path", response, expected_params) @@ -1024,7 +1027,7 @@ def test_ssm_provider_get_multiple_different_path(mock_name, mock_value, mock_ve "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}/{name}", } for name in mock_param_names - ] + ], } expected_params = {"Path": mock_name, "Recursive": False, "WithDecryption": False} stubber.add_response("get_parameters_by_path", response, expected_params) @@ -1090,7 +1093,7 @@ def test_ssm_provider_get_multiple_next_token(mock_name, mock_value, mock_versio "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}/{name}", } for name in mock_param_names[1:] - ] + ], } expected_params = {"Path": mock_name, "Recursive": False, "WithDecryption": False, "NextToken": "next_token"} stubber.add_response("get_parameters_by_path", response, expected_params) @@ -1134,7 +1137,7 @@ def test_ssm_provider_get_multiple_sdk_options(mock_name, mock_value, mock_versi "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}/{name}", } for name in mock_param_names - ] + ], } expected_params = {"Path": mock_name, "Recursive": False, "WithDecryption": False, "MaxResults": 10} stubber.add_response("get_parameters_by_path", response, expected_params) @@ -1178,7 +1181,7 @@ def test_ssm_provider_get_multiple_sdk_options_overwrite(mock_name, mock_value, "ARN": f"arn:aws:ssm:us-east-2:111122223333:parameter/{mock_name}/{name}", } for name in mock_param_names - ] + ], } expected_params = {"Path": mock_name, "Recursive": False, "WithDecryption": False} stubber.add_response("get_parameters_by_path", response, expected_params) @@ -1186,7 +1189,10 @@ def test_ssm_provider_get_multiple_sdk_options_overwrite(mock_name, mock_value, try: values = provider.get_multiple( - mock_name, Path="THIS_SHOULD_BE_OVERWRITTEN", Recursive=False, WithDecryption=True + mock_name, + Path="THIS_SHOULD_BE_OVERWRITTEN", + Recursive=False, + WithDecryption=True, ) stubber.assert_no_pending_responses() @@ -1843,7 +1849,10 @@ def __init__(self, config: Config = config, **kwargs): # as that's right before we call SSM, and when options have been merged # def _get_parameters_by_name(self, parameters: Dict[str, Dict], raise_on_error: bool = True) -> Dict[str, Any]: def _get_parameters_by_name( - self, parameters: Dict[str, Dict], raise_on_error: bool = True, decrypt: bool = False + self, + parameters: Dict[str, Dict], + raise_on_error: bool = True, + decrypt: bool = False, ) -> Tuple[Dict[str, Any], List[str]]: # THEN max_age should use no_cache_param override assert parameters[mock_name]["max_age"] == 0 @@ -1866,7 +1875,10 @@ def __init__(self, config: Config = config, **kwargs): super().__init__(config, **kwargs) def _get_parameters_by_name( - self, parameters: Dict[str, Dict], raise_on_error: bool = True, decrypt: bool = False + self, + parameters: Dict[str, Dict], + raise_on_error: bool = True, + decrypt: bool = False, ) -> Tuple[Dict[str, Any], List[str]]: # THEN we should always split to respect GetParameters max assert len(parameters) == self._MAX_GET_PARAMETERS_ITEM @@ -2096,7 +2108,10 @@ def test_appconf_provider_get_configuration_json_content_type(mock_name, config) try: value = provider.get( - mock_name, transform="json", ApplicationIdentifier=application, EnvironmentIdentifier=environment + mock_name, + transform="json", + ApplicationIdentifier=application, + EnvironmentIdentifier=environment, ) assert value == mock_body_json @@ -2135,7 +2150,10 @@ def test_appconf_provider_get_configuration_json_content_type_with_custom_client try: value = provider.get( - mock_name, transform="json", ApplicationIdentifier=application, EnvironmentIdentifier=environment + mock_name, + transform="json", + ApplicationIdentifier=application, + EnvironmentIdentifier=environment, ) assert value == mock_body_json diff --git a/tests/functional/validator/conftest.py b/tests/functional/validator/conftest.py index b492e7846f1..750f7648d40 100644 --- a/tests/functional/validator/conftest.py +++ b/tests/functional/validator/conftest.py @@ -62,7 +62,7 @@ def schema_array(): "examples": ["lessa"], }, }, - } + }, ], }, } @@ -202,8 +202,8 @@ def sns_event(): "TestBinary": {"Type": "Binary", "Value": "TestBinary"}, }, }, - } - ] + }, + ], } @@ -226,8 +226,8 @@ def kinesis_event(): "eventName": "aws:kinesis:record", "eventSourceARN": "arn:aws:kinesis:EXAMPLE", "awsRegion": "us-east-1", - } - ] + }, + ], } @@ -339,7 +339,7 @@ def sqs_event(): "eventSourceARN": "arn:aws:sqs:us-east-1:123456789012:MyQueue", "awsRegion": "us-east-1", }, - ] + ], } @@ -347,8 +347,8 @@ def sqs_event(): def cloudwatch_logs_event(): return { "awslogs": { - "data": "H4sIACZAXl8C/52PzUrEMBhFX2UILpX8tPbHXWHqIOiq3Q1F0ubrWEiakqTWofTdTYYB0YWL2d5zvnuTFellBIOedoiyKH5M0iwnlKH7HZL6dDB6ngLDfLFYctUKjie9gHFaS/sAX1xNEq525QxwFXRGGMEkx4Th491rUZdV3YiIZ6Ljfd+lfSyAtZloacQgAkqSJCGhxM6t7cwwuUGPz4N0YKyvO6I9WDeMPMSo8Z4Ca/kJ6vMEYW5f1MX7W1lVxaG8vqX8hNFdjlc0iCBBSF4ERT/3Pl7RbMGMXF2KZMh/C+gDpNS7RRsp0OaRGzx0/t8e0jgmcczyLCWEePhni/23JWalzjdu0a3ZvgEaNLXeugEAAA==" # noqa: E501 - } + "data": "H4sIACZAXl8C/52PzUrEMBhFX2UILpX8tPbHXWHqIOiq3Q1F0ubrWEiakqTWofTdTYYB0YWL2d5zvnuTFellBIOedoiyKH5M0iwnlKH7HZL6dDB6ngLDfLFYctUKjie9gHFaS/sAX1xNEq525QxwFXRGGMEkx4Th491rUZdV3YiIZ6Ljfd+lfSyAtZloacQgAkqSJCGhxM6t7cwwuUGPz4N0YKyvO6I9WDeMPMSo8Z4Ca/kJ6vMEYW5f1MX7W1lVxaG8vqX8hNFdjlc0iCBBSF4ERT/3Pl7RbMGMXF2KZMh/C+gDpNS7RRsp0OaRGzx0/t8e0jgmcczyLCWEePhni/23JWalzjdu0a3ZvgEaNLXeugEAAA==", # noqa: E501 + }, } @@ -372,7 +372,7 @@ def cloudwatch_logs_schema(): "message": {"username": "dummy", "message": "hello world"}, "timestamp": 1440442987001, }, - ] + ], ], "additionalItems": True, "items": { @@ -426,7 +426,7 @@ def cloudwatch_logs_schema(): "examples": [1440442987000], }, }, - } + }, ], }, } diff --git a/tests/functional/validator/test_validator.py b/tests/functional/validator/test_validator.py index c3e89c1bcfe..b8e4a977025 100644 --- a/tests/functional/validator/test_validator.py +++ b/tests/functional/validator/test_validator.py @@ -59,7 +59,8 @@ def test_validate_invalid_schema_format(raw_event): def test_validate_accept_schema_custom_format( - eventbridge_schema_registry_cloudtrail_v2_s3, eventbridge_cloudtrail_s3_head_object_event + eventbridge_schema_registry_cloudtrail_v2_s3, + eventbridge_cloudtrail_s3_head_object_event, ): validate( event=eventbridge_cloudtrail_s3_head_object_event, @@ -70,7 +71,9 @@ def test_validate_accept_schema_custom_format( @pytest.mark.parametrize("invalid_format", [None, bool(), {}, [], object]) def test_validate_invalid_custom_format( - eventbridge_schema_registry_cloudtrail_v2_s3, eventbridge_cloudtrail_s3_head_object_event, invalid_format + eventbridge_schema_registry_cloudtrail_v2_s3, + eventbridge_cloudtrail_s3_head_object_event, + invalid_format, ): with pytest.raises(exceptions.InvalidSchemaFormatError): validate( diff --git a/tests/unit/data_classes/test_api_gateway_authorizer.py b/tests/unit/data_classes/test_api_gateway_authorizer.py index f54f8897ab2..fe4706596c0 100644 --- a/tests/unit/data_classes/test_api_gateway_authorizer.py +++ b/tests/unit/data_classes/test_api_gateway_authorizer.py @@ -50,7 +50,7 @@ def test_authorizer_response_allow_all_routes_with_context(): "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": ["arn:aws:execute-api:us-west-1:123456789:fantom/dev/*/*"], - } + }, ], }, "context": {"name": "Foo"}, @@ -70,7 +70,7 @@ def test_authorizer_response_allow_all_routes_with_usage_identifier_key(): "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": ["arn:aws:execute-api:us-east-1:1111111111:api/dev/*/*"], - } + }, ], }, "usageIdentifierKey": "key", @@ -88,7 +88,7 @@ def test_authorizer_response_deny_all_routes(builder: APIGatewayAuthorizerRespon "Action": "execute-api:Invoke", "Effect": "Deny", "Resource": ["arn:aws:execute-api:us-west-1:123456789:fantom/dev/*/*"], - } + }, ], }, } @@ -104,7 +104,7 @@ def test_authorizer_response_allow_route(builder: APIGatewayAuthorizerResponse): "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": ["arn:aws:execute-api:us-west-1:123456789:fantom/dev/GET/foo"], - } + }, ], }, "principalId": "foo", @@ -122,7 +122,7 @@ def test_authorizer_response_deny_route(builder: APIGatewayAuthorizerResponse): "Action": "execute-api:Invoke", "Effect": "Deny", "Resource": ["arn:aws:execute-api:us-west-1:123456789:fantom/dev/PUT/foo"], - } + }, ], }, } @@ -145,7 +145,7 @@ def test_authorizer_response_allow_route_with_conditions(builder: APIGatewayAuth "Effect": "Allow", "Resource": ["arn:aws:execute-api:us-west-1:123456789:fantom/dev/POST/foo"], "Condition": [{"StringEquals": {"method.request.header.Content-Type": "text/html"}}], - } + }, ], }, } @@ -164,7 +164,7 @@ def test_authorizer_response_deny_route_with_conditions(builder: APIGatewayAutho "Effect": "Deny", "Resource": ["arn:aws:execute-api:us-west-1:123456789:fantom/dev/POST/foo"], "Condition": [{"StringEquals": {"method.request.header.Content-Type": "application/json"}}], - } + }, ], }, } @@ -192,7 +192,7 @@ def test_authorizer_response_allow_route_with_underscore(builder: APIGatewayAuth "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": ["arn:aws:execute-api:us-west-1:123456789:fantom/dev/GET/has_underscore"], - } + }, ], }, } diff --git a/tests/unit/data_classes/test_code_pipeline_job_event.py b/tests/unit/data_classes/test_code_pipeline_job_event.py index 68d764e2ba8..3ce681f3ffd 100644 --- a/tests/unit/data_classes/test_code_pipeline_job_event.py +++ b/tests/unit/data_classes/test_code_pipeline_job_event.py @@ -181,6 +181,6 @@ def download_file(bucket: str, key: str, tmp_name: str): "aws_access_key_id": event.data.artifact_credentials.access_key_id, "aws_secret_access_key": event.data.artifact_credentials.secret_access_key, "aws_session_token": event.data.artifact_credentials.session_token, - } + }, ) assert artifact_str == file_contents diff --git a/tests/unit/data_classes/test_s3_event.py b/tests/unit/data_classes/test_s3_event.py index 293a08e462b..eaa4cdce6d0 100644 --- a/tests/unit/data_classes/test_s3_event.py +++ b/tests/unit/data_classes/test_s3_event.py @@ -69,10 +69,10 @@ def test_s3_glacier_event(): "restoreEventData": { "lifecycleRestorationExpiryTime": "1970-01-01T00:01:00.000Z", "lifecycleRestoreStorageClass": "standard", - } - } - } - ] + }, + }, + }, + ], } event = S3Event(example_event) record = next(event.records) diff --git a/tests/unit/parser/test_s3.py b/tests/unit/parser/test_s3.py index 6ae2656ddd2..c77c70095a3 100644 --- a/tests/unit/parser/test_s3.py +++ b/tests/unit/parser/test_s3.py @@ -121,7 +121,7 @@ def test_s3_sqs_event_notification(): assert model.Records[0].body.Records[0].eventVersion == body["Records"][0]["eventVersion"] assert model.Records[0].body.Records[0].eventSource == body["Records"][0]["eventSource"] assert model.Records[0].body.Records[0].eventTime == datetime.fromisoformat( - body["Records"][0]["eventTime"].replace("Z", "+00:00") + body["Records"][0]["eventTime"].replace("Z", "+00:00"), ) assert model.Records[0].body.Records[0].eventName == body["Records"][0]["eventName"] diff --git a/tests/unit/test_tracing.py b/tests/unit/test_tracing.py index a40301a44c2..ae140eb2bee 100644 --- a/tests/unit/test_tracing.py +++ b/tests/unit/test_tracing.py @@ -60,7 +60,8 @@ def reset_tracing_config(mocker): Tracer._reset_config() # reset global cold start module mocker.patch( - "aws_lambda_powertools.tracing.tracer.is_cold_start", new_callable=mocker.PropertyMock(return_value=True) + "aws_lambda_powertools.tracing.tracer.is_cold_start", + new_callable=mocker.PropertyMock(return_value=True), ) yield @@ -107,7 +108,9 @@ def handler(event, context): assert in_subsegment_mock.in_subsegment.call_count == 1 assert in_subsegment_mock.in_subsegment.call_args == mocker.call(name="## handler") assert in_subsegment_mock.put_metadata.call_args == mocker.call( - key="handler response", value=dummy_response, namespace="booking" + key="handler response", + value=dummy_response, + namespace="booking", ) @@ -128,7 +131,7 @@ def greeting(name, message): # and use service name as a metadata namespace assert in_subsegment_mock.in_subsegment.call_count == 1 assert in_subsegment_mock.in_subsegment.call_args == mocker.call( - name=f"## {MODULE_PREFIX}.test_tracer_method..greeting" + name=f"## {MODULE_PREFIX}.test_tracer_method..greeting", ) assert in_subsegment_mock.put_metadata.call_args == mocker.call( key=f"{MODULE_PREFIX}.test_tracer_method..greeting response", @@ -153,7 +156,9 @@ def test_tracer_custom_metadata(monkeypatch, mocker, dummy_response, provider_st # THEN we should have metadata expected and booking as namespace assert put_metadata_mock.call_count == 1 assert put_metadata_mock.call_args_list[0] == mocker.call( - key=annotation_key, value=annotation_value, namespace="booking" + key=annotation_key, + value=annotation_value, + namespace="booking", ) @@ -315,10 +320,10 @@ async def greeting(name, message): # THEN we should add metadata for each response like we would for a sync decorated method assert in_subsegment_mock.in_subsegment.call_count == 2 assert in_subsegment_greeting_call_args == mocker.call( - name=f"## {MODULE_PREFIX}.test_tracer_method_nested_async..greeting" + name=f"## {MODULE_PREFIX}.test_tracer_method_nested_async..greeting", ) assert in_subsegment_greeting2_call_args == mocker.call( - name=f"## {MODULE_PREFIX}.test_tracer_method_nested_async..greeting_2" + name=f"## {MODULE_PREFIX}.test_tracer_method_nested_async..greeting_2", ) assert in_subsegment_mock.put_metadata.call_count == 2 @@ -408,7 +413,7 @@ def handler(event, context): assert in_subsegment_mock.in_subsegment.call_count == 2 assert handler_trace == mocker.call(name="## handler") assert yield_function_trace == mocker.call( - name=f"## {MODULE_PREFIX}.test_tracer_yield_from_context_manager..yield_with_capture" + name=f"## {MODULE_PREFIX}.test_tracer_yield_from_context_manager..yield_with_capture", ) assert "test result" in result @@ -479,7 +484,7 @@ def handler(event, context): assert in_subsegment_mock.in_subsegment.call_count == 2 assert handler_trace == mocker.call(name="## handler") assert yield_function_trace == mocker.call( - name=f"## {MODULE_PREFIX}.test_tracer_yield_from_nested_context_manager..yield_with_capture" + name=f"## {MODULE_PREFIX}.test_tracer_yield_from_nested_context_manager..yield_with_capture", ) assert "test result" in result @@ -511,7 +516,7 @@ def handler(event, context): assert in_subsegment_mock.in_subsegment.call_count == 2 assert handler_trace == mocker.call(name="## handler") assert generator_fn_trace == mocker.call( - name=f"## {MODULE_PREFIX}.test_tracer_yield_from_generator..generator_fn" + name=f"## {MODULE_PREFIX}.test_tracer_yield_from_generator..generator_fn", ) assert "test result" in result @@ -647,7 +652,10 @@ def handler(event, context): def test_tracer_lambda_handler_do_not_add_service_annotation_when_missing( - mocker, dummy_response, provider_stub, in_subsegment_mock + mocker, + dummy_response, + provider_stub, + in_subsegment_mock, ): # GIVEN provider = provider_stub(in_subsegment=in_subsegment_mock.in_subsegment)