Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0c97ada

Browse files
committed
enhance Element and ElementRegistry classes with detailed docstrings and improve code formatting
1 parent 09aebcf commit 0c97ada

1 file changed

Lines changed: 111 additions & 32 deletions

File tree

nt_msg/__init__.py

Lines changed: 111 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,45 @@
77

88
from db import GroupMessage
99

10-
E = TypeVar('E', bound="Element")
10+
E = TypeVar("E", bound="Element")
1111

1212

1313
class ElementRegistry:
14+
"""
15+
A registry for managing and decoding elements based on their IDs.
16+
17+
Attributes:
18+
_decoders (defaultdict): A dictionary mapping element IDs to their corresponding decoder classes.
19+
20+
Methods:
21+
register(elem_id: int) -> callable:
22+
A class method that registers a decoder class for a given element ID.
23+
24+
decode(data) -> E:
25+
A class method that decodes the given data using the registered decoder class for the element ID.
26+
"""
27+
1428
_decoders = defaultdict(lambda: UnsupportedElement)
1529

1630
@classmethod
1731
def register(cls, elem_id: int) -> callable:
32+
"""
33+
Registers a class as a decoder for a specific element ID.
34+
35+
This method is intended to be used as a decorator to register a class
36+
that can decode messages of a specific type identified by `elem_id`.
37+
38+
Args:
39+
elem_id (int): The element ID to register the class for.
40+
41+
Example:
42+
@ElementRegistry.register(elem_id=10)
43+
class SomeElement(Element):
44+
@classmethod
45+
def decode(cls, data):
46+
return SomeElement()
47+
"""
48+
1849
def decorator(element_class: Type[E]) -> Type[E]:
1950
cls._decoders[elem_id] = element_class
2051
return element_class
@@ -23,35 +54,83 @@ def decorator(element_class: Type[E]) -> Type[E]:
2354

2455
@classmethod
2556
def decode(cls, data) -> E:
57+
"""
58+
Decodes the given data using the appropriate decoder.
59+
60+
Args:
61+
data (dict): The data to decode.
62+
63+
Returns:
64+
E: The decoded element if successful.
65+
UnsupportedElement: If decoding fails due to a ValueError.
66+
"""
2667
try:
2768
return cls._decoders[data.get("45002")].decode(data)
2869
except ValueError:
2970
return UnsupportedElement(data=None)
3071

3172

3273
class Element(ABC, BaseModel):
74+
"""
75+
Abstract base class for elements, inheriting from ABC and BaseModel.
76+
77+
Methods:
78+
decode(cls, data) -> E:
79+
Decodes the given data into an instance of the element.
80+
Must be implemented by subclasses.
81+
82+
__str__(self):
83+
Returns a string representation of the element.
84+
Must be implemented by subclasses.
85+
"""
3386
...
3487

3588
@classmethod
3689
@abstractmethod
3790
def decode(cls, data) -> E:
91+
"""
92+
Abstract method to decode the given data into an instance of the element.
93+
94+
Args:
95+
data: The data to be decoded.
96+
97+
Returns:
98+
An instance of type E.
99+
100+
Raises:
101+
NotImplementedError: This method is not yet implemented.
102+
"""
38103
raise NotImplementedError
39104

40105
@abstractmethod
41106
def __str__(self):
107+
"""
108+
Return a string representation of the object.
109+
This method should be overridden by subclasses to provide a meaningful
110+
string representation of the object. If not implemented, it raises a
111+
NotImplementedError.
112+
113+
Returns:
114+
str: A string representation of the object.
115+
116+
Raises:
117+
NotImplementedError: If the method is not overridden by a subclass.
118+
"""
119+
42120
raise NotImplementedError
43121

44122

45123
class UnsupportedElement(Element):
46-
""" data is None when error raised in parsing, is dict when no parse function found """
124+
"""data is None when error raised in parsing, is dict when no parse function found"""
125+
47126
data: dict | None
48127

49128
@classmethod
50129
def decode(cls, data):
51130
return UnsupportedElement(data=data)
52131

53132
def __str__(self):
54-
return "不支持的消息"
133+
return "[不支持的消息]"
55134

56135

57136
@ElementRegistry.register(elem_id=1)
@@ -104,31 +183,30 @@ class FileElement(Element):
104183
hash: str | None
105184
path: str | None
106185

107-
108186
@classmethod
109187
def decode(cls, data):
110188
return FileElement(
111-
hash=hash.hex() if isinstance(hash:=data.get("45406"), bytes) else None,
112-
path=path.decode() if isinstance(path:=data.get("45954"), bytes) else None,
189+
hash=hash.hex() if isinstance(hash := data.get("45406"), bytes) else None,
190+
path=(
191+
path.decode() if isinstance(path := data.get("45954"), bytes) else None
192+
),
113193
)
114194

115195
def __str__(self):
116196
return "[文件]"
117-
197+
118198

119199
@ElementRegistry.register(elem_id=4)
120200
class AudioElement(Element):
121201
filename: str
122202
hash: str | None
123203

