11import logging , copy , pickle
2+ from weakref import ref
23
34from ..returnvalues import ReturnValue
45from ..utils import update_info_dict
56
67logger = logging .getLogger ('itchat' )
78
9+ class AttributeDict (dict ):
10+ def __getattr__ (self , value ):
11+ keyName = value [0 ].upper () + value [1 :]
12+ try :
13+ return self [keyName ]
14+ except KeyError :
15+ raise AttributeError ("'%s' object has no attribute '%s'" % (
16+ self .__class__ .__name__ .split ('.' )[- 1 ], value ))
17+ def get (self , v , d = None ):
18+ try :
19+ return self [v ]
20+ except KeyError :
21+ return d
22+
823class UnInitializedItchat (object ):
924 def _raise_error (self , * args , ** kwargs ):
1025 logger .warning ('An itchat instance is called before initialized' )
1126 def __getattr__ (self , value ):
1227 return self ._raise_error
1328
14- fakeItchat = UnInitializedItchat ()
15-
1629class ContactList (list ):
17- ''' when a dict is append, init function will be called to format that dict
18- '''
30+ ''' when a dict is append, init function will be called to format that dict '''
1931 def __init__ (self , * args , ** kwargs ):
2032 super (ContactList , self ).__init__ (* args , ** kwargs )
2133 self .__setstate__ (None )
34+ @property
35+ def core (self ):
36+ return getattr (self , '_core' , lambda : fakeItchat )() or fakeItchat
37+ @core .setter
38+ def core (self , value ):
39+ self ._core = ref (value )
2240 def set_default_value (self , initFunction = None , contactClass = None ):
2341 if hasattr (initFunction , '__call__' ):
2442 self .contactInitFn = initFunction
@@ -28,7 +46,7 @@ def append(self, value):
2846 contact = self .contactClass (value )
2947 contact .core = self .core
3048 if self .contactInitFn is not None :
31- contact = self .contactInitFn (contact ) or contact
49+ contact = self .contactInitFn (self , contact ) or contact
3250 super (ContactList , self ).append (contact )
3351 def __deepcopy__ (self , memo ):
3452 r = self .__class__ ([copy .deepcopy (v ) for v in self ])
@@ -41,19 +59,21 @@ def __getstate__(self):
4159 def __setstate__ (self , state ):
4260 self .contactInitFn = None
4361 self .contactClass = User
44- self .core = fakeItchat
4562 def __str__ (self ):
4663 return '[%s]' % ', ' .join ([repr (v ) for v in self ])
4764 def __repr__ (self ):
4865 return '<%s: %s>' % (self .__class__ .__name__ .split ('.' )[- 1 ],
4966 self .__str__ ())
5067
51- fakeContactList = ContactList
52-
53- class AbstractUserDict (dict ):
68+ class AbstractUserDict (AttributeDict ):
5469 def __init__ (self , * args , ** kwargs ):
5570 super (AbstractUserDict , self ).__init__ (* args , ** kwargs )
56- self .__setstate__ (None )
71+ @property
72+ def core (self ):
73+ return getattr (self , '_core' , lambda : fakeItchat )() or fakeItchat
74+ @core .setter
75+ def core (self , value ):
76+ self ._core = ref (value )
5777 def update (self ):
5878 return ReturnValue ({'BaseResponse' : {
5979 'Ret' : - 1006 ,
@@ -104,9 +124,6 @@ def search_member(self, name=None, userName=None, remarkName=None, nickName=None
104124 'Ret' : - 1006 ,
105125 'ErrMsg' : '%s do not have members' % \
106126 self .__class__ .__name__ , }, })
107- def __getattr__ (self , value ):
108- value = value [0 ].upper () + value [1 :]
109- return self .get (value , '' )
110127 def __deepcopy__ (self , memo ):
111128 r = self .__class__ ()
112129 for k , v in self .items ():
@@ -122,7 +139,7 @@ def __repr__(self):
122139 def __getstate__ (self ):
123140 return 1
124141 def __setstate__ (self , state ):
125- self . core = fakeItchat
142+ pass
126143
127144class User (AbstractUserDict ):
128145 def __init__ (self , * args , ** kwargs ):
@@ -146,32 +163,39 @@ def __deepcopy__(self, memo):
146163 def __setstate__ (self , state ):
147164 super (User , self ).__setstate__ (state )
148165 self .verifyDict = {}
149- self . memberList = fakeContactList
166+ self [ 'MemberList' ] = fakeContactList
150167
151168class MassivePlatform (AbstractUserDict ):
152169 def __init__ (self , * args , ** kwargs ):
153170 super (MassivePlatform , self ).__init__ (* args , ** kwargs )
154171 self .__setstate__ (None )
155172 def __setstate__ (self , state ):
156173 super (MassivePlatform , self ).__setstate__ (state )
157- self . memberList = fakeContactList
174+ self [ 'MemberList' ] = fakeContactList
158175
159176class Chatroom (AbstractUserDict ):
160177 def __init__ (self , * args , ** kwargs ):
161178 super (Chatroom , self ).__init__ (* args , ** kwargs )
162179 memberList = ContactList ()
163- def init_fn (d ):
164- d .chatroom = self
180+ userName = self .get ('UserName' , '' )
181+ refSelf = ref (self )
182+ def init_fn (parentList , d ):
183+ d .chatroom = refSelf () or \
184+ parentList .core .search_chatrooms (userName = userName )
165185 memberList .set_default_value (init_fn , ChatroomMember )
166186 if 'MemberList' in self :
167- if not isinstance (self .memberList , ContactList ):
168- for member in self .memberList :
169- memberList .append (member )
170- self ['MemberList' ] = memberList
171- else :
172187 for member in self .memberList :
173188 memberList .append (member )
174- self ['MemberList' ] = memberList
189+ self ['MemberList' ] = memberList
190+ @property
191+ def core (self ):
192+ return getattr (self , '_core' , lambda : fakeItchat )() or fakeItchat
193+ @core .setter
194+ def core (self , value ):
195+ self ._core = ref (value )
196+ self .memberList .core = value
197+ for member in self .memberList :
198+ member .core = value
175199 def update (self , detailedMember = False ):
176200 r = self .core .update_chatroom (self .userName , detailedMember )
177201 if r :
@@ -218,11 +242,29 @@ def search_member(self, name=None, userName=None, remarkName=None, nickName=None
218242 return copy .deepcopy (friendList )
219243 else :
220244 return copy .deepcopy (contact )
245+ def __setstate__ (self , state ):
246+ super (Chatroom , self ).__setstate__ (state )
247+ if not 'MemberList' in self :
248+ self ['MemberList' ] = fakeContactList
221249
222250class ChatroomMember (AbstractUserDict ):
223251 def __init__ (self , * args , ** kwargs ):
224252 super (AbstractUserDict , self ).__init__ (* args , ** kwargs )
225253 self .__setstate__ (None )
254+ @property
255+ def chatroom (self ):
256+ r = getattr (self , '_chatroom' , lambda : fakeChatroom )()
257+ if r is None :
258+ userName = getattr (self , '_chatroomUserName' , '' )
259+ r = self .core .search_chatrooms (userName = userName )
260+ if isinstance (r , dict ):
261+ self .chatroom = r
262+ return r or fakeChatroom
263+ @chatroom .setter
264+ def chatroom (self , value ):
265+ if isinstance (value , dict ) and 'UserName' in value :
266+ self ._chatroom = ref (value )
267+ self ._chatroomUserName = value ['UserName' ]
226268 def get_head_image (self , imageDir = None ):
227269 return self .core .get_head_img (self .userName , self .chatroom .userName , picDir = imageDir )
228270 def delete_member (self , userName ):
@@ -263,9 +305,7 @@ def __deepcopy__(self, memo):
263305 return r
264306 def __setstate__ (self , state ):
265307 super (ChatroomMember , self ).__setstate__ (state )
266- self .chatroom = self .fakeChatroom
267-
268- ChatroomMember .fakeChatroom = Chatroom ()
308+ self ['MemberList' ] = fakeContactList
269309
270310def wrap_user_dict (d ):
271311 userName = d .get ('UserName' )
@@ -276,3 +316,7 @@ def wrap_user_dict(d):
276316 else :
277317 r = MassivePlatform (d )
278318 return r
319+
320+ fakeItchat = UnInitializedItchat ()
321+ fakeContactList = ContactList ()
322+ fakeChatroom = Chatroom ()
0 commit comments