Changelog

Versions follow Semantic Versioning (<major>.<minor>.<patch>), but with minor syntax differences to satisfy python package version specifiers.

Until a stable version is released (end of beta), new versions may contain backward-incompatible changes, but we will strive to deprecate features first instead of immediately removal. After that, breaking changes will only be introduced in major versions.

Non-guaranteed behavior

Some aspects of behavior are not guaranteed and could be changed at any release without any mention in the changelog (or even vary in different environments or different runs).

Such details are highlighted in the documentation via this admonition.


3.0.0b12 – 2026-04-04

Features

  • Improve formatting types inside generics for error messages

    Old error example
     adaptix.ProviderNotFoundError: Cannot produce dumper for type <class '__main__.Foo'>
     × Cannot create dumper for model. Dumpers for some fields cannot be created
     │ Location: ‹Foo›
     ╰──▷ Cannot create dumper for model. Dumpers for some fields cannot be created
        │ Location: ‹Foo.limit: __main__.MinMax[__main__.Bar]›
        ├──▷ Cannot create dumper for union. Dumpers for some union cases cannot be created
        │  │ Location: ‹__main__.MinMax[__main__.Bar].min: Optional[__main__.Bar]›
        │  ╰──▷ Cannot find dumper
        │       Location: ‹Bar›
        ╰──▷ Cannot create dumper for union. Dumpers for some union cases cannot be created
           │ Location: ‹__main__.MinMax[__main__.Bar].max: Optional[__main__.Bar]›
           ╰──▷ Cannot find dumper
                Location: ‹Bar›
    
    New error example
     adaptix.ProviderNotFoundError: Cannot produce dumper for type <class '__main__.Foo'>
       × Cannot create dumper for model. Dumpers for some fields cannot be created
       │ Location: ‹Foo›
       ╰──▷ Cannot create dumper for model. Dumpers for some fields cannot be created
          │ Location: ‹Foo.limit: MinMax[Bar]›
          ├──▷ Cannot create dumper for union. Dumpers for some union cases cannot be created
          │  │ Location: ‹MinMax[Bar].min: Optional[Bar]›
          │  ╰──▷ Cannot find dumper
          │       Location: ‹Bar›
          ╰──▷ Cannot create dumper for union. Dumpers for some union cases cannot be created
             │ Location: ‹MinMax[Bar].max: Optional[Bar]›
             ╰──▷ Cannot find dumper
                  Location: ‹Bar›
    
  • Add support for CPython 3.14

  • Add support for PyPy 3.11

  • Add support for ForwardRef inside conversion

  • Allow to dump Union with Annotated as one of cases

Breaking Changes

  • Drop support for Python 3.9

Bug Fixes

  • Fixed impl_converter failure with signatures when forward references is used (from __future__ import annotations) #393

  • Fix introspection of SQLAlchemy models with custom column name

  • Predicates correctly matches Final, Annotated, ClassVar and InitVar

Other

  • Switched package build-backend from setuptools to uv_build. #397

  • Add real_world_app example to documentation

  • Add Known Issues page to documentation

  • Improve style of documentation


3.0.0b11 – 2025-05-09

Features

  • Completely redesigned error rendering system. All errors related to loader, dumper, and converter generation now utilize a new compact and intuitive display format. Error messages have also been substantially improved for clarity.

    Old error example
       | adaptix.AggregateCannotProvide: Cannot create loader for model. Loaders for some fields cannot be created (1 sub-exception)
       | Location: `Book`
       +-+---------------- 1 ----------------
         | adaptix.AggregateCannotProvide: Cannot create loader for model. Cannot fetch InputNameLayout (1 sub-exception)
         | Location: `Book.author: Person`
         +-+---------------- 1 ----------------
           | adaptix.CannotProvide: Required fields ['last_name'] are skipped
           | Location: `Book.author: Person`
           +------------------------------------
    
     The above exception was the direct cause of the following exception:
    
     Traceback (most recent call last):
       ...
     adaptix.ProviderNotFoundError: Cannot produce loader for type <class '__main__.Book'>
     Note: The attached exception above contains verbose description of the problem
    
    New error example
     Traceback (most recent call last):
       ...
     adaptix.ProviderNotFoundError: Cannot produce loader for type <class '__main__.Book'>
       × Cannot create loader for model. Loaders for some fields cannot be created
       │ Location: ‹Book›
       ╰──▷ Cannot create loader for model. Cannot fetch `InputNameLayout`
          │ Location: ‹Book.author: Person›
          ╰──▷ Required fields ['last_name'] are skipped
    

