|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import dill |
|
from enum import EnumMeta |
|
import sys |
|
dill.settings['recurse'] = True |
|
|
|
|
|
class _class: |
|
def _method(self): |
|
pass |
|
def ok(self): |
|
return True |
|
|
|
class _class2: |
|
def __call__(self): |
|
pass |
|
def ok(self): |
|
return True |
|
|
|
class _newclass(object): |
|
def _method(self): |
|
pass |
|
def ok(self): |
|
return True |
|
|
|
class _newclass2(object): |
|
def __call__(self): |
|
pass |
|
def ok(self): |
|
return True |
|
|
|
class _meta(type): |
|
pass |
|
|
|
def __call__(self): |
|
pass |
|
def ok(self): |
|
return True |
|
|
|
_mclass = _meta("_mclass", (object,), {"__call__": __call__, "ok": ok}) |
|
|
|
del __call__ |
|
del ok |
|
|
|
o = _class() |
|
oc = _class2() |
|
n = _newclass() |
|
nc = _newclass2() |
|
m = _mclass() |
|
|
|
if sys.hexversion < 0x03090000: |
|
import typing |
|
class customIntList(typing.List[int]): |
|
pass |
|
else: |
|
class customIntList(list[int]): |
|
pass |
|
|
|
|
|
def test_class_instances(): |
|
assert dill.pickles(o) |
|
assert dill.pickles(oc) |
|
assert dill.pickles(n) |
|
assert dill.pickles(nc) |
|
assert dill.pickles(m) |
|
|
|
def test_class_objects(): |
|
clslist = [_class,_class2,_newclass,_newclass2,_mclass] |
|
objlist = [o,oc,n,nc,m] |
|
_clslist = [dill.dumps(obj) for obj in clslist] |
|
_objlist = [dill.dumps(obj) for obj in objlist] |
|
|
|
for obj in clslist: |
|
globals().pop(obj.__name__) |
|
del clslist |
|
for obj in ['o','oc','n','nc']: |
|
globals().pop(obj) |
|
del objlist |
|
del obj |
|
|
|
for obj,cls in zip(_objlist,_clslist): |
|
_cls = dill.loads(cls) |
|
_obj = dill.loads(obj) |
|
assert _obj.ok() |
|
assert _cls.ok(_cls()) |
|
if _cls.__name__ == "_mclass": |
|
assert type(_cls).__name__ == "_meta" |
|
|
|
|
|
def test_specialtypes(): |
|
assert dill.pickles(type(None)) |
|
assert dill.pickles(type(NotImplemented)) |
|
assert dill.pickles(type(Ellipsis)) |
|
assert dill.pickles(type(EnumMeta)) |
|
|
|
from collections import namedtuple |
|
Z = namedtuple("Z", ['a','b']) |
|
Zi = Z(0,1) |
|
X = namedtuple("Y", ['a','b']) |
|
X.__name__ = "X" |
|
X.__qualname__ = "X" |
|
Xi = X(0,1) |
|
Bad = namedtuple("FakeName", ['a','b']) |
|
Badi = Bad(0,1) |
|
Defaults = namedtuple('Defaults', ['x', 'y'], defaults=[1]) |
|
Defaultsi = Defaults(2) |
|
|
|
|
|
def test_namedtuple(): |
|
assert Z is dill.loads(dill.dumps(Z)) |
|
assert Zi == dill.loads(dill.dumps(Zi)) |
|
assert X is dill.loads(dill.dumps(X)) |
|
assert Xi == dill.loads(dill.dumps(Xi)) |
|
assert Defaults is dill.loads(dill.dumps(Defaults)) |
|
assert Defaultsi == dill.loads(dill.dumps(Defaultsi)) |
|
assert Bad is not dill.loads(dill.dumps(Bad)) |
|
assert Bad._fields == dill.loads(dill.dumps(Bad))._fields |
|
assert tuple(Badi) == tuple(dill.loads(dill.dumps(Badi))) |
|
|
|
class A: |
|
class B(namedtuple("C", ["one", "two"])): |
|
'''docstring''' |
|
B.__module__ = 'testing' |
|
|
|
a = A() |
|
assert dill.copy(a) |
|
|
|
assert dill.copy(A.B).__name__ == 'B' |
|
assert dill.copy(A.B).__qualname__.endswith('.<locals>.A.B') |
|
assert dill.copy(A.B).__doc__ == 'docstring' |
|
assert dill.copy(A.B).__module__ == 'testing' |
|
|
|
from typing import NamedTuple |
|
|
|
def A(): |
|
class B(NamedTuple): |
|
x: int |
|
return B |
|
|
|
assert type(dill.copy(A()(8))).__qualname__ == type(A()(8)).__qualname__ |
|
|
|
def test_dtype(): |
|
try: |
|
import numpy as np |
|
|
|
dti = np.dtype('int') |
|
assert np.dtype == dill.copy(np.dtype) |
|
assert dti == dill.copy(dti) |
|
except ImportError: pass |
|
|
|
|
|
def test_array_nested(): |
|
try: |
|
import numpy as np |
|
|
|
x = np.array([1]) |
|
y = (x,) |
|
assert y == dill.copy(y) |
|
|
|
except ImportError: pass |
|
|
|
|
|
def test_array_subclass(): |
|
try: |
|
import numpy as np |
|
|
|
class TestArray(np.ndarray): |
|
def __new__(cls, input_array, color): |
|
obj = np.asarray(input_array).view(cls) |
|
obj.color = color |
|
return obj |
|
def __array_finalize__(self, obj): |
|
if obj is None: |
|
return |
|
if isinstance(obj, type(self)): |
|
self.color = obj.color |
|
def __getnewargs__(self): |
|
return np.asarray(self), self.color |
|
|
|
a1 = TestArray(np.zeros(100), color='green') |
|
if not dill._dill.IS_PYPY: |
|
assert dill.pickles(a1) |
|
assert a1.__dict__ == dill.copy(a1).__dict__ |
|
|
|
a2 = a1[0:9] |
|
if not dill._dill.IS_PYPY: |
|
assert dill.pickles(a2) |
|
assert a2.__dict__ == dill.copy(a2).__dict__ |
|
|
|
class TestArray2(np.ndarray): |
|
color = 'blue' |
|
|
|
a3 = TestArray2([1,2,3,4,5]) |
|
a3.color = 'green' |
|
if not dill._dill.IS_PYPY: |
|
assert dill.pickles(a3) |
|
assert a3.__dict__ == dill.copy(a3).__dict__ |
|
|
|
except ImportError: pass |
|
|
|
|
|
def test_method_decorator(): |
|
class A(object): |
|
@classmethod |
|
def test(cls): |
|
pass |
|
|
|
a = A() |
|
|
|
res = dill.dumps(a) |
|
new_obj = dill.loads(res) |
|
new_obj.__class__.test() |
|
|
|
|
|
class Y(object): |
|
__slots__ = ('y', '__weakref__') |
|
def __init__(self, y): |
|
self.y = y |
|
|
|
value = 123 |
|
y = Y(value) |
|
|
|
class Y2(object): |
|
__slots__ = 'y' |
|
def __init__(self, y): |
|
self.y = y |
|
|
|
def test_slots(): |
|
assert dill.pickles(Y) |
|
assert dill.pickles(y) |
|
assert dill.pickles(Y.y) |
|
assert dill.copy(y).y == value |
|
assert dill.copy(Y2(value)).y == value |
|
|
|
def test_origbases(): |
|
assert dill.copy(customIntList).__orig_bases__ == customIntList.__orig_bases__ |
|
|
|
def test_attr(): |
|
import attr |
|
@attr.s |
|
class A: |
|
a = attr.ib() |
|
|
|
v = A(1) |
|
assert dill.copy(v) == v |
|
|
|
def test_metaclass(): |
|
class metaclass_with_new(type): |
|
def __new__(mcls, name, bases, ns, **kwds): |
|
cls = super().__new__(mcls, name, bases, ns, **kwds) |
|
assert mcls is not None |
|
assert cls.method(mcls) |
|
return cls |
|
def method(cls, mcls): |
|
return isinstance(cls, mcls) |
|
|
|
l = locals() |
|
exec("""class subclass_with_new(metaclass=metaclass_with_new): |
|
def __new__(cls): |
|
self = super().__new__(cls) |
|
return self""", None, l) |
|
subclass_with_new = l['subclass_with_new'] |
|
|
|
assert dill.copy(subclass_with_new()) |
|
|
|
def test_enummeta(): |
|
from http import HTTPStatus |
|
import enum |
|
assert dill.copy(HTTPStatus.OK) is HTTPStatus.OK |
|
assert dill.copy(enum.EnumMeta) is enum.EnumMeta |
|
|
|
def test_inherit(): |
|
class Foo: |
|
w = 0 |
|
x = 1 |
|
y = 1.1 |
|
a = () |
|
b = (1,) |
|
n = None |
|
|
|
class Bar(Foo): |
|
w = 2 |
|
x = 1 |
|
y = 1.1 |
|
z = 0.2 |
|
a = () |
|
b = (1,) |
|
c = (2,) |
|
n = None |
|
|
|
Baz = dill.copy(Bar) |
|
|
|
import platform |
|
is_pypy = platform.python_implementation() == 'PyPy' |
|
assert Bar.__dict__ == Baz.__dict__ |
|
|
|
assert 'w' in Bar.__dict__ and 'w' in Baz.__dict__ |
|
assert Bar.__dict__['w'] is Baz.__dict__['w'] |
|
assert 'x' in Bar.__dict__ and 'x' in Baz.__dict__ |
|
assert Bar.__dict__['x'] is Baz.__dict__['x'] |
|
|
|
assert 'y' in Bar.__dict__ and 'y' in Baz.__dict__ |
|
same = Bar.__dict__['y'] is Baz.__dict__['y'] |
|
assert same if is_pypy else not same |
|
assert 'z' in Bar.__dict__ and 'z' in Baz.__dict__ |
|
same = Bar.__dict__['z'] is Baz.__dict__['z'] |
|
assert same if is_pypy else not same |
|
|
|
assert 'a' in Bar.__dict__ and 'a' in Baz.__dict__ |
|
assert Bar.__dict__['a'] is Baz.__dict__['a'] |
|
assert 'b' in Bar.__dict__ and 'b' in Baz.__dict__ |
|
assert Bar.__dict__['b'] is not Baz.__dict__['b'] |
|
assert 'c' in Bar.__dict__ and 'c' in Baz.__dict__ |
|
assert Bar.__dict__['c'] is not Baz.__dict__['c'] |
|
|
|
assert 'n' in Bar.__dict__ and 'n' in Baz.__dict__ |
|
assert Bar.__dict__['n'] is Baz.__dict__['n'] |
|
|
|
|
|
if __name__ == '__main__': |
|
test_class_instances() |
|
test_class_objects() |
|
test_specialtypes() |
|
test_namedtuple() |
|
test_dtype() |
|
test_array_nested() |
|
test_array_subclass() |
|
test_method_decorator() |
|
test_slots() |
|
test_origbases() |
|
test_metaclass() |
|
test_enummeta() |
|
test_inherit() |
|
|