cython

Форк
0
/
no_gc_clear.pyx 
101 строка · 2.3 Кб
1
"""
2
Check that the @cython.no_gc_clear decorator disables generation of the
3
tp_clear slot so that __dealloc__ will still see the original reference
4
contents.
5

6
Discussed here: https://article.gmane.org/gmane.comp.python.cython.devel/14986
7
"""
8

9
cimport cython
10
from cpython.ref cimport PyObject, Py_TYPE
11

12
# Pull tp_clear for PyTypeObject as I did not find another way to access it
13
# from Cython code.
14

15
cdef extern from *:
16
    ctypedef struct PyTypeObject:
17
        void (*tp_clear)(object)
18

19
    ctypedef struct __pyx_CyFunctionObject:
20
        PyObject* func_closure
21

22

23
def is_tp_clear_null(obj):
24
    return (<PyTypeObject*>Py_TYPE(obj)).tp_clear is NULL
25

26

27
def is_closure_tp_clear_null(func):
28
    return is_tp_clear_null(
29
        <object>(<__pyx_CyFunctionObject*>func).func_closure)
30

31

32
@cython.no_gc_clear
33
cdef class DisableTpClear:
34
    """
35
    An extension type that has a tp_clear method generated to test that it
36
    actually clears the references to NULL.
37

38
    >>> uut = DisableTpClear()
39
    >>> is_tp_clear_null(uut)
40
    True
41
    >>> uut.call_tp_clear()
42
    >>> type(uut.requires_cleanup) == list
43
    True
44
    >>> del uut
45
    """
46

47
    cdef public object requires_cleanup
48

49
    def __cinit__(self):
50
        self.requires_cleanup = [
51
                "Some object that needs cleaning in __dealloc__"]
52

53
    def call_tp_clear(self):
54
        cdef PyTypeObject *pto = Py_TYPE(self)
55
        if pto.tp_clear != NULL:
56
            pto.tp_clear(self)
57

58

59
cdef class ReallowTpClear(DisableTpClear):
60
    """
61
    >>> import gc
62
    >>> obj = ReallowTpClear()
63
    >>> is_tp_clear_null(obj)
64
    False
65

66
    >>> obj.attr = obj  # create hard reference cycle
67
    >>> del obj; _ignore = gc.collect()
68

69
    # Problem: cannot really validate that the cycle was cleaned up without using weakrefs etc...
70
    """
71
    cdef public object attr
72

73

74
def test_closure_without_clear(str x):
75
    """
76
    >>> c = test_closure_without_clear('abc')
77
    >>> is_tp_clear_null(c)
78
    False
79
    >>> is_closure_tp_clear_null(c)
80
    True
81
    >>> c('cba')
82
    'abcxyzcba'
83
    """
84
    def c(str s):
85
        return x + 'xyz' + s
86
    return c
87

88

89
def test_closure_with_clear(list x):
90
    """
91
    >>> c = test_closure_with_clear(list('abc'))
92
    >>> is_tp_clear_null(c)
93
    False
94
    >>> is_closure_tp_clear_null(c)
95
    False
96
    >>> c('cba')
97
    'abcxyzcba'
98
    """
99
    def c(str s):
100
        return ''.join(x) + 'xyz' + s
101
    return c
102

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

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

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

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