Breaking Changes

  • Custom iterable subclasses are no longer supported. To use them, register via the internal (temporary) API with IterableProvider.

  • The Retort.replace method now requires Omitted instead of None to skip parameter values.

  • Removed the hide_traceback parameter from Retort and Retort.replace. Error rendering is now controlled via the error_renderer parameter. Pass None to display raw Python ExceptionGroup traces.

Bug Fixes

  • Fixed incorrect classification of parametrized generic Pydantic models as iterables (due to Pydantic model instances being inherently iterable).

  • Corrected hint generation errors during model conversion.

  • Fixed handling of parametrized TypeAlias.


3.0.0b10 – 2025-04-13

Features

  • Add support for msgspec models!

    Now you can work with msgspec models like any other: construct from a dict, serialize to a dict, and convert it into any other model.

    Also, you can use integrations.msgspec.native_msgspec to delegate loading and dumping to msgspec itself.

    This allows you to combine the flexibility of adaptix with the incredible speed of msgspec

  • A completely new algorithm for model dumper code generation has been implemented.

    Dumping models with default values is now faster. For GitHub Issues models, which include only a few default fields, dump time has been reduced by 22%.

  • Now you can easily distinguish between a missing field and a None value. The new as_sentinel function allows you to mark types as sentinels, ensuring they remain hidden from the outside world. See Detecting absence of a field for detail. #214

  • Add support for ZoneInfo. #375

Breaking Changes

Bug Fixes

  • Fix default values loading for types inherited from builtin types. #363

  • Fix the error caused by using with_property when the function was used only once for a type.

Other

  • Internal benchmarking framework now can use SQLite to store result data #370

  • Add Gurubase AI to documentation


3.0.0b9 – 2024-12-15

Features

  • Add support for all Python 3.13 new features.

Breaking Changes

  • All iterables now are dumped to tuple (or list for list children). #348

Bug Fixes

  • Fix NoRequiredFieldsLoadError raising for fields generated by name flattening.

  • hide_traceback=False shows traceback now.

Other

  • Add “Why not Pydantic?” article.


3.0.0b8 – 2024-09-02

Features

  • Add new datetime_by_timestamp and date_by_timestamp provider factories. #281

  • Add datetime_by_format to public API. #286

  • Add type_tools.exec_type_checking function to deal with cyclic references by executing if TYPE_CHECKING: constructs. #288

  • Add support for bytes inside literal, for example Literal[b"abc"]. #318

  • The library shows a hint if one class is a model and the other is not.

  • Traceback of CannotProvide is hidden (it is raised when loader, dumper, or converter can not be created). It simplifies error messages to users. You can show traceback by disabling hide_traceback parameter of Retort.

Breaking Changes

  • Drop support of Python 3.8.

  • TypedDictAt38Warning is removed.

Other

  • Refactor internal provider routing system. It becomes more simple and readable. Also, internal caching is added. This led to a 40% speedup in loader generation for medium models and up to 4x speedup for large models with many recursive types.


3.0.0b7 – 2024-06-10

Deprecations

  • NoSuitableProvider exception was renamed to ProviderNotFoundError. #245

Bug Fixes

  • Allow redefining coercer inside Optional using an inner type if source and destination types are same. #279

  • Fix ForwardRef evaluation inside bound of TypeVar for Python 3.12.4. #312


3.0.0b6 – 2024-05-23

Features

  • Now, you can merge several fields or access the model directly via conversion.link_function.

    See Link function for details.

  • Add a special column type for serializing and deserializing JSON inside SQLAlchemy.

    See SQLAlchemy JSON for details.

  • Add Extended Usage article for model conversion and other documentation updates.

