diff --git a/dill/_dill.py b/dill/_dill.py index 8eeb28a7..eaab6ebb 100644 --- a/dill/_dill.py +++ b/dill/_dill.py @@ -1383,10 +1383,32 @@ def save_module(pickler, obj): return return + @register(abc.ABCMeta) def save_abc(pickler, obj): """Use StockePickler to ignore ABC internal state which should not be serialized""" - StockPickler.save_type(pickler, obj) + + name = getattr(obj, '__qualname__', getattr(obj, '__name__', None)) + if '' in name or obj.__module__ != '__main__': + log.info("C2: %s" % obj) + # + _dict = _dict_from_dictproxy(obj.__dict__) + (registry, _, _, _) = abc._get_dump(obj) + + _dict["_abc_impl"] = [reg() for reg in registry] + + pickler.save_reduce(_create_type, (type(obj), obj.__name__, + obj.__bases__, _dict), obj=obj) + log.info("# C2") + else: + log.info("C1: %s" % obj) + + StockPickler.save_type(pickler, obj) + #StockPickler.save_global(pickler, obj, name=name) + + log.info("# C1") + + @register(TypeType) def save_type(pickler, obj): diff --git a/tests/test_abc.py b/tests/test_abc.py index 219b2fcf..34506bae 100644 --- a/tests/test_abc.py +++ b/tests/test_abc.py @@ -3,7 +3,6 @@ test dill's ability to pickle abstract base class objects """ import dill as pickle -#import pickle import abc from types import FunctionType @@ -78,6 +77,7 @@ def test_abc_non_local(): assert depickled.sfoo() == "Static Method SFOO" assert depickled.cfoo() == "Class Method CFOO" assert depickled.foo() == "Instance Method FOO" + print("Tada") def test_local(): """ @@ -86,7 +86,10 @@ def test_local(): """ class Local(object): pass - assert pickle.loads(pickle.dumps(Local)) == Local + + res = pickle.dumps(Local) + assert type(pickle.loads(res)) == type(Local) + print("Tada") def test_abc_local(): """ @@ -97,11 +100,27 @@ def test_abc_local(): With Dill (master): TypeError: cannot pickle '_abc._abc_data' object With Dill (issue_332_abc_data): - _pickle.PicklingError: Can't pickle .LocalABC'>: it's not found as __main__.test_abc_local..LocalABC + Tada """ class LocalABC(abc.ABC): - pass - assert pickle.loads(pickle.dumps(LocalABC)) == LocalABC + @abc.abstractmethod + def foo(self): + pass + + res = pickle.dumps(LocalABC) + pik = pickle.loads(res) + assert type(pik) == type(LocalABC) + + class Real(pik): + def foo(self): + return "True!" + try: + pik() + except TypeError: + print("Tada") + else: + print('Failed to raise type error') + assert False def test_meta_local(): """ @@ -113,11 +132,13 @@ def test_meta_local(): With Dill (master): _pickle.PicklingError: Can't pickle : it's not found as abc.LocalMetaABC With Dill (issue_332_abc_data): - _pickle.PicklingError: Can't pickle : it's not found as abc.LocalMetaABC + tada! """ LocalMetaABC = abc.ABCMeta('LocalMetaABC', (), {}) - assert pickle.loads(pickle.dumps(LocalMetaABC)) == LocalMetaABC - + res = pickle.dumps(LocalMetaABC) + pik = pickle.loads(res) + assert type(pik) == type(LocalMetaABC) + print("tada") # TODO add registration tests # https://github.com/python/cpython/blob/5010c044c73ee55d0fd578cfecd3f4c3f01a4140/Lib/test/test_abc.py#L273 @@ -125,8 +146,8 @@ def test_meta_local(): if __name__ == '__main__': - #test_abc_non_local() - test_local - #test_abc_local() - #test_meta_local() + test_abc_non_local() + test_local() + test_abc_local() + test_meta_local()