Skip to content

Commit f42ffc8

Browse files
author
Michael Brewer
authored
Merge branch 'awslabs:develop' into fix-logger-util-tests
2 parents 62922ef + 0c35e5a commit f42ffc8

File tree

34 files changed

+177
-95
lines changed

34 files changed

+177
-95
lines changed

.github/workflows/python_build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ jobs:
3030
run: make dev
3131
- name: Formatting and Linting
3232
run: make lint
33+
- name: Static type checking
34+
run: make mypy
3335
- name: Test with pytest
3436
run: make test
3537
- name: Security baseline

CONTRIBUTING.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,14 @@ You might find useful to run both the documentation website and the API referenc
4949

5050
Category | Convention
5151
------------------------------------------------- | ---------------------------------------------------------------------------------
52-
**Docstring** | We use a slight variation of numpy convention with markdown to help generate more readable API references.
53-
**Style guide** | We use black as well as flake8 extensions to enforce beyond good practices [PEP8](https://pep8.org/). We strive to make use of type annotation as much as possible, but don't overdo in creating custom types.
52+
**Docstring** | We use a slight variation of Numpy convention with markdown to help generate more readable API references.
53+
**Style guide** | We use black as well as flake8 extensions to enforce beyond good practices [PEP8](https://pep8.org/). We use type annotations and enforce static type checking at CI (mypy).
5454
**Core utilities** | Core utilities use a Class, always accept `service` as a constructor parameter, can work in isolation, and are also available in other languages implementation.
5555
**Utilities** | Utilities are not as strict as core and focus on solving a developer experience problem while following the project [Tenets](https://awslabs.github.io/aws-lambda-powertools-python/#tenets).
5656
**Exceptions** | Specific exceptions live within utilities themselves and use `Error` suffix e.g. `MetricUnitError`.
57-
**Git commits** | We follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/). These are not enforced as we squash and merge PRs, but PR titles are enforced during CI.
58-
**Documentation** | API reference docs are generated from docstrings which should have Examples section to allow developers to have what they need within their own IDE. Documentation website covers the wider usage, tips, and strive to be concise.
57+
**Git commits** | We follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/). We do not enforce conventional commits on contributors to lower the entry bar. Instead, we enforce a conventional PR title so our label automation and changelog are generated correctly.
58+
**API documentation** | API reference docs are generated from docstrings which should have Examples section to allow developers to have what they need within their own IDE. Documentation website covers the wider usage, tips, and strive to be concise.
59+
**Documentation** | We treat it like a product. We sub-divide content aimed at getting started (80% of customers) vs advanced usage (20%). We also ensure customers know how to unit test their code when using our features.
5960

6061
## Finding contributions to work on
6162

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ coverage-html:
2929
pre-commit:
3030
pre-commit run --show-diff-on-failure
3131

32-
pr: lint pre-commit test security-baseline complexity-baseline
32+
pr: lint mypy pre-commit test security-baseline complexity-baseline
3333

3434
build: pr
3535
poetry build

aws_lambda_powertools/event_handler/api_gateway.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from enum import Enum
1111
from functools import partial
1212
from http import HTTPStatus
13-
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union
13+
from typing import Any, Callable, Dict, List, Match, Optional, Pattern, Set, Tuple, Type, Union
1414

1515
from aws_lambda_powertools.event_handler import content_types
1616
from aws_lambda_powertools.event_handler.exceptions import NotFoundError, ServiceError
@@ -167,7 +167,7 @@ class Route:
167167
"""Internally used Route Configuration"""
168168

169169
def __init__(
170-
self, method: str, rule: Any, func: Callable, cors: bool, compress: bool, cache_control: Optional[str]
170+
self, method: str, rule: Pattern, func: Callable, cors: bool, compress: bool, cache_control: Optional[str]
171171
):
172172
self.method = method.upper()
173173
self.rule = rule
@@ -446,10 +446,6 @@ def __init__(
446446
# Allow for a custom serializer or a concise json serialization
447447
self._serializer = serializer or partial(json.dumps, separators=(",", ":"), cls=Encoder)
448448

449-
if self._debug:
450-
# Always does a pretty print when in debug mode
451-
self._serializer = partial(json.dumps, indent=4, cls=Encoder)
452-
453449
def route(
454450
self,
455451
rule: str,
@@ -496,7 +492,7 @@ def resolve(self, event, context) -> Dict[str, Any]:
496492
Returns the dict response
497493
"""
498494
if self._debug:
499-
print(self._json_dump(event))
495+
print(self._json_dump(event), end="")
500496
BaseRouter.current_event = self._to_proxy_event(event)
501497
BaseRouter.lambda_context = context
502498
return self._resolve().build(self.current_event, self._cors)
@@ -555,7 +551,7 @@ def _resolve(self) -> ResponseBuilder:
555551
for route in self._routes:
556552
if method != route.method:
557553
continue
558-
match_results: Optional[re.Match] = route.rule.match(path)
554+
match_results: Optional[Match] = route.rule.match(path)
559555
if match_results:
560556
logger.debug("Found a registered route. Calling function")
561557
return self._call_route(route, match_results.groupdict()) # pass fn args

aws_lambda_powertools/logging/logger.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ def decorate(event, context, **kwargs):
349349

350350
if log_event:
351351
logger.debug("Event received")
352-
self.info(event)
352+
self.info(getattr(event, "raw_event", event))
353353

354354
return lambda_handler(event, context)
355355

aws_lambda_powertools/metrics/metrics.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def lambda_handler():
5353
----------
5454
service : str, optional
5555
service name to be used as metric dimension, by default "service_undefined"
56-
namespace : str
56+
namespace : str, optional
5757
Namespace for metrics
5858
5959
Raises
@@ -209,5 +209,6 @@ def __add_cold_start_metric(self, context: Any) -> None:
209209
logger.debug("Adding cold start metric and function_name dimension")
210210
with single_metric(name="ColdStart", unit=MetricUnit.Count, value=1, namespace=self.namespace) as metric:
211211
metric.add_dimension(name="function_name", value=context.function_name)
212-
metric.add_dimension(name="service", value=self.service)
212+
if self.service:
213+
metric.add_dimension(name="service", value=str(self.service))
213214
is_cold_start = False

aws_lambda_powertools/shared/functions.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Optional, Union
1+
from typing import Optional, Union
22

33

44
def strtobool(value: str) -> bool:
@@ -38,21 +38,23 @@ def resolve_truthy_env_var_choice(env: str, choice: Optional[bool] = None) -> bo
3838
return choice if choice is not None else strtobool(env)
3939

4040

41-
def resolve_env_var_choice(env: Any, choice: Optional[Any] = None) -> Union[bool, Any]:
41+
def resolve_env_var_choice(
42+
env: Optional[str] = None, choice: Optional[Union[str, float]] = None
43+
) -> Optional[Union[str, float]]:
4244
"""Pick explicit choice over env, if available, otherwise return env value received
4345
4446
NOTE: Environment variable should be resolved by the caller.
4547
4648
Parameters
4749
----------
48-
env : Any
50+
env : str, Optional
4951
environment variable actual value
50-
choice : bool
52+
choice : str|float, optional
5153
explicit choice
5254
5355
Returns
5456
-------
55-
choice : str
57+
choice : str, Optional
5658
resolved choice as either bool or environment value
5759
"""
5860
return choice if choice is not None else env

aws_lambda_powertools/utilities/batch/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from types import TracebackType
66
from typing import List, Optional, Tuple, Type
77

8-
ExceptionInfo = Tuple[Type[BaseException], BaseException, TracebackType]
8+
ExceptionInfo = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]]
99

1010

1111
class BaseBatchProcessingError(Exception):

aws_lambda_powertools/utilities/batch/sqs.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
"""
66
import logging
77
import sys
8-
from typing import Callable, Dict, List, Optional, Tuple
8+
from typing import Callable, Dict, List, Optional, Tuple, cast
99

1010
import boto3
1111
from botocore.config import Config
1212

13+
from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord
14+
1315
from ...middleware_factory import lambda_handler_decorator
1416
from .base import BasePartialProcessor
1517
from .exceptions import SQSBatchProcessingError
@@ -84,11 +86,17 @@ def _get_queue_url(self) -> Optional[str]:
8486
*_, account_id, queue_name = self.records[0]["eventSourceARN"].split(":")
8587
return f"{self.client._endpoint.host}/{account_id}/{queue_name}"
8688

87-
def _get_entries_to_clean(self) -> List:
89+
def _get_entries_to_clean(self) -> List[Dict[str, str]]:
8890
"""
8991
Format messages to use in batch deletion
9092
"""
91-
return [{"Id": msg["messageId"], "ReceiptHandle": msg["receiptHandle"]} for msg in self.success_messages]
93+
entries = []
94+
# success_messages has generic type of union of SQS, Dynamodb and Kinesis Streams records or Pydantic models.
95+
# Here we get SQS Record only
96+
messages = cast(List[SQSRecord], self.success_messages)
97+
for msg in messages:
98+
entries.append({"Id": msg["messageId"], "ReceiptHandle": msg["receiptHandle"]})
99+
return entries
92100

93101
def _process_record(self, record) -> Tuple:
94102
"""

aws_lambda_powertools/utilities/idempotency/idempotency.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def process_order(customer_id: str, order: dict, **kwargs):
112112
return {"StatusCode": 200}
113113
"""
114114

115-
if function is None:
115+
if not function:
116116
return cast(
117117
AnyCallableT,
118118
functools.partial(
@@ -132,7 +132,7 @@ def decorate(*args, **kwargs):
132132

133133
payload = kwargs.get(data_keyword_argument)
134134

135-
if payload is None:
135+
if not payload:
136136
raise RuntimeError(
137137
f"Unable to extract '{data_keyword_argument}' from keyword arguments."
138138
f" Ensure this exists in your function's signature as well as the caller used it as a keyword argument"

0 commit comments

Comments
 (0)