Python Forum
TypeError: cannot create weak reference to 'str' object
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
TypeError: cannot create weak reference to 'str' object
#1
Hello, I'm trying to fix an outdated piece of code someone made called ItChat: https://github.com/jerrypnz/ItChat
I've come across a problem that I am having trouble fixing; when I run the program it gets this error:
File "D:\Python\WeSync\venv\lib\site-packages\itchat\storage\templates.py", line 39, in core
self._core = ref(value)
TypeError: cannot create weak reference to 'str' object


The part its referencing is this:
    def core(self, value):
        self._core = ref(value)
I'm not sure what the problem is and was wondering if anyone could help.
I think it may be an issue linked to a newer version of python as I am fixing old code.
Thanks, Harry Smile

\/ \/ Full File Below \/ \/

import logging, copy, pickle
from weakref import ref

from ..returnvalues import ReturnValue
from ..utils import update_info_dict

logger = logging.getLogger('itchat')

class AttributeDict(dict):
    def __getattr__(self, value):
        keyName = value[0].upper() + value[1:]
        try:
            return self[keyName]
        except KeyError:
            raise AttributeError("'%s' object has no attribute '%s'" % (
                self.__class__.__name__.split('.')[-1], value))
    def get(self, v, d=None):
        try:
            return self[v]
        except KeyError:
            return d

class UnInitializedItchat(object):
    def _raise_error(self, *args, **kwargs):
        logger.warning('An itchat instance is called before initialized')
    def __getattr__(self, value):
        return self._raise_error

class ContactList(list):
    ''' when a dict is append, init function will be called to format that dict '''
    def __init__(self, *args, **kwargs):
        super(ContactList, self).__init__(*args, **kwargs)
        self.__setstate__(None)
    @property
    def core(self):
        return getattr(self, '_core', lambda: fakeItchat)() or fakeItchat
    @core.setter
    def core(self, value):
        self._core = ref(value)
    def set_default_value(self, initFunction=None, contactClass=None):
        if hasattr(initFunction, '__call__'):
            self.contactInitFn = initFunction
        if hasattr(contactClass, '__call__'):
            self.contactClass = contactClass
    def append(self, value):
        contact = self.contactClass(value)
        contact.core = self.core
        if self.contactInitFn is not None:
            contact = self.contactInitFn(self, contact) or contact
        super(ContactList, self).append(contact)
    def __deepcopy__(self, memo):
        r = self.__class__([copy.deepcopy(v) for v in self])
        r.contactInitFn = self.contactInitFn
        r.contactClass = self.contactClass
        r.core = self.core
        return r
    def __getstate__(self):
        return 1
    def __setstate__(self, state):
        self.contactInitFn = None
        self.contactClass = User
    def __str__(self):
        return '[%s]' % ', '.join([repr(v) for v in self])
    def __repr__(self):
        return '<%s: %s>' % (self.__class__.__name__.split('.')[-1],
            self.__str__())

class AbstractUserDict(AttributeDict):
    def __init__(self, *args, **kwargs):
        super(AbstractUserDict, self).__init__(*args, **kwargs)
    @property
    def core(self):
        return getattr(self, '_core', lambda: fakeItchat)() or fakeItchat
    @core.setter
    def core(self, value):
        self._core = ref(value)
    def update(self):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not be updated' % \
                self.__class__.__name__, }, })
    def set_alias(self, alias):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not set alias' % \
                self.__class__.__name__, }, })
    def set_pinned(self, isPinned=True):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not be pinned' % \
                self.__class__.__name__, }, })
    def verify(self):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s do not need verify' % \
                self.__class__.__name__, }, })
    def get_head_image(self, imageDir=None):
        return self.core.get_head_img(self.userName, picDir=imageDir)
    def delete_member(self, userName):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not delete member' % \
                self.__class__.__name__, }, })
    def add_member(self, userName):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not add member' % \
                self.__class__.__name__, }, })
    def send_raw_msg(self, msgType, content):
        return self.core.send_raw_msg(msgType, content, self.userName)
    def send_msg(self, msg='Test Message'):
        return self.core.send_msg(msg, self.userName)
    def send_file(self, fileDir, mediaId=None):
        return self.core.send_file(fileDir, self.userName, mediaId)
    def send_image(self, fileDir, mediaId=None):
        return self.core.send_image(fileDir, self.userName, mediaId)
    def send_video(self, fileDir=None, mediaId=None):
        return self.core.send_video(fileDir, self.userName, mediaId)
    def send(self, msg, mediaId=None):
        return self.core.send(msg, self.userName, mediaId)
    def search_member(self, name=None, userName=None, remarkName=None, nickName=None,
            wechatAccount=None):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s do not have members' % \
                self.__class__.__name__, }, })
    def __deepcopy__(self, memo):
        r = self.__class__()
        for k, v in self.items():
            r[copy.deepcopy(k)] = copy.deepcopy(v)
        r.core = self.core
        return r
    def __str__(self):
        return '{%s}' % ', '.join(
            ['%s: %s' % (repr(k),repr(v)) for k,v in self.items()])
    def __repr__(self):
        return '<%s: %s>' % (self.__class__.__name__.split('.')[-1],
            self.__str__())
    def __getstate__(self):
        return 1
    def __setstate__(self, state):
        pass
        
