feat: add PEP 695 type alias support and improve type handling
Summary
This PR adds full support for type aliases from PEP 695 (Python 3.12+) and improves overall type handling in polyfactory.
Key Changes
1. TypeCompatibilityAdapter Class
Added a new TypeCompatibilityAdapter class that serves as a compatibility layer for handling different type representations across Python versions. This adapter:
- Problem it solves: PEP 695 introduces TypeAliasType, which requires special handling to extract the underlying type value. Polyfactory couldn't process this new type during data generation, which led to errors:
polyfactory.exceptions.ParameterException: Unsupported type: ExampleTypeAliasType on field 'example_field' from class FooFactory.
Either use 'add_provider', extend the providers map, or add a factory function for the field on the model.
The adapter also correctly handles nested scenarios such as list[ExampleTypeAliasType], resolves generic TypeAliasType, and cases where other TypeAliasType instances are used as generic type parameters.
Additionally, I've refactored type checking logic by introducing two utility methods:
is_generic_alias(): Checks if a type is a generic aliasis_type_var(): Checks if a type is aTypeVar
All instances of isinstance(value, TypeVar) have been replaced with is_type_var(value) for consistency. Comprehensive tests have been added to ensure the adapter works correctly with various type scenarios.
2. PydanticFieldMeta.from_field_info Refactoring
The from_field_info method has been decomposed into smaller, more focused methods to improve code readability and reduce cyclomatic complexity. This refactoring makes the code easier to understand and maintain without changing its functionality.
3. Rationale for the Chosen Approach
The type normalization in PydanticFieldMeta.from_field_info is implemented as:
field_info = FieldInfo.merge_field_infos(
field_info,
FieldInfo.from_annotation(TypeCompatibilityAdapter(field_info.annotation).normalize())
)
This approach provides several benefits:
- Clean implementation: Using normalization without conditional checks like is_type_alias improves code readability and eliminates the need for redundant tests that verify conditional behavior for each type scenario
- Metadata preservation: Using
merge_field_infosensures that metadata like example values aren't lost during the annotation transformation
Testing
- Added extensive test coverage for PEP 695 type aliases including:
- Basic type aliases
- Generic type aliases with single and multiple type parameters
- Nested generic structures
- Annotated types with constraints
- Union types and optional types
- Complex nested combinations
- Added tests for the
TypeCompatibilityAdapterclass
Fixes #707
Conflict has been fixed 👍
Apologies - realised created another conflict for here when merging other things. Can this be updated again please?
Apologies - realised created another conflict for here when merging other things. Can this be updated again please?
Conflict has been fixed
Documentation preview will be available shortly at https://litestar-org.github.io/polyfactory-docs-preview/711
https://github.com/all-contributors add @Rub1kCube for code
Thanks for the work on this!