Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Invalid Coverage for Optional Fields with Annotated Constraint #514

Open
1 of 4 tasks
tharindurr opened this issue Mar 28, 2024 · 0 comments
Open
1 of 4 tasks
Labels
bug Something isn't working

Comments

@tharindurr
Copy link

tharindurr commented Mar 28, 2024

Description

I was trying to produce coverage for a Pydantic model with Annotated Field constraints.

class PartialA(BaseModel):
    a: Annotated[str | None, Field(min_length=1, max_length=10)] = None

The coverage function does not yield proper attributes for field a.

I tracked it down to the method get_field_value_coverage in BaseFactory which should extract the proper constraints.

Hope the issue is clear, happy to give further clarifications.

URL to code causing the issue

No response

MCVE

  • This is a test that I wrote which can be used to test my issue
from pydantic import BaseModel, Field
from typing import Annotated
from polyfactory.factories.pydantic_factory import ModelFactory


from polyfactory.pytest_plugin import register_fixture


class A(BaseModel):
    a: Annotated[str, Field(min_length=1, max_length=10)]

class PartialA(BaseModel):
    a: Annotated[str | None, Field(min_length=1, max_length=10)] = None

class PartialB(BaseModel):
    a: str | None = None

class PartialC(BaseModel):
    a: Annotated[int | None, Field(ge=0, le=10)] = None

@register_fixture
class ASchemaFactory(ModelFactory[A]):
    __model__ = A

@register_fixture
class PartialASchemaFactory(ModelFactory[PartialA]):
    __model__ = PartialA

@register_fixture
class PartialBSchemaFactory(ModelFactory[PartialB]):
    __model__ = PartialB

@register_fixture
class PartialCSchemaFactory(ModelFactory[PartialC]):
    __model__ = PartialC

def test_a_schema_factory(
        a_schema_factory: ASchemaFactory):
    for spec in a_schema_factory.coverage():
        pass

def test_partial_a_schema_factory(
        partial_a_schema_factory: PartialASchemaFactory):
    for spec in partial_a_schema_factory.coverage():
        pass

def test_partial_b_schema_factory(
        partial_b_schema_factory: PartialBSchemaFactory):
    for spec in partial_b_schema_factory.coverage():
        pass

def test_partial_c_schema_factory(
        partial_c_schema_factory: PartialCSchemaFactory):
    for spec in partial_c_schema_factory.coverage():
        pass

Steps to reproduce

No response

Screenshots

No response

Logs

==================================================================== test session starts =====================================================================
platform linux -- Python 3.12.2, pytest-7.4.3, pluggy-1.3.0
rootdir: /home/rr/work/oss/polyfactory
configfile: pyproject.toml
plugins: cov-4.1.0, hypothesis-6.92.1, Faker-21.0.0, asyncio-0.23.2
asyncio: mode=Mode.AUTO
collected 4 items                                                                                                                                            

tests/test_optional_constraint_coverage_factory.py .F.F

========================================================================== FAILURES ==========================================================================
_______________________________________________________________ test_partial_a_schema_factory ________________________________________________________________

partial_a_schema_factory = <class 'tests.test_optional_constraint_coverage_factory.PartialASchemaFactory'>

    def test_partial_a_schema_factory(
            partial_a_schema_factory: PartialASchemaFactory):
>       for spec in partial_a_schema_factory.coverage():

tests/test_optional_constraint_coverage_factory.py:44: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'tests.test_optional_constraint_coverage_factory.PartialASchemaFactory'>, kwargs = {}, data = {'a': 'GHTBnvXwdvDGBsyHYejs'}

    @classmethod
    def coverage(cls, **kwargs: Any) -> abc.Iterator[T]:
        """Build a batch of the factory's Meta.model will full coverage of the sub-types of the model.
    
        :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used.
    
        :returns: A iterator of instances of type T.
    
        """
        for data in cls.process_kwargs_coverage(**kwargs):