class User(AbstractUserDict):
    def __init__(self, *args, **kwargs):
        super(User, self).__init__(*args, **kwargs)
        self.__setstate__(None)
    def update(self):
        r = self.core.update_friend(self.userName)
        if r:
            update_info_dict(self, r)
        return r
    def set_alias(self, alias):
        return self.core.set_alias(self.userName, alias)
    def set_pinned(self, isPinned=True):
        return self.core.set_pinned(self.userName, isPinned)
    def verify(self):
        return self.core.add_friend(**self.verifyDict)
    def __deepcopy__(self, memo):
        r = super(User, self).__deepcopy__(memo)
        r.verifyDict = copy.deepcopy(self.verifyDict)
        return r
    def __setstate__(self, state):
        super(User, self).__setstate__(state)
        self.verifyDict = {}
        self['MemberList'] = fakeContactList

class MassivePlatform(AbstractUserDict):
    def __init__(self, *args, **kwargs):
        super(MassivePlatform, self).__init__(*args, **kwargs)
        self.__setstate__(None)
    def __setstate__(self, state):
        super(MassivePlatform, self).__setstate__(state)
        self['MemberList'] = fakeContactList

class Chatroom(AbstractUserDict):
    def __init__(self, *args, **kwargs):
        super(Chatroom, self).__init__(*args, **kwargs)
        memberList = ContactList()
        userName = self.get('UserName', '')
        refSelf = ref(self)
        def init_fn(parentList, d):
            d.chatroom = refSelf() or \
                parentList.core.search_chatrooms(userName=userName)
        memberList.set_default_value(init_fn, ChatroomMember)
        if 'MemberList' in self:
            for member in self.memberList:
                memberList.append(member)
        self['MemberList'] = memberList
    @property
    def core(self):
        return getattr(self, '_core', lambda: fakeItchat)() or fakeItchat
    @core.setter
    def core(self, value):
        self._core = ref(value)
        self.memberList.core = value
        for member in self.memberList:
            member.core = value
    def update(self, detailedMember=False):
        r = self.core.update_chatroom(self.userName, detailedMember)
        if r:
            update_info_dict(self, r)
            self['MemberList'] = r['MemberList']
        return r
    def set_alias(self, alias):
        return self.core.set_chatroom_name(self.userName, alias)
    def set_pinned(self, isPinned=True):
        return self.core.set_pinned(self.userName, isPinned)
    def delete_member(self, userName):
        return self.core.delete_member_from_chatroom(self.userName, userName)
    def add_member(self, userName):
        return self.core.add_member_into_chatroom(self.userName, userName)
    def search_member(self, name=None, userName=None, remarkName=None, nickName=None,
            wechatAccount=None):
        with self.core.storageClass.updateLock:
            if (name or userName or remarkName or nickName or wechatAccount) is None:
                return None
            elif userName: # return the only userName match
                for m in self.memberList:
                    if m.userName == userName:
                        return copy.deepcopy(m)
            else:
                matchDict = {
                    'RemarkName' : remarkName,
                    'NickName'   : nickName,
                    'Alias'      : wechatAccount, }
                for k in ('RemarkName', 'NickName', 'Alias'):
                    if matchDict[k] is None:
                        del matchDict[k]
                if name: # select based on name
                    contact = []
                    for m in self.memberList:
                        if any([m.get(k) == name for k in ('RemarkName', 'NickName', 'Alias')]):
                            contact.append(m)
                else:
                    contact = self.memberList[:]
                if matchDict: # select again based on matchDict
                    friendList = []
                    for m in contact:
                        if all([m.get(k) == v for k, v in matchDict.items()]):
                            friendList.append(m)
                    return copy.deepcopy(friendList)
                else:
                    return copy.deepcopy(contact)
    def __setstate__(self, state):
        super(Chatroom, self).__setstate__(state)
        if not 'MemberList' in self:
            self['MemberList'] = fakeContactList

class ChatroomMember(AbstractUserDict):
    def __init__(self, *args, **kwargs):
        super(AbstractUserDict, self).__init__(*args, **kwargs)
        self.__setstate__(None)
    @property
    def chatroom(self):
        r = getattr(self, '_chatroom', lambda: fakeChatroom)()
        if r is None:
            userName = getattr(self, '_chatroomUserName', '')
            r = self.core.search_chatrooms(userName=userName)
            if isinstance(r, dict):
                self.chatroom = r
        return r or fakeChatroom
    @chatroom.setter
    def chatroom(self, value):
        if isinstance(value, dict) and 'UserName' in value:
            self._chatroom = ref(value)
            self._chatroomUserName = value['UserName']
    def get_head_image(self, imageDir=None):
        return self.core.get_head_img(self.userName, self.chatroom.userName, picDir=imageDir)
    def delete_member(self, userName):
        return self.core.delete_member_from_chatroom(self.chatroom.userName, self.userName)
    def send_raw_msg(self, msgType, content):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not send message directly' % \
                self.__class__.__name__, }, })
    def send_msg(self, msg='Test Message'):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not send message directly' % \
                self.__class__.__name__, }, })
    def send_file(self, fileDir, mediaId=None):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not send message directly' % \
                self.__class__.__name__, }, })
    def send_image(self, fileDir, mediaId=None):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not send message directly' % \
                self.__class__.__name__, }, })
    def send_video(self, fileDir=None, mediaId=None):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not send message directly' % \
                self.__class__.__name__, }, })
    def send(self, msg, mediaId=None):
        return ReturnValue({'BaseResponse': {
            'Ret': -1006,
            'ErrMsg': '%s can not send message directly' % \
                self.__class__.__name__, }, })
    def __setstate__(self, state):
        super(ChatroomMember, self).__setstate__(state)
        self['MemberList'] = fakeContactList

def wrap_user_dict(d):
    userName = d.get('UserName')
    if '@@' in userName:
        r = Chatroom(d)
    elif d.get('VerifyFlag', 8) & 8 == 0:
        r = User(d)
    else:
        r = MassivePlatform(d)
    return r

fakeItchat = UnInitializedItchat()
fakeContactList = ContactList()
fakeChatroom = Chatroom()
Reply
#2
To explain what happens in that part of code,not look at all.
vaule that comes in from outside is a string which is not weak referenceable.
Example:
from weakref import ref

class Bar:
    def __init__(self, x=0):
        self._x = x

    @property
    def foo(self):
        print("Getting value")
        return self._x

    @foo.setter
    def foo(self, value):
        print("Setting value")
        self._x = ref(value) 
Use:
>>> obj = Bar()
>>> obj.foo
Getting value
0
>>> obj.foo = 'hello'
Setting value
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "<module3>", line 15, in foo
TypeError: cannot create weak reference to 'str' object

>>> # Fix it
>>> class MyDict(dict):
...     pass
... 
>>> my_dict = MyDict(red=1, green=2)
>>> obj.foo = my_dict
Setting value

>>> obj.foo
Getting value
<weakref at 0x0503E5D0; to 'MyDict' at 0x03266A40>
So when use ref(value) the object given to @setter need to be weak referenceable.
Reply
#3
Thanks snippsat, I understand how it all works now :)
Can you recommend what I do to fix the code?
Thanks, Harry
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  TypeError: cannot pickle ‘_asyncio.Future’ object Abdul_Rafey 1 268 Mar-07-2024, 03:40 PM
Last Post: deanhystad
  error in class: TypeError: 'str' object is not callable akbarza 2 444 Dec-30-2023, 04:35 PM
Last Post: deanhystad
Bug TypeError: 'NoneType' object is not subscriptable TheLummen 4 679 Nov-27-2023, 11:34 AM
Last Post: TheLummen
  TypeError: 'NoneType' object is not callable akbarza 4 917 Aug-24-2023, 05:14 PM
Last Post: snippsat
  [NEW CODER] TypeError: Object is not callable iwantyoursec 5 1,260 Aug-23-2023, 06:21 PM
Last Post: deanhystad
  how to return a reference to an object? Skaperen 8 1,106 Jun-07-2023, 05:30 PM
Last Post: Skaperen
  Possible to create an object inside another object that is visible outside that objec MeghansUncle2 17 2,087 May-25-2023, 02:08 PM
Last Post: MeghansUncle2
  TypeError: 'float' object is not callable #1 isdito2001 1 1,044 Jan-21-2023, 12:43 AM
Last Post: Yoriz
  TypeError: a bytes-like object is required ZeroX 13 3,837 Jan-07-2023, 07:02 PM
Last Post: deanhystad
  TypeError: 'float' object is not callable TimofeyKolpakov 3 1,371 Dec-04-2022, 04:58 PM
Last Post: TimofeyKolpakov

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020