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

Fix strict parsing for some Sequences #8614

Merged
merged 3 commits into from Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion pydantic/_internal/_generate_schema.py
Expand Up @@ -1388,8 +1388,9 @@ def _subclass_schema(self, type_: Any) -> core_schema.CoreSchema:
def _sequence_schema(self, sequence_type: Any) -> core_schema.CoreSchema:
"""Generate schema for a Sequence, e.g. `Sequence[int]`."""
item_type = self._get_first_arg_or_any(sequence_type)
item_type_schema = self.generate_schema(item_type)
list_schema = core_schema.list_schema(item_type_schema)

list_schema = core_schema.list_schema(self.generate_schema(item_type))
python_schema = core_schema.is_instance_schema(typing.Sequence, cls_repr='Sequence')
if item_type != Any:
from ._validators import sequence_validator
Expand Down
10 changes: 10 additions & 0 deletions pydantic/_internal/_validators.py
Expand Up @@ -31,6 +31,14 @@ def sequence_validator(
{'type_name': value_type.__name__},
)

# TODO: refactor sequence validation to validate with either a list or a tuple
# schema, depending on the type of the value.
# Additionally, we should be able to remove one of either this validator or the
# SequenceValidator in _std_types_schema.py (preferably this one, while porting over some logic).
# Effectively, a refactor for sequence validation is needed.
if value_type == tuple:
__input_value = list(__input_value)

Comment on lines +39 to +41
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is certainly not the most performant, but we already warn about the performance consequences of using Sequence[X] in the docs, so I'm ok with this change for now, assuming we implement the refactor for sequence validators in the future.

v_list = validator(__input_value)

# the rest of the logic is just re-creating the original type from `v_list`
Expand All @@ -39,6 +47,8 @@ def sequence_validator(
elif issubclass(value_type, range):
# return the list as we probably can't re-create the range
return v_list
elif value_type == tuple:
return tuple(v_list)
else:
# best guess at how to re-create the original type, more custom construction logic might be required
return value_type(v_list) # type: ignore[call-arg]
Expand Down
4 changes: 4 additions & 0 deletions tests/test_types.py
Expand Up @@ -2389,6 +2389,10 @@ class Model(BaseModel):
assert exc_info.value.errors(include_url=False) == errors


def test_sequence_strict():
assert TypeAdapter(Sequence[int]).validate_python((), strict=True) == ()


def test_int_validation():
class Model(BaseModel):
a: PositiveInt = None
Expand Down