Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dill can't pickle abstractproperty, abstractclassmethod, or abstractstaticmethod objects #365

Closed
alimuldal opened this issue May 11, 2020 · 2 comments

Comments

@alimuldal
Copy link

The following:

import abc
import dill

print(dill.__version__)  # 0.3.1.1

class FooBar(abc.ABC):

    @abc.abstractproperty
    def thingy(self):
        return 42


dill.dumps(FooBar)

fails with:

---------------------------------------------------------------------------                                                                                                                                         
TypeError                                 Traceback (most recent call last)                                                                                                                                         
<ipython-input-4-ad16237f3136> in <module>                                                                                                                                                                          
----> 1 dill.dumps(FooBar)                                                                                                                                                                                          
                                                                                                                                                                                                                    
~/.venvs/dill/lib/python3.7/site-packages/dill/_dill.py in dumps(obj, protocol, byref, fmode, recurse, **kwds)                                                                                                      
    263     """pickle an object to a string"""                                                                                                                                                                      
    264     file = StringIO()                                                                                                                                                                                       
--> 265     dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)                                                                                                                                    
    266     return file.getvalue()                                                                                                                                                                                  
    267                                                                                                                                                                                                             
                                                                                                                                                                                                                    
~/.venvs/dill/lib/python3.7/site-packages/dill/_dill.py in dump(obj, file, protocol, byref, fmode, recurse, **kwds)                                                                                                 
    257     _kwds = kwds.copy()                                                                                                                                                                                     
    258     _kwds.update(dict(byref=byref, fmode=fmode, recurse=recurse))                                                                                                                                           
--> 259     Pickler(file, protocol, **_kwds).dump(obj)                                                                                                                                                              
    260     return                                                                                                                                                                                                  
    261                                                                                                                                                                                                             
                                                                                                                                                                                                                    
~/.venvs/dill/lib/python3.7/site-packages/dill/_dill.py in dump(self, obj)                                                                                                                                          
    443             raise PicklingError(msg)                                                                                                                                                                        
    444         else:                                                                                                                                                                                               
--> 445             StockPickler.dump(self, obj)                                                                                                                                                                    
    446         stack.clear()  # clear record of 'recursion-sensitive' pickled objects                                                                                                                              
    447         return                                                                                                                                                                                              
                                                                                                                                                                                                                    
/usr/lib/python3.7/pickle.py in dump(self, obj)                                                                                                                                                                     
    435         if self.proto >= 4:                                                                                                                                                                                 
    436             self.framer.start_framing()                                                                                                                                                                     
--> 437         self.save(obj)                                                                                                                                                                                      
    438         self.write(STOP)                                                                                                                                                                                    
    439         self.framer.end_framing()                                                                                                                                                                           
                                                                                                                                                                                                                    
/usr/lib/python3.7/pickle.py in save(self, obj, save_persistent_id)                                                                                                                                                 
    502         f = self.dispatch.get(t)                                                                                                                                                                            
    503         if f is not None:                                                                                                                                                                                   
--> 504             f(self, obj) # Call unbound method with explicit self                                                                                                                                           
    505             return                                                                                                                                                                                          
    506                                                                                                                                                                                                             
                                                                                                                                                                                                                    
~/.venvs/dill/lib/python3.7/site-packages/dill/_dill.py in save_type(pickler, obj)                                                                                                                                  
   1339             del _dict[name]                                                                                                                                                                                 
   1340         pickler.save_reduce(_create_type, (type(obj), obj.__name__,
-> 1341                                            obj.__bases__, _dict), obj=obj)
   1342         log.info("# %s" % _t)
   1343     # special cases: NoneType

/usr/lib/python3.7/pickle.py in save_reduce(self, func, args, state, listitems, dictitems, obj)
    636         else:
    637             save(func)
--> 638             save(args)
    639             write(REDUCE)
    640 

/usr/lib/python3.7/pickle.py in save(self, obj, save_persistent_id)
    502         f = self.dispatch.get(t)
    503         if f is not None:
--> 504             f(self, obj) # Call unbound method with explicit self
    505             return
    506 

/usr/lib/python3.7/pickle.py in save_tuple(self, obj)
    787         write(MARK)
    788         for element in obj:
--> 789             save(element)
    790 
    791         if id(obj) in memo:

/usr/lib/python3.7/pickle.py in save(self, obj, save_persistent_id)
    502         f = self.dispatch.get(t)
    503         if f is not None:
--> 504             f(self, obj) # Call unbound method with explicit self
    505             return
    506 

~/.venvs/dill/lib/python3.7/site-packages/dill/_dill.py in save_module_dict(pickler, obj)
    910             # we only care about session the first pass thru
    911             pickler._session = False
--> 912         StockPickler.save_dict(pickler, obj)
    913         log.info("# D2")
    914     return

/usr/lib/python3.7/pickle.py in save_dict(self, obj)
    857 
    858         self.memoize(obj)
--> 859         self._batch_setitems(obj.items())
    860 
    861     dispatch[dict] = save_dict

/usr/lib/python3.7/pickle.py in _batch_setitems(self, items)
    883                 for k, v in tmp:
    884                     save(k)
--> 885                     save(v)
    886                 write(SETITEMS)
    887             elif n:

/usr/lib/python3.7/pickle.py in save(self, obj, save_persistent_id)
    522             reduce = getattr(obj, "__reduce_ex__", None)
    523             if reduce is not None:
--> 524                 rv = reduce(self.proto)
    525             else:
    526                 reduce = getattr(obj, "__reduce__", None)

TypeError: can't pickle abstractproperty objects

abstractclassmethod and abstractstaticmethod also fail in the same way.

@LarsHill
Copy link

Is probably related to #332

@mmckerns
Copy link
Member

Python 3.8.17 (default, Jun 11 2023, 01:54:00) 
[Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import abc
>>> import dill
>>> class FooBar(abc.ABC):
...     @abc.abstractproperty
...     def thingy(self):
...         return 42
... 
>>> dill.dumps(FooBar)
b'\x80\x04\x95\x97\x01\x00\x00\x00\x00\x00\x00\x8c\ndill._dill\x94\x8c\x0c_create_type\x94\x93\x94(\x8c\x03abc\x94\x8c\x07ABCMeta\x94\x93\x94\x8c\x06FooBar\x94h\x03\x8c\x03ABC\x94\x93\x94\x85\x94}\x94(\x8c\n__module__\x94\x8c\x08__main__\x94\x8c\x06thingy\x94h\x03\x8c\x10abstractproperty\x94\x93\x94(h\x00\x8c\x10_create_function\x94\x93\x94(h\x00\x8c\x0c_create_code\x94\x93\x94(K\x01K\x00K\x00K\x01K\x01KCC\x04d\x01S\x00\x94NK*\x86\x94)\x8c\x04self\x94\x85\x94\x8c\x07<stdin>\x94h\rK\x02C\x02\x00\x02\x94))t\x94R\x94c__builtin__\n__main__\nh\rNNt\x94R\x94}\x94}\x94(\x8c\x0f__annotations__\x94}\x94\x8c\x0c__qualname__\x94\x8c\rFooBar.thingy\x94u\x86\x94bNNNt\x94R\x94\x8c\x07__doc__\x94N\x8c\x13__abstractmethods__\x94(h\r\x91\x94ut\x94R\x94\x8c\x08builtins\x94\x8c\x07setattr\x94\x93\x94h+h"h\x06\x87\x94R0.'
>>> dill.__version__
'0.3.8.dev0'

This now works. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants