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

Allows Optional lists with unique_items check #4568

Merged
merged 1 commit into from Oct 17, 2022
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
1 change: 1 addition & 0 deletions changes/4568-mfulgo.md
@@ -0,0 +1 @@
Fixes error passing None for optional lists with `unique_items`
5 changes: 4 additions & 1 deletion pydantic/types.py
Expand Up @@ -599,7 +599,10 @@ def list_length_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]':
return v

@classmethod
def unique_items_validator(cls, v: 'List[T]') -> 'List[T]':
def unique_items_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]':
if v is None:
return None

for i, value in enumerate(v, start=1):
if value in v[i:]:
raise errors.ListUniqueItemsError()
Expand Down
18 changes: 17 additions & 1 deletion tests/test_validators.py
Expand Up @@ -7,7 +7,7 @@
import pytest
from typing_extensions import Literal

from pydantic import BaseModel, ConfigError, Extra, Field, ValidationError, errors, validator
from pydantic import BaseModel, ConfigError, Extra, Field, ValidationError, conlist, errors, validator
from pydantic.class_validators import make_generic_validator, root_validator


Expand Down Expand Up @@ -1329,3 +1329,19 @@ def post_root(cls, values):

B(x='pika')
assert validate_stub.call_args_list == [mocker.call('B', 'pre'), mocker.call('B', 'post')]


def test_list_unique_items_with_optional():
class Model(BaseModel):
foo: Optional[List[str]] = Field(None, unique_items=True)
bar: conlist(str, unique_items=True) = Field(None)

assert Model().dict() == {'foo': None, 'bar': None}
assert Model(foo=None, bar=None).dict() == {'foo': None, 'bar': None}
assert Model(foo=['k1'], bar=['k1']).dict() == {'foo': ['k1'], 'bar': ['k1']}
with pytest.raises(ValidationError) as exc_info:
Model(foo=['k1', 'k1'], bar=['k1', 'k1'])
assert exc_info.value.errors() == [
{'loc': ('foo',), 'msg': 'the list has duplicated items', 'type': 'value_error.list.unique_items'},
{'loc': ('bar',), 'msg': 'the list has duplicated items', 'type': 'value_error.list.unique_items'},
]