-
-
Notifications
You must be signed in to change notification settings - Fork 187
Description
Context: Our code uses dill to serialize callables only under certain circumstances, including when the callable's module is __main__. We want to be able to test this at an integration level, using dill on a function where func.__module__ == __main__.
Prior to the release of 0.3.5, we did this by manually setting the __module__ attribute. However, our tests have been failing since the release of 0.3.5.
I'm not sure if this is supposed to be an allowed use case. But is there supposed to be another way that I make it look like my functions were defined in __main__ (for the part our code manages) such that dill can also handle it, when really I'm running under pytest or another testing framework?
MCVE: In an environment with pytest and dill installed:
# test_dill.py
import dill
def setup_module():
print(f"\nDill version: {dill.__version__}")
def external_func_pretending_to_be_main():
return
def test_dill_lambda():
print() # cleaner output
func = lambda x: x
func.__module__ = "__main__"
dill.dumps(func)
def test_dill_func():
print() # cleaner output
func = external_func_pretending_to_be_main
func.__module__ = "__main__"
dill.dumps(func)pytest -vs test_dill.pyOutput in 0.3.4:
test_dill.py::test_dill_lambda
Dill version: 0.3.4
PASSED
test_dill.py::test_dill_func
PASSED
Output in 0.3.5.1
test_dill.py::test_dill_lambda
Dill version: 0.3.5.1
FAILED
test_dill.py::test_dill_func
FAILED
Tracebacks, as reported by pytest:
test_dill_lambda
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:364: in dumps
dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:336: in dump
Pickler(file, protocol, **_kwds).dump(obj)
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:620: in dump
StockPickler.dump(self, obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:487: in dump
self.save(obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1963: in save_function
_save_with_postproc(pickler, (_create_function, (
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1154: in _save_with_postproc
pickler._batch_setitems(iter(source.items()))
../../mambaforge/envs/dill/lib/python3.10/pickle.py:998: in _batch_setitems
save(v)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:603: in save
self.save_reduce(obj=obj, *rv)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:717: in save_reduce
save(state)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1251: in save_module_dict
StockPickler.save_dict(pickler, obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:972: in save_dict
self._batch_setitems(obj.items())
../../mambaforge/envs/dill/lib/python3.10/pickle.py:998: in _batch_setitems
save(v)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:603: in save
self.save_reduce(obj=obj, *rv)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:717: in save_reduce
save(state)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1251: in save_module_dict
StockPickler.save_dict(pickler, obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:972: in save_dict
self._batch_setitems(obj.items())
../../mambaforge/envs/dill/lib/python3.10/pickle.py:998: in _batch_setitems
save(v)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:603: in save
self.save_reduce(obj=obj, *rv)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:687: in save_reduce
save(cls)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1838: in save_type
_save_with_postproc(pickler, (_create_type, (
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1140: in _save_with_postproc
pickler.save_reduce(*reduction, obj=obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:692: in save_reduce
save(args)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/pickle.py:902: in save_tuple
save(element)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1251: in save_module_dict
StockPickler.save_dict(pickler, obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:972: in save_dict
self._batch_setitems(obj.items())
../../mambaforge/envs/dill/lib/python3.10/pickle.py:998: in _batch_setitems
save(v)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1963: in save_function
_save_with_postproc(pickler, (_create_function, (
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1154: in _save_with_postproc
pickler._batch_setitems(iter(source.items()))
../../mambaforge/envs/dill/lib/python3.10/pickle.py:998: in _batch_setitems
save(v)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:2004: in save_function
StockPickler.save_global(pickler, obj, name=name)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <dill._dill.Pickler object at 0x1082f2e90>
obj = <function make_set_closure_cell.<locals>.set_closure_cell at 0x1053c6290>
name = 'make_set_closure_cell.<locals>.set_closure_cell'
def save_global(self, obj, name=None):
write = self.write
memo = self.memo
if name is None:
name = getattr(obj, '__qualname__', None)
if name is None:
name = obj.__name__
module_name = whichmodule(obj, name)
try:
__import__(module_name, level=0)
module = sys.modules[module_name]
obj2, parent = _getattribute(module, name)
except (ImportError, KeyError, AttributeError):
> raise PicklingError(
"Can't pickle %r: it's not found as %s.%s" %
(obj, module_name, name)) from None
E _pickle.PicklingError: Can't pickle <function make_set_closure_cell.<locals>.set_closure_cell at 0x1053c6290>: it's not found as attr._compat.make_set_closure_cell.<locals>.set_closure_cell
../../mambaforge/envs/dill/lib/python3.10/pickle.py:1071: PicklingErrortest_dill_func
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:364: in dumps
dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:336: in dump
Pickler(file, protocol, **_kwds).dump(obj)
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:620: in dump
StockPickler.dump(self, obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:487: in dump
self.save(obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1963: in save_function
_save_with_postproc(pickler, (_create_function, (
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1154: in _save_with_postproc
pickler._batch_setitems(iter(source.items()))
../../mambaforge/envs/dill/lib/python3.10/pickle.py:998: in _batch_setitems
save(v)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:603: in save
self.save_reduce(obj=obj, *rv)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:717: in save_reduce
save(state)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1251: in save_module_dict
StockPickler.save_dict(pickler, obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:972: in save_dict
self._batch_setitems(obj.items())
../../mambaforge/envs/dill/lib/python3.10/pickle.py:998: in _batch_setitems
save(v)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:603: in save
self.save_reduce(obj=obj, *rv)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:717: in save_reduce
save(state)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1251: in save_module_dict
StockPickler.save_dict(pickler, obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:972: in save_dict
self._batch_setitems(obj.items())
../../mambaforge/envs/dill/lib/python3.10/pickle.py:998: in _batch_setitems
save(v)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:603: in save
self.save_reduce(obj=obj, *rv)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:687: in save_reduce
save(cls)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1838: in save_type
_save_with_postproc(pickler, (_create_type, (
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1140: in _save_with_postproc
pickler.save_reduce(*reduction, obj=obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:692: in save_reduce
save(args)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/pickle.py:902: in save_tuple
save(element)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1251: in save_module_dict
StockPickler.save_dict(pickler, obj)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:972: in save_dict
self._batch_setitems(obj.items())
../../mambaforge/envs/dill/lib/python3.10/pickle.py:998: in _batch_setitems
save(v)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1963: in save_function
_save_with_postproc(pickler, (_create_function, (
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:1154: in _save_with_postproc
pickler._batch_setitems(iter(source.items()))
../../mambaforge/envs/dill/lib/python3.10/pickle.py:998: in _batch_setitems
save(v)
../../mambaforge/envs/dill/lib/python3.10/pickle.py:560: in save
f(self, obj) # Call unbound method with explicit self
../../mambaforge/envs/dill/lib/python3.10/site-packages/dill/_dill.py:2004: in save_function
StockPickler.save_global(pickler, obj, name=name)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <dill._dill.Pickler object at 0x10849f910>
obj = <function make_set_closure_cell.<locals>.set_closure_cell at 0x1053c6290>
name = 'make_set_closure_cell.<locals>.set_closure_cell'
def save_global(self, obj, name=None):
write = self.write
memo = self.memo
if name is None:
name = getattr(obj, '__qualname__', None)
if name is None:
name = obj.__name__
module_name = whichmodule(obj, name)
try:
__import__(module_name, level=0)
module = sys.modules[module_name]
obj2, parent = _getattribute(module, name)
except (ImportError, KeyError, AttributeError):
> raise PicklingError(
"Can't pickle %r: it's not found as %s.%s" %
(obj, module_name, name)) from None
E _pickle.PicklingError: Can't pickle <function make_set_closure_cell.<locals>.set_closure_cell at 0x1053c6290>: it's not found as attr._compat.make_set_closure_cell.<locals>.set_closure_cell
../../mambaforge/envs/dill/lib/python3.10/pickle.py:1071: PicklingError