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
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.
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
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.