cpython/Modules/_testcapimodule.c

/*
 * C Extension module to test Python interpreter C APIs.
 *
 * The 'test_*' functions exported by this module are run as part of the
 * standard Python regression test, via Lib/test/test_capi.py.
 */

// Include parts.h first since it takes care of NDEBUG and Py_BUILD_CORE macros
// and including Python.h.
//
// Several parts of this module are broken out into files in _testcapi/.
// Include definitions from there.
#include "_testcapi/parts.h"

#include "frameobject.h"          // PyFrame_New()
#include "marshal.h"              // PyMarshal_WriteLongToFile()

#include <float.h>                // FLT_MAX
#include <signal.h>
#include <stddef.h>               // offsetof()

#ifdef HAVE_SYS_WAIT_H
#  include <sys/wait.h>           // W_STOPCODE
#endif

#ifdef bool
#  error "The public headers should not include <stdbool.h>, see gh-48924"
#endif

#include "_testcapi/util.h"


// Forward declarations
static struct PyModuleDef _testcapimodule;

// Module state
testcapistate_t;

static testcapistate_t*
get_testcapi_state(PyObject *module)
{}

static PyObject *
get_testerror(PyObject *self) {}

/* Raise _testcapi.error with test_name + ": " + msg, and return NULL. */

static PyObject *
raiseTestError(PyObject *self, const char* test_name, const char* msg)
{}

/* Test #defines from pyconfig.h (particularly the SIZEOF_* defines).

   The ones derived from autoconf on the UNIX-like OSes can be relied
   upon (in the absence of sloppy cross-compiling), but the Windows
   platforms have these hardcoded.  Better safe than sorry.
*/
static PyObject*
sizeof_error(PyObject *self, const char* fatname, const char* typname,
    int expected, int got)
{}

