From 94ad5611772e2bed977b693a030f517b3567a6ea Mon Sep 17 00:00:00 2001 From: Andrew Truong <40660973+adhtruong@users.noreply.github.com> Date: Fri, 19 Jan 2024 02:57:57 +0000 Subject: [PATCH] feat: support type alias (#487) Co-authored-by: guacs <126393040+guacs@users.noreply.github.com> --- .github/workflows/ci.yaml | 14 +++++++------- .github/workflows/docs.yaml | 4 ++-- .github/workflows/publish.yaml | 8 ++++---- .pre-commit-config.yaml | 2 +- polyfactory/utils/helpers.py | 11 +++++++++-- polyfactory/utils/predicates.py | 10 +--------- pyproject.toml | 1 + tests/test_new_types.py | 27 ++++++++++++++++++++++++++- 8 files changed, 51 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f8b3b20a..b196e1f3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,7 +14,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - name: Install Pre-Commit run: python -m pip install pre-commit && pre-commit install @@ -34,7 +34,7 @@ jobs: strategy: fail-fast: true matrix: - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] pydantic-version: ["1.10", "2.0"] sqla-version: ["1.4", "2"] exclude: @@ -78,15 +78,15 @@ jobs: run: echo "PYTHONPATH=$PWD" >> $GITHUB_ENV - name: Test - if: matrix.python-version != '3.11' || matrix.pydantic-version != '2.0' || matrix.sqla-version != '2' + if: matrix.python-version != '3.12' || matrix.pydantic-version != '2.0' || matrix.sqla-version != '2' run: pdm run pytest tests - name: Test with Coverage - if: matrix.python-version == '3.11' && matrix.pydantic-version == '2.0' && matrix.sqla-version == '2' + if: matrix.python-version == '3.12' && matrix.pydantic-version == '2.0' && matrix.sqla-version == '2' run: pdm run pytest tests docs/examples --cov=. --cov-report=xml - uses: actions/upload-artifact@v4 - if: matrix.python-version == '3.11' + if: matrix.python-version == '3.12' with: name: coverage-xml path: coverage.xml @@ -103,12 +103,12 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - uses: pdm-project/setup-pdm@v3 name: Set up PDM with: - python-version: "3.11" + python-version: "3.12" allow-python-prereleases: true cache: true diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 56cafc3b..8561c185 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -17,12 +17,12 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - uses: pdm-project/setup-pdm@v3 name: Set up PDM with: - python-version: "3.11" + python-version: "3.12" allow-python-prereleases: true cache: true diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 2e0654c2..2cb8dc5c 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -18,12 +18,12 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - uses: pdm-project/setup-pdm@v3 name: Set up PDM with: - python-version: "3.11" + python-version: "3.12" allow-python-prereleases: true cache: true @@ -42,12 +42,12 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - uses: pdm-project/setup-pdm@v3 name: Set up PDM with: - python-version: "3.11" + python-version: "3.12" allow-python-prereleases: true cache: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dca2fe20..4a693c30 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ default_language_version: - python: "3.11" + python: "3.12" repos: - repo: https://github.com/compilerla/conventional-pre-commit rev: v3.0.0 diff --git a/polyfactory/utils/helpers.py b/polyfactory/utils/helpers.py index a6432b58..572c79b6 100644 --- a/polyfactory/utils/helpers.py +++ b/polyfactory/utils/helpers.py @@ -8,7 +8,7 @@ except ImportError: NoneType = type(None) # type: ignore[misc,assignment] -from typing_extensions import get_args, get_origin +from typing_extensions import TypeAliasType, get_args, get_origin from polyfactory.constants import TYPE_MAPPING from polyfactory.utils.predicates import is_annotated, is_new_type, is_optional, is_safe_subclass, is_union @@ -65,13 +65,20 @@ def unwrap_annotation(annotation: Any, random: Random) -> Any: :returns: The unwrapped annotation. """ - while is_optional(annotation) or is_new_type(annotation) or is_annotated(annotation): + while ( + is_optional(annotation) + or is_new_type(annotation) + or is_annotated(annotation) + or isinstance(annotation, TypeAliasType) + ): if is_new_type(annotation): annotation = unwrap_new_type(annotation) elif is_optional(annotation): annotation = unwrap_optional(annotation) elif is_annotated(annotation): annotation = unwrap_annotated(annotation, random=random)[0] + elif isinstance(annotation, TypeAliasType): + annotation = annotation.__value__ return annotation diff --git a/polyfactory/utils/predicates.py b/polyfactory/utils/predicates.py index 4ce47910..eaa6dff4 100644 --- a/polyfactory/utils/predicates.py +++ b/polyfactory/utils/predicates.py @@ -3,15 +3,7 @@ from inspect import isclass from typing import Any, Literal, NewType, Optional, TypeVar, Union, get_args -from typing_extensions import ( - Annotated, - NotRequired, - ParamSpec, - Required, - TypeGuard, - _AnnotatedAlias, - get_origin, -) +from typing_extensions import Annotated, NotRequired, ParamSpec, Required, TypeGuard, _AnnotatedAlias, get_origin from polyfactory.constants import TYPE_MAPPING diff --git a/pyproject.toml b/pyproject.toml index 4c210b5c..a8217ba8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Testing :: Unit", diff --git a/tests/test_new_types.py b/tests/test_new_types.py index 63d0a9e6..3788d6b7 100644 --- a/tests/test_new_types.py +++ b/tests/test_new_types.py @@ -1,6 +1,8 @@ +import sys from datetime import date from decimal import Decimal -from typing import Any, Dict, List, NewType, Optional, Tuple, Union +from types import ModuleType +from typing import Any, Callable, Dict, List, NewType, Optional, Tuple, Union import pytest from pydantic import ( @@ -18,6 +20,7 @@ constr, ) +from polyfactory.factories.dataclass_factory import DataclassFactory from polyfactory.factories.pydantic_factory import ModelFactory @@ -137,3 +140,25 @@ class MyFactory(ModelFactory): assert isinstance(result.conpositive_float_field, float) assert result.conpositive_float_field > 0 + + +@pytest.mark.skipif(sys.version_info < (3, 12), reason="3.12 only syntax") +def test_type_alias(create_module: Callable[[str], ModuleType]) -> None: + module = create_module( + """ +from typing import Literal +from dataclasses import dataclass + + +type LiteralAlias = Literal["a", "b"] + + +@dataclass +class A: + field: LiteralAlias +""", + ) + + factory = DataclassFactory.create_factory(module.A) # type: ignore[var-annotated] + result = factory.build() + assert result.field in {"a", "b"}