lodum.field API documentation

# lodum.field

View Source

      1# SPDX-FileCopyrightText: 2025-present Michael R. Bernstein <zopemaven@gmail.com>
      2#
      3# SPDX-License-Identifier: Apache-2.0
      4import threading
      5from typing import Any, Callable, Dict, List, Optional, Type, Union
      6
      7
      8# Global registry for lodum-enabled classes to support ForwardRef resolution
      9_NAME_TO_TYPE_CACHE: Dict[str, Type[Any]] = {}
     10_REGISTRY_LOCK = threading.RLock()
     11
     12
     13def register_type(cls: Type[Any]) -> None:
     14    """Registers a class in the global name-to-type cache."""
     15    with _REGISTRY_LOCK:
     16        _NAME_TO_TYPE_CACHE[cls.__name__] = cls
     17
     18
     19# A sentinel object to detect if a parameter is supplied or not.
     20class _MISSING_TYPE:
     21    pass
     22
     23
     24_MISSING = _MISSING_TYPE()
     25
     26
     27class Field:
     28    """
     29    A class that stores metadata for a field in a lodum-enabled class.
     30
     31    This is not intended to be instantiated directly. Instead, use the `field()`
     32    function, which provides a more convenient API.
     33    """
     34
     35    def __init__(
     36        self,
     37        rename: Optional[str] = None,
     38        skip_serializing: bool = False,
     39        default: Any = _MISSING,
     40        default_factory: Optional[Callable[[], Any]] = None,
     41        serializer: Optional[Callable[[Any], Any]] = None,
     42        deserializer: Optional[Callable[[Any], Any]] = None,
     43        validate: Optional[
     44            Union[Callable[[Any], None], List[Callable[[Any], None]]]
     45        ] = None,
     46    ) -> None:
     47        if default is not _MISSING and default_factory is not None:
     48            raise ValueError("cannot specify both default and default_factory")
     49
     50        self.rename = rename
     51        self.skip_serializing = skip_serializing
     52        self.default = default
     53        self.default_factory = default_factory
     54        self.serializer = serializer
     55        self.deserializer = deserializer
     56        self.validate = validate
     57        self.name: str = ""  # Will be populated by the decorator
     58        self.type: Any = None  # Will be populated by the decorator
     59
     60    @property
     61    def has_default(self) -> bool:
     62        return self.default is not _MISSING or self.default_factory is not None
     63
     64    def get_default(self) -> Any:
     65        if self.default_factory is not None:
     66            return self.default_factory()
     67        return self.default
     68
     69    def __repr__(self) -> str:
     70        parts = []
     71        if self.name:
     72            parts.append(f"name={self.name!r}")
     73        if self.type:
     74            parts.append(f"type={self.type!r}")
     75        if self.rename:
     76            parts.append(f"rename={self.rename!r}")
     77        if self.skip_serializing:
     78            parts.append(f"skip_serializing={self.skip_serializing!r}")
     79        if self.default is not _MISSING:
     80            parts.append(f"default={self.default!r}")
     81        if self.default_factory:
     82            parts.append(f"default_factory={self.default_factory!r}")
     83        if self.serializer:
     84            parts.append(f"serializer={self.serializer!r}")
     85        if self.deserializer:
     86            parts.append(f"deserializer={self.deserializer!r}")
     87        if self.validate:
     88            parts.append(f"validate={self.validate!r}")
     89        return f"Field({', '.join(parts)})"
     90
     91    def __eq__(self, other: Any) -> bool:
     92        if not isinstance(other, Field):
     93            return NotImplemented
     94        return (
     95            self.name == other.name
     96            and self.type == other.type
     97            and self.rename == other.rename
     98            and self.skip_serializing == other.skip_serializing
     99            and self.default == other.default
    100            and self.default_factory == other.default_factory
    101            and self.serializer == other.serializer
    102            and self.deserializer == other.deserializer
    103            and self.validate == other.validate
    104        )
    105
    106
    107def field(
    108    *,
    109    rename: Optional[str] = None,
    110    skip_serializing: bool = False,
    111    default: Any = _MISSING,
    112    default_factory: Optional[Callable[[], Any]] = None,
    113    serializer: Optional[Callable[[Any], Any]] = None,
    114    deserializer: Optional[Callable[[Any], Any]] = None,
    115    validate: Optional[
    116        Union[Callable[[Any], None], List[Callable[[Any], None]]]
    117    ] = None,
    118) -> Any:
    119    """
    120    Provides metadata to the `@lodum` decorator for a single field.
    121
    122    Args:
    123        rename: The name to use for the field in the output.
    124        skip_serializing: If `True`, the field will not be included in the
    125            output.
    126        default: A default value to use for the field during decoding
    127            if it is missing from the input data.
    128        default_factory: A zero-argument function that will be called to
    129            create a default value for a missing field.
    130        serializer: A function to call to encode the field's value.
    131        deserializer: A function to call to decode the field's value.
    132        validate: A callable or list of callables to validate the field's value during decoding.
    133    """
    134    return Field(
    135        rename=rename,
    136        skip_serializing=skip_serializing,
    137        default=default,
    138        default_factory=default_factory,
    139        serializer=serializer,
    140        deserializer=deserializer,
    141        validate=validate,
    142    )

