Module aws_lambda_powertools.event_handler.openapi.encoders

Functions

def decimal_encoder(dec_value: Decimal) ‑> int | float
Expand source code
def decimal_encoder(dec_value: Decimal) -> int | float:
    """
    Encodes a Decimal as int of there's no exponent, otherwise float

    This is useful when we use ConstrainedDecimal to represent Numeric(x,0)
    where an integer (but not int typed) is used. Encoding this as a float
    results in failed round-tripping between encode and parse.

    >>> decimal_encoder(Decimal("1.0"))
    1.0

    >>> decimal_encoder(Decimal("1"))
    1
    """
    if dec_value.as_tuple().exponent >= 0:  # type: ignore[operator]
        return int(dec_value)
    else:
        return float(dec_value)

Encodes a Decimal as int of there's no exponent, otherwise float

This is useful when we use ConstrainedDecimal to represent Numeric(x,0) where an integer (but not int typed) is used. Encoding this as a float results in failed round-tripping between encode and parse.

>>> decimal_encoder(Decimal("1.0"))
1.0
>>> decimal_encoder(Decimal("1"))
1
def generate_encoders_by_class_tuples(type_encoder_map: dict[Any, Callable[[Any], Any]]) ‑> dict[typing.Callable[[typing.Any], typing.Any], tuple[typing.Any, ...]]
Expand source code
def generate_encoders_by_class_tuples(
    type_encoder_map: dict[Any, Callable[[Any], Any]],
) -> dict[Callable[[Any], Any], tuple[Any, ...]]:
    encoders: dict[Callable[[Any], Any], tuple[Any, ...]] = defaultdict(tuple)
    for type_, encoder in type_encoder_map.items():
        encoders[encoder] += (type_,)
    return encoders
def iso_format(o: datetime.date | datetime.time) ‑> str
Expand source code
def iso_format(o: datetime.date | datetime.time) -> str:
    """
    ISO format for date and time
    """
    return o.isoformat()

ISO format for date and time

def jsonable_encoder(obj: Any,
include: IncEx | None = None,
exclude: IncEx | None = None,
by_alias: bool = True,
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
custom_serializer: Callable[[Any], str] | None = None) ‑> Any
Expand source code
def jsonable_encoder(  # noqa: PLR0911
    obj: Any,
    include: IncEx | None = None,
    exclude: IncEx | None = None,
    by_alias: bool = True,
    exclude_unset: bool = False,
    exclude_defaults: bool = False,
    exclude_none: bool = False,
    custom_serializer: Callable[[Any], str] | None = None,
) -> Any:
    """
    JSON encodes an arbitrary Python object into JSON serializable data types.

    This is a modified version of fastapi.encoders.jsonable_encoder that supports
    encoding of pydantic.BaseModel objects.

    Parameters
    ----------
    obj : Any
        The object to encode
    include : IncEx | None, optional
        A set or dictionary of strings that specifies which properties should be included, by default None,
        meaning everything is included
    exclude : IncEx | None, optional
        A set or dictionary of strings that specifies which properties should be excluded, by default None,
        meaning nothing is excluded
    by_alias : bool, optional
        Whether field aliases should be respected, by default True
    exclude_unset : bool, optional
        Whether fields that are not set should be excluded, by default False
    exclude_defaults : bool, optional
        Whether fields that are equal to their default value (as specified in the model) should be excluded,
        by default False
    exclude_none : bool, optional
        Whether fields that are equal to None should be excluded, by default False
    custom_serializer : Callable, optional
        A custom serializer to use for encoding the object, when everything else fails.

    Returns
    -------
    Any
        The JSON serializable data types
    """
    if include is not None and not isinstance(include, (set, dict)):
        include = set(include)
    if exclude is not None and not isinstance(exclude, (set, dict)):
        exclude = set(exclude)

    try:
        # Pydantic models
        if isinstance(obj, BaseModel):
            return _dump_base_model(
                obj=obj,
                include=include,
                exclude=exclude,
                by_alias=by_alias,
                exclude_unset=exclude_unset,
                exclude_none=exclude_none,
                exclude_defaults=exclude_defaults,
            )

        # Dataclasses
        if dataclasses.is_dataclass(obj):
            obj_dict = dataclasses.asdict(obj)  # type: ignore[arg-type]
            return jsonable_encoder(
                obj_dict,
                include=include,
                exclude=exclude,
                by_alias=by_alias,
                exclude_unset=exclude_unset,
                exclude_defaults=exclude_defaults,
                exclude_none=exclude_none,
                custom_serializer=custom_serializer,
            )

        # Enums
        if isinstance(obj, Enum):
            return obj.value

        # Paths
        if isinstance(obj, PurePath):
            return str(obj)

        # Scalars
        if isinstance(obj, (str, int, float, type(None))):
            return obj

        # Dictionaries
        if isinstance(obj, dict):
            return _dump_dict(
                obj=obj,
                include=include,
                exclude=exclude,
                by_alias=by_alias,
                exclude_unset=exclude_unset,
                exclude_none=exclude_none,
                custom_serializer=custom_serializer,
            )

        # Sequences
        if isinstance(obj, (list, set, frozenset, GeneratorType, tuple, deque)):
            return _dump_sequence(
                obj=obj,
                include=include,
                exclude=exclude,
                by_alias=by_alias,
                exclude_none=exclude_none,
                exclude_defaults=exclude_defaults,
                exclude_unset=exclude_unset,
                custom_serializer=custom_serializer,
            )

        # Other types
        if type(obj) in ENCODERS_BY_TYPE:
            return ENCODERS_BY_TYPE[type(obj)](obj)

        for encoder, classes_tuple in encoders_by_class_tuples.items():
            if isinstance(obj, classes_tuple):
                return encoder(obj)

        # Use custom serializer if present
        if custom_serializer:
            return custom_serializer(obj)

        # Default
        return _dump_other(
            obj=obj,
            include=include,
            exclude=exclude,
            by_alias=by_alias,
            exclude_none=exclude_none,
            exclude_unset=exclude_unset,
            exclude_defaults=exclude_defaults,
            custom_serializer=custom_serializer,
        )
    except ValueError as exc:
        raise SerializationError(
            f"Unable to serialize the object {obj} as it is not a supported type. Error details: {exc}",
            "See: https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/#serializing-objects",
        ) from exc

JSON encodes an arbitrary Python object into JSON serializable data types.

This is a modified version of fastapi.encoders.jsonable_encoder that supports encoding of pydantic.BaseModel objects.

Parameters

obj : Any
The object to encode
include : IncEx | None, optional
A set or dictionary of strings that specifies which properties should be included, by default None, meaning everything is included
exclude : IncEx | None, optional
A set or dictionary of strings that specifies which properties should be excluded, by default None, meaning nothing is excluded
by_alias : bool, optional
Whether field aliases should be respected, by default True
exclude_unset : bool, optional
Whether fields that are not set should be excluded, by default False
exclude_defaults : bool, optional
Whether fields that are equal to their default value (as specified in the model) should be excluded, by default False
exclude_none : bool, optional
Whether fields that are equal to None should be excluded, by default False
custom_serializer : Callable, optional
A custom serializer to use for encoding the object, when everything else fails.

Returns

Any
The JSON serializable data types