124-
125204
@classmethod
126205
def decode(cls, data):
127206
return AudioElement(
128207
filename=data.get("45402"),
129-
hash=hash.hex() if isinstance(hash:=data.get("45406"), bytes) else None,
208+
hash=hash.hex() if isinstance(hash := data.get("45406"), bytes) else None,
130209
)
131-
132210

133211
def __str__(self):
134212
return "[语音消息]"
@@ -139,14 +217,12 @@ class VideoElement(Element):
139217
filename: str | None
140218
hash: str | None
141219

142-
143220
@classmethod
144221
def decode(cls, data):
145222
return VideoElement(
146223
filename=data.get("40402"),
147-
hash=hash.hex() if isinstance(hash:=data.get("45406"), bytes) else None
224+
hash=hash.hex() if isinstance(hash := data.get("45406"), bytes) else None,
148225
)
149-
150226

151227
def __str__(self):
152228
return "[视频消息]"
@@ -172,16 +248,18 @@ class Reply(Element):
172248
source_sender_uin: str | None
173249
source_sender_qq: int | None
174250
source_time: int | None
175-
source_content: 'Message'
251+
source_content: "Message"
176252

177253
@classmethod
178254
def decode(cls, data):
179255
return Reply(
180256
source_seq=data.get("47402"),
181-
source_sender_uin=sender_uin if isinstance(sender_uin:=data.get("40020"), str) else None,
257+
source_sender_uin=(
258+
sender_uin if isinstance(sender_uin := data.get("40020"), str) else None
259+
),
182260
source_sender_qq=data.get("47403"),
183261
source_time=data.get("47404"),
184-
source_content=Message.from_reply(data.get("47423"))
262+
source_content=Message.from_reply(data.get("47423")),
185263
)
186264

187265
def __str__(self):
@@ -214,22 +292,23 @@ class WithdrawNotifyElement(SystemNotificationElement):
214292
@classmethod
215293
def system_decode(cls, data):
216294
return WithdrawNotifyElement(
217-
sender=sender if isinstance(sender:=data.get("47705"), str) else None,
218-
withdrawer=withdrawer if isinstance(withdrawer:=data.get("47716"), str) else None,
219-
suffix=suffix if (suffix:=data.get("47713")) else None,
295+
sender=sender if isinstance(sender := data.get("47705"), str) else None,
296+
withdrawer=(
297+
withdrawer if isinstance(withdrawer := data.get("47716"), str) else None
298+
),
299+
suffix=suffix if (suffix := data.get("47713")) else None,
220300
)
221301

222302
def __str__(self):
223303
return "撤回了一条消息"
224-
304+
225305

226306
@ElementRegistry.register(elem_id=9)
227307
class RedPackElement(Element):
228308
greet: str
229309
alt: str
230310
skin_type: str | None
231311

232-
233312
@classmethod
234313
def decode(cls, data):
235314
desc = data.get("48403")
@@ -241,9 +320,13 @@ def decode(cls, data):
241320
return RedPackElement(
242321
greet=desc.get("48443"),
243322
alt=desc.get("48448"),
244-
skin_type=skin_type if isinstance(skin_type:=data.get("48421").get("5"), str) else None,
323+
skin_type=(
324+
skin_type
325+
if isinstance(skin_type := data.get("48421").get("5"), str)
326+
else None
327+
),
245328
)
246-
329+
247330
def __str__(self):
248331
return self.alt
249332

@@ -254,9 +337,7 @@ class AppElement(Element):
254337

255338
@classmethod
256339
def decode(cls, data):
257-
return AppElement(
258-
data=data.get("47901").decode()
259-
)
340+
return AppElement(data=data.get("47901").decode())
260341

261342
def __str__(self):
262343
return "[应用消息]"
@@ -323,21 +404,19 @@ def decode(cls, data):
323404

324405
def __str__(self):
325406
return "[Bot卡片]"
326-
407+
327408

328409
@ElementRegistry.register(elem_id=21)
329410
class CallNotifyElement(Element):
330411
alt_1: str
331412
alt_2: str
332413

333-
334414
@classmethod
335415
def decode(cls, data):
336416
return CallNotifyElement(
337417
alt_1=data.get("48153"),
338418
alt_2=data.get("48157"),
339419
)
340-
341420

342421
def __str__(self):
343422
return self.alt_1
@@ -346,10 +425,10 @@ def __str__(self):
346425
class Message(BaseModel):
347426
ID: int | None
348427
seq: int | None
349-
elements: List['Element']
428+
elements: List["Element"]
350429

351430
@classmethod
352-
def from_db(cls, dbo: GroupMessage) -> 'Message':
431+
def from_db(cls, dbo: GroupMessage) -> "Message":
353432
if dbo.message_body is None:
354433
elements = []
355434
else:
@@ -366,7 +445,7 @@ def from_db(cls, dbo: GroupMessage) -> 'Message':
366445
)
367446

368447
@classmethod
369-
def from_reply(cls, embed) -> 'Message':
448+
def from_reply(cls, embed) -> "Message":
370449
if embed is None:
371450
embed = []
372451
if isinstance(embed, dict):

0 commit comments

Comments
 (0)