Search code examples
pythonpydanticpylint

Non-iterable value used in iterating context in Pydantic validator


I have a Pydantic DTO that looks like this:

from pydantic import AfterValidator, model_validator, BaseModel

class Bid(BaseModel):

    start_block: Annotated[DateTime, AfterValidator(block_validator)]

    end_block: Annotated[DateTime, AfterValidator(block_validator)]

    threshold: int

    pq_pairs: Annotated[List[PriceQuantityPair], AfterValidator(pq_pair_validator)] = Field(min_length=1)

    @model_validator(mode="after")
    def validate_bid(self) -> Self:
        """Validate an offer."""
        # Check that the start block is before the end block
        if self.start_block >= self.end_block:
            raise ValueError("The start block must be before the end block.")

        for pq_pair in self.pq_pairs:
            if self.threshold > pq_pair.quantity:
                raise ValueError("The threshold must be less than or equal to the quantity.")

        # Return the object now that we've validated it
        return self

This works fine but Pylint is raising a linting error:

E1133: Non-iterable value self.pq_pairs is used in an iterating context (not-an-iterable)

I would assume that this has something to do with the use of Annotated but I'm not sure what to do about it. Any help would be appreciated.


Solution

  • It took a while, but after some experimenting I figured it out! Defining pq_pairs in the following way fixes the problem:

    class Bid(BaseModel):
        pq_pairs: Annotated[List[PriceQuantityPair], AfterValidator(pq_pair_validator), Field(min_length=1)]
    

    Assume that assigning Field to the attribute confusing pylint.