pydantic icon indicating copy to clipboard operation
pydantic copied to clipboard

pydantic.validate_call has different behavior when type hint union has typing.Iterable

Open hb2638 opened this issue 5 months ago • 4 comments

Initial Checks

  • [X] I confirm that I'm using Pydantic V2

Description

In the below code, both functions should return the same value. The only difference is where in the union the typing.Iterable type hint resides. The code works when it's the first type in the union but fails when it's the last.

My wild guess is pydantic is draining the input for validation and subsequent validators get an empty iterable because the 1st one drained it. If that's the case you need to make that idempotent for the other validators... So they have access to the previously read values as if they're reading the iterable for the first time. And if you do that, you need to make sure the actuall caleee can do this, but just once.. So maybe use the iter function to return a read-once only stream of the input.

Example Code

import pydantic
import typing


@pydantic.validate_call
def back(tags: dict[str, object]|list[dict[str, object]]|typing.Iterable[dict[str, object]]):
    return list(tags)


@pydantic.validate_call
def front(tags: typing.Iterable[dict[str, object]]|dict[str, object]|list[dict[str, object]]):
    return list(tags)

input = [
  {
    "TagKey": "tr7h6hturtyrtyr",
    "TagValue": "23424234324"
  },
  {
    "TagKey": "rtyge4fwesft",
    "TagValue": "Sep 27 2024 09:43AM EST"
  },
  {
    "TagKey": "h6gurgyreyg45g",
    "TagValue": "85654654645"
  },
  {
    "TagKey": "Name",
    "TagValue": "5yhtrytr54g646h4"
  }
]

# should return a list of dictionaries but instead returns empty list. This is not working.
print(back(iter(input)))

# should return a list of dictionaries, and returns a list of dictionaries. This is working.
print(front(iter(input)))

Python, Pydantic & OS Version

python -c "import pydantic.version; print(pydantic.version.version_info())"
             pydantic version: 2.9.1
        pydantic-core version: 2.23.3
          pydantic-core build: profile=release pgo=false
                 install path: D:\code\site-packages\pydantic
               python version: 3.12.1 (tags/v3.12.1:2305ca5, Dec  7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)]
                     platform: Windows-11-10.0.22631-SP0
             related packages: typing_extensions-4.12.2
                       commit: unknown

hb2638 avatar Sep 27 '24 14:09 hb2638