-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Closed
Labels
Description
Question
Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":
pydantic version: 1.5
pydantic compiled: False
install path: D:\dev\github\pydantic\issues\.venv\Lib\site-packages\pydantic
python version: 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 18 2019, 23:46:00) [MSC v.1916 32 bit (Intel)]
platform: Windows-10-10.0.19559-SP0
optional deps. installed: []
import os
from pathlib import Path
import pydantic
class Config1(pydantic.BaseSettings):
port: int = pydantic.Field(1234, const=True)
class Config2(pydantic.BaseSettings):
port: int = pydantic.Field("1234", const=True)
print("No env")
print("Config1", Config1().dict())
print("Config2", Config2().dict())
print("With .env")
Path(".env").write_text("port=1234\n")
print("Config1", Config1(_env_file=".env").dict()) # FAILS
print("Config2", Config2(_env_file=".env").dict())
print("With os.environ")
os.environ["port"] = "1234"
print("Config1", Config1().dict()) # FAILS
print("Config2", Config2().dict())Copy-paste in the Python REPL to continue on errors:
>>> import os
>>> from pathlib import Path
>>> import pydantic
>>>
>>> class Config1(pydantic.BaseSettings):
... port: int = pydantic.Field(1234, const=True)
...
>>> class Config2(pydantic.BaseSettings):
... port: int = pydantic.Field("1234", const=True)
...
>>> print("No env")
No env
>>> print("Config1", Config1().dict())
Config1 {'port': 1234}
>>> print("Config2", Config2().dict())
Config2 {'port': 1234}
>>>
>>> print("With .env")
With .env
>>> Path(".env").write_text("port=1234\n")
10
>>> print("Config1", Config1(_env_file=".env").dict()) # FAILS
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\dev\github\pydantic\issues\.venv\lib\site-packages\pydantic\env_settings.py", line 28, in __init__
super().__init__(**__pydantic_self__._build_values(values, _env_file=_env_file))
File "D:\dev\github\pydantic\issues\.venv\lib\site-packages\pydantic\main.py", line 338, in __init__
raise validation_error
pydantic.error_wrappers.ValidationError: 1 validation error for Config1
port
unexpected value; permitted: 1234 (type=value_error.const; given=1234; permitted=[1234])
>>> print("Config2", Config2(_env_file=".env").dict())
Config2 {'port': 1234}
>>>
>>> print("With os.environ")
With os.environ
>>> os.environ["port"] = "1234"
>>> print("Config1", Config1().dict()) # FAILS
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\dev\github\pydantic\issues\.venv\lib\site-packages\pydantic\env_settings.py", line 28, in __init__
super().__init__(**__pydantic_self__._build_values(values, _env_file=_env_file))
File "D:\dev\github\pydantic\issues\.venv\lib\site-packages\pydantic\main.py", line 338, in __init__
raise validation_error
pydantic.error_wrappers.ValidationError: 1 validation error for Config1
port
unexpected value; permitted: 1234 (type=value_error.const; given=1234; permitted=[1234])
>>> print("Config2", Config2().dict())
Config2 {'port': 1234}Looked at the code, and noticed that constant_validator was applied with pre_validators -- before the type validators -- which explains the behaviour.
My question is: is this by design? It looks odd to have the default value be of a different type than the annotation. Additionally, if the value comes from a JSON object instead, then using const means the input type is now constrained to the type of the default value. For instance:
>>> import pydantic
>>>
>>> class Config1(pydantic.BaseSettings):
... port_const: int = pydantic.Field(1234, const=True)
... port: int = pydantic.Field(1234)
...
>>> print(Config1())
port_const=1234 port=1234
>>> print(Config1(port_const=1234, port=1234))
port_const=1234 port=1234
>>> print(Config1(port_const="1234", port="1234"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\dev\github\pydantic\issues\.venv\lib\site-packages\pydantic\env_settings.py", line 28, in __init__
super().__init__(**__pydantic_self__._build_values(values, _env_file=_env_file))
File "D:\dev\github\pydantic\issues\.venv\lib\site-packages\pydantic\main.py", line 338, in __init__
raise validation_error
pydantic.error_wrappers.ValidationError: 1 validation error for Config1
port_const
unexpected value; permitted: 1234 (type=value_error.const; given=1234; permitted=[1234])