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

Validating a dict value agains a Literal type gives the wrong ValidationError #6188

Closed
5 of 15 tasks
markus1978 opened this issue Jun 20, 2023 · 4 comments
Closed
5 of 15 tasks
Labels
bug V1 Bug related to Pydantic V1.X

Comments

@markus1978
Copy link

Initial Checks

  • I have searched GitHub for a duplicate issue and I'm sure this is something new
  • I have searched Google & StackOverflow for a solution and couldn't find anything
  • I have read and followed the docs and still think this is a bug
  • I am confident that the issue is with pydantic (not my code, or another library in the ecosystem like FastAPI or mypy)

Description

Validating a dict value agains a Literal type gives the wrong ValidationError. Instead of unexpected value; permitted: '*' the validation error just says unhashable type: 'dict' (type=type_error). Which does not describe the problem and is confusing, e.g. if handing this to API users in fastAPI. I would also expect an unexpected value; permitted: '*' for all non string values.

The respective validator in pydantic/validators.py (line 480ff) only catches a KeyError:

def make_literal_validator(type_: Any) -> Callable[[Any], Any]:
    permitted_choices = all_literal_values(type_)

    # To have a O(1) complexity and still return one of the values set inside the `Literal`,
    # we create a dict with the set values (a set causes some problems with the way intersection works).
    # In some cases the set value and checked value can indeed be different (see `test_literal_validator_str_enum`)
    allowed_choices = {v: v for v in permitted_choices}

    def literal_validator(v: Any) -> Any:
        try:
            return allowed_choices[v]
        except KeyError:
            raise errors.WrongConstantError(given=v, permitted=permitted_choices)

    return literal_validator

IMHO, it should also catch a TypeError (i.e. the "unhashable type") and produce a corresponding error. Or, it could check for isinstance(v, str) first and raise respective error if it is not a string.

Example Code

import pydantic
from typing import Literal

pydantic.parse_obj_as(Literal['*'], {})

Python, Pydantic & OS Version

pydantic version: 1.10.9
            pydantic compiled: True
                 install path: ********.pyenv/lib/python3.9/site-packages/pydantic
               python version: 3.9.16 (main, Dec  7 2022, 10:16:11)  [Clang 14.0.0 (clang-1400.0.29.202)]
                     platform: macOS-13.2-x86_64-i386-64bit
     optional deps. installed: ['devtools', 'dotenv', 'email-validator', 'typing-extensions']

Affected Components

@markus1978 markus1978 added bug V1 Bug related to Pydantic V1.X unconfirmed Bug not yet confirmed as valid/applicable labels Jun 20, 2023
@hramezani
Copy link
Member

Thanks @markus1978 for reporting.

Would you like to open a PR for fixing?

@hramezani hramezani removed the unconfirmed Bug not yet confirmed as valid/applicable label Jun 20, 2023
@markus1978
Copy link
Author

@hramezani

Would you like to open a PR for fixing?

Sure. I guess, I should base of and target 1.10.X-fixes?

@hramezani
Copy link
Member

@hramezani

Would you like to open a PR for fixing?

Sure. I guess, I should base of and target 1.10.X-fixes?

Yes

@hramezani
Copy link
Member

Fixed in d7afe99

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug V1 Bug related to Pydantic V1.X
Projects
None yet
Development

No branches or pull requests

2 participants