def register_type(cls: Type[Any]) -> None: View Source

    14def register_type(cls: Type[Any]) -> None:
    15    """Registers a class in the global name-to-type cache."""
    16    with _REGISTRY_LOCK:
    17        _NAME_TO_TYPE_CACHE[cls.__name__] = cls

Registers a class in the global name-to-type cache.

class Field: View Source

     28class Field:
     29    """
     30    A class that stores metadata for a field in a lodum-enabled class.
     31
     32    This is not intended to be instantiated directly. Instead, use the `field()`
     33    function, which provides a more convenient API.
     34    """
     35
     36    def __init__(
     37        self,
     38        rename: Optional[str] = None,
     39        skip_serializing: bool = False,
     40        default: Any = _MISSING,
     41        default_factory: Optional[Callable[[], Any]] = None,
     42        serializer: Optional[Callable[[Any], Any]] = None,
     43        deserializer: Optional[Callable[[Any], Any]] = None,
     44        validate: Optional[
     45            Union[Callable[[Any], None], List[Callable[[Any], None]]]
     46        ] = None,
     47    ) -> None:
     48        if default is not _MISSING and default_factory is not None:
     49            raise ValueError("cannot specify both default and default_factory")
     50
     51        self.rename = rename
     52        self.skip_serializing = skip_serializing
     53        self.default = default
     54        self.default_factory = default_factory
     55        self.serializer = serializer
     56        self.deserializer = deserializer
     57        self.validate = validate
     58        self.name: str = ""  # Will be populated by the decorator
     59        self.type: Any = None  # Will be populated by the decorator
     60
     61    @property
     62    def has_default(self) -> bool:
     63        return self.default is not _MISSING or self.default_factory is not None
     64
     65    def get_default(self) -> Any:
     66        if self.default_factory is not None:
     67            return self.default_factory()
     68        return self.default
     69
     70    def __repr__(self) -> str:
     71        parts = []
     72        if self.name:
     73            parts.append(f"name={self.name!r}")
     74        if self.type:
     75            parts.append(f"type={self.type!r}")
     76        if self.rename:
     77            parts.append(f"rename={self.rename!r}")
     78        if self.skip_serializing:
     79            parts.append(f"skip_serializing={self.skip_serializing!r}")
     80        if self.default is not _MISSING:
     81            parts.append(f"default={self.default!r}")
     82        if self.default_factory:
     83            parts.append(f"default_factory={self.default_factory!r}")
     84        if self.serializer:
     85            parts.append(f"serializer={self.serializer!r}")
     86        if self.deserializer:
     87            parts.append(f"deserializer={self.deserializer!r}")
     88        if self.validate:
     89            parts.append(f"validate={self.validate!r}")
     90        return f"Field({', '.join(parts)})"
     91
     92    def __eq__(self, other: Any) -> bool:
     93        if not isinstance(other, Field):
     94            return NotImplemented
     95        return (
     96            self.name == other.name
     97            and self.type == other.type
     98            and self.rename == other.rename
     99            and self.skip_serializing == other.skip_serializing
    100            and self.default == other.default
    101            and self.default_factory == other.default_factory
    102            and self.serializer == other.serializer
    103            and self.deserializer == other.deserializer
    104            and self.validate == other.validate
    105        )

