2024-04-16 00:33:48 +08:00
from typing import TYPE_CHECKING , Union , Optional
2024-01-15 13:24:55 +08:00
import pytest
2024-03-07 14:57:26 +08:00
from pydantic import Field , BaseModel
2024-01-15 13:24:55 +08:00
2024-04-16 00:33:48 +08:00
from nonebot . compat import PYDANTIC_V2
from nonebot . config import DOTENV_TYPE , BaseSettings , SettingsError , SettingsConfig
2024-01-15 13:24:55 +08:00
class Simple ( BaseModel ) :
a : int = 0
b : int = 0
c : dict = { }
complex : list = [ ]
class Example ( BaseSettings ) :
2024-04-16 00:33:48 +08:00
if TYPE_CHECKING :
_env_file : Optional [ DOTENV_TYPE ] = " .env " , " .env.example "
_env_nested_delimiter : Optional [ str ] = " __ "
if PYDANTIC_V2 :
model_config = SettingsConfig (
env_file = ( " .env " , " .env.example " ) , env_nested_delimiter = " __ "
)
else :
class Config ( # pyright: ignore[reportIncompatibleVariableOverride]
SettingsConfig
) :
env_file = " .env " , " .env.example "
env_nested_delimiter = " __ "
2024-01-15 13:24:55 +08:00
simple : str = " "
2024-04-16 00:33:48 +08:00
complex : list [ int ] = Field ( default = [ 1 ] )
complex_none : Optional [ list [ int ] ] = None
complex_union : Union [ int , list [ int ] ] = 1
2024-01-15 13:24:55 +08:00
nested : Simple = Simple ( )
nested_inner : Simple = Simple ( )
class ExampleWithoutDelimiter ( Example ) :
2024-04-16 00:33:48 +08:00
if PYDANTIC_V2 :
model_config = SettingsConfig ( env_nested_delimiter = None )
else :
class Config ( # pyright: ignore[reportIncompatibleVariableOverride]
SettingsConfig
) :
env_nested_delimiter = None
2024-01-15 13:24:55 +08:00
@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