Skip to content

Commit 88fe6ba

Browse files
FollowTheProcessleandrodamascenaheitorlessa
authored andcommitted
fix(logger): add explicit None return type annotations (#3113)
Co-authored-by: Leandro Damascena <[email protected]> Co-authored-by: Heitor Lessa <[email protected]>
1 parent f17023c commit 88fe6ba

File tree

3 files changed

+46
-35
lines changed

3 files changed

+46
-35
lines changed

aws_lambda_powertools/logging/filters.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33

44
class SuppressFilter(logging.Filter):
5-
def __init__(self, logger):
5+
def __init__(self, logger: str):
66
self.logger = logger
77

8-
def filter(self, record): # noqa: A003
8+
def filter(self, record: logging.LogRecord) -> bool: # noqa: A003
99
"""Suppress Log Records from registered logger
1010
1111
It rejects log records from registered logger e.g. a child logger

aws_lambda_powertools/logging/formatter.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@
4444

4545
class BasePowertoolsFormatter(logging.Formatter, metaclass=ABCMeta):
4646
@abstractmethod
47-
def append_keys(self, **additional_keys):
47+
def append_keys(self, **additional_keys) -> None:
4848
raise NotImplementedError()
4949

50-
def remove_keys(self, keys: Iterable[str]):
50+
def remove_keys(self, keys: Iterable[str]) -> None:
5151
raise NotImplementedError()
5252

5353
@abstractmethod
54-
def clear_state(self):
54+
def clear_state(self) -> None:
5555
"""Removes any previously added logging keys"""
5656
raise NotImplementedError()
5757

@@ -78,7 +78,7 @@ def __init__(
7878
utc: bool = False,
7979
use_rfc3339: bool = False,
8080
**kwargs,
81-
):
81+
) -> None:
8282
"""Return a LambdaPowertoolsFormatter instance.
8383
8484
The `log_record_order` kwarg is used to specify the order of the keys used in
@@ -217,26 +217,26 @@ def formatTime(self, record: logging.LogRecord, datefmt: Optional[str] = None) -
217217
custom_fmt = self.default_time_format.replace(self.custom_ms_time_directive, msecs)
218218
return time.strftime(custom_fmt, record_ts)
219219

220-
def append_keys(self, **additional_keys):
220+
def append_keys(self, **additional_keys) -> None:
221221
self.log_format.update(additional_keys)
222222

223-
def remove_keys(self, keys: Iterable[str]):
223+
def remove_keys(self, keys: Iterable[str]) -> None:
224224
for key in keys:
225225
self.log_format.pop(key, None)
226226

227-
def clear_state(self):
227+
def clear_state(self) -> None:
228228
self.log_format = dict.fromkeys(self.log_record_order)
229229
self.log_format.update(**self.keys_combined)
230230

231231
@staticmethod
232-
def _build_default_keys():
232+
def _build_default_keys() -> Dict[str, str]:
233233
return {
234234
"level": "%(levelname)s",
235235
"location": "%(funcName)s:%(lineno)d",
236236
"timestamp": "%(asctime)s",
237237
}
238238

239-
def _get_latest_trace_id(self):
239+
def _get_latest_trace_id(self) -> Optional[str]:
240240
xray_trace_id_key = self.log_format.get("xray_trace_id", "")
241241
if xray_trace_id_key is None:
242242
# key is explicitly disabled; ignore it. e.g., Logger(xray_trace_id=None)

aws_lambda_powertools/logging/logger.py

+35-24
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ def __init__(
221221
utc: bool = False,
222222
use_rfc3339: bool = False,
223223
**kwargs,
224-
):
224+
) -> None:
225225
self.service = resolve_env_var_choice(
226226
choice=service,
227227
env=os.getenv(constants.SERVICE_NAME_ENV, "service_undefined"),
@@ -270,15 +270,20 @@ def __getattr__(self, name):
270270
# https://github.com/aws-powertools/powertools-lambda-python/issues/97
271271
return getattr(self._logger, name)
272272

273-
def _get_logger(self):
273+
def _get_logger(self) -> logging.Logger:
274274
"""Returns a Logger named {self.service}, or {self.service.filename} for child loggers"""
275275
logger_name = self.service
276276
if self.child:
277277
logger_name = f"{self.service}.{_get_caller_filename()}"
278278

279279
return logging.getLogger(logger_name)
280280

281-
def _init_logger(self, formatter_options: Optional[Dict] = None, log_level: Union[str, int, None] = None, **kwargs):
281+
def _init_logger(
282+
self,
283+
formatter_options: Optional[Dict] = None,
284+
log_level: Union[str, int, None] = None,
285+
**kwargs,
286+
) -> None:
282287
"""Configures new logger"""
283288

284289
# Skip configuration if it's a child logger or a pre-configured logger
@@ -296,7 +301,7 @@ def _init_logger(self, formatter_options: Optional[Dict] = None, log_level: Unio
296301
self.structure_logs(formatter_options=formatter_options, **kwargs)
297302

298303
# Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work
299-
self._logger.findCaller = compat.findCaller
304+
self._logger.findCaller = compat.findCaller # type: ignore[method-assign]
300305

301306
# Pytest Live Log feature duplicates log records for colored output
302307
# but we explicitly add a filter for log deduplication.
@@ -313,9 +318,9 @@ def _init_logger(self, formatter_options: Optional[Dict] = None, log_level: Unio
313318
# therefore we set a custom attribute in the Logger that will be returned
314319
# std logging will return the same Logger with our attribute if name is reused
315320
logger.debug(f"Marking logger {self.service} as preconfigured")
316-
self._logger.init = True
321+
self._logger.init = True # type: ignore[attr-defined]
317322

318-
def _configure_sampling(self):
323+
def _configure_sampling(self) -> None:
319324
"""Dynamically set log level based on sampling rate
320325
321326
Raises
@@ -329,8 +334,10 @@ def _configure_sampling(self):
329334
self._logger.setLevel(logging.DEBUG)
330335
except ValueError:
331336
raise InvalidLoggerSamplingRateError(
332-
f"Expected a float value ranging 0 to 1, but received {self.sampling_rate} instead."
333-
f"Please review POWERTOOLS_LOGGER_SAMPLE_RATE environment variable.",
337+
(
338+
f"Expected a float value ranging 0 to 1, but received {self.sampling_rate} instead."
339+
"Please review POWERTOOLS_LOGGER_SAMPLE_RATE environment variable."
340+
),
334341
)
335342

336343
@overload
@@ -452,7 +459,7 @@ def info(
452459
stacklevel: int = 2,
453460
extra: Optional[Mapping[str, object]] = None,
454461
**kwargs,
455-
):
462+
) -> None:
456463
extra = extra or {}
457464
extra = {**extra, **kwargs}
458465

@@ -477,7 +484,7 @@ def error(
477484
stacklevel: int = 2,
478485
extra: Optional[Mapping[str, object]] = None,
479486
**kwargs,
480-
):
487+
) -> None:
481488
extra = extra or {}
482489
extra = {**extra, **kwargs}
483490

@@ -502,7 +509,7 @@ def exception(
502509
stacklevel: int = 2,
503510
extra: Optional[Mapping[str, object]] = None,
504511
**kwargs,
505-
):
512+
) -> None:
506513
extra = extra or {}
507514
extra = {**extra, **kwargs}
508515

@@ -527,7 +534,7 @@ def critical(
527534
stacklevel: int = 2,
528535
extra: Optional[Mapping[str, object]] = None,
529536
**kwargs,
530-
):
537+
) -> None:
531538
extra = extra or {}
532539
extra = {**extra, **kwargs}
533540

@@ -552,7 +559,7 @@ def warning(
552559
stacklevel: int = 2,
553560
extra: Optional[Mapping[str, object]] = None,
554561
**kwargs,
555-
):
562+
) -> None:
556563
extra = extra or {}
557564
extra = {**extra, **kwargs}
558565

@@ -577,7 +584,7 @@ def debug(
577584
stacklevel: int = 2,
578585
extra: Optional[Mapping[str, object]] = None,
579586
**kwargs,
580-
):
587+
) -> None:
581588
extra = extra or {}
582589
extra = {**extra, **kwargs}
583590

@@ -593,13 +600,13 @@ def debug(
593600
extra=extra,
594601
)
595602

596-
def append_keys(self, **additional_keys):
603+
def append_keys(self, **additional_keys) -> None:
597604
self.registered_formatter.append_keys(**additional_keys)
598605

599-
def remove_keys(self, keys: Iterable[str]):
606+
def remove_keys(self, keys: Iterable[str]) -> None:
600607
self.registered_formatter.remove_keys(keys)
601608

602-
def structure_logs(self, append: bool = False, formatter_options: Optional[Dict] = None, **keys):
609+
def structure_logs(self, append: bool = False, formatter_options: Optional[Dict] = None, **keys) -> None:
603610
"""Sets logging formatting to JSON.
604611
605612
Optionally, it can append keyword arguments
@@ -645,7 +652,7 @@ def structure_logs(self, append: bool = False, formatter_options: Optional[Dict]
645652
self.registered_formatter.clear_state()
646653
self.registered_formatter.append_keys(**log_keys)
647654

648-
def set_correlation_id(self, value: Optional[str]):
655+
def set_correlation_id(self, value: Optional[str]) -> None:
649656
"""Sets the correlation_id in the logging json
650657
651658
Parameters
@@ -676,7 +683,9 @@ def addHandler(self, handler: logging.Handler) -> None:
676683
@property
677684
def registered_handler(self) -> logging.Handler:
678685
"""Convenience property to access the first logger handler"""
679-
handlers = self._logger.parent.handlers if self.child else self._logger.handlers
686+
# We ignore mypy here because self.child encodes whether or not self._logger.parent is
687+
# None, mypy can't see this from context but we can
688+
handlers = self._logger.parent.handlers if self.child else self._logger.handlers # type: ignore[union-attr]
680689
return handlers[0]
681690

682691
@property
@@ -720,7 +729,7 @@ def set_package_logger(
720729
level: Union[str, int] = logging.DEBUG,
721730
stream: Optional[IO[str]] = None,
722731
formatter: Optional[logging.Formatter] = None,
723-
):
732+
) -> None:
724733
"""Set an additional stream handler, formatter, and log level for aws_lambda_powertools package logger.
725734
726735
**Package log by default is suppressed (NullHandler), this should only used for debugging.
@@ -755,16 +764,18 @@ def set_package_logger(
755764
logger.addHandler(handler)
756765

757766

758-
def log_uncaught_exception_hook(exc_type, exc_value, exc_traceback, logger: Logger):
767+
def log_uncaught_exception_hook(exc_type, exc_value, exc_traceback, logger: Logger) -> None:
759768
"""Callback function for sys.excepthook to use Logger to log uncaught exceptions"""
760769
logger.exception(exc_value, exc_info=(exc_type, exc_value, exc_traceback)) # pragma: no cover
761770

762771

763-
def _get_caller_filename():
772+
def _get_caller_filename() -> str:
764773
"""Return caller filename by finding the caller frame"""
765774
# Current frame => _get_logger()
766775
# Previous frame => logger.py
767776
# Before previous frame => Caller
777+
# We ignore mypy here because *we* know that there will always be at least
778+
# 3 frames (above) so repeatedly calling f_back is safe here
768779
frame = inspect.currentframe()
769-
caller_frame = frame.f_back.f_back.f_back
770-
return caller_frame.f_globals["__name__"]
780+
caller_frame = frame.f_back.f_back.f_back # type: ignore[union-attr]
781+
return caller_frame.f_globals["__name__"] # type: ignore[union-attr]

0 commit comments

Comments
 (0)