support user-defined format spec for message template

This commit is contained in:
Mix 2022-01-01 21:52:54 +08:00
parent 620938c26c
commit 983e5aefdb

View File

@ -4,6 +4,9 @@ from string import Formatter
from typing import (
TYPE_CHECKING,
Any,
Callable,
Dict,
Optional,
Set,
List,
Type,
@ -23,6 +26,9 @@ if TYPE_CHECKING:
TM = TypeVar("TM", bound="Message")
TF = TypeVar("TF", str, "Message")
FormatSpecFunc = Callable[[Any], str]
FormatSpecFunc_T = TypeVar("FormatSpecFunc_T", bound=FormatSpecFunc)
class MessageTemplate(Formatter, Generic[TF]):
"""消息模板格式化实现类"""
@ -50,8 +56,18 @@ class MessageTemplate(Formatter, Generic[TF]):
* ``template: Union[str, Message]``: 模板
* ``factory: Union[str, Message]``: 消息构造类型默认为 `str`
"""
self.template: Union[str, TF] = template
self.template: TF = template
self.factory: Type[TF] = factory
self.format_specs: Dict[str, FormatSpecFunc] = {}
def add_format_spec(
self, spec: FormatSpecFunc_T, name: Optional[str] = None
) -> FormatSpecFunc_T:
name = name or spec.__name__
if name in self.format_specs:
raise ValueError(f"Format spec {name} already exists!")
self.format_specs[name] = spec
return spec
def format(self, *args: Any, **kwargs: Any) -> TF:
"""
@ -69,7 +85,7 @@ class MessageTemplate(Formatter, Generic[TF]):
else:
raise TypeError("template must be a string or instance of Message!")
return msg
return msg # type:ignore
def vformat(
self, format_string: str, args: Sequence[Any], kwargs: Mapping[str, Any]
@ -165,13 +181,15 @@ class MessageTemplate(Formatter, Generic[TF]):
(
super().format_field(value, format_spec)
if (
(method is None)
or (
not isinstance(method_type, (classmethod, staticmethod))
) # Only Call staticmethod or classmethod
method is None
or not isinstance(method_type, (classmethod, staticmethod))
)
else (
self.format_specs[format_spec](value)
if format_spec in self.format_specs
else method(value)
)
)
if format_spec
else value
)