cython

Форк
0
/
reduce_pickle.pyx 
321 строка · 7.6 Кб
1
# mode: run
2
# tag: pickle
3

4
import cython
5

6

7
cdef class A:
8
    """
9
    >>> a = A(3); a
10
    A(3)
11
    >>> import pickle
12
    >>> pickle.loads(pickle.dumps(a))
13
    A(3)
14
    """
15

16
    cdef int value
17

18
    def __init__(self, value):
19
        self.value = value
20

21
    def __repr__(self):
22
        return "A(%s)" % self.value
23

24
    def __reduce__(self):
25
        return A, (self.value,)
26

27
cdef class B:
28
    """
29
    >>> b = B(x=37, y=389); b
30
    B(x=37, y=389)
31
    >>> import pickle
32
    >>> pickle.loads(pickle.dumps(b))
33
    B(x=37, y=389)
34
    """
35

36
    cdef int x, y
37

38
    def __cinit__(self):
39
        self.x = self.y = -1
40

41
    def __init__(self, x=0, y=0):
42
        self.x = x
43
        self.y = y
44

45
    def __repr__(self):
46
        return "%s(x=%s, y=%s)" % (self.__class__.__name__, self.x, self.y)
47

48
    def __reduce__(self):
49
        return makeObj, (type(self), {'x': self.x, 'y': self.y})
50

51
def makeObj(obj_type, kwds):
52
    return obj_type(**kwds)
53

54

55
cdef class C(B):
56
    """
57
    >>> import pickle
58
    >>> pickle.loads(pickle.dumps(C(x=37, y=389)))
59
    C(x=37, y=389)
60
    """
61
    pass
62

63

64
@cython.auto_pickle(True)  # Not needed, just to test the directive.
65
cdef class DefaultReduce(object):
66
    """
67
    >>> a = DefaultReduce(11, 'abc'); a
68
    DefaultReduce(i=11, s='abc')
69
    >>> import pickle
70
    >>> pickle.loads(pickle.dumps(a))
71
    DefaultReduce(i=11, s='abc')
72
    >>> pickle.loads(pickle.dumps(DefaultReduce(i=11, s=None)))
73
    DefaultReduce(i=11, s=None)
74
    """
75

76
    cdef readonly int i
77
    cdef readonly str s
78

79
    def __init__(self, i=0, s=None):
80
        self.i = i
81
        self.s = s
82

83
    def __repr__(self):
84
        return "DefaultReduce(i=%s, s=%r)" % (self.i, self.s)
85

86

87
cdef class DefaultReduceSubclass(DefaultReduce):
88
    """
89
    >>> a = DefaultReduceSubclass(i=11, s='abc', x=1.5); a
90
    DefaultReduceSubclass(i=11, s='abc', x=1.5)
91
    >>> import pickle
92
    >>> pickle.loads(pickle.dumps(a))
93
    DefaultReduceSubclass(i=11, s='abc', x=1.5)
94
    """
95

96
    cdef double x
97

98
    def __init__(self, **kwargs):
99
        self.x = kwargs.pop('x', 0)
100
        super(DefaultReduceSubclass, self).__init__(**kwargs)
101

102
    def __repr__(self):
103
        return "DefaultReduceSubclass(i=%s, s=%r, x=%s)" % (self.i, self.s, self.x)
104

105

106
cdef class result(DefaultReduceSubclass):
107
    """
108
    >>> a = result(i=11, s='abc', x=1.5); a
109
    result(i=11, s='abc', x=1.5)
110
    >>> import pickle
111
    >>> pickle.loads(pickle.dumps(a))
112
    result(i=11, s='abc', x=1.5)
113
    """
114

115
    def __repr__(self):
116
        return "result(i=%s, s=%r, x=%s)" % (self.i, self.s, self.x)
117

118

119
class DefaultReducePySubclass(DefaultReduce):
120
    """
121
    >>> a = DefaultReducePySubclass(i=11, s='abc', x=1.5); a
122
    DefaultReducePySubclass(i=11, s='abc', x=1.5)
123
    >>> import pickle
124
    >>> pickle.loads(pickle.dumps(a))
125
    DefaultReducePySubclass(i=11, s='abc', x=1.5)
126

127
    >>> a.self_reference = a
128
    >>> a2 = pickle.loads(pickle.dumps(a))
129
    >>> a2.self_reference is a2
130
    True
131
    """
132
    def __init__(self, **kwargs):
133
        self.x = kwargs.pop('x', 0)
134
        super(DefaultReducePySubclass, self).__init__(**kwargs)
135

136
    def __repr__(self):
137
        return "DefaultReducePySubclass(i=%s, s=%r, x=%s)" % (self.i, self.s, self.x)
138

139

140
cdef class NoReduceDueToIntPtr(object):
141
    """
142
    >>> import pickle
143
    >>> pickle.dumps(NoReduceDueToIntPtr())
144
    Traceback (most recent call last):
145
    ...
146
    TypeError: self.int_ptr cannot be converted to a Python object for pickling
147
    """
148
    cdef int* int_ptr
149

150
cdef class NoReduceDueToNontrivialCInit(object):
151
    """
152
    >>> import pickle
153
    >>> pickle.dumps(NoReduceDueToNontrivialCInit(None))
154
    Traceback (most recent call last):
155
    ...
156
    TypeError: no default __reduce__ due to non-trivial __cinit__
157
    """
158
    def __cinit__(self, arg):
159
        pass
160

161

162
cdef class NoMembers(object):
163
    """
164
    >>> import pickle
165
    >>> pickle.loads(pickle.dumps(NoMembers()))
166
    NoMembers()
167
    """
168
    def __repr__(self):
