From 919e902f4f8b7db5057ff65b4f1c7156c83cb961 Mon Sep 17 00:00:00 2001 From: Sander Teunissen Date: Sun, 17 May 2026 10:46:48 +0200 Subject: [PATCH 1/4] fix coverage output on constrained optional. --- polyfactory/factories/base.py | 6 +++++- tests/test_type_coverage_generation.py | 21 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/polyfactory/factories/base.py b/polyfactory/factories/base.py index 3224e248..e6095f0d 100644 --- a/polyfactory/factories/base.py +++ b/polyfactory/factories/base.py @@ -894,7 +894,11 @@ def get_field_value_coverage( # noqa: C901,PLR0912 unwrapped_annotation_meta = field_meta if is_union(field_meta.annotation): unwrapped_annotation_meta = next( - (meta for meta in (field_meta.children or []) if meta.annotation == unwrapped_annotation), + ( + meta + for meta in (field_meta.children or []) + if unwrap_annotation(meta.annotation) == unwrapped_annotation + ), field_meta, ) if unwrapped_annotation in (None, NoneType): diff --git a/tests/test_type_coverage_generation.py b/tests/test_type_coverage_generation.py index 3638230c..6b3ee8d6 100644 --- a/tests/test_type_coverage_generation.py +++ b/tests/test_type_coverage_generation.py @@ -1,10 +1,11 @@ # ruff: noqa: UP007 from __future__ import annotations +from annotated_types import Gt, Lt from collections.abc import Iterable from dataclasses import dataclass, make_dataclass from datetime import date -from typing import Any, Literal, Optional, Union +from typing import Any, Literal, Optional, Union, Annotated from uuid import UUID import pytest @@ -371,3 +372,21 @@ class Model(BaseModel): assert type_exists_at_path_any(results, ["maybe_uuids"], list) assert type_exists_at_path_any(results, ["maybe_uuids", "*"], UUID) assert type_exists_at_path_any(results, ["maybe_uuids"], NoneType) + + +def test_annotated_optional() -> None: + # Struggling a bit on how to properly test this. + # We are constraining random generation of an int value + # within a constraint. The actual constraint is actually under test + # here. But in case the constraint is not doing its job, + # there is a case where the generation falls within the constraint + # which actually results in a false positive. + @dataclass + class Model: + maybe_constraint_int: Optional[Annotated[int, Gt(0), Lt(3)]] + + results = list(DataclassFactory.create_factory(Model).coverage()) + + assert len(results) == 2 + for result in results: + assert result.maybe_constraint_int in {1, 2, None} From 9e96c4a7799da1b47628905b17246074246f47d8 Mon Sep 17 00:00:00 2001 From: Sander Teunissen Date: Sun, 17 May 2026 11:03:55 +0200 Subject: [PATCH 2/4] fix ruff --- tests/test_type_coverage_generation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_type_coverage_generation.py b/tests/test_type_coverage_generation.py index 6b3ee8d6..e7d75112 100644 --- a/tests/test_type_coverage_generation.py +++ b/tests/test_type_coverage_generation.py @@ -383,7 +383,7 @@ def test_annotated_optional() -> None: # which actually results in a false positive. @dataclass class Model: - maybe_constraint_int: Optional[Annotated[int, Gt(0), Lt(3)]] + maybe_constraint_int: Annotated[int, Gt(0), Lt(3)] | None results = list(DataclassFactory.create_factory(Model).coverage()) From 0d7a23db8174ae5aaa908b6a48942f0f6c9b2e3c Mon Sep 17 00:00:00 2001 From: Sander Teunissen Date: Sun, 17 May 2026 11:14:00 +0200 Subject: [PATCH 3/4] exclude py3.9 --- tests/test_type_coverage_generation.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_type_coverage_generation.py b/tests/test_type_coverage_generation.py index e7d75112..7b275df6 100644 --- a/tests/test_type_coverage_generation.py +++ b/tests/test_type_coverage_generation.py @@ -1,5 +1,6 @@ # ruff: noqa: UP007 from __future__ import annotations +from sys import version_info from annotated_types import Gt, Lt from collections.abc import Iterable @@ -374,12 +375,13 @@ class Model(BaseModel): assert type_exists_at_path_any(results, ["maybe_uuids"], NoneType) +@pytest.mark.skipif(version_info < (3, 10), reason="Union with annotated and None not support on <3.10") def test_annotated_optional() -> None: # Struggling a bit on how to properly test this. # We are constraining random generation of an int value - # within a constraint. The actual constraint is actually under test + # The actual constraint is actually under test # here. But in case the constraint is not doing its job, - # there is a case where the generation falls within the constraint + # there is a possibility where the generation falls within the constraint # which actually results in a false positive. @dataclass class Model: From f1a34a410d248e9a392c491323373eb27cf32dae Mon Sep 17 00:00:00 2001 From: Sander Teunissen Date: Sun, 17 May 2026 11:17:27 +0200 Subject: [PATCH 4/4] ruff fixes --- tests/test_type_coverage_generation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_type_coverage_generation.py b/tests/test_type_coverage_generation.py index 7b275df6..406da1b8 100644 --- a/tests/test_type_coverage_generation.py +++ b/tests/test_type_coverage_generation.py @@ -1,15 +1,15 @@ # ruff: noqa: UP007 from __future__ import annotations -from sys import version_info -from annotated_types import Gt, Lt from collections.abc import Iterable from dataclasses import dataclass, make_dataclass from datetime import date -from typing import Any, Literal, Optional, Union, Annotated +from sys import version_info +from typing import Annotated, Any, Literal, Optional, Union from uuid import UUID import pytest +from annotated_types import Gt, Lt from typing_extensions import TypedDict from pydantic import BaseModel