Bug Fixes

  • Fix processing of list relationships in SQLAlchemy.

  • Fix model loader generation with non-required field and DebugTrail.DISABLE.


3.0.0b5 – 2024-04-20

Features

  • Add support for Pydantic models!

    Now you can work with pydantic models like any other: construct from dict, serialize to dict, and convert it to any other model.

    Also, you can use integrations.pydantic.native_pydantic to delegate loading and dumping to pydantic itself.

  • Add support for dumping Literal inside Union. #237

  • Add support for BytesIO and IO[bytes]. #270

  • Error messages are more obvious.

Breaking Changes

  • Forbid use of constructs like P[SomeClass].ANY because it is misleading (you have to use P.ANY directly).

  • Private fields (any field starting with underscore) are skipped at dumping. See Private fields dumping for details.


3.0.0b4 – 2024-03-30

Features

  • Add coercer for builtin iterables and dict.

  • Models can be automatically converted inside compound types like Optional, list, dict etc.

  • Add conversion.from_param predicate factory to match only parameters

  • An error of loader, dumper, and converter generation contains a much more readable location.

    For example:

    • Linking: `Book.author_ids: list[int] -> BookDTO.author_ids: list[str]`

    • Location: `Stub.f3: memoryview`

Breaking Changes

  • Now, parameters are automatically linked only to top-level model fields. For manual linking, you can use the new adaptix.conversion.from_param predicate factory.

Bug Fixes

  • Fix fail to import adaptix package on python 3.8-3.10 when -OO is used.

  • Fix unexpected error on creating coercer between fields with Optional type.

  • Fix unexpected error with type vars getting from UnionType.


3.0.0b3 – 2024-03-08

Features

  • conversion.link accepts coercer parameter. #256

  • Add conversion.link_constant to link constant values and constant factories. #258

  • Add coercer for case when source union is subset of destination union (simple == check is using). #242

  • No coercer error now contains type information. #252

  • Add coercer for Optional[S] -> Optional[D] if S is coercible to D. #254

Bug Fixes

  • Fix SyntaxError with lambda in coercer. #243

  • Model dumping now trying to save the original order of fields inside the dict. #247

  • Fix introspection of sqlalchemy models with column_property (all ColumnElement is ignored excepting Column itself). #250


3.0.0b2 – 2024-02-16

Features

  • New major feature is out! Added support for model conversion! Now, you can generate boilerplate converter function by adaptix. See conversion tutorial for details.

  • Basic support for sqlalchemy models are added!

  • Added enum support inside Literal. #178

  • Added flags support.

    Now adaptix has two different ways to process flags: flag_by_exact_value (by default) and flag_by_member_names. #197

  • Added defaultdict support. #216

  • Added support of mapping for enum_by_name provider. #223

  • Created the correct path (fixing python bug) for processing Required and NotRequired with stringified annotations or from __future__ import annotations. #227

Breaking Changes

  • Due to refactoring of predicate system required for new features:

    1. create_request_checker was renamed to create_loc_stack_checker

    2. RequestPattern (class of P) was renamed to LocStackPattern

    3. method RequestPattern.build_request_checker() was renamed to LocStackPattern.build_loc_stack_checker()

Deprecations

  • Standardize names inside adaptix.load_error. Import of old names will emit DeprecationWarning.

    Old name

    New name

    MsgError

    MsgLoadError

    ExtraFieldsError

    ExtraFieldsLoadError

    ExtraItemsError

    ExtraItemsLoadError

    NoRequiredFieldsError

    NoRequiredFieldsLoadError

    NoRequiredItemsError

    NoRequiredItemsLoadError

    ValidationError

    ValidationLoadError

    BadVariantError

    BadVariantLoadError

    DatetimeFormatMismatch

    FormatMismatchLoadError

Bug Fixes

  • Fixed parameter shuffling on skipping optional field. #229


3.0.0b1 – 2023-12-16

Start of changelog.