from typing import List, Union, Optional import pytest from pydantic import Field, BaseModel from nonebot.config import DOTENV_TYPE, BaseSettings, SettingsError class Simple(BaseModel): a: int = 0 b: int = 0 c: dict = {} complex: list = [] class Example(BaseSettings): _env_file: Optional[DOTENV_TYPE] = ".env", ".env.example" _env_nested_delimiter: Optional[str] = "__" simple: str = "" complex: List[int] = Field(default=[1]) complex_none: Optional[List[int]] = None complex_union: Union[int, List[int]] = 1 nested: Simple = Simple() nested_inner: Simple = Simple() class Config: env_file = ".env", ".env.example" env_nested_delimiter = "__" class ExampleWithoutDelimiter(Example): class Config: env_nested_delimiter = None @pytest.mark.asyncio async def test_config_no_env(): config = Example(_env_file=None) assert config.simple == "" with pytest.raises(AttributeError): config.common_config @pytest.mark.asyncio async def test_config_with_env(): config = Example(_env_file=(".env", ".env.example")) assert config.simple == "simple" assert config.complex == [1, 2, 3] assert config.complex_none is None assert config.complex_union == [1, 2, 3] assert config.nested.a == 1 assert config.nested.b == 2 assert config.nested.c == {"c": "3"} assert config.nested.complex == [1, 2, 3] with pytest.raises(AttributeError): config.nested__b with pytest.raises(AttributeError): config.nested__c__c with pytest.raises(AttributeError): config.nested__complex assert config.nested_inner.a == 1 assert config.nested_inner.b == 2 with pytest.raises(AttributeError): config.nested_inner__a with pytest.raises(AttributeError): config.nested_inner__b assert config.common_config == "common" assert config.other_simple == "simple" assert config.other_nested == {"a": 1, "b": 2} with pytest.raises(AttributeError): config.other_nested__b assert config.other_nested_inner == {"a": 1, "b": 2} with pytest.raises(AttributeError): config.other_nested_inner__a with pytest.raises(AttributeError): config.other_nested_inner__b @pytest.mark.asyncio async def test_config_error_env(): with pytest.MonkeyPatch().context() as m: m.setenv("COMPLEX", "not json") with pytest.raises(SettingsError): Example(_env_file=(".env", ".env.example")) @pytest.mark.asyncio async def test_config_without_delimiter(): config = ExampleWithoutDelimiter() assert config.nested.a == 1 assert config.nested.b == 0 assert config.nested__b == 2 assert config.nested.c == {} assert config.nested__c__c == 3 assert config.nested.complex == [] assert config.nested__complex == [1, 2, 3] assert config.nested_inner.a == 0 assert config.nested_inner.b == 0 assert config.other_nested == {"a": 1} assert config.other_nested__b == 2 with pytest.raises(AttributeError): config.other_nested_inner assert config.other_nested_inner__a == 1 assert config.other_nested_inner__b == 2