1# mode: run
2# tag: freelist, cyclicgc
3
4cimport cython
5
6@cython.freelist(4)
7cdef class ExtTypeNoGC:
8    """
9    >>> obj = ExtTypeNoGC()
10    >>> obj = ExtTypeNoGC()
11    >>> obj = ExtTypeNoGC()
12    >>> obj = ExtTypeNoGC()
13    >>> obj = ExtTypeNoGC()
14    >>> obj = ExtTypeNoGC()
15
16    >>> class PyClass(ExtTypeNoGC): a = 1
17    >>> obj = PyClass()
18    >>> obj = PyClass()
19    >>> obj = PyClass()
20    >>> obj = PyClass()
21    >>> del PyClass, obj
22
23    >>> class PyClass(ExtTypeNoGC): __slots__ = ()
24    >>> obj = PyClass()
25    >>> obj = PyClass()
26    >>> obj = PyClass()
27    >>> obj = PyClass()
28    >>> del PyClass, obj
29    """
30
31
32cdef class ExtSubTypeNoGC(ExtTypeNoGC):
33    """
34    >>> obj = ExtSubTypeNoGC()
35    >>> obj = ExtSubTypeNoGC()
36    >>> obj = ExtSubTypeNoGC()
37    >>> obj = ExtSubTypeNoGC()
38    >>> obj = ExtSubTypeNoGC()
39    >>> obj = ExtSubTypeNoGC()
40
41    >>> class PyClass(ExtSubTypeNoGC): a = 1
42    >>> obj = PyClass()
43    >>> obj = PyClass()
44    >>> obj = PyClass()
45    >>> obj = PyClass()
46    >>> del PyClass, obj
47
48    >>> class PyClass(ExtSubTypeNoGC): __slots__ = ()
49    >>> obj = PyClass()
50    >>> obj = PyClass()
51    >>> obj = PyClass()
52    >>> obj = PyClass()
53    >>> del PyClass, obj
54    """
55    cdef bytes x
56
57
58@cython.freelist(4)
59cdef class ExtTypeWithGC:
60    """
61    >>> obj = ExtTypeWithGC()
62    >>> obj = ExtTypeWithGC()
63    >>> obj = ExtTypeWithGC()
64    >>> obj = ExtTypeWithGC()
65    >>> obj = ExtTypeWithGC()
66    >>> obj = ExtTypeWithGC()
67
68    >>> class PyClass(ExtTypeWithGC): a = 1
69    >>> obj = PyClass()
70    >>> obj = PyClass()
71    >>> obj = PyClass()
72    >>> obj = PyClass()
73    >>> del PyClass, obj
74
75    >>> class PyClass(ExtTypeWithGC): __slots__ = ()
76    >>> obj = PyClass()
77    >>> obj = PyClass()
78    >>> obj = PyClass()
79    >>> obj = PyClass()
80    >>> del PyClass, obj
81    """
82    cdef attribute
83
84    def __init__(self):
85        self.attribute = object()
86
87
88def tpnew_ExtTypeWithGC():
89    """
90    >>> obj = tpnew_ExtTypeWithGC()
91    >>> obj = tpnew_ExtTypeWithGC()
92    >>> obj = tpnew_ExtTypeWithGC()
93    >>> obj = tpnew_ExtTypeWithGC()
94    >>> obj = tpnew_ExtTypeWithGC()
95    >>> obj = tpnew_ExtTypeWithGC()
96    """
97    return ExtTypeWithGC.__new__(ExtTypeWithGC)
98
99
100cdef class ExtSubType(ExtTypeWithGC):
101    """
102    >>> obj = ExtSubType()
103    >>> obj = ExtSubType()
104    >>> obj = ExtSubType()
105    >>> obj = ExtSubType()
106    >>> obj = ExtSubType()
107    >>> obj = ExtSubType()
108
109    >>> class PyClass(ExtSubType): a = 1
110    >>> obj = PyClass()
111    >>> obj = PyClass()
112    >>> obj = PyClass()
113    >>> obj = PyClass()
114    >>> del PyClass, obj
115
116    >>> class PyClass(ExtSubType): __slots__ = ()
117    >>> obj = PyClass()
118    >>> obj = PyClass()
119    >>> obj = PyClass()
120    >>> obj = PyClass()
121    >>> del PyClass, obj
122    """
123
124
125cdef class LargerExtSubType(ExtSubType):
126    """
127    >>> obj = LargerExtSubType()
128    >>> obj = LargerExtSubType()
129    >>> obj = LargerExtSubType()
130    >>> obj = LargerExtSubType()
131    >>> obj = LargerExtSubType()
132    >>> obj = LargerExtSubType()
133
134    >>> class PyClass(LargerExtSubType): a = 1
135    >>> obj = PyClass()
136    >>> obj = PyClass()
137    >>> obj = PyClass()
138    >>> obj = PyClass()
139    >>> del PyClass, obj
140
141    >>> class PyClass(LargerExtSubType): __slots__ = ()
142    >>> obj = PyClass()
143    >>> obj = PyClass()
144    >>> obj = PyClass()
145    >>> obj = PyClass()
146    >>> del PyClass, obj
147    """
148    cdef attribute2
149
150    def __cinit__(self):
151        self.attribute2 = object()
152
153
154@cython.freelist(4)
155cdef class ExtTypeWithCAttr:
156    """
157    >>> obj = ExtTypeWithCAttr()
158    >>> obj = ExtTypeWithCAttr()
159    >>> obj = ExtTypeWithCAttr()
160    >>> obj = ExtTypeWithCAttr()
161    >>> obj = ExtTypeWithCAttr()
162    >>> obj = ExtTypeWithCAttr()
163
164    >>> class PyClass(ExtTypeWithCAttr): a = 1
165    >>> obj = PyClass()
166    >>> obj = PyClass()
167    >>> obj = PyClass()
168    >>> obj = PyClass()
169    >>> del PyClass, obj
170
171    >>> class PyClass(ExtTypeWithCAttr): __slots__ = ()
172    >>> obj = PyClass()
173    >>> obj = PyClass()
174    >>> obj = PyClass()
175    >>> obj = PyClass()
176    >>> del PyClass, obj
177    """
178    cdef int cattr
179
180    def __cinit__(self):
181        assert self.cattr == 0
182        self.cattr = 1
183
184
185cdef class ExtSubTypeWithCAttr(ExtTypeWithCAttr):
186    """
187    >>> obj = ExtSubTypeWithCAttr()
188    >>> obj = ExtSubTypeWithCAttr()
189    >>> obj = ExtSubTypeWithCAttr()
190    >>> obj = ExtSubTypeWithCAttr()
191    >>> obj = ExtSubTypeWithCAttr()
192    >>> obj = ExtSubTypeWithCAttr()
193
194    >>> class PyClass(ExtSubTypeWithCAttr): a = 1
195    >>> obj = PyClass()
196    >>> obj = PyClass()
197    >>> obj = PyClass()
198    >>> obj = PyClass()
199
200    >>> class PyClass(ExtSubTypeWithCAttr): __slots__ = ()
201    >>> obj = PyClass()
202    >>> obj = PyClass()
203    >>> obj = PyClass()
204    >>> obj = PyClass()
205    """
206
207
208cdef class ExtTypeWithCAttrNoFreelist:
209    """
210    For comparison with normal CPython instantiation.
211
212    >>> obj = ExtTypeWithCAttrNoFreelist()
213    >>> obj = ExtTypeWithCAttrNoFreelist()
214    >>> obj = ExtTypeWithCAttrNoFreelist()
215    >>> obj = ExtTypeWithCAttrNoFreelist()
216    >>> obj = ExtTypeWithCAttrNoFreelist()
217    >>> obj = ExtTypeWithCAttrNoFreelist()
218
219    >>> class PyClass(ExtTypeWithCAttrNoFreelist): a = 1
220    >>> obj = PyClass()
221    >>> obj = PyClass()
222    >>> obj = PyClass()
223    >>> obj = PyClass()
224    >>> del PyClass, obj
225
226    >>> class PyClass(ExtTypeWithCAttrNoFreelist): __slots__ = ()
227    >>> obj = PyClass()
228    >>> obj = PyClass()
229    >>> obj = PyClass()
230    >>> obj = PyClass()
231    >>> del PyClass, obj
232    """
233    cdef int cattr
234
235    def __cinit__(self):
236        assert self.cattr == 0
237        self.cattr = 1
238
239
240@cython.freelist(4)
241cdef class ExtTypeWithCMethods:
242    """
243    >>> obj = ExtTypeWithCMethods()
244    >>> test_cmethods(obj)
245    (1, 2)
246    >>> obj = ExtTypeWithCMethods()
247    >>> test_cmethods(obj)
248    (1, 2)
249    >>> obj = ExtTypeWithCMethods()
250    >>> test_cmethods(obj)
251    (1, 2)
252    >>> obj = ExtTypeWithCMethods()
253    >>> test_cmethods(obj)
254    (1, 2)
255    >>> obj = ExtTypeWithCMethods()
256    >>> test_cmethods(obj)
257    (1, 2)
258    >>> obj = ExtTypeWithCMethods()
259    >>> test_cmethods(obj)
260    (1, 2)
261
262    >>> class PyClass(ExtTypeWithCMethods): a = 1
263    >>> obj = PyClass()
264    >>> obj = PyClass()
265    >>> test_cmethods(obj)
266    (1, 2)
267    >>> obj = PyClass()
268    >>> test_cmethods(obj)
269    (1, 2)
270    >>> obj = PyClass()
271    >>> del PyClass, obj
272
273    >>> class PyClass(ExtTypeWithCMethods): __slots__ = ()
274    >>> obj = PyClass()
275    >>> obj = PyClass()
276    >>> test_cmethods(obj)
277    (1, 2)
278    >>> obj = PyClass()
279    >>> test_cmethods(obj)
280    (1, 2)
281    >>> obj = PyClass()
282    >>> del PyClass, obj
283    """
284    cdef int cattr
285
286    def __cinit__(self):
287        assert self.cattr == 0
288        self.cattr = 1
289
290    cdef int get_cattr(self):
291        return self.cattr
292
293    cdef set_cattr(self, int value):
294        self.cattr = value
295
296
297def test_cmethods(ExtTypeWithCMethods obj not None):
298    x = obj.get_cattr()
299    obj.set_cattr(2)
300    return x, obj.get_cattr()
301
302
303cdef class ExtSubTypeWithCMethods(ExtTypeWithCMethods):
304    """
305    >>> obj = ExtSubTypeWithCMethods()
306    >>> test_cmethods(obj)
307    (1, 2)
308    >>> obj = ExtSubTypeWithCMethods()
309    >>> test_cmethods(obj)
310    (1, 2)
311    >>> obj = ExtSubTypeWithCMethods()
312    >>> test_cmethods(obj)
313    (1, 2)
314    >>> obj = ExtSubTypeWithCMethods()
315    >>> test_cmethods(obj)
316    (1, 2)
317    >>> obj = ExtSubTypeWithCMethods()
318    >>> test_cmethods(obj)
319    (1, 2)
320    >>> obj = ExtSubTypeWithCMethods()
321    >>> test_cmethods(obj)
322    (1, 2)
323
324    >>> class PyClass(ExtSubTypeWithCMethods): a = 1
325    >>> obj = PyClass()
326    >>> obj = PyClass()
327    >>> obj = PyClass()
328    >>> obj = PyClass()
329    >>> del PyClass, obj
330
331    >>> class PyClass(ExtSubTypeWithCMethods): __slots__ = ()
332    >>> obj = PyClass()
333    >>> obj = PyClass()
334    >>> obj = PyClass()
335    >>> obj = PyClass()
336    >>> del PyClass, obj
337    """
338
339
340cdef class ExtSubTypeWithMoreCMethods(ExtSubTypeWithCMethods):
341    """
342    >>> obj = ExtSubTypeWithMoreCMethods()
343    >>> test_more_cmethods(obj)
344    (2, 3, 3)
345    >>> obj = ExtSubTypeWithCMethods()
346    >>> test_cmethods(obj)
347    (1, 2)
348    >>> obj = ExtTypeWithCMethods()
349    >>> test_cmethods(obj)
350    (1, 2)
351    >>> obj = ExtSubTypeWithMoreCMethods()
352    >>> test_more_cmethods(obj)
353    (2, 3, 3)
354    >>> obj2 = ExtSubTypeWithMoreCMethods()
355    >>> test_more_cmethods(obj2)
356    (2, 3, 3)
357    >>> obj2 = ExtSubTypeWithCMethods()
358    >>> test_cmethods(obj2)
359    (1, 2)
360    >>> obj = ExtSubTypeWithMoreCMethods()
361    >>> test_more_cmethods(obj)
362    (2, 3, 3)
363    >>> obj2 = ExtTypeWithCMethods()
364    >>> test_cmethods(obj2)
365    (1, 2)
366    >>> obj = ExtSubTypeWithMoreCMethods()
367    >>> test_more_cmethods(obj)
368    (2, 3, 3)
369    >>> obj2 = ExtSubTypeWithCMethods()
370    >>> test_cmethods(obj2)
371    (1, 2)
372    >>> obj = ExtSubTypeWithMoreCMethods()
373    >>> test_more_cmethods(obj)
374    (2, 3, 3)
375    >>> obj2 = ExtSubTypeWithCMethods()
376    >>> test_cmethods(obj2)
377    (1, 2)
378    >>> obj = ExtTypeWithCMethods()
379    >>> test_cmethods(obj)
380    (1, 2)
381
382    >>> class PyClass(ExtSubTypeWithMoreCMethods): a = 1
383    >>> obj = PyClass()
384    >>> obj = PyClass()
385    >>> obj = PyClass()
386    >>> obj = PyClass()
387    >>> del PyClass, obj
388
389    >>> class PyClass(ExtSubTypeWithMoreCMethods): __slots__ = ()
390    >>> obj = PyClass()
391    >>> obj = PyClass()
392    >>> obj = PyClass()
393    >>> obj = PyClass()
394    >>> del PyClass, obj
395    """
396    def __cinit__(self):
397        assert self.cattr == 1
398        self.cattr = 2
399
400    cdef int get_cattr2(self):
401        return self.cattr
402
403    cdef set_cattr2(self, int value):
404        self.cattr = value
405
406
407def test_more_cmethods(ExtSubTypeWithMoreCMethods obj not None):
408    x = obj.get_cattr()
409    assert obj.get_cattr2() == x
410    obj.set_cattr2(2)
411    assert obj.get_cattr2() == 2
412    obj.set_cattr(3)
413    return x, obj.get_cattr(), obj.get_cattr2()
414
415
416@cython.freelist(4)
417cdef class ExtTypeWithRefCycle:
418    """
419    >>> obj = first = ExtTypeWithRefCycle()
420    >>> obj.attribute is None
421    True
422    >>> obj = ExtTypeWithRefCycle(obj)
423    >>> obj.attribute is first
424    True
425    >>> obj = ExtTypeWithRefCycle(obj)
426    >>> obj = ExtTypeWithRefCycle(obj)
427    >>> obj = ExtTypeWithRefCycle(obj)
428    >>> obj = ExtTypeWithRefCycle(obj)
429    >>> obj.attribute is not None
430    True
431    >>> first.attribute = obj
432    >>> del obj, first
433
434    >>> class PyClass(ExtTypeWithRefCycle): a = 1
435    >>> obj = PyClass()
436    >>> obj.attribute = obj
437    >>> obj.attribute = PyClass(obj)
438    >>> obj = PyClass()
439    >>> obj = PyClass()
440    >>> del PyClass, obj
441
442    >>> class PyClass(ExtTypeWithRefCycle): __slots__ = ()
443    >>> obj = PyClass()
444    >>> obj.attribute = obj
445    >>> obj.attribute = PyClass(obj)
446    >>> obj = PyClass()
447    >>> obj = PyClass()
448    >>> del PyClass, obj
449    """
450    cdef public attribute
451
452    def __init__(self, obj=None):
453        self.attribute = obj
454
455
456@cython.freelist(3)
457@cython.cclass
458class DecoratedPyClass(object):
459    """
460    >>> obj1 = DecoratedPyClass()
461    >>> obj2 = DecoratedPyClass()
462    >>> obj3 = DecoratedPyClass()
463    >>> obj4 = DecoratedPyClass()
464
465    >>> obj1 = DecoratedPyClass()
466    >>> obj2 = DecoratedPyClass()
467    >>> obj3 = DecoratedPyClass()
468    >>> obj4 = DecoratedPyClass()
469    """
470