From 5e3f1b5435ab8909e4673b4f6462ceacc866429b Mon Sep 17 00:00:00 2001 From: yanyongyu Date: Wed, 27 Jan 2021 11:39:34 +0800 Subject: [PATCH] :sparkles: new common config loading from .env --- docs/guide/basic-configuration.md | 5 ++++- nonebot/__init__.py | 1 + nonebot/config.py | 32 ++++++++++++++++++++++++++++++- tests/.env | 1 + 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/docs/guide/basic-configuration.md b/docs/guide/basic-configuration.md index 0cd9156a..84ed8fe0 100644 --- a/docs/guide/basic-configuration.md +++ b/docs/guide/basic-configuration.md @@ -13,11 +13,14 @@ NoneBot 在启动时将会从系统环境变量或者 `.env` 文件中寻找变量 `ENVIRONMENT` (大小写不敏感),默认值为 `prod`。 这将引导 NoneBot 从系统环境变量或者 `.env.{ENVIRONMENT}` 文件中进一步加载具体配置。 +`.env` 文件是基础环境配置文件,该文件中的配置项在不同环境下都会被加载,但会被 `.env.{ENVIRONMENT}` 文件中的配置所覆盖。 + 现在,我们在 `.env` 文件中写入当前环境信息: ```bash # .env ENVIRONMENT=dev +CUSTOM_CONFIG=common config # 这个配置项在任何环境中都会被加载 ``` 如你所想,之后 NoneBot 就会从 `.env.dev` 文件中加载环境变量。 @@ -26,7 +29,7 @@ ENVIRONMENT=dev NoneBot 使用 [pydantic](https://pydantic-docs.helpmanual.io/) 进行配置管理,会从 `.env.{ENVIRONMENT}` 文件中获悉环境配置。 -可以在 NoneBot 初始化时指定加载某个环境配置文件: `nonebot.init(_env_file=".env.dev")`,这将忽略你在 `.env` 中设置的环境信息。 +可以在 NoneBot 初始化时指定加载某个环境配置文件: `nonebot.init(_env_file=".env.dev")`,这将忽略你在 `.env` 中设置的 `ENVIRONMENT` 。 :::warning 提示 由于 `pydantic` 使用 JSON 解析配置项,请确保配置项值为 JSON 格式的数据。如: diff --git a/nonebot/__init__.py b/nonebot/__init__.py index 11dad7cd..54857891 100644 --- a/nonebot/__init__.py +++ b/nonebot/__init__.py @@ -175,6 +175,7 @@ def init(*, _env_file: Optional[str] = None, **kwargs): logger.opt( colors=True).info(f"Current Env: {env.environment}") config = Config(**kwargs, + _common_config=env.dict(), _env_file=_env_file or f".env.{env.environment}") default_filter.level = "DEBUG" if config.debug else "INFO" diff --git a/nonebot/config.py b/nonebot/config.py index ae5b6c4b..9fb09e46 100644 --- a/nonebot/config.py +++ b/nonebot/config.py @@ -20,12 +20,41 @@ from datetime import timedelta from ipaddress import IPv4Address from typing import Any, Set, Dict, Union, Mapping, Optional +from pydantic.utils import deep_update from pydantic import BaseSettings, IPvAnyAddress from pydantic.env_settings import SettingsError, env_file_sentinel, read_env_file class BaseConfig(BaseSettings): + def __init__( + __pydantic_self__, # type: ignore + _common_config: Optional[Dict[Any, Any]] = None, + _env_file: Union[Path, str, None] = env_file_sentinel, + _env_file_encoding: Optional[str] = None, + _secrets_dir: Union[Path, str, None] = None, + **values: Any) -> None: + super(BaseSettings, + __pydantic_self__).__init__(**__pydantic_self__._build_values( + values, + _common_config=_common_config, + _env_file=_env_file, + _env_file_encoding=_env_file_encoding, + _secrets_dir=_secrets_dir)) + + def _build_values( + self, + init_kwargs: Dict[str, Any], + _common_config: Optional[Dict[Any, Any]] = None, + _env_file: Union[Path, str, None] = None, + _env_file_encoding: Optional[str] = None, + _secrets_dir: Union[Path, str, None] = None, + ) -> Dict[str, Any]: + return deep_update(self._build_secrets_files(_secrets_dir), + _common_config or {}, + self._build_environ(_env_file, + _env_file_encoding), init_kwargs) + def _build_environ( self, _env_file: Union[Path, str, None] = None, @@ -92,7 +121,7 @@ class BaseConfig(BaseSettings): return self.__dict__.get(name) -class Env(BaseSettings): +class Env(BaseConfig): """ 运行环境配置。大小写不敏感。 @@ -109,6 +138,7 @@ class Env(BaseSettings): """ class Config: + extra = "allow" env_file = ".env" diff --git a/tests/.env b/tests/.env index baf48fa8..9ef1d705 100644 --- a/tests/.env +++ b/tests/.env @@ -1 +1,2 @@ ENVIRONMENT=dev +CUSTOM_CONFIG=common