A class that stores metadata for a field in a lodum-enabled class.

This is not intended to be instantiated directly. Instead, use the `field()` function, which provides a more convenient API.

Field( rename: Optional[str] = None, skip_serializing: bool = False, default: Any = <lodum.field._MISSING_TYPE object>, default_factory: Optional[Callable[[], Any]] = None, serializer: Optional[Callable[[Any], Any]] = None, deserializer: Optional[Callable[[Any], Any]] = None, validate: Union[Callable[[Any], NoneType], List[Callable[[Any], NoneType]], NoneType] = None) View Source

    36    def __init__(
    37        self,
    38        rename: Optional[str] = None,
    39        skip_serializing: bool = False,
    40        default: Any = _MISSING,
    41        default_factory: Optional[Callable[[], Any]] = None,
    42        serializer: Optional[Callable[[Any], Any]] = None,
    43        deserializer: Optional[Callable[[Any], Any]] = None,
    44        validate: Optional[
    45            Union[Callable[[Any], None], List[Callable[[Any], None]]]
    46        ] = None,
    47    ) -> None:
    48        if default is not _MISSING and default_factory is not None:
    49            raise ValueError("cannot specify both default and default_factory")
    50
    51        self.rename = rename
    52        self.skip_serializing = skip_serializing
    53        self.default = default
    54        self.default_factory = default_factory
    55        self.serializer = serializer
    56        self.deserializer = deserializer
    57        self.validate = validate
    58        self.name: str = ""  # Will be populated by the decorator
    59        self.type: Any = None  # Will be populated by the decorator

rename
skip_serializing
default
default_factory
serializer
deserializer
validate
name: str
type: Any
has_default: bool View Source

    61    @property
    62    def has_default(self) -> bool:
    63        return self.default is not _MISSING or self.default_factory is not None

def get_default(self) -> Any: View Source

    65    def get_default(self) -> Any:
    66        if self.default_factory is not None:
    67            return self.default_factory()
    68        return self.default

def field( *, rename: Optional[str] = None, skip_serializing: bool = False, default: Any = <lodum.field._MISSING_TYPE object>, default_factory: Optional[Callable[[], Any]] = None, serializer: Optional[Callable[[Any], Any]] = None, deserializer: Optional[Callable[[Any], Any]] = None, validate: Union[Callable[[Any], NoneType], List[Callable[[Any], NoneType]], NoneType] = None) -> Any: View Source

    108def field(
    109    *,
    110    rename: Optional[str] = None,
    111    skip_serializing: bool = False,
    112    default: Any = _MISSING,
    113    default_factory: Optional[Callable[[], Any]] = None,
    114    serializer: Optional[Callable[[Any], Any]] = None,
    115    deserializer: Optional[Callable[[Any], Any]] = None,
    116    validate: Optional[
    117        Union[Callable[[Any], None], List[Callable[[Any], None]]]
    118    ] = None,
    119) -> Any:
    120    """
    121    Provides metadata to the `@lodum` decorator for a single field.
    122
    123    Args:
    124        rename: The name to use for the field in the output.
    125        skip_serializing: If `True`, the field will not be included in the
    126            output.
    127        default: A default value to use for the field during decoding
    128            if it is missing from the input data.
    129        default_factory: A zero-argument function that will be called to
    130            create a default value for a missing field.
    131        serializer: A function to call to encode the field's value.
    132        deserializer: A function to call to decode the field's value.
    133        validate: A callable or list of callables to validate the field's value during decoding.
    134    """
    135    return Field(
    136        rename=rename,
    137        skip_serializing=skip_serializing,
    138        default=default,
    139        default_factory=default_factory,
    140        serializer=serializer,
    141        deserializer=deserializer,
    142        validate=validate,
    143    )

Provides metadata to the `@lodum` decorator for a single field.

Args: rename: The name to use for the field in the output. skip_serializing: If `True`, the field will not be included in the output. default: A default value to use for the field during decoding if it is missing from the input data. default_factory: A zero-argument function that will be called to create a default value for a missing field. serializer: A function to call to encode the field's value. deserializer: A function to call to decode the field's value. validate: A callable or list of callables to validate the field's value during decoding.