From 2650a534f3d3c86d6c8d84b10ab9547895c5c1a8 Mon Sep 17 00:00:00 2001 From: Douglas RAILLARD Date: Thu, 7 Nov 2019 13:39:19 +0000 Subject: [PATCH] exception: Fix DevlibError unpickling Unpickling of BaseException is done by feeding self.args to the exception type. This self.args attribute is initialized in two places: in BaseException.__new__ (before __init__ is called) and in BaseException.__init__ as well. The following code ends up with self.args == ('hello',), instead of (1, 2): class MyExcep(BaseException): def __init__(self, foo, bar): print('before super().__init__()', self.args) super().__init__('hello') print('after super().__init__()', self.args) MyExcep(1, 2) # Prints: # before super().__init__() (1, 2) # after super().__init__() ('hello',) When unplickling such instance, ('hello',) will be fed to MyExcep.__init__(), which will fail with a TypeError since it requires 2 positional arguments. In order to fix that, super().__init__() needs to be handwritten instead of getting the one from BaseException: class MyBase(BaseException): def __init__(self, msg): self.msg = msg class MyExcep(MyBase): def __init__(self, foo, bar): print('before super().__init__()', self.args) super().__init__('hello') print('after super().__init__()', self.args) MyExcep(1, 2) # Prints: # before super().__init__() (1, 2) # after super().__init__() (1, 2) This will correctly initialize self.args == (1, 2), allowing unpickling to work. --- devlib/exception.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/devlib/exception.py b/devlib/exception.py index 2f5018c..0042cb1 100644 --- a/devlib/exception.py +++ b/devlib/exception.py @@ -15,11 +15,17 @@ class DevlibError(Exception): """Base class for all Devlib exceptions.""" + + def __init__(self, *args): + message = args[0] if args else None + self._message = message + @property def message(self): - if self.args: - return self.args[0] - return str(self) + if self._message is not None: + return self._message + else: + return str(self) class DevlibStableError(DevlibError):