diff options
-rw-r--r-- | Cython/Compiler/ParseTreeTransforms.py | 10 | ||||
-rw-r--r-- | tests/run/reduce_pickle.pyx | 11 |
2 files changed, 19 insertions, 2 deletions
diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 18ad386a2..c2e6f8d2f 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -1571,8 +1571,10 @@ if VALUE is not None: env = self.current_env() all_members = [] cls = node.entry.type + cinit = None while cls is not None: all_members.extend(cls.scope.var_entries) + cinit = cinit or cls.scope.lookup('__cinit__') cls = cls.base_type all_members.sort(key=lambda e: e.name) @@ -1581,8 +1583,12 @@ if VALUE is not None: if not e.type.is_pyobject and (not e.type.create_from_py_utility_code(env) or not e.type.create_to_py_utility_code(env))] - if non_py: - msg = "%s cannot be converted to a Python object" % ','.join("self.%s" % e.name for e in non_py) + if cinit or non_py: + if cinit: + # TODO(robertwb): We could allow this if __cinit__ has no require arguments. + msg = 'no default __reduce__ due to non-trivial __cinit__' + else: + msg = "%s cannot be converted to a Python object" % ','.join("self.%s" % e.name for e in non_py) pickle_func = TreeFragment(u""" def __reduce__(self): raise TypeError("%s") diff --git a/tests/run/reduce_pickle.pyx b/tests/run/reduce_pickle.pyx index 8497c7aea..33bb7165e 100644 --- a/tests/run/reduce_pickle.pyx +++ b/tests/run/reduce_pickle.pyx @@ -107,3 +107,14 @@ cdef class NoReduceDueToIntPtr(object): TypeError: self.int_ptr cannot be converted to a Python object """ cdef int* int_ptr + +cdef class NoReduceDueToNontrivialCInit(object): + """ + >>> import pickle + >>> pickle.dumps(NoReduceDueToNontrivialCInit(None)) + Traceback (most recent call last): + ... + TypeError: no default __reduce__ due to non-trivial __cinit__ + """ + def __cinit__(self, arg): + pass |