>           instance = cls.__model__(**data)
E           pydantic_core._pydantic_core.ValidationError: 1 validation error for PartialA
E           a
E             String should have at most 10 characters [type=string_too_long, input_value='GHTBnvXwdvDGBsyHYejs', input_type=str]
E               For further information visit https://errors.pydantic.dev/2.5/v/string_too_long

polyfactory/factories/base.py:1058: ValidationError
_______________________________________________________________ test_partial_c_schema_factory ________________________________________________________________

partial_c_schema_factory = <class 'tests.test_optional_constraint_coverage_factory.PartialCSchemaFactory'>

    def test_partial_c_schema_factory(
            partial_c_schema_factory: PartialCSchemaFactory):
>       for spec in partial_c_schema_factory.coverage():

tests/test_optional_constraint_coverage_factory.py:54: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'tests.test_optional_constraint_coverage_factory.PartialCSchemaFactory'>, kwargs = {}, data = {'a': 7693}

    @classmethod
    def coverage(cls, **kwargs: Any) -> abc.Iterator[T]:
        """Build a batch of the factory's Meta.model will full coverage of the sub-types of the model.
    
        :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used.
    
        :returns: A iterator of instances of type T.
    
        """
        for data in cls.process_kwargs_coverage(**kwargs):
>           instance = cls.__model__(**data)
E           pydantic_core._pydantic_core.ValidationError: 1 validation error for PartialC
E           a
E             Input should be less than or equal to 10 [type=less_than_equal, input_value=7693, input_type=int]
E               For further information visit https://errors.pydantic.dev/2.5/v/less_than_equal

polyfactory/factories/base.py:1058: ValidationError
====================================================================== warnings summary ======================================================================
.venv/lib/python3.12/site-packages/beanie/odm/fields.py:581
  /home/rr/work/oss/polyfactory/.venv/lib/python3.12/site-packages/beanie/odm/fields.py:581: DeprecationWarning: `general_plain_validator_function` is deprecated, use `with_info_plain_validator_function` instead.
    return core_schema.general_plain_validator_function(validate)

.venv/lib/python3.12/site-packages/pydantic_core/core_schema.py:3902
.venv/lib/python3.12/site-packages/pydantic_core/core_schema.py:3902
.venv/lib/python3.12/site-packages/pydantic_core/core_schema.py:3902
  /home/rr/work/oss/polyfactory/.venv/lib/python3.12/site-packages/pydantic_core/core_schema.py:3902: DeprecationWarning: `general_plain_validator_function` is deprecated, use `with_info_plain_validator_function` instead.
    warnings.warn(

.venv/lib/python3.12/site-packages/beanie/odm/fields.py:150
.venv/lib/python3.12/site-packages/beanie/odm/fields.py:150
  /home/rr/work/oss/polyfactory/.venv/lib/python3.12/site-packages/beanie/odm/fields.py:150: DeprecationWarning: `general_plain_validator_function` is deprecated, use `with_info_plain_validator_function` instead.
    python_schema=core_schema.general_plain_validator_function(

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================================================== short test summary info ===================================================================
FAILED tests/test_optional_constraint_coverage_factory.py::test_partial_a_schema_factory - pydantic_core._pydantic_core.ValidationError: 1 validation error for PartialA
FAILED tests/test_optional_constraint_coverage_factory.py::test_partial_c_schema_factory - pydantic_core._pydantic_core.ValidationError: 1 validation error for PartialC
========================================================== 2 failed, 2 passed, 6 warnings in 0.46s ===========================================================

Release Version

2.15.0

Platform

  • Linux
  • Mac
  • Windows
  • Other (Please specify in the description above)

Note

While we are open for sponsoring on GitHub Sponsors and
OpenCollective, we also utilize Polar.sh to engage in pledge-based sponsorship.

Check out all issues funded or available for funding on our Polar.sh dashboard

  • If you would like to see an issue prioritized, make a pledge towards it!
  • We receive the pledge once the issue is completed & verified
  • This, along with engagement in the community, helps us know which features are a priority to our users.
Fund with Polar
@tharindurr tharindurr added the bug Something isn't working label Mar 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant