I’m getting the weirdest error while converting an application from python 2 to python 3.
Briefly this application uses wxPython to create an interface where the user can draw different objects on a canvas, and when clicking on objects the user can edit them and set different parameters. All these edits can be saved when closing the application. This save is performed with shelve library frome python.
This app was perfectly working with python 2, however for compatibility reasons I was trying to bring it on python 3 but here comes the problem: on python 3 I can save all the possible objects, however, if I add a specific object that instead of consisting of an icon is just a line between two icons, I can not reopen the project. I can add the object, work with it, change its settings, save the file, however I can not reopen it.
Biggest problem is that I don’t have a call stack to analyze. It just says that it is trying to unpickle the object in the shelf and next info I have is:
File "\Unpickle.py", line 25, in renamed_load
return RenameUnpickler(file_obj, encoding=encoding).load()
TypeError: Rect(): arguments did not match any overloaded call:
overload 1: too many arguments
overload 2: not enough arguments
overload 3: argument 1 has unexpected type 'float'
overload 4: argument 1 has unexpected type 'float'
overload 5: argument 1 has unexpected type 'float'
overload 6: argument 1 has unexpected type 'float'
What is really weired is that if I open a file generated in python 2 (which is converted using something really similar to this, I don’t get the same error, I can open and edit the file. However the problem still arises when the file is closed and reopened once again.
This is the class performing the read, that inherits from Unpickler so that I can override the find_class method. Biggest problem with this error, that is really driving me crazy is that the call stack doesn’t tell me where the error is during the unpickling process and that if I scan my code for occurences of Rect I can’t find any.
class RenameUnpickler(pickle.Unpickler):
def find_class(self, module, name):
renamed_module = module
if module == "wx._gdi":
renamed_module = "wx"
return super(RenameUnpickler, self).find_class(renamed_module, name)
def renamed_load(file_obj, encoding):
return RenameUnpickler(file_obj, encoding=encoding).load()
def renamed_loads(pickled_bytes):
file_obj = io.BytesIO(pickled_bytes)
return renamed_load(file_obj)
class ShelfFileVO( shelve.DbfilenameShelf ):
def __init__(self, *args, **kwds):
kwds[ 'protocol' ] = 2
shelve.DbfilenameShelf.__init__( self, *args, **kwds )
self._semaphore = threading.BoundedSemaphore( 1 )
self.find_globals = None
def keys(self):
return [ k.decode() for k in self.dict.keys() ]
def has_key(self, key):
return key.encode() in self.dict
def __contains__(self, key):
return key.encode() in self.dict
def get(self, key, default=None):
#key = key.encode()
if key in self.dict:
return self[ key ]
else:
return default
def __getitem__(self, key):
#key = key.encode()
if key in list(self.cache.keys()):
value = self.cache[ key ]
else:
f = BytesIO( self.dict[ key ] )
value = renamed_load(f, encoding='latin1')