169
        return "NoMembers()"
170

171

172
cdef class NoPyMembers(object):
173
    """
174
    >>> import pickle
175
    >>> pickle.loads(pickle.dumps(NoPyMembers(2, 1.75)))
176
    NoPyMembers(ii=[2, 4, 8], x=1.75)
177
    """
178
    cdef int[3] ii
179
    cdef double x
180

181
    def __init__(self, i, x):
182
        self.ii[0] = i
183
        self.ii[1] = i * i
184
        self.ii[2] = i * i * i
185
        self.x = x
186

187
    def __repr__(self):
188
        return "%s(ii=%s, x=%s)" % (type(self).__name__, self.ii, self.x)
189

190
    def __eq__(self, other):
191
        return (
192
            isinstance(other, NoPyMembers) and
193
            (<NoPyMembers> other).ii[0] == self.ii[0] and
194
            (<NoPyMembers> other).ii[1] == self.ii[1] and
195
            (<NoPyMembers> other).ii[2] == self.ii[2] and
196
            (<NoPyMembers> other).x == self.x
197
        )
198

199

200
class NoPyMembersPySubclass(NoPyMembers):
201
    """
202
    >>> import pickle
203
    >>> pickle.loads(pickle.dumps(NoPyMembersPySubclass(2, 1.75, 'xyz')))
204
    NoPyMembersPySubclass(ii=[2, 4, 8], x=1.75, s='xyz')
205
    """
206
    def __init__(self, i, x, s):
207
        super(NoPyMembersPySubclass, self).__init__(i, x)
208
        self.s = s
209
    def __repr__(self):
210
        return (super(NoPyMembersPySubclass, self).__repr__()
211
                [:-1] + ', s=%r)' % self.s)
212

213

214
cdef struct MyStruct:
215
    int i
216
    double x
217

218
cdef class StructMemberDefault(object):
219
    """
220
    >>> import pickle
221
    >>> s = StructMemberDefault(1, 1.5); s
222
    StructMemberDefault(i=1, x=1.5)
223
    >>> pickle.dumps(s)   # doctest: +ELLIPSIS
224
    Traceback (most recent call last):
225
    TypeError: ...my_struct...
226
    """
227

228
    cdef MyStruct my_struct
229

230
    def __init__(self, i, x):
231
        self.my_struct.i = i
232
        self.my_struct.x = x
233

234
    def __repr__(self):
235
        return "%s(i=%s, x=%s)" % (
236
            type(self).__name__, self.my_struct.i, self.my_struct.x)
237

238
@cython.auto_pickle(True)  # Forced due to the (inherited) struct attribute.
239
cdef class StructMemberForcedPickle(StructMemberDefault):
240
    """
241
    >>> import pickle
242
    >>> s = StructMemberForcedPickle(1, 1.5); s
243
    StructMemberForcedPickle(i=1, x=1.5)
244
    >>> pickle.loads(pickle.dumps(s))
245
    StructMemberForcedPickle(i=1, x=1.5)
246
    """
247

248

249
cdef _unset = object()
250

251
# Test cyclic references.
252
cdef class Wrapper(object):
253
  """
254
  >>> import pickle
255
  >>> w = Wrapper(); w
256
  Wrapper(...)
257
  >>> w2 = pickle.loads(pickle.dumps(w)); w2
258
  Wrapper(...)
259
  >>> w2.ref is w2
260
  True
261

262
  >>> pickle.loads(pickle.dumps(Wrapper(DefaultReduce(1, 'xyz'))))
263
  Wrapper(DefaultReduce(i=1, s='xyz'))
264
  >>> L = [None]
265
  >>> L[0] = L
266
  >>> w = Wrapper(L)
267
  >>> pickle.loads(pickle.dumps(Wrapper(L)))
268
  Wrapper([[...]])
269

270
  >>> L[0] = w   # Don't print this one out...
271
  >>> w2 = pickle.loads(pickle.dumps(w))
272
  >>> w2.ref[0] is w2
273
  True
274
  """
275
  cdef public object ref
276
  def __init__(self, ref=_unset):
277
      if ref is _unset:
278
          self.ref = self
279
      else:
280
          self.ref = ref
281
  def __repr__(self):
282
      if self.ref is self:
283
          return "Wrapper(...)"
284
      else:
285
          return "Wrapper(%r)" % self.ref
286

287

288
# Non-regression test for pickling bound and unbound methods of non-extension
289
# classes
290
class MyClass(object):
291
    """
292
    >>> import pickle
293
    >>> pickle.loads(pickle.dumps(MyClass.my_method)) is MyClass.my_method
294
    True
295
    >>> bound_method = pickle.loads(pickle.dumps(MyClass().my_method))
296
    >>> bound_method(1)
297
    1
298
    """
299
    def my_method(self, x):
300
        return x
301

302

303
# Pickled with Cython 0.29.28 (using MD5 for the checksum).
304
OLD_MD5_PICKLE = b'''\
305
creduce_pickle\n__pyx_unpickle_NoPyMembers\nq\x00\
306
(creduce_pickle\nNoPyMembers\nq\x01J\xf2K_\n(]q\x02\
307
(K\x0bKyM3\x05eG?\xf8\x00\x00\x00\x00\x00\x00tq\x03tq\x04Rq\x05.\
308
'''
309

310
try:
311
    from hashlib import md5
312
except ImportError:
313
    pass
314
else:
315
    def unpickle_old_0_29_28():
316
        """
317
        >>> import pickle
318
        >>> b = pickle.loads(OLD_MD5_PICKLE)
319
        >>> b == NoPyMembers(i=11, x=1.5) or b
320
        True
321
        """
322

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.