Skip to content

Commit

Permalink
🔇 Feature: 调整日志输出格式与等级 (#1233)
Browse files Browse the repository at this point in the history
  • Loading branch information
yanyongyu authored Sep 9, 2022
1 parent 179d710 commit 8c42490
Show file tree
Hide file tree
Showing 29 changed files with 261 additions and 165 deletions.
17 changes: 15 additions & 2 deletions nonebot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@
import importlib
from typing import Any, Dict, Type, Optional

import loguru

from nonebot.log import logger
from nonebot.adapters import Bot
from nonebot.utils import escape_tag
from nonebot.config import Env, Config
from nonebot.log import logger, default_filter
from nonebot.drivers import Driver, ReverseDriver, combine_driver

try:
Expand Down Expand Up @@ -206,6 +208,15 @@ def _resolve_combine_expr(obj_str: str) -> Type[Driver]:
return combine_driver(DriverClass, *mixins)


def _log_patcher(record: "loguru.Record"):
record["name"] = (
plugin.name
if (module_name := record["name"])
and (plugin := get_plugin_by_module_name(module_name))
else (module_name and module_name.split(".")[0])
)


def init(*, _env_file: Optional[str] = None, **kwargs: Any) -> None:
"""初始化 NoneBot 以及 全局 {ref}`nonebot.drivers.Driver` 对象。
Expand All @@ -232,7 +243,9 @@ def init(*, _env_file: Optional[str] = None, **kwargs: Any) -> None:
_env_file=_env_file or f".env.{env.environment}",
)

default_filter.level = config.log_level
logger.configure(
extra={"nonebot_log_level": config.log_level}, patcher=_log_patcher
)
logger.opt(colors=True).info(
f"Current <y><b>Env: {escape_tag(env.environment)}</b></y>"
)
Expand Down
17 changes: 9 additions & 8 deletions nonebot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
)

from nonebot.log import logger
from nonebot.utils import escape_tag


class CustomEnvSettings(EnvSettingsSource):
Expand Down Expand Up @@ -85,13 +84,15 @@ def __call__(self, settings: BaseSettings) -> Dict[str, Any]:
if env_file_vars:
for env_name in env_file_vars.keys():
env_val = env_vars[env_name]
try:
if env_val:
env_val = settings.__config__.json_loads(env_val.strip())
except ValueError as e:
logger.opt(colors=True, exception=e).trace(
f"Error while parsing JSON for {escape_tag(env_name)}. Assumed as string."
)
if env_val and (val_striped := env_val.strip()):
try:
env_val = settings.__config__.json_loads(val_striped)
except ValueError as e:
logger.trace(
"Error while parsing JSON for "
f"{env_name!r}={val_striped!r}. "
"Assumed as string."
)

d[env_name] = env_val

Expand Down
34 changes: 23 additions & 11 deletions nonebot/dependencies/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

from nonebot.log import logger
from nonebot.typing import _DependentCallable
from nonebot.exception import SkippedException
from nonebot.utils import run_sync, is_coroutine_callable

from .utils import check_field_type, get_typed_signature
Expand Down Expand Up @@ -85,7 +86,15 @@ class Dependent(Generic[R]):
parameterless: Tuple[Param] = field(default_factory=tuple)

def __repr__(self) -> str:
return f"<Dependent call={self.call}>"
if inspect.isfunction(self.call) or inspect.isclass(self.call):
call_str = self.call.__name__
else:
call_str = repr(self.call)
return (
f"Dependent(call={call_str}"
+ (f", parameterless={self.parameterless}" if self.parameterless else "")
+ ")"
)

async def __call__(self, **kwargs: Any) -> R:
# do pre-check
Expand Down Expand Up @@ -178,19 +187,22 @@ def parse(
else cls.parse_parameterless(tuple(parameterless), allow_types)
)

logger.trace(
f"Parsed dependent with call={call}, "
f"params={params}, "
f"parameterless={parameterless_params}"
)

return cls(call, params, parameterless_params)

async def check(self, **params: Any) -> None:
await asyncio.gather(*(param._check(**params) for param in self.parameterless))
await asyncio.gather(
*(cast(Param, param.field_info)._check(**params) for param in self.params)
)
try:
await asyncio.gather(
*(param._check(**params) for param in self.parameterless)
)
await asyncio.gather(
*(
cast(Param, param.field_info)._check(**params)
for param in self.params
)
)
except SkippedException as e:
logger.trace(f"{self} skipped due to {e}")
raise

async def _solve_field(self, field: ModelField, params: Dict[str, Any]) -> Any:
value = await cast(Param, field.field_info)._solve(**params)
Expand Down
2 changes: 1 addition & 1 deletion nonebot/drivers/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

try:
import aiohttp
except ImportError:
except ImportError: # pragma: no cover
raise ImportError(
"Please install aiohttp first to use this driver. `pip install nonebot2[aiohttp]`"
) from None
Expand Down
2 changes: 1 addition & 1 deletion nonebot/drivers/httpx.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

try:
import httpx
except ImportError:
except ImportError: # pragma: no cover
raise ImportError(
"Please install httpx by using `pip install nonebot2[httpx]`"
) from None
Expand Down
2 changes: 1 addition & 1 deletion nonebot/drivers/quart.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
from quart import Quart, Request, Response
from quart.datastructures import FileStorage
from quart import Websocket as QuartWebSocket
except ImportError:
except ImportError: # pragma: no cover
raise ImportError(
"Please install Quart by using `pip install nonebot2[quart]`"
) from None
Expand Down
4 changes: 2 additions & 2 deletions nonebot/drivers/websockets.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
try:
from websockets.exceptions import ConnectionClosed
from websockets.legacy.client import Connect, WebSocketClientProtocol
except ImportError:
except ImportError: # pragma: no cover
raise ImportError(
"Please install websockets by using `pip install nonebot2[websockets]`"
)
) from None

logger = logging.Logger("websockets.client", "INFO")
logger.addHandler(LoguruHandler())
Expand Down
45 changes: 30 additions & 15 deletions nonebot/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,14 @@ def __init__(self, status: int = 0, message: Optional[str] = None):
self.status = status
self.message = message

def __repr__(self):
return f"<ParserExit status={self.status} message={self.message}>"
def __repr__(self) -> str:
return (
f"ParserExit(status={self.status}"
+ (f", message={self.message!r}" if self.message else "")
+ ")"
)

def __str__(self):
def __str__(self) -> str:
return self.__repr__()


Expand All @@ -68,10 +72,10 @@ class IgnoredException(ProcessException):
def __init__(self, reason: Any):
self.reason: Any = reason

def __repr__(self):
return f"<IgnoredException, reason={self.reason}>"
def __repr__(self) -> str:
return f"IgnoredException(reason={self.reason!r})"

def __str__(self):
def __str__(self) -> str:
return self.__repr__()


Expand Down Expand Up @@ -99,11 +103,14 @@ def __init__(self, param: ModelField, value: Any):
self.param: ModelField = param
self.value: Any = value

def __repr__(self):
return f"<TypeMisMatch, param={self.param}, value={self.value}>"
def __repr__(self) -> str:
return (
f"TypeMisMatch(param={self.param.name}, "
f"type={self.param._type_display()}, value={self.value!r}>"
)

def __str__(self):
self.__repr__()
def __str__(self) -> str:
return self.__repr__()


class MockApiException(ProcessException):
Expand All @@ -116,10 +123,10 @@ class MockApiException(ProcessException):
def __init__(self, result: Any):
self.result = result

def __repr__(self):
return f"<ApiCancelledException, result={self.result}>"
def __repr__(self) -> str:
return f"MockApiException(result={self.result!r})"

def __str__(self):
def __str__(self) -> str:
return self.__repr__()


Expand Down Expand Up @@ -195,7 +202,8 @@ class AdapterException(NoneBotException):
adapter_name: 标识 adapter
"""

def __init__(self, adapter_name: str) -> None:
def __init__(self, adapter_name: str, *args: object) -> None:
super().__init__(*args)
self.adapter_name: str = adapter_name


Expand Down Expand Up @@ -231,4 +239,11 @@ def __init__(self, code: int, reason: Optional[str] = None):
self.reason = reason

def __repr__(self) -> str:
return f"<WebSocketClosed code={self.code} reason={self.reason}>"
return (
f"WebSocketClosed(code={self.code}"
+ (f", reason={self.reason!r}" if self.reason else "")
+ ")"
)

def __str__(self) -> str:
return self.__repr__()
3 changes: 3 additions & 0 deletions nonebot/internal/adapter/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ def __init__(self, driver: Driver, **kwargs: Any):
self.bots: Dict[str, Bot] = {}
"""本协议适配器已建立连接的 {ref}`nonebot.adapters.Bot` 实例"""

def __repr__(self) -> str:
return f"Adapter(name={self.get_name()!r})"

@classmethod
@abc.abstractmethod
def get_name(cls) -> str:
Expand Down
12 changes: 7 additions & 5 deletions nonebot/internal/adapter/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@
from .adapter import Adapter
from .message import Message, MessageSegment


class _ApiCall(Protocol):
async def __call__(self, **kwargs: Any) -> Any:
...
class _ApiCall(Protocol):
async def __call__(self, **kwargs: Any) -> Any:
...


class Bot(abc.ABC):
Expand All @@ -40,7 +39,10 @@ def __init__(self, adapter: "Adapter", self_id: str):
self.self_id: str = self_id
"""机器人 ID"""

def __getattr__(self, name: str) -> _ApiCall:
def __repr__(self) -> str:
return f"Bot(type={self.type!r}, self_id={self.self_id!r})"

def __getattr__(self, name: str) -> "_ApiCall":
return partial(self.call_api, name)

@property
Expand Down
3 changes: 3 additions & 0 deletions nonebot/internal/adapter/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ def __init__( # type:ignore
self.factory: Type[TF] = factory
self.format_specs: Dict[str, FormatSpecFunc] = {}

def __repr__(self) -> str:
return f"MessageTemplate({self.template!r}, factory={self.factory!r})"

def add_format_spec(
self, spec: FormatSpecFunc_T, name: Optional[str] = None
) -> FormatSpecFunc_T:
Expand Down
18 changes: 12 additions & 6 deletions nonebot/internal/driver/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,18 @@ def __init__(self, env: Env, config: Config):
"""环境名称"""
self.config: Config = config
"""全局配置对象"""
self._clients: Dict[str, "Bot"] = {}
self._bots: Dict[str, "Bot"] = {}

def __repr__(self) -> str:
return (
f"Driver(type={self.type!r}, "
f"adapters={len(self._adapters)}, bots={len(self._bots)})"
)

@property
def bots(self) -> Dict[str, "Bot"]:
"""获取当前所有已连接的 Bot"""
return self._clients
return self._bots

def register_adapter(self, adapter: Type["Adapter"], **kwargs) -> None:
"""注册一个协议适配器
Expand Down Expand Up @@ -124,9 +130,9 @@ def on_bot_disconnect(cls, func: T_BotDisconnectionHook) -> T_BotDisconnectionHo

def _bot_connect(self, bot: "Bot") -> None:
"""在连接成功后,调用该函数来注册 bot 对象"""
if bot.self_id in self._clients:
if bot.self_id in self._bots:
raise RuntimeError(f"Duplicate bot connection with id {bot.self_id}")
self._clients[bot.self_id] = bot
self._bots[bot.self_id] = bot

async def _run_hook(bot: "Bot") -> None:
coros = list(
Expand All @@ -148,8 +154,8 @@ async def _run_hook(bot: "Bot") -> None:

def _bot_disconnect(self, bot: "Bot") -> None:
"""在连接断开后,调用该函数来注销 bot 对象"""
if bot.self_id in self._clients:
del self._clients[bot.self_id]
if bot.self_id in self._bots:
del self._bots[bot.self_id]

async def _run_hook(bot: "Bot") -> None:
coros = list(
Expand Down
21 changes: 11 additions & 10 deletions nonebot/internal/driver/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ def __init__(
self.files.append((name, file_info)) # type: ignore

def __repr__(self) -> str:
class_name = self.__class__.__name__
url = str(self.url)
return f"<{class_name}({self.method!r}, {url!r})>"
return f"{self.__class__.__name__}(method={self.method!r}, url='{self.url!s}')"


class Response:
Expand Down Expand Up @@ -161,12 +159,18 @@ def __init__(
# request
self.request: Optional[Request] = request

def __repr__(self) -> str:
return f"{self.__class__.__name__}(status_code={self.status_code!r})"


class WebSocket(abc.ABC):
def __init__(self, *, request: Request):
# request
self.request: Request = request

def __repr__(self) -> str:
return f"{self.__class__.__name__}('{self.request.url!s}')"

@property
@abc.abstractmethod
def closed(self) -> bool:
Expand Down Expand Up @@ -320,17 +324,14 @@ def __len__(self) -> int:
return len(self.jar)

def __iter__(self) -> Iterator[Cookie]:
return (cookie for cookie in self.jar)
return iter(self.jar)

def __repr__(self) -> str:
cookies_repr = ", ".join(
[
f"<Cookie {cookie.name}={cookie.value} for {cookie.domain} />"
for cookie in self.jar
]
f"Cookie({cookie.name}={cookie.value} for {cookie.domain})"
for cookie in self.jar
)

return f"<Cookies [{cookies_repr}]>"
return f"{self.__class__.__name__}({cookies_repr})"


@dataclass
Expand Down
Loading

0 comments on commit 8c42490

Please sign in to comment.