Branch data Line data Source code
1 : : /*
2 : : * C Extension module to test Python internal C APIs (Include/internal).
3 : : */
4 : :
5 : : #ifndef Py_BUILD_CORE_BUILTIN
6 : : # define Py_BUILD_CORE_MODULE 1
7 : : #endif
8 : :
9 : : /* Always enable assertions */
10 : : #undef NDEBUG
11 : :
12 : : #define PY_SSIZE_T_CLEAN
13 : :
14 : : #include "Python.h"
15 : : #include "pycore_atomic_funcs.h" // _Py_atomic_int_get()
16 : : #include "pycore_bitutils.h" // _Py_bswap32()
17 : : #include "pycore_fileutils.h" // _Py_normpath
18 : : #include "pycore_frame.h" // _PyInterpreterFrame
19 : : #include "pycore_gc.h" // PyGC_Head
20 : : #include "pycore_hashtable.h" // _Py_hashtable_new()
21 : : #include "pycore_initconfig.h" // _Py_GetConfigsAsDict()
22 : : #include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
23 : : #include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy()
24 : : #include "pycore_pyerrors.h" // _Py_UTF8_Edit_Cost()
25 : : #include "pycore_pystate.h" // _PyThreadState_GET()
26 : : #include "osdefs.h" // MAXPATHLEN
27 : :
28 : :
29 : : static PyObject *
30 : 41 : get_configs(PyObject *self, PyObject *Py_UNUSED(args))
31 : : {
32 : 41 : return _Py_GetConfigsAsDict();
33 : : }
34 : :
35 : :
36 : : static PyObject*
37 : 423 : get_recursion_depth(PyObject *self, PyObject *Py_UNUSED(args))
38 : : {
39 : 423 : PyThreadState *tstate = _PyThreadState_GET();
40 : :
41 : : /* subtract one to ignore the frame of the get_recursion_depth() call */
42 : :
43 : 423 : return PyLong_FromLong(tstate->recursion_limit - tstate->recursion_remaining - 1);
44 : : }
45 : :
46 : :
47 : : static PyObject*
48 : 1 : test_bswap(PyObject *self, PyObject *Py_UNUSED(args))
49 : : {
50 : 1 : uint16_t u16 = _Py_bswap16(UINT16_C(0x3412));
51 [ - + ]: 1 : if (u16 != UINT16_C(0x1234)) {
52 : 0 : PyErr_Format(PyExc_AssertionError,
53 : : "_Py_bswap16(0x3412) returns %u", u16);
54 : 0 : return NULL;
55 : : }
56 : :
57 : 1 : uint32_t u32 = _Py_bswap32(UINT32_C(0x78563412));
58 [ - + ]: 1 : if (u32 != UINT32_C(0x12345678)) {
59 : 0 : PyErr_Format(PyExc_AssertionError,
60 : : "_Py_bswap32(0x78563412) returns %lu", u32);
61 : 0 : return NULL;
62 : : }
63 : :
64 : 1 : uint64_t u64 = _Py_bswap64(UINT64_C(0xEFCDAB9078563412));
65 [ - + ]: 1 : if (u64 != UINT64_C(0x1234567890ABCDEF)) {
66 : 0 : PyErr_Format(PyExc_AssertionError,
67 : : "_Py_bswap64(0xEFCDAB9078563412) returns %llu", u64);
68 : 0 : return NULL;
69 : : }
70 : :
71 : 1 : Py_RETURN_NONE;
72 : : }
73 : :
74 : :
75 : : static int
76 : 8 : check_popcount(uint32_t x, int expected)
77 : : {
78 : : // Use volatile to prevent the compiler to optimize out the whole test
79 : 8 : volatile uint32_t u = x;
80 : 8 : int bits = _Py_popcount32(u);
81 [ - + ]: 8 : if (bits != expected) {
82 : 0 : PyErr_Format(PyExc_AssertionError,
83 : : "_Py_popcount32(%lu) returns %i, expected %i",
84 : : (unsigned long)x, bits, expected);
85 : 0 : return -1;
86 : : }
87 : 8 : return 0;
88 : : }
89 : :
90 : :
91 : : static PyObject*
92 : 1 : test_popcount(PyObject *self, PyObject *Py_UNUSED(args))
93 : : {
94 : : #define CHECK(X, RESULT) \
95 : : do { \
96 : : if (check_popcount(X, RESULT) < 0) { \
97 : : return NULL; \
98 : : } \
99 : : } while (0)
100 : :
101 [ - + ]: 1 : CHECK(0, 0);
102 [ - + ]: 1 : CHECK(1, 1);
103 [ - + ]: 1 : CHECK(0x08080808, 4);
104 [ - + ]: 1 : CHECK(0x10000001, 2);
105 [ - + ]: 1 : CHECK(0x10101010, 4);
106 [ - + ]: 1 : CHECK(0x10204080, 4);
107 [ - + ]: 1 : CHECK(0xDEADCAFE, 22);
108 [ - + ]: 1 : CHECK(0xFFFFFFFF, 32);
109 : 1 : Py_RETURN_NONE;
110 : :
111 : : #undef CHECK
112 : : }
113 : :
114 : :
115 : : static int
116 : 7 : check_bit_length(unsigned long x, int expected)
117 : : {
118 : : // Use volatile to prevent the compiler to optimize out the whole test
119 : 7 : volatile unsigned long u = x;
120 : 7 : int len = _Py_bit_length(u);
121 [ - + ]: 7 : if (len != expected) {
122 : 0 : PyErr_Format(PyExc_AssertionError,
123 : : "_Py_bit_length(%lu) returns %i, expected %i",
124 : : x, len, expected);
125 : 0 : return -1;
126 : : }
127 : 7 : return 0;
128 : : }
129 : :
130 : :
131 : : static PyObject*
132 : 1 : test_bit_length(PyObject *self, PyObject *Py_UNUSED(args))
133 : : {
134 : : #define CHECK(X, RESULT) \
135 : : do { \
136 : : if (check_bit_length(X, RESULT) < 0) { \
137 : : return NULL; \
138 : : } \
139 : : } while (0)
140 : :
141 [ - + ]: 1 : CHECK(0, 0);
142 [ - + ]: 1 : CHECK(1, 1);
143 [ - + ]: 1 : CHECK(0x1000, 13);
144 [ - + ]: 1 : CHECK(0x1234, 13);
145 [ - + ]: 1 : CHECK(0x54321, 19);
146 [ - + ]: 1 : CHECK(0x7FFFFFFF, 31);
147 [ - + ]: 1 : CHECK(0xFFFFFFFF, 32);
148 : 1 : Py_RETURN_NONE;
149 : :
150 : : #undef CHECK
151 : : }
152 : :
153 : :
154 : : #define TO_PTR(ch) ((void*)(uintptr_t)ch)
155 : : #define FROM_PTR(ptr) ((uintptr_t)ptr)
156 : : #define VALUE(key) (1 + ((int)(key) - 'a'))
157 : :
158 : : static Py_uhash_t
159 : 82 : hash_char(const void *key)
160 : : {
161 : 82 : char ch = (char)FROM_PTR(key);
162 : 82 : return ch;
163 : : }
164 : :
165 : :
166 : : static int
167 : 25 : hashtable_cb(_Py_hashtable_t *table,
168 : : const void *key_ptr, const void *value_ptr,
169 : : void *user_data)
170 : : {
171 : 25 : int *count = (int *)user_data;
172 : 25 : char key = (char)FROM_PTR(key_ptr);
173 : 25 : int value = (int)FROM_PTR(value_ptr);
174 [ - + ]: 25 : assert(value == VALUE(key));
175 : 25 : *count += 1;
176 : 25 : return 0;
177 : : }
178 : :
179 : :
180 : : static PyObject*
181 : 1 : test_hashtable(PyObject *self, PyObject *Py_UNUSED(args))
182 : : {
183 : 1 : _Py_hashtable_t *table = _Py_hashtable_new(hash_char,
184 : : _Py_hashtable_compare_direct);
185 [ - + ]: 1 : if (table == NULL) {
186 : : return PyErr_NoMemory();
187 : : }
188 : :
189 : : // Using an newly allocated table must not crash
190 [ - + ]: 1 : assert(table->nentries == 0);
191 [ - + ]: 1 : assert(table->nbuckets > 0);
192 [ - + ]: 1 : assert(_Py_hashtable_get(table, TO_PTR('x')) == NULL);
193 : :
194 : : // Test _Py_hashtable_set()
195 : : char key;
196 [ + + ]: 27 : for (key='a'; key <= 'z'; key++) {
197 : 26 : int value = VALUE(key);
198 [ - + ]: 26 : if (_Py_hashtable_set(table, TO_PTR(key), TO_PTR(value)) < 0) {
199 : 0 : _Py_hashtable_destroy(table);
200 : : return PyErr_NoMemory();
201 : : }
202 : : }
203 [ - + ]: 1 : assert(table->nentries == 26);
204 [ - + ]: 1 : assert(table->nbuckets > table->nentries);
205 : :
206 : : // Test _Py_hashtable_get_entry()
207 [ + + ]: 27 : for (key='a'; key <= 'z'; key++) {
208 : 26 : _Py_hashtable_entry_t *entry = _Py_hashtable_get_entry(table, TO_PTR(key));
209 [ - + ]: 26 : assert(entry != NULL);
210 [ - + ]: 26 : assert(entry->key == TO_PTR(key));
211 [ - + ]: 26 : assert(entry->value == TO_PTR(VALUE(key)));
212 : : }
213 : :
214 : : // Test _Py_hashtable_get()
215 [ + + ]: 27 : for (key='a'; key <= 'z'; key++) {
216 : 26 : void *value_ptr = _Py_hashtable_get(table, TO_PTR(key));
217 [ - + ]: 26 : assert((int)FROM_PTR(value_ptr) == VALUE(key));
218 : : }
219 : :
220 : : // Test _Py_hashtable_steal()
221 : 1 : key = 'p';
222 : 1 : void *value_ptr = _Py_hashtable_steal(table, TO_PTR(key));
223 [ - + ]: 1 : assert((int)FROM_PTR(value_ptr) == VALUE(key));
224 [ - + ]: 1 : assert(table->nentries == 25);
225 [ - + ]: 1 : assert(_Py_hashtable_get_entry(table, TO_PTR(key)) == NULL);
226 : :
227 : : // Test _Py_hashtable_foreach()
228 : 1 : int count = 0;
229 : 1 : int res = _Py_hashtable_foreach(table, hashtable_cb, &count);
230 [ - + ]: 1 : assert(res == 0);
231 [ - + ]: 1 : assert(count == 25);
232 : :
233 : : // Test _Py_hashtable_clear()
234 : 1 : _Py_hashtable_clear(table);
235 [ - + ]: 1 : assert(table->nentries == 0);
236 [ - + ]: 1 : assert(table->nbuckets > 0);
237 [ - + ]: 1 : assert(_Py_hashtable_get(table, TO_PTR('x')) == NULL);
238 : :
239 : 1 : _Py_hashtable_destroy(table);
240 : 1 : Py_RETURN_NONE;
241 : : }
242 : :
243 : :
244 : : static PyObject *
245 : 41 : test_get_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
246 : : {
247 : : PyConfig config;
248 : 41 : PyConfig_InitIsolatedConfig(&config);
249 [ - + ]: 41 : if (_PyInterpreterState_GetConfigCopy(&config) < 0) {
250 : 0 : PyConfig_Clear(&config);
251 : 0 : return NULL;
252 : : }
253 : 41 : PyObject *dict = _PyConfig_AsDict(&config);
254 : 41 : PyConfig_Clear(&config);
255 : 41 : return dict;
256 : : }
257 : :
258 : :
259 : : static PyObject *
260 : 187 : test_set_config(PyObject *Py_UNUSED(self), PyObject *dict)
261 : : {
262 : : PyConfig config;
263 : 187 : PyConfig_InitIsolatedConfig(&config);
264 [ + + ]: 187 : if (_PyConfig_FromDict(&config, dict) < 0) {
265 : 146 : goto error;
266 : : }
267 [ - + ]: 41 : if (_PyInterpreterState_SetConfig(&config) < 0) {
268 : 0 : goto error;
269 : : }
270 : 41 : PyConfig_Clear(&config);
271 : 41 : Py_RETURN_NONE;
272 : :
273 : 146 : error:
274 : 146 : PyConfig_Clear(&config);
275 : 146 : return NULL;
276 : : }
277 : :
278 : :
279 : : static PyObject *
280 : 7 : test_reset_path_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(arg))
281 : : {
282 : 7 : _PyPathConfig_ClearGlobal();
283 : 7 : Py_RETURN_NONE;
284 : : }
285 : :
286 : :
287 : : static PyObject*
288 : 1 : test_atomic_funcs(PyObject *self, PyObject *Py_UNUSED(args))
289 : : {
290 : : // Test _Py_atomic_size_get() and _Py_atomic_size_set()
291 : 1 : Py_ssize_t var = 1;
292 : 1 : _Py_atomic_size_set(&var, 2);
293 [ - + ]: 1 : assert(_Py_atomic_size_get(&var) == 2);
294 : 1 : Py_RETURN_NONE;
295 : : }
296 : :
297 : :
298 : : static int
299 : 19 : check_edit_cost(const char *a, const char *b, Py_ssize_t expected)
300 : : {
301 : 19 : int ret = -1;
302 : 19 : PyObject *a_obj = NULL;
303 : 19 : PyObject *b_obj = NULL;
304 : :
305 : 19 : a_obj = PyUnicode_FromString(a);
306 [ - + ]: 19 : if (a_obj == NULL) {
307 : 0 : goto exit;
308 : : }
309 : 19 : b_obj = PyUnicode_FromString(b);
310 [ - + ]: 19 : if (b_obj == NULL) {
311 : 0 : goto exit;
312 : : }
313 : 19 : Py_ssize_t result = _Py_UTF8_Edit_Cost(a_obj, b_obj, -1);
314 [ - + ]: 19 : if (result != expected) {
315 : 0 : PyErr_Format(PyExc_AssertionError,
316 : : "Edit cost from '%s' to '%s' returns %zd, expected %zd",
317 : : a, b, result, expected);
318 : 0 : goto exit;
319 : : }
320 : : // Check that smaller max_edits thresholds are exceeded.
321 : 19 : Py_ssize_t max_edits = result;
322 [ + + ]: 71 : while (max_edits > 0) {
323 : 52 : max_edits /= 2;
324 : 52 : Py_ssize_t result2 = _Py_UTF8_Edit_Cost(a_obj, b_obj, max_edits);
325 [ - + ]: 52 : if (result2 <= max_edits) {
326 : 0 : PyErr_Format(PyExc_AssertionError,
327 : : "Edit cost from '%s' to '%s' (threshold %zd) "
328 : : "returns %zd, expected greater than %zd",
329 : : a, b, max_edits, result2, max_edits);
330 : 0 : goto exit;
331 : : }
332 : : }
333 : : // Check that bigger max_edits thresholds don't change anything
334 : 19 : Py_ssize_t result3 = _Py_UTF8_Edit_Cost(a_obj, b_obj, result * 2 + 1);
335 [ - + ]: 19 : if (result3 != result) {
336 : 0 : PyErr_Format(PyExc_AssertionError,
337 : : "Edit cost from '%s' to '%s' (threshold %zd) "
338 : : "returns %zd, expected %zd",
339 : : a, b, result * 2, result3, result);
340 : 0 : goto exit;
341 : : }
342 : 19 : ret = 0;
343 : 19 : exit:
344 : 19 : Py_XDECREF(a_obj);
345 : 19 : Py_XDECREF(b_obj);
346 : 19 : return ret;
347 : : }
348 : :
349 : : static PyObject *
350 : 1 : test_edit_cost(PyObject *self, PyObject *Py_UNUSED(args))
351 : : {
352 : : #define CHECK(a, b, n) do { \
353 : : if (check_edit_cost(a, b, n) < 0) { \
354 : : return NULL; \
355 : : } \
356 : : } while (0) \
357 : :
358 [ - + ]: 1 : CHECK("", "", 0);
359 [ - + ]: 1 : CHECK("", "a", 2);
360 [ - + ]: 1 : CHECK("a", "A", 1);
361 [ - + ]: 1 : CHECK("Apple", "Aple", 2);
362 [ - + ]: 1 : CHECK("Banana", "B@n@n@", 6);
363 [ - + ]: 1 : CHECK("Cherry", "Cherry!", 2);
364 [ - + ]: 1 : CHECK("---0---", "------", 2);
365 [ - + ]: 1 : CHECK("abc", "y", 6);
366 [ - + ]: 1 : CHECK("aa", "bb", 4);
367 [ - + ]: 1 : CHECK("aaaaa", "AAAAA", 5);
368 [ - + ]: 1 : CHECK("wxyz", "wXyZ", 2);
369 [ - + ]: 1 : CHECK("wxyz", "wXyZ123", 8);
370 [ - + ]: 1 : CHECK("Python", "Java", 12);
371 [ - + ]: 1 : CHECK("Java", "C#", 8);
372 [ - + ]: 1 : CHECK("AbstractFoobarManager", "abstract_foobar_manager", 3+2*2);
373 [ - + ]: 1 : CHECK("CPython", "PyPy", 10);
374 [ - + ]: 1 : CHECK("CPython", "pypy", 11);
375 [ - + ]: 1 : CHECK("AttributeError", "AttributeErrop", 2);
376 [ - + ]: 1 : CHECK("AttributeError", "AttributeErrorTests", 10);
377 : :
378 : : #undef CHECK
379 : 1 : Py_RETURN_NONE;
380 : : }
381 : :
382 : :
383 : : static PyObject *
384 : 34 : normalize_path(PyObject *self, PyObject *filename)
385 : : {
386 : 34 : Py_ssize_t size = -1;
387 : 34 : wchar_t *encoded = PyUnicode_AsWideCharString(filename, &size);
388 [ - + ]: 34 : if (encoded == NULL) {
389 : 0 : return NULL;
390 : : }
391 : :
392 : 34 : PyObject *result = PyUnicode_FromWideChar(_Py_normpath(encoded, size), -1);
393 : 34 : PyMem_Free(encoded);
394 : :
395 : 34 : return result;
396 : : }
397 : :
398 : : static PyObject *
399 : 0 : get_getpath_codeobject(PyObject *self, PyObject *Py_UNUSED(args)) {
400 : 0 : return _Py_Get_Getpath_CodeObject();
401 : : }
402 : :
403 : :
404 : : static PyObject *
405 : 12 : encode_locale_ex(PyObject *self, PyObject *args)
406 : : {
407 : : PyObject *unicode;
408 : 12 : int current_locale = 0;
409 : : wchar_t *wstr;
410 : 12 : PyObject *res = NULL;
411 : 12 : const char *errors = NULL;
412 : :
413 [ - + ]: 12 : if (!PyArg_ParseTuple(args, "U|is", &unicode, ¤t_locale, &errors)) {
414 : 0 : return NULL;
415 : : }
416 : 12 : wstr = PyUnicode_AsWideCharString(unicode, NULL);
417 [ - + ]: 12 : if (wstr == NULL) {
418 : 0 : return NULL;
419 : : }
420 : 12 : _Py_error_handler error_handler = _Py_GetErrorHandler(errors);
421 : :
422 : 12 : char *str = NULL;
423 : : size_t error_pos;
424 : 12 : const char *reason = NULL;
425 : 12 : int ret = _Py_EncodeLocaleEx(wstr,
426 : : &str, &error_pos, &reason,
427 : : current_locale, error_handler);
428 : 12 : PyMem_Free(wstr);
429 : :
430 [ + - + + : 12 : switch(ret) {
- ]
431 : 9 : case 0:
432 : 9 : res = PyBytes_FromString(str);
433 : 9 : PyMem_RawFree(str);
434 : 9 : break;
435 : 0 : case -1:
436 : : PyErr_NoMemory();
437 : 0 : break;
438 : 1 : case -2:
439 : 1 : PyErr_Format(PyExc_RuntimeError, "encode error: pos=%zu, reason=%s",
440 : : error_pos, reason);
441 : 1 : break;
442 : 2 : case -3:
443 : 2 : PyErr_SetString(PyExc_ValueError, "unsupported error handler");
444 : 2 : break;
445 : 0 : default:
446 : 0 : PyErr_SetString(PyExc_ValueError, "unknown error code");
447 : 0 : break;
448 : : }
449 : 12 : return res;
450 : : }
451 : :
452 : :
453 : : static PyObject *
454 : 18 : decode_locale_ex(PyObject *self, PyObject *args)
455 : : {
456 : : char *str;
457 : 18 : int current_locale = 0;
458 : 18 : PyObject *res = NULL;
459 : 18 : const char *errors = NULL;
460 : :
461 [ - + ]: 18 : if (!PyArg_ParseTuple(args, "y|is", &str, ¤t_locale, &errors)) {
462 : 0 : return NULL;
463 : : }
464 : 18 : _Py_error_handler error_handler = _Py_GetErrorHandler(errors);
465 : :
466 : 18 : wchar_t *wstr = NULL;
467 : 18 : size_t wlen = 0;
468 : 18 : const char *reason = NULL;
469 : 18 : int ret = _Py_DecodeLocaleEx(str,
470 : : &wstr, &wlen, &reason,
471 : : current_locale, error_handler);
472 : :
473 [ + - + + : 18 : switch(ret) {
- ]
474 : 12 : case 0:
475 : 12 : res = PyUnicode_FromWideChar(wstr, wlen);
476 : 12 : PyMem_RawFree(wstr);
477 : 12 : break;
478 : 0 : case -1:
479 : : PyErr_NoMemory();
480 : 0 : break;
481 : 4 : case -2:
482 : 4 : PyErr_Format(PyExc_RuntimeError, "decode error: pos=%zu, reason=%s",
483 : : wlen, reason);
484 : 4 : break;
485 : 2 : case -3:
486 : 2 : PyErr_SetString(PyExc_ValueError, "unsupported error handler");
487 : 2 : break;
488 : 0 : default:
489 : 0 : PyErr_SetString(PyExc_ValueError, "unknown error code");
490 : 0 : break;
491 : : }
492 : 18 : return res;
493 : : }
494 : :
495 : : static PyObject *record_list = NULL;
496 : :
497 : : static PyObject *
498 : 2 : set_eval_frame_default(PyObject *self, PyObject *Py_UNUSED(args))
499 : : {
500 : 2 : _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), _PyEval_EvalFrameDefault);
501 [ + - ]: 2 : Py_CLEAR(record_list);
502 : 2 : Py_RETURN_NONE;
503 : : }
504 : :
505 : : static PyObject *
506 : 200 : record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
507 : : {
508 : 200 : PyList_Append(record_list, f->f_func->func_name);
509 : 200 : return _PyEval_EvalFrameDefault(tstate, f, exc);
510 : : }
511 : :
512 : :
513 : : static PyObject *
514 : 2 : set_eval_frame_record(PyObject *self, PyObject *list)
515 : : {
516 [ - + ]: 2 : if (!PyList_Check(list)) {
517 : 0 : PyErr_SetString(PyExc_TypeError, "argument must be a list");
518 : 0 : return NULL;
519 : : }
520 [ - + ]: 2 : Py_CLEAR(record_list);
521 : 2 : Py_INCREF(list);
522 : 2 : record_list = list;
523 : 2 : _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), record_eval);
524 : 2 : Py_RETURN_NONE;
525 : : }
526 : :
527 : :
528 : : static PyMethodDef TestMethods[] = {
529 : : {"get_configs", get_configs, METH_NOARGS},
530 : : {"get_recursion_depth", get_recursion_depth, METH_NOARGS},
531 : : {"test_bswap", test_bswap, METH_NOARGS},
532 : : {"test_popcount", test_popcount, METH_NOARGS},
533 : : {"test_bit_length", test_bit_length, METH_NOARGS},
534 : : {"test_hashtable", test_hashtable, METH_NOARGS},
535 : : {"get_config", test_get_config, METH_NOARGS},
536 : : {"set_config", test_set_config, METH_O},
537 : : {"reset_path_config", test_reset_path_config, METH_NOARGS},
538 : : {"test_atomic_funcs", test_atomic_funcs, METH_NOARGS},
539 : : {"test_edit_cost", test_edit_cost, METH_NOARGS},
540 : : {"normalize_path", normalize_path, METH_O, NULL},
541 : : {"get_getpath_codeobject", get_getpath_codeobject, METH_NOARGS, NULL},
542 : : {"EncodeLocaleEx", encode_locale_ex, METH_VARARGS},
543 : : {"DecodeLocaleEx", decode_locale_ex, METH_VARARGS},
544 : : {"set_eval_frame_default", set_eval_frame_default, METH_NOARGS, NULL},
545 : : {"set_eval_frame_record", set_eval_frame_record, METH_O, NULL},
546 : : {NULL, NULL} /* sentinel */
547 : : };
548 : :
549 : :
550 : : static struct PyModuleDef _testcapimodule = {
551 : : PyModuleDef_HEAD_INIT,
552 : : "_testinternalcapi",
553 : : NULL,
554 : : -1,
555 : : TestMethods,
556 : : NULL,
557 : : NULL,
558 : : NULL,
559 : : NULL
560 : : };
561 : :
562 : :
563 : : PyMODINIT_FUNC
564 : 64 : PyInit__testinternalcapi(void)
565 : : {
566 : 64 : PyObject *module = PyModule_Create(&_testcapimodule);
567 [ - + ]: 64 : if (module == NULL) {
568 : 0 : return NULL;
569 : : }
570 : :
571 [ - + ]: 64 : if (PyModule_AddObject(module, "SIZEOF_PYGC_HEAD",
572 : : PyLong_FromSsize_t(sizeof(PyGC_Head))) < 0) {
573 : 0 : goto error;
574 : : }
575 : :
576 : 64 : return module;
577 : :
578 : 0 : error:
579 : 0 : Py_DECREF(module);
580 : 0 : return NULL;
581 : : }
|