mirror of
https://github.com/kennethreitz/pydantic.git
synced 2026-06-05 23:00:18 +00:00
04391da318
* fix for 'missing' error with validate_all or validate_always * update HISTORY
180 lines
4.1 KiB
Python
180 lines
4.1 KiB
Python
from typing import List, Set
|
|
|
|
import pytest
|
|
|
|
from pydantic import BaseModel, BaseSettings, NoneStr, ValidationError, dataclasses
|
|
from pydantic.env_settings import SettingsError
|
|
|
|
|
|
class SimpleSettings(BaseSettings):
|
|
apple: str
|
|
|
|
|
|
def test_sub_env(env):
|
|
env.set('APP_APPLE', 'hello')
|
|
s = SimpleSettings()
|
|
assert s.apple == 'hello'
|
|
|
|
|
|
def test_sub_env_override(env):
|
|
env.set('APP_APPLE', 'hello')
|
|
s = SimpleSettings(apple='goodbye')
|
|
assert s.apple == 'goodbye'
|
|
|
|
|
|
def test_sub_env_missing():
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
SimpleSettings()
|
|
assert exc_info.value.errors() == [{'loc': ('apple',), 'msg': 'field required', 'type': 'value_error.missing'}]
|
|
|
|
|
|
def test_other_setting(env):
|
|
with pytest.raises(ValidationError):
|
|
SimpleSettings(apple='a', foobar=42)
|
|
|
|
|
|
def test_env_with_aliass(env):
|
|
class Settings(BaseSettings):
|
|
apple: str = ...
|
|
|
|
class Config:
|
|
fields = {'apple': 'BOOM'}
|
|
|
|
env.set('BOOM', 'hello')
|
|
assert Settings().apple == 'hello'
|
|
|
|
|
|
class DateModel(BaseModel):
|
|
pips: bool = False
|
|
|
|
|
|
class ComplexSettings(BaseSettings):
|
|
apples: List[str] = []
|
|
bananas: Set[int] = set()
|
|
carrots: dict = {}
|
|
date: DateModel = DateModel()
|
|
|
|
|
|
def test_list(env):
|
|
env.set('APP_APPLES', '["russet", "granny smith"]')
|
|
s = ComplexSettings()
|
|
assert s.apples == ['russet', 'granny smith']
|
|
assert s.date.pips is False
|
|
|
|
|
|
def test_set_dict_model(env):
|
|
env.set('APP_BANANAS', '[1, 2, 3, 3]')
|
|
env.set('APP_CARROTS', '{"a": null, "b": 4}')
|
|
env.set('APP_DATE', '{"pips": true}')
|
|
s = ComplexSettings()
|
|
assert s.bananas == {1, 2, 3}
|
|
assert s.carrots == {'a': None, 'b': 4}
|
|
assert s.date.pips is True
|
|
|
|
|
|
def test_invalid_json(env):
|
|
env.set('APP_APPLES', '["russet", "granny smith",]')
|
|
with pytest.raises(SettingsError):
|
|
ComplexSettings()
|
|
|
|
|
|
def test_required_sub_model(env):
|
|
class Settings(BaseSettings):
|
|
foobar: DateModel
|
|
|
|
with pytest.raises(ValidationError):
|
|
Settings()
|
|
env.set('APP_FOOBAR', '{"pips": "TRUE"}')
|
|
s = Settings()
|
|
assert s.foobar.pips is True
|
|
|
|
|
|
def test_non_class(env):
|
|
class Settings(BaseSettings):
|
|
foobar: NoneStr
|
|
|
|
env.set('APP_FOOBAR', 'xxx')
|
|
s = Settings()
|
|
assert s.foobar == 'xxx'
|
|
|
|
|
|
def test_alias_matches_name(env):
|
|
class Settings(BaseSettings):
|
|
foobar: str
|
|
|
|
class Config:
|
|
fields = {'foobar': 'foobar'}
|
|
|
|
env.set('foobar', 'xxx')
|
|
s = Settings()
|
|
assert s.foobar == 'xxx'
|
|
|
|
|
|
def test_case_insensitive(env):
|
|
class Settings(BaseSettings):
|
|
foo: str
|
|
bAR: str
|
|
|
|
class Config:
|
|
case_insensitive = True
|
|
|
|
env.set('apP_foO', 'foo')
|
|
env.set('app_bar', 'bar')
|
|
s = Settings()
|
|
assert s.foo == 'foo'
|
|
assert s.bAR == 'bar'
|
|
|
|
|
|
def test_nested_dataclass(env):
|
|
@dataclasses.dataclass
|
|
class MyDataclass:
|
|
foo: int
|
|
bar: str
|
|
|
|
class Settings(BaseSettings):
|
|
n: MyDataclass
|
|
|
|
env.set('APP_N', '[123, "bar value"]')
|
|
s = Settings()
|
|
assert isinstance(s.n, MyDataclass)
|
|
assert s.n.foo == 123
|
|
assert s.n.bar == 'bar value'
|
|
|
|
|
|
def test_config_file_settings(env):
|
|
class Settings(BaseSettings):
|
|
foo: int
|
|
bar: str
|
|
|
|
def _build_values(self, init_kwargs):
|
|
return {**init_kwargs, **self._build_environ()}
|
|
|
|
env.set('APP_BAR', 'env setting')
|
|
|
|
s = Settings(foo='123', bar='argument')
|
|
assert s.foo == 123
|
|
assert s.bar == 'env setting'
|
|
|
|
|
|
def test_config_file_settings_nornir(env):
|
|
"""
|
|
See https://github.com/samuelcolvin/pydantic/pull/341#issuecomment-450378771
|
|
"""
|
|
|
|
class Settings(BaseSettings):
|
|
a: str
|
|
b: str
|
|
c: str
|
|
|
|
def _build_values(self, init_kwargs):
|
|
config_settings = init_kwargs.pop('__config_settings__')
|
|
return {**config_settings, **init_kwargs, **self._build_environ()}
|
|
|
|
env.set('APP_C', 'env setting c')
|
|
|
|
config = {'a': 'config a', 'b': 'config b', 'c': 'config c'}
|
|
s = Settings(__config_settings__=config, b='argument b', c='argument c')
|
|
assert s.a == 'config a'
|
|
assert s.b == 'argument b'
|
|
assert s.c == 'env setting c'
|