1
PYTHON setup.py build_ext --inplace
2
PYTHON -c "import runner"
4
######## setup.py ########
6
from Cython.Build.Dependencies import cythonize
7
from Cython.Compiler.Errors import CompileError
8
from distutils.core import setup
10
# force the build order
11
setup(ext_modules= cythonize("check_size.pyx"))
13
setup(ext_modules = cythonize("_check_size*.pyx"))
16
setup(ext_modules= cythonize("check_size_invalid.pyx"))
18
except CompileError as e:
21
######## check_size_nominal.h ########
40
######## check_size_bigger.h ########
61
######## check_size_smaller.h ########
79
######## check_size.pyx ########
82
cdef public int field0, field1, field2;
84
def __init__(self, f0, f1, f2):
89
######## _check_size_exact.pyx ########
91
cdef extern from "check_size_nominal.h":
93
ctypedef class check_size.Foo [object FooStructNominal]:
99
cpdef public int testme(Foo f) except -1:
102
######## _check_size_too_small.pyx ########
104
cdef extern from "check_size_bigger.h":
106
ctypedef class check_size.Foo [object FooStructBig]:
113
cpdef public int testme(Foo f, int f2) except -1:
115
return f.f0 + f.f1 + f.f2
117
######## _check_size_default.pyx ########
119
cdef extern from "check_size_smaller.h":
121
ctypedef class check_size.Foo [object FooStructSmall]:
126
cpdef public int testme(Foo f) except -1:
129
######## _check_size_warn.pyx ########
131
cdef extern from "check_size_smaller.h":
133
# make sure missing check_size is equivalent to warn
134
ctypedef class check_size.Foo [object FooStructSmall, check_size warn]:
139
cpdef public int testme(Foo f) except -1:
142
######## _check_size_ignore.pyx ########
144
cdef extern from "check_size_smaller.h":
146
# Allow size to be larger
147
ctypedef class check_size.Foo [object FooStructSmall, check_size ignore]:
152
cpdef public int testme(Foo f) except -1:
155
######## _check_size_error.pyx ########
157
cdef extern from "check_size_smaller.h":
159
# Strict checking, will raise an error
160
ctypedef class check_size.Foo [object FooStructSmall, check_size error]:
165
cpdef public int testme(Foo f) except -1:
168
######## check_size_invalid.pyx ########
170
cdef extern from "check_size_smaller.h":
172
# Raise CompileError when using bad value
173
ctypedef class check_size.Foo [object FooStructSmall, check_size hihi]:
178
cpdef public int testme(Foo f) except -1:
181
######## runner.py ########
183
import check_size, _check_size_exact, warnings
185
foo = check_size.Foo(23, 123, 1023)
187
assert foo.field0 == 23
188
assert foo.field1 == 123
190
ret = _check_size_exact.testme(foo)
191
assert ret == 23 + 123
193
# ValueError since check_size.Foo's tp_basicsize is smaller than what is needed
194
# for FooStructBig. Messing with f2 will access memory outside the struct!
196
import _check_size_too_small
198
except ValueError as e:
199
assert str(e).startswith('check_size.Foo size changed')
201
# Warning since check_size.Foo's tp_basicsize is larger than what is needed
202
# for FooStructSmall. There is "spare", accessing FooStructSmall's fields will
203
# never access invalid memory. This can happen, for instance, when using old
204
# headers with a newer runtime, or when using an old _check_size{2,3} with a newer
205
# check_size, where the developers of check_size are careful to be backward
208
with warnings.catch_warnings(record=True) as w:
209
warnings.simplefilter("always")
210
import _check_size_default
211
import _check_size_warn
212
assert len(w) == 2, 'expected two warnings, got %d' % len(w)
213
assert str(w[0].message).startswith('check_size.Foo size changed')
214
assert str(w[1].message).startswith('check_size.Foo size changed')
216
ret = _check_size_default.testme(foo)
218
ret = _check_size_warn.testme(foo)
221
with warnings.catch_warnings(record=True) as w:
222
# No warning, runtime vendor must provide backward compatibility
223
import _check_size_ignore
226
ret = _check_size_ignore.testme(foo)
230
# Enforce strict checking
231
import _check_size_error
233
except ValueError as e:
234
assert str(e).startswith('check_size.Foo size changed')