1

I want to create a pydantic Model with a Literal field, but the options should be derived from a list. Something like this:

from pydantic import BaseModel
from typing import Literal

opts=['foo','bar']

class MyModel(BaseModel):
    select_one : Literal[opts]

Is there some way this could be solved by enumeration?

Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
Erysol
  • 424
  • 1
  • 4
  • 14
  • 1
    Does this answer your question? [Python typing: Dynamically Create Literal Alias from List of Valid Values](https://stackoverflow.com/questions/64522040/python-typing-dynamically-create-literal-alias-from-list-of-valid-values) – MisterMiyagi Sep 02 '21 at 17:08

2 Answers2

1

Yes, there is. If you mix in str with enum.Enum, you'll get an enumeration with members that are fully backwards-compatible with strings (can be used anywhere a str type is expected) and are type-checker friendly.

from enum import Enum
from pydantic import BaseModel

class Options(str, Enum):
    FOO = 'foo'
    BAR = 'bar'

class MyModel(BaseModel):
    select_one : Options
Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
-1

In order for this to work, the Literal needs to be over a tuple (see also here).

There are several options, depending on your situation:

from pydantic import BaseModel
from typing import Literal

# First option:
class MyModel(BaseModel):
    select_one: Literal['foo', 'bar']

# Second option:
opts_tuple = ('foo', 'bar')
class MyModel(BaseModel):
    select_one: Literal[opts_tuple]

# Third option:
opts_list = ['foo', 'bar']
class MyModel(BaseModel):
    select_one: Literal[tuple(opts_list)]
Paul P
  • 3,346
  • 2
  • 12
  • 26
  • 2
    From the mypy documentation: "`Literal` types may contain one or more literal bools, ints, strs, bytes, and enum values. However, literal types cannot contain arbitrary expressions: types like `Literal[my_string.trim()]`, `Literal[x > 3]`, or `Literal[3j + 4]` are all illegal." As such, while all your options are valid *python* syntax, it is only your first option that would mean anything to a type-checker (and meaning something to the type checker is the whole point of adding type hints). https://mypy.readthedocs.io/en/stable/literal_types.html#limitations – Alex Waygood Sep 02 '21 at 21:13
  • 1
    Fair enough, I wasn't aware of the `mypy` limitations. Thanks for pointing it out! – Paul P Sep 02 '21 at 22:31