static PyObject*
test_config(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

static PyObject*
test_sizeof_c_types(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

static PyObject*
test_list_api(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

static int
test_dict_inner(PyObject *self, int count)
{}



static PyObject*
test_dict_iteration(PyObject* self, PyObject *Py_UNUSED(ignored))
{}

/* Issue #4701: Check that PyObject_Hash implicitly calls
 *   PyType_Ready if it hasn't already been called
 */
static PyTypeObject _HashInheritanceTester_Type =;

static PyObject*
pycompilestring(PyObject* self, PyObject *obj) {}

static PyObject*
test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
return_none(void *unused)
{}

static PyObject *
raise_error(void *unused)
{}

static PyObject *
py_buildvalue(PyObject *self, PyObject *args)
{}

static PyObject *
py_buildvalue_ints(PyObject *self, PyObject *args)
{}

static int
test_buildvalue_N_error(PyObject *self, const char *fmt)
{}

static PyObject *
test_buildvalue_N(PyObject *self, PyObject *Py_UNUSED(ignored))
{}


static PyObject *
test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored))
{}


static PyType_Slot HeapTypeNameType_slots[] =;

static PyType_Spec HeapTypeNameType_Spec =;

static PyObject *
get_heaptype_for_name(PyObject *self, PyObject *Py_UNUSED(ignored))
{}


static PyObject *
get_type_name(PyObject *self, PyObject *type)
{}


static PyObject *
get_type_qualname(PyObject *self, PyObject *type)
{}


static PyObject *
get_type_fullyqualname(PyObject *self, PyObject *type)
{}


static PyObject *
get_type_module_name(PyObject *self, PyObject *type)
{}


static PyObject *
test_get_type_dict(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
pyobject_repr_from_null(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
pyobject_str_from_null(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
pyobject_bytes_from_null(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
set_errno(PyObject *self, PyObject *args)
{}

/* test_thread_state spawns a thread of its own, and that thread releases
 * `thread_done` when it's finished.  The driver code has to know when the
 * thread finishes, because the thread uses a PyObject (the callable) that
 * may go away when the driver finishes.  The former lack of this explicit
 * synchronization caused rare segfaults, so rare that they were seen only
 * on a Mac buildbot (although they were possible on any box).
 */
static PyThread_type_lock thread_done =;

static int
_make_call(void *callable)
{}

/* Same thing, but releases `thread_done` when it returns.  This variant
 * should be called only from threads spawned by test_thread_state().
 */
static void
_make_call_from_thread(void *callable)
{}

static PyObject *
test_thread_state(PyObject *self, PyObject *args)
{}

static PyObject *
gilstate_ensure_release(PyObject *module, PyObject *Py_UNUSED(ignored))
{}

#ifndef MS_WINDOWS
static PyThread_type_lock wait_done =;

static void wait_for_lock(void *unused) {}

// These can be used to test things that care about the existence of another
// thread that the threading module doesn't know about.

static PyObject *
spawn_pthread_waiter(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
end_spawned_pthread(PyObject *self, PyObject *Py_UNUSED(ignored))
{}
#endif  // not MS_WINDOWS

/* test Py_AddPendingCalls using threads */
static int _pending_callback(void *arg)
{}

/* The following requests n callbacks to _pending_callback.  It can be
 * run from any python thread.
 */
static PyObject *
pending_threadfunc(PyObject *self, PyObject *arg, PyObject *kwargs)
{}

/* Test PyOS_string_to_double. */
static PyObject *
test_string_to_double(PyObject *self, PyObject *Py_UNUSED(ignored)) {}


/* Coverage testing of capsule objects. */

static const char *capsule_name =;
static       char *capsule_pointer =;
static       char *capsule_context =;
static const char *capsule_error =;
static int
capsule_destructor_call_count =;

static void
capsule_destructor(PyObject *o) {}

known_capsule;

static PyObject *
test_capsule(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

#ifdef HAVE_GETTIMEOFDAY
/* Profiling of integer performance */
static void print_delta(int test, struct timeval *s, struct timeval *e)
{
    e->tv_sec -= s->tv_sec;
    e->tv_usec -= s->tv_usec;
    if (e->tv_usec < 0) {
        e->tv_sec -=1;
        e->tv_usec += 1000000;
    }
    printf("Test %d: %d.%06ds\n", test, (int)e->tv_sec, (int)e->tv_usec);
}

static PyObject *
profile_int(PyObject *self, PyObject* args)
{
    int i, k;
    struct timeval start, stop;
    PyObject *single, **multiple, *op1, *result;

    /* Test 1: Allocate and immediately deallocate
       many small integers */
    gettimeofday(&start, NULL);
    for(k=0; k < 20000; k++)
        for(i=0; i < 1000; i++) {
            single = PyLong_FromLong(i);
            Py_DECREF(single);
        }
    gettimeofday(&stop, NULL);
    print_delta(1, &start, &stop);

    /* Test 2: Allocate and immediately deallocate
       many large integers */
    gettimeofday(&start, NULL);
    for(k=0; k < 20000; k++)
        for(i=0; i < 1000; i++) {
            single = PyLong_FromLong(i+1000000);
            Py_DECREF(single);
        }
    gettimeofday(&stop, NULL);
    print_delta(2, &start, &stop);

    /* Test 3: Allocate a few integers, then release
       them all simultaneously. */
    multiple = malloc(sizeof(PyObject*) * 1000);
    if (multiple == NULL)
        return PyErr_NoMemory();
    gettimeofday(&start, NULL);
    for(k=0; k < 20000; k++) {
        for(i=0; i < 1000; i++) {
            multiple[i] = PyLong_FromLong(i+1000000);
        }
        for(i=0; i < 1000; i++) {
            Py_DECREF(multiple[i]);
        }
    }
    gettimeofday(&stop, NULL);
    print_delta(3, &start, &stop);
    free(multiple);

    /* Test 4: Allocate many integers, then release
       them all simultaneously. */
    multiple = malloc(sizeof(PyObject*) * 1000000);
    if (multiple == NULL)
        return PyErr_NoMemory();
    gettimeofday(&start, NULL);
    for(k=0; k < 20; k++) {
        for(i=0; i < 1000000; i++) {
            multiple[i] = PyLong_FromLong(i+1000000);
        }
        for(i=0; i < 1000000; i++) {
            Py_DECREF(multiple[i]);
        }
    }
    gettimeofday(&stop, NULL);
    print_delta(4, &start, &stop);
    free(multiple);

    /* Test 5: Allocate many integers < 32000 */
    multiple = malloc(sizeof(PyObject*) * 1000000);
    if (multiple == NULL)
        return PyErr_NoMemory();
    gettimeofday(&start, NULL);
    for(k=0; k < 10; k++) {
        for(i=0; i < 1000000; i++) {
            multiple[i] = PyLong_FromLong(i+1000);
        }
        for(i=0; i < 1000000; i++) {
            Py_DECREF(multiple[i]);
        }
    }
    gettimeofday(&stop, NULL);
    print_delta(5, &start, &stop);
    free(multiple);

    /* Test 6: Perform small int addition */
    op1 = PyLong_FromLong(1);
    gettimeofday(&start, NULL);
    for(i=0; i < 10000000; i++) {
        result = PyNumber_Add(op1, op1);
        Py_DECREF(result);
    }
    gettimeofday(&stop, NULL);
    Py_DECREF(op1);
    print_delta(6, &start, &stop);

    /* Test 7: Perform medium int addition */
    op1 = PyLong_FromLong(1000);
    if (op1 == NULL)
        return NULL;
    gettimeofday(&start, NULL);
    for(i=0; i < 10000000; i++) {
        result = PyNumber_Add(op1, op1);
        Py_XDECREF(result);
    }
    gettimeofday(&stop, NULL);
    Py_DECREF(op1);
    print_delta(7, &start, &stop);

    Py_RETURN_NONE;
}
#endif

/* Issue 6012 */
static PyObject *str1, *str2;
static int
failing_converter(PyObject *obj, void *arg)
{}
static PyObject*
argparsing(PyObject *o, PyObject *args)
{}

/* To test that the result of PyCode_NewEmpty has the right members. */
static PyObject *
code_newempty(PyObject *self, PyObject *args)
{}

static PyObject *
make_memoryview_from_NULL_pointer(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
buffer_fill_info(PyObject *self, PyObject *args)
{}

static PyObject *
test_from_contiguous(PyObject* self, PyObject *Py_UNUSED(ignored))
{}

#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__GNUC__)

static PyObject *
test_pep3118_obsolete_write_locks(PyObject* self, PyObject *Py_UNUSED(ignored))
{}
#endif

/* This tests functions that historically supported write locks.  It is
   wrong to call getbuffer() with view==NULL and a compliant getbufferproc
   is entitled to segfault in that case. */
static PyObject *
getbuffer_with_null_view(PyObject* self, PyObject *obj)
{}

/* PyBuffer_SizeFromFormat() */
static PyObject *
test_PyBuffer_SizeFromFormat(PyObject *self, PyObject *args)
{}

/* Test that the fatal error from not having a current thread doesn't
   cause an infinite loop.  Run via Lib/test/test_capi.py */
static PyObject *
crash_no_current_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

/* Test that the GILState thread and the "current" thread match. */
static PyObject *
test_current_tstate_matches(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

/* To run some code in a sub-interpreter. */
static PyObject *
run_in_subinterp(PyObject *self, PyObject *args)
{}

static PyMethodDef ml;

static PyObject *
create_cfunction(PyObject *self, PyObject *args)
{}

static PyMethodDef ml =;

static PyObject *
_test_incref(PyObject *ob)
{}

static PyObject *
test_xincref_doesnt_leak(PyObject *ob, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
test_incref_doesnt_leak(PyObject *ob, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
test_xdecref_doesnt_leak(PyObject *ob, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
test_decref_doesnt_leak(PyObject *ob, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
test_structseq_newtype_doesnt_leak(PyObject *Py_UNUSED(self),
                              PyObject *Py_UNUSED(args))
{}

static PyObject *
test_structseq_newtype_null_descr_doc(PyObject *Py_UNUSED(self),
                              PyObject *Py_UNUSED(args))
{}

static PyObject *
test_incref_decref_API(PyObject *ob, PyObject *Py_UNUSED(ignored))
{}

test_c_thread_t;

static void
temporary_c_thread(void *data)
{}

static test_c_thread_t test_c_thread;

static PyObject *
call_in_temporary_c_thread(PyObject *self, PyObject *args)
{}

static PyObject *
join_temporary_c_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

/* marshal */

static PyObject*
pymarshal_write_long_to_file(PyObject* self, PyObject *args)
{}

static PyObject*
pymarshal_write_object_to_file(PyObject* self, PyObject *args)
{}

static PyObject*
pymarshal_read_short_from_file(PyObject* self, PyObject *args)
{}

static PyObject*
pymarshal_read_long_from_file(PyObject* self, PyObject *args)
{}

static PyObject*
pymarshal_read_last_object_from_file(PyObject* self, PyObject *args)
{}

static PyObject*
pymarshal_read_object_from_file(PyObject* self, PyObject *args)
{}

static PyObject*
return_null_without_error(PyObject *self, PyObject *args)
{}

static PyObject*
return_result_with_error(PyObject *self, PyObject *args)
{}

static PyObject *
getitem_with_error(PyObject *self, PyObject *args)
{}


static PyObject *
raise_SIGINT_then_send_None(PyObject *self, PyObject *args)
{}


static PyObject*
stack_pointer(PyObject *self, PyObject *args)
{}


#ifdef W_STOPCODE
static PyObject*
py_w_stopcode(PyObject *self, PyObject *args)
{}
#endif


static PyObject *
test_pythread_tss_key_state(PyObject *self, PyObject *args)
{}


/* def bad_get(self, obj, cls):
       cls()
       return repr(self)
*/
static PyObject*
bad_get(PyObject *module, PyObject *args)
{}


#ifdef Py_REF_DEBUG
static PyObject *
negative_refcount(PyObject *self, PyObject *Py_UNUSED(args))
{
    PyObject *obj = PyUnicode_FromString("negative_refcount");
    if (obj == NULL) {
        return NULL;
    }
    assert(Py_REFCNT(obj) == 1);

    Py_SET_REFCNT(obj,  0);
    /* Py_DECREF() must call _Py_NegativeRefcount() and abort Python */
    Py_DECREF(obj);

    Py_RETURN_NONE;
}

static PyObject *
decref_freed_object(PyObject *self, PyObject *Py_UNUSED(args))
{
    PyObject *obj = PyUnicode_FromString("decref_freed_object");
    if (obj == NULL) {
        return NULL;
    }
    assert(Py_REFCNT(obj) == 1);

    // Deallocate the memory
    Py_DECREF(obj);
    // obj is a now a dangling pointer

    // gh-109496: If Python is built in debug mode, Py_DECREF() must call
    // _Py_NegativeRefcount() and abort Python.
    Py_DECREF(obj);

    Py_RETURN_NONE;
}
#endif


/* Functions for testing C calling conventions (METH_*) are named meth_*,
 * e.g. "meth_varargs" for METH_VARARGS.
 *
 * They all return a tuple of their C-level arguments, with None instead
 * of NULL and Python tuples instead of C arrays.
 */


static PyObject*
_null_to_none(PyObject* obj)
{}

static PyObject*
meth_varargs(PyObject* self, PyObject* args)
{}

static PyObject*
meth_varargs_keywords(PyObject* self, PyObject* args, PyObject* kwargs)
{}

static PyObject*
meth_o(PyObject* self, PyObject* obj)
{}

static PyObject*
meth_noargs(PyObject* self, PyObject* ignored)
{}

static PyObject*
_fastcall_to_tuple(PyObject* const* args, Py_ssize_t nargs)
{}

static PyObject*
meth_fastcall(PyObject* self, PyObject* const* args, Py_ssize_t nargs)
{}

static PyObject*
meth_fastcall_keywords(PyObject* self, PyObject* const* args,
                       Py_ssize_t nargs, PyObject* kwargs)
{}

static PyObject*
test_pycfunction_call(PyObject *module, PyObject *args)
{}

static PyObject*
pynumber_tobase(PyObject *module, PyObject *args)
{}

static PyObject*
test_set_type_size(PyObject *self, PyObject *Py_UNUSED(ignored))
{}


// Test Py_CLEAR() macro
static PyObject*
test_py_clear(PyObject *self, PyObject *Py_UNUSED(ignored))
{}


// Test Py_SETREF() and Py_XSETREF() macros, similar to test_py_clear()
static PyObject*
test_py_setref(PyObject *self, PyObject *Py_UNUSED(ignored))
{}


#define TEST_REFCOUNT()


// Test Py_NewRef() and Py_XNewRef() macros
static PyObject*
test_refcount_macros(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

#undef Py_NewRef
#undef Py_XNewRef

// Test Py_NewRef() and Py_XNewRef() functions, after undefining macros.
static PyObject*
test_refcount_funcs(PyObject *self, PyObject *Py_UNUSED(ignored))
{}


// Test Py_Is() function
#define TEST_PY_IS()

// Test Py_Is() macro
static PyObject*
test_py_is_macros(PyObject *self, PyObject *Py_UNUSED(ignored))
{}

#undef Py_Is

// Test Py_Is() function, after undefining its macro.
static PyObject*
test_py_is_funcs(PyObject *self, PyObject *Py_UNUSED(ignored))
{}


// type->tp_version_tag
static PyObject *
type_get_version(PyObject *self, PyObject *type)
{}

static PyObject *
type_modified(PyObject *self, PyObject *type)
{}


static PyObject *
type_assign_version(PyObject *self, PyObject *type)
{}


static PyObject *
type_get_tp_bases(PyObject *self, PyObject *type)
{}

static PyObject *
type_get_tp_mro(PyObject *self, PyObject *type)
{}


/* We only use 2 in test_capi/test_misc.py. */
#define NUM_BASIC_STATIC_TYPES
static PyTypeObject BasicStaticTypes[NUM_BASIC_STATIC_TYPES] =;
static int num_basic_static_types_used =;

static PyObject *
get_basic_static_type(PyObject *self, PyObject *args)
{}


// Test PyThreadState C API
static PyObject *
test_tstate_capi(PyObject *self, PyObject *Py_UNUSED(args))
{}

static PyObject *
frame_getlocals(PyObject *self, PyObject *frame)
{}

static PyObject *
frame_getglobals(PyObject *self, PyObject *frame)
{}

static PyObject *
frame_getgenerator(PyObject *self, PyObject *frame)
{}

static PyObject *
frame_getbuiltins(PyObject *self, PyObject *frame)
{}

static PyObject *
frame_getlasti(PyObject *self, PyObject *frame)
{}

static PyObject *
frame_new(PyObject *self, PyObject *args)
{}

static PyObject *
test_frame_getvar(PyObject *self, PyObject *args)
{}

static PyObject *
test_frame_getvarstring(PyObject *self, PyObject *args)
{}


static PyObject *
gen_get_code(PyObject *self, PyObject *gen)
{}

static PyObject *
eval_eval_code_ex(PyObject *mod, PyObject *pos_args)
{}

static PyObject *
get_feature_macros(PyObject *self, PyObject *Py_UNUSED(args))
{}

static PyObject *
test_code_api(PyObject *self, PyObject *Py_UNUSED(args))
{}

static int
record_func(PyObject *obj, PyFrameObject *f, int what, PyObject *arg)
{}

static PyObject *
settrace_to_record(PyObject *self, PyObject *list)
{}

static int
error_func(PyObject *obj, PyFrameObject *f, int what, PyObject *arg)
{}

static PyObject *
settrace_to_error(PyObject *self, PyObject *list)
{}

static PyObject *
clear_managed_dict(PyObject *self, PyObject *obj)
{}


static PyObject *
test_macros(PyObject *self, PyObject *Py_UNUSED(args))
{}

static PyObject *
function_get_code(PyObject *self, PyObject *func)
{}

static PyObject *
function_get_globals(PyObject *self, PyObject *func)
{}

static PyObject *
function_get_module(PyObject *self, PyObject *func)
{}

static PyObject *
function_get_defaults(PyObject *self, PyObject *func)
{}

static PyObject *
function_set_defaults(PyObject *self, PyObject *args)
{}

static PyObject *
function_get_kw_defaults(PyObject *self, PyObject *func)
{}

static PyObject *
function_set_kw_defaults(PyObject *self, PyObject *args)
{}

static PyObject *
function_get_closure(PyObject *self, PyObject *func)
{}

static PyObject *
function_set_closure(PyObject *self, PyObject *args)
{}

static PyObject *
check_pyimport_addmodule(PyObject *self, PyObject *args)
{}


static PyObject *
test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{}

struct simpletracer_data {};

static int _simpletracer(PyObject *obj, PyRefTracerEvent event, void* data) {}

static PyObject *
test_reftracer(PyObject *ob, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
function_set_warning(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{}

static PyObject *
test_critical_sections(PyObject *module, PyObject *Py_UNUSED(args))
{}


// Used by `finalize_thread_hang`.
#ifdef _POSIX_THREADS
static void finalize_thread_hang_cleanup_callback(void *Py_UNUSED(arg)) {}
#endif

// Tests that finalization does not trigger pthread cleanup.
//
// Must be called with a single nullary callable function that should block
// (with GIL released) until finalization is in progress.
static PyObject *
finalize_thread_hang(PyObject *self, PyObject *callback)
{}


static PyObject *
type_freeze(PyObject *module, PyObject *args)
{}


static PyMethodDef TestMethods[] =;


matmulObject;

static PyObject *
matmulType_matmul(PyObject *self, PyObject *other)
{}

static PyObject *
matmulType_imatmul(PyObject *self, PyObject *other)
{}

static void
matmulType_dealloc(PyObject *self)
{}

static PyNumberMethods matmulType_as_number =;

static PyTypeObject matmulType =;

ipowObject;

static PyObject *
ipowType_ipow(PyObject *self, PyObject *other, PyObject *mod)
{}

static PyNumberMethods ipowType_as_number =;

static PyTypeObject ipowType =;

awaitObject;


static PyObject *
awaitObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{}


static void
awaitObject_dealloc(awaitObject *ao)
{}


static PyObject *
awaitObject_await(awaitObject *ao)
{}

static PyAsyncMethods awaitType_as_async =;


static PyTypeObject awaitType =;


/* Test bpo-35983: create a subclass of "list" which checks that instances
 * are not deallocated twice */

MyListObject;

static PyObject *
MyList_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{}

void
MyList_dealloc(MyListObject* op)
{}

static PyTypeObject MyList_Type =;

/* Test PEP 560 */

PyGenericAliasObject;

static void
generic_alias_dealloc(PyGenericAliasObject *self)
{}

static PyObject *
generic_alias_mro_entries(PyGenericAliasObject *self, PyObject *bases)
{}

static PyMethodDef generic_alias_methods[] =;

static PyTypeObject GenericAlias_Type =;

static PyObject *
generic_alias_new(PyObject *item)
{}

PyGenericObject;

static PyObject *
generic_class_getitem(PyObject *type, PyObject *item)
{}

static PyMethodDef generic_methods[] =;

static PyTypeObject Generic_Type =;

static PyMethodDef meth_instance_methods[] =;


static PyTypeObject MethInstance_Type =;

static PyMethodDef meth_class_methods[] =;


static PyTypeObject MethClass_Type =;

static PyMethodDef meth_static_methods[] =;


static PyTypeObject MethStatic_Type =;

/* ContainerNoGC -- a simple container without GC methods */

ContainerNoGCobject;

static PyObject *
ContainerNoGC_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{}

static void
ContainerNoGC_dealloc(ContainerNoGCobject *self)
{}

static PyMemberDef ContainerNoGC_members[] =;

static PyTypeObject ContainerNoGC_type =;


static struct PyModuleDef _testcapimodule =;

/* Per PEP 489, this module will not be converted to multi-phase initialization
 */

PyMODINIT_FUNC
PyInit__testcapi(void)
{}