Conversation
CodSpeed Performance ReportMerging #1792 will not alter performanceComparing Summary
|
Viicos
left a comment
There was a problem hiding this comment.
In Python, an iterable is an object that has an __iter__() method and presumably can produce iterators multiple times from it. What if users want the iterable to just be validated that we can grab an iterator from it (that is what input.validate_iter() is doing), and leave it as is? I guess the issue is that we can't validate the type of the values this way?
|
Or maybe my point is that as it stands now, we support ABCs to try to preserve the input type to our best knowledge. If someone uses With |
I guess exactly this, yes. Validation may in general lead to coercions (e.g. string '1' to integer 1) so
A great question. Perhaps you're right, and the answer is that For So... seems like this needs more design? |
|
It feels to me that several users reported issues with
|
yeah your guess is correct, we want to be as loose as possible for type checkers.
fwiw if you added a config for this case we (the maintainers of the SDK) would add it to our |
|
In anthropic-sdk, we generate TypedDicts from the OpenAPI spec, and we’d like to work around this until Pydantic fixes it. We’re considering the approach below, and I’d love to hear your thoughts before I apply it @Viicos @davidhewitt from __future__ import annotations
from typing import Annotated, Any, Generic, Iterable, TypeVar, get_args
from pydantic import BaseModel
from pydantic_core import CoreSchema, core_schema
T = TypeVar("T")
class IterableToList(list[T], Generic[T]):
"""
Accepts any Iterable[T] input (including generators),
consumes it once, validates items, and stores as list[T].
"""
@classmethod
def __get_pydantic_core_schema__(
cls,
source_type: Any,
handler: Any,
) -> CoreSchema:
# Resolve T from IterableToList[T]
(item_type,) = get_args(source_type) or (Any,)
item_schema: CoreSchema = handler.generate_schema(item_type)
list_of_items_schema: CoreSchema = core_schema.list_schema(item_schema)
return core_schema.no_info_before_validator_function(
cls._to_list,
list_of_items_schema,
)
@staticmethod
def _to_list(v: Any) -> list[Any]:
if isinstance(v, list):
return v
try:
# Consume iterables (including generators) exactly once
return list(v) # type: ignore[arg-type]
except TypeError as e:
raise TypeError("Value is not iterable") from e
class Model(BaseModel):
values: Annotated[Iterable, IterableToList[int]]
model = Model(values=iter([0, 1, 2])) # type is ok
print(model.model_dump_json())
print(model.model_dump_json()) # preserves the list
model = Model(values=(i for i in range(3))) # type is ok
print(model.model_dump_json())
print(model.model_dump_json()) # preserves the list |
Change Summary
Adds
iterable_schema, which is intended to solve my proposal in pydantic/pydantic#9541 (comment)pydanticshould update all existing uses ofgenerator_schematoiterable_schema, which allows forlazy = Falseas a field-level setting. We should probably also have a config setting calledlazy_iterablesor similar, (TODO).If we want to allow support for
IteratorandGeneratortypes inpydantic, those can usegenerator_schema.Related issue number
pydantic/pydantic#9541
Checklist
pydantic-core(except for expected changes)