How to pass dynamic strings to pydantic fields

Question:

I have this code in my framework on Python 3.10 + Pydantic

class DataInclude(BaseModel):
    currencyAccount: Literal["CNY счет", "AMD счет", "RUB счет", "USD счет", "EUR счет", "GBP счет", "CHF счет"]

I want to learn how to do it right to use dynamic parameters in a string

name = (CNY, AMD, RUB, USD, EUR, GBP, CHF)
class DataInclude(BaseModel):
        currencyAccount: Literal[f"{name}счет"]

With the help of regex I couldn’t either

Asked By: Alex

||

Answers:

As I mentioned in my comment already, you cannot dynamically specify a typing.Literal type.

Instead of doing that, you could just create your own enum.Enum to represent the valid currency options. Pydantic plays nicely with those. And the Enum functional API allows you to set it up dynamically.

from enum import Enum

from pydantic import BaseModel, ValidationError


CURRENCIES = (
    "CNY",
    "AMD",
    "RUB",
    "USD",
    "EUR",
    "GBP",
    "CHF",
)

Currency = Enum(
    "Currency",
    ((curr, f"{curr} счет") for curr in CURRENCIES),
    type=str,
)


class Data(BaseModel):
    currency: Currency


if __name__ == "__main__":
    obj = Data(currency="CNY счет")
    print(obj, "n")
    try:
        Data(currency="foo")
    except ValidationError as e:
        print(e)

Output:

currency=<Currency.CNY: 'CNY счет'> 

1 validation error for Data
currency
  value is not a valid enumeration member ...

The drawback to the Enum functional API is that your average static type checker will not be able to infer any enumeration members. Thus, your IDE will probably not provide you with auto-suggestions, if you wanted to use a member like Currency.AMD for example. If that bothers you, consider using the regular class definition for that Currency enum.

Answered By: Daniil Fajnberg
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.