Skip to content

gh-128911: Add tests on the PyImport C API #128915

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 17, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
327 changes: 327 additions & 0 deletions Lib/test/test_capi/test_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
import importlib.util
import os.path
import sys
import types
import unittest
from test.support import os_helper
from test.support import import_helper
from test.support.warnings_helper import check_warnings

_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
NULL = None


class ImportTests(unittest.TestCase):
def test_getmagicnumber(self):
# Test PyImport_GetMagicNumber()
magic = _testlimitedcapi.PyImport_GetMagicNumber()
self.assertEqual(magic,
int.from_bytes(importlib.util.MAGIC_NUMBER, 'little'))

def test_getmagictag(self):
# Test PyImport_GetMagicTag()
tag = _testlimitedcapi.PyImport_GetMagicTag()
self.assertEqual(tag, sys.implementation.cache_tag)

def test_getmoduledict(self):
# Test PyImport_GetModuleDict()
modules = _testlimitedcapi.PyImport_GetModuleDict()
self.assertIs(modules, sys.modules)

def check_import_loaded_module(self, import_module):
for name in ('os', 'sys', 'test', 'unittest'):
with self.subTest(name=name):
self.assertIn(name, sys.modules)
old_module = sys.modules[name]
module = import_module(name)
self.assertIsInstance(module, types.ModuleType)
self.assertIs(module, old_module)

def check_import_fresh_module(self, import_module):
old_modules = dict(sys.modules)
try:
for name in ('colorsys', 'math'):
with self.subTest(name=name):
sys.modules.pop(name, None)
module = import_module(name)
self.assertIsInstance(module, types.ModuleType)
self.assertIs(module, sys.modules[name])
self.assertEqual(module.__name__, name)
finally:
sys.modules.clear()
sys.modules.update(old_modules)

def test_getmodule(self):
# Test PyImport_GetModule()
getmodule = _testlimitedcapi.PyImport_GetModule
self.check_import_loaded_module(getmodule)

nonexistent = 'nonexistent'
self.assertNotIn(nonexistent, sys.modules)
self.assertIs(getmodule(nonexistent), KeyError)
self.assertIs(getmodule(''), KeyError)
self.assertIs(getmodule(object()), KeyError)

self.assertRaises(TypeError, getmodule, []) # unhashable
# CRASHES getmodule(NULL)

def check_addmodule(self, add_module, accept_nonstr=False):
# create a new module
names = ['nonexistent']
if accept_nonstr:
names.append(b'\xff') # non-UTF-8
# PyImport_AddModuleObject() accepts non-string names
names.append(tuple(['hashable non-string']))
for name in names:
with self.subTest(name=name):
self.assertNotIn(name, sys.modules)
try:
module = add_module(name)
self.assertIsInstance(module, types.ModuleType)
self.assertEqual(module.__name__, name)
self.assertIs(module, sys.modules[name])
finally:
sys.modules.pop(name, None)

# get an existing module
self.check_import_loaded_module(add_module)

def test_addmoduleobject(self):
# Test PyImport_AddModuleObject()
addmoduleobject = _testlimitedcapi.PyImport_AddModuleObject
self.check_addmodule(addmoduleobject, accept_nonstr=True)

self.assertRaises(TypeError, addmoduleobject, []) # unhashable
# CRASHES addmoduleobject(NULL)

def test_addmodule(self):
# Test PyImport_AddModule()
addmodule = _testlimitedcapi.PyImport_AddModule
self.check_addmodule(addmodule)

self.assertRaises(UnicodeDecodeError, addmodule, b'\xff')
# CRASHES addmodule(NULL)

def test_addmoduleref(self):
# Test PyImport_AddModuleRef()
addmoduleref = _testlimitedcapi.PyImport_AddModuleRef
self.check_addmodule(addmoduleref)

self.assertRaises(UnicodeDecodeError, addmoduleref, b'\xff')
# CRASHES addmoduleref(NULL)

def check_import_func(self, import_module):
self.check_import_loaded_module(import_module)
self.check_import_fresh_module(import_module)
self.assertRaises(ModuleNotFoundError, import_module, 'nonexistent')
self.assertRaises(ValueError, import_module, '')

def test_import(self):
# Test PyImport_Import()
import_ = _testlimitedcapi.PyImport_Import
self.check_import_func(import_)

self.assertRaises(TypeError, import_, b'os')
self.assertRaises(SystemError, import_, NULL)

def test_importmodule(self):
# Test PyImport_ImportModule()
importmodule = _testlimitedcapi.PyImport_ImportModule
self.check_import_func(importmodule)

self.assertRaises(UnicodeDecodeError, importmodule, b'\xff')
# CRASHES importmodule(NULL)

def test_importmodulenoblock(self):
# Test deprecated PyImport_ImportModuleNoBlock()
importmodulenoblock = _testlimitedcapi.PyImport_ImportModuleNoBlock
with check_warnings(('', DeprecationWarning)):
self.check_import_func(importmodulenoblock)
self.assertRaises(UnicodeDecodeError, importmodulenoblock, b'\xff')

# CRASHES importmodulenoblock(NULL)

def check_frozen_import(self, import_frozen_module):
# Importing a frozen module executes its code, so start by unloading
# the module to execute the code in a new (temporary) module.
old_zipimport = sys.modules.pop('zipimport')
try:
self.assertEqual(import_frozen_module('zipimport'), 1)

# import zipimport again
self.assertEqual(import_frozen_module('zipimport'), 1)
finally:
sys.modules['zipimport'] = old_zipimport

# not a frozen module
self.assertEqual(import_frozen_module('sys'), 0)
self.assertEqual(import_frozen_module('nonexistent'), 0)
self.assertEqual(import_frozen_module(''), 0)

def test_importfrozenmodule(self):
# Test PyImport_ImportFrozenModule()
importfrozenmodule = _testlimitedcapi.PyImport_ImportFrozenModule
self.check_frozen_import(importfrozenmodule)

self.assertRaises(UnicodeDecodeError, importfrozenmodule, b'\xff')
# CRASHES importfrozenmodule(NULL)

def test_importfrozenmoduleobject(self):
# Test PyImport_ImportFrozenModuleObject()
importfrozenmoduleobject = _testlimitedcapi.PyImport_ImportFrozenModuleObject
self.check_frozen_import(importfrozenmoduleobject)
self.assertEqual(importfrozenmoduleobject(b'zipimport'), 0)
self.assertEqual(importfrozenmoduleobject(NULL), 0)

def test_importmoduleex(self):
# Test PyImport_ImportModuleEx()
importmoduleex = _testlimitedcapi.PyImport_ImportModuleEx
self.check_import_func(lambda name: importmoduleex(name, NULL, NULL, NULL))

self.assertRaises(ModuleNotFoundError, importmoduleex, 'nonexistent', NULL, NULL, NULL)
self.assertRaises(ValueError, importmoduleex, '', NULL, NULL, NULL)
self.assertRaises(UnicodeDecodeError, importmoduleex, b'\xff', NULL, NULL, NULL)
# CRASHES importmoduleex(NULL, NULL, NULL, NULL)

def check_importmodulelevel(self, importmodulelevel):
self.check_import_func(lambda name: importmodulelevel(name, NULL, NULL, NULL, 0))

self.assertRaises(ModuleNotFoundError, importmodulelevel, 'nonexistent', NULL, NULL, NULL, 0)
self.assertRaises(ValueError, importmodulelevel, '', NULL, NULL, NULL, 0)

if __package__:
self.assertIs(importmodulelevel('test_import', globals(), NULL, NULL, 1),
sys.modules['test.test_capi.test_import'])
self.assertIs(importmodulelevel('test_capi', globals(), NULL, NULL, 2),
sys.modules['test.test_capi'])
self.assertRaises(ValueError, importmodulelevel, 'os', NULL, NULL, NULL, -1)
with self.assertWarns(ImportWarning):
self.assertRaises(KeyError, importmodulelevel, 'test_import', {}, NULL, NULL, 1)
self.assertRaises(TypeError, importmodulelevel, 'test_import', [], NULL, NULL, 1)

def test_importmodulelevel(self):
# Test PyImport_ImportModuleLevel()
importmodulelevel = _testlimitedcapi.PyImport_ImportModuleLevel
self.check_importmodulelevel(importmodulelevel)

self.assertRaises(UnicodeDecodeError, importmodulelevel, b'\xff', NULL, NULL, NULL, 0)
# CRASHES importmodulelevel(NULL, NULL, NULL, NULL, 0)

def test_importmodulelevelobject(self):
# Test PyImport_ImportModuleLevelObject()
importmodulelevel = _testlimitedcapi.PyImport_ImportModuleLevelObject
self.check_importmodulelevel(importmodulelevel)

self.assertRaises(TypeError, importmodulelevel, b'os', NULL, NULL, NULL, 0)
self.assertRaises(ValueError, importmodulelevel, NULL, NULL, NULL, NULL, 0)

def check_executecodemodule(self, execute_code, *args):
name = 'test_import_executecode'
try:
# Create a temporary module where the code will be executed
self.assertNotIn(name, sys.modules)
module = _testlimitedcapi.PyImport_AddModuleRef(name)
self.assertNotHasAttr(module, 'attr')

# Execute the code
code = compile('attr = 1', '<test>', 'exec')
module2 = execute_code(name, code, *args)
self.assertIs(module2, module)

# Check the function side effects
self.assertEqual(module.attr, 1)
finally:
sys.modules.pop(name, None)
return module.__spec__.origin

def test_executecodemodule(self):
# Test PyImport_ExecCodeModule()
execcodemodule = _testlimitedcapi.PyImport_ExecCodeModule
self.check_executecodemodule(execcodemodule)

code = compile('attr = 1', '<test>', 'exec')
self.assertRaises(UnicodeDecodeError, execcodemodule, b'\xff', code)
# CRASHES execcodemodule(NULL, code)
# CRASHES execcodemodule(name, NULL)

def test_executecodemoduleex(self):
# Test PyImport_ExecCodeModuleEx()
execcodemoduleex = _testlimitedcapi.PyImport_ExecCodeModuleEx

# Test NULL path (it should not crash)
self.check_executecodemodule(execcodemoduleex, NULL)

# Test non-NULL path
pathname = b'pathname'
origin = self.check_executecodemodule(execcodemoduleex, pathname)
self.assertEqual(origin, os.path.abspath(os.fsdecode(pathname)))

pathname = os_helper.TESTFN_UNDECODABLE
if pathname:
origin = self.check_executecodemodule(execcodemoduleex, pathname)
self.assertEqual(origin, os.path.abspath(os.fsdecode(pathname)))

code = compile('attr = 1', '<test>', 'exec')
self.assertRaises(UnicodeDecodeError, execcodemoduleex, b'\xff', code, NULL)
# CRASHES execcodemoduleex(NULL, code, NULL)
# CRASHES execcodemoduleex(name, NULL, NULL)

def check_executecode_pathnames(self, execute_code_func, object=False):
# Test non-NULL pathname and NULL cpathname

# Test NULL paths (it should not crash)
self.check_executecodemodule(execute_code_func, NULL, NULL)

pathname = 'pathname'
origin = self.check_executecodemodule(execute_code_func, pathname, NULL)
self.assertEqual(origin, os.path.abspath(os.fsdecode(pathname)))
origin = self.check_executecodemodule(execute_code_func, NULL, pathname)
if not object:
self.assertEqual(origin, os.path.abspath(os.fsdecode(pathname)))

pathname = os_helper.TESTFN_UNDECODABLE
if pathname:
if object:
pathname = os.fsdecode(pathname)
origin = self.check_executecodemodule(execute_code_func, pathname, NULL)
self.assertEqual(origin, os.path.abspath(os.fsdecode(pathname)))
self.check_executecodemodule(execute_code_func, NULL, pathname)

# Test NULL pathname and non-NULL cpathname
pyc_filename = importlib.util.cache_from_source(__file__)
py_filename = importlib.util.source_from_cache(pyc_filename)
origin = self.check_executecodemodule(execute_code_func, NULL, pyc_filename)
if not object:
self.assertEqual(origin, py_filename)

def test_executecodemodulewithpathnames(self):
# Test PyImport_ExecCodeModuleWithPathnames()
execute_code_func = _testlimitedcapi.PyImport_ExecCodeModuleWithPathnames
self.check_executecode_pathnames(execute_code_func)

code = compile('attr = 1', '<test>', 'exec')
self.assertRaises(UnicodeDecodeError, execute_code_func, b'\xff', code, NULL, NULL)
# CRASHES execute_code_func(NULL, code, NULL, NULL)
# CRASHES execute_code_func(name, NULL, NULL, NULL)

def test_executecodemoduleobject(self):
# Test PyImport_ExecCodeModuleObject()
execute_code_func = _testlimitedcapi.PyImport_ExecCodeModuleObject
self.check_executecode_pathnames(execute_code_func, object=True)

code = compile('attr = 1', '<test>', 'exec')
self.assertRaises(TypeError, execute_code_func, [], code, NULL, NULL)
nonstring = tuple(['hashable non-string'])
self.assertRaises(AttributeError, execute_code_func, nonstring, code, NULL, NULL)
sys.modules.pop(nonstring, None)
# CRASHES execute_code_func(NULL, code, NULL, NULL)
# CRASHES execute_code_func(name, NULL, NULL, NULL)

# TODO: test PyImport_GetImporter()
# TODO: test PyImport_ReloadModule()
# TODO: test PyImport_ExtendInittab()
# PyImport_AppendInittab() is tested by test_embed


if __name__ == "__main__":
unittest.main()
24 changes: 0 additions & 24 deletions Lib/test/test_import/__init__.py
Original file line number Diff line number Diff line change
@@ -3311,30 +3311,6 @@ def test_basic_multiple_interpreters_reset_each(self):
# * module's global state was initialized, not reset


@cpython_only
class CAPITests(unittest.TestCase):
def test_pyimport_addmodule(self):
# gh-105922: Test PyImport_AddModuleRef(), PyImport_AddModule()
# and PyImport_AddModuleObject()
_testcapi = import_module("_testcapi")
for name in (
'sys', # frozen module
'test', # package
__name__, # package.module
):
_testcapi.check_pyimport_addmodule(name)

def test_pyimport_addmodule_create(self):
# gh-105922: Test PyImport_AddModuleRef(), create a new module
_testcapi = import_module("_testcapi")
name = 'dontexist'
self.assertNotIn(name, sys.modules)
self.addCleanup(unload, name)

mod = _testcapi.check_pyimport_addmodule(name)
self.assertIs(mod, sys.modules[name])


@cpython_only
class TestMagicNumber(unittest.TestCase):
def test_magic_number_endianness(self):
2 changes: 1 addition & 1 deletion Modules/Setup.stdlib.in
Original file line number Diff line number Diff line change
@@ -163,7 +163,7 @@
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/monitoring.c _testcapi/config.c
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c

47 changes: 0 additions & 47 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
@@ -3059,52 +3059,6 @@ function_set_closure(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}

static PyObject *
check_pyimport_addmodule(PyObject *self, PyObject *args)
{
const char *name;
if (!PyArg_ParseTuple(args, "s", &name)) {
return NULL;
}

// test PyImport_AddModuleRef()
PyObject *module = PyImport_AddModuleRef(name);
if (module == NULL) {
return NULL;
}
assert(PyModule_Check(module));
// module is a strong reference

// test PyImport_AddModule()
PyObject *module2 = PyImport_AddModule(name);
if (module2 == NULL) {
goto error;
}
assert(PyModule_Check(module2));
assert(module2 == module);
// module2 is a borrowed ref

// test PyImport_AddModuleObject()
PyObject *name_obj = PyUnicode_FromString(name);
if (name_obj == NULL) {
goto error;
}
PyObject *module3 = PyImport_AddModuleObject(name_obj);
Py_DECREF(name_obj);
if (module3 == NULL) {
goto error;
}
assert(PyModule_Check(module3));
assert(module3 == module);
// module3 is a borrowed ref

return module;

error:
Py_DECREF(module);
return NULL;
}


static PyObject *
test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
@@ -3570,7 +3524,6 @@ static PyMethodDef TestMethods[] = {
{"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL},
{"function_get_closure", function_get_closure, METH_O, NULL},
{"function_set_closure", function_set_closure, METH_VARARGS, NULL},
{"check_pyimport_addmodule", check_pyimport_addmodule, METH_VARARGS},
{"test_weakref_capi", test_weakref_capi, METH_NOARGS},
{"function_set_warning", function_set_warning, METH_NOARGS},
{"test_critical_sections", test_critical_sections, METH_NOARGS},
3 changes: 3 additions & 0 deletions Modules/_testlimitedcapi.c
Original file line number Diff line number Diff line change
@@ -56,6 +56,9 @@ PyInit__testlimitedcapi(void)
if (_PyTestLimitedCAPI_Init_HeaptypeRelative(mod) < 0) {
return NULL;
}
if (_PyTestLimitedCAPI_Init_Import(mod) < 0) {
return NULL;
}
if (_PyTestLimitedCAPI_Init_List(mod) < 0) {
return NULL;
}
306 changes: 306 additions & 0 deletions Modules/_testlimitedcapi/import.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
// Need limited C API version 3.13 for PyImport_AddModuleRef()
#include "pyconfig.h" // Py_GIL_DISABLED
#if !defined(Py_GIL_DISABLED) && !defined(Py_LIMITED_API)
# define Py_LIMITED_API 0x030d0000
#endif

#include "parts.h"
#include "util.h"


/* Test PyImport_GetMagicNumber() */
static PyObject *
pyimport_getmagicnumber(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
long magic = PyImport_GetMagicNumber();
return PyLong_FromLong(magic);
}


/* Test PyImport_GetMagicTag() */
static PyObject *
pyimport_getmagictag(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
const char *tag = PyImport_GetMagicTag();
return PyUnicode_FromString(tag);
}


/* Test PyImport_GetModuleDict() */
static PyObject *
pyimport_getmoduledict(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
return Py_XNewRef(PyImport_GetModuleDict());
}


/* Test PyImport_GetModule() */
static PyObject *
pyimport_getmodule(PyObject *Py_UNUSED(module), PyObject *name)
{
assert(!PyErr_Occurred());
NULLABLE(name);
PyObject *module = PyImport_GetModule(name);
if (module == NULL && !PyErr_Occurred()) {
return Py_NewRef(PyExc_KeyError);
}
return module;
}


/* Test PyImport_AddModuleObject() */
static PyObject *
pyimport_addmoduleobject(PyObject *Py_UNUSED(module), PyObject *name)
{
NULLABLE(name);
return Py_XNewRef(PyImport_AddModuleObject(name));
}


/* Test PyImport_AddModule() */
static PyObject *
pyimport_addmodule(PyObject *Py_UNUSED(module), PyObject *args)
{
const char *name;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "z#", &name, &size)) {
return NULL;
}

return Py_XNewRef(PyImport_AddModule(name));
}


/* Test PyImport_AddModuleRef() */
static PyObject *
pyimport_addmoduleref(PyObject *Py_UNUSED(module), PyObject *args)
{
const char *name;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "z#", &name, &size)) {
return NULL;
}

return PyImport_AddModuleRef(name);
}


/* Test PyImport_Import() */
static PyObject *
pyimport_import(PyObject *Py_UNUSED(module), PyObject *name)
{
NULLABLE(name);
return PyImport_Import(name);
}


/* Test PyImport_ImportModule() */
static PyObject *
pyimport_importmodule(PyObject *Py_UNUSED(module), PyObject *args)
{
const char *name;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "z#", &name, &size)) {
return NULL;
}

return PyImport_ImportModule(name);
}


/* Test PyImport_ImportModuleNoBlock() */
static PyObject *
pyimport_importmodulenoblock(PyObject *Py_UNUSED(module), PyObject *args)
{
const char *name;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "z#", &name, &size)) {
return NULL;
}

_Py_COMP_DIAG_PUSH
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
return PyImport_ImportModuleNoBlock(name);
_Py_COMP_DIAG_POP
}


/* Test PyImport_ImportModuleEx() */
static PyObject *
pyimport_importmoduleex(PyObject *Py_UNUSED(module), PyObject *args)
{
const char *name;
Py_ssize_t size;
PyObject *globals, *locals, *fromlist;
if (!PyArg_ParseTuple(args, "z#OOO",
&name, &size, &globals, &locals, &fromlist)) {
return NULL;
}
NULLABLE(globals);
NULLABLE(locals);
NULLABLE(fromlist);

return PyImport_ImportModuleEx(name, globals, locals, fromlist);
}


/* Test PyImport_ImportModuleLevel() */
static PyObject *
pyimport_importmodulelevel(PyObject *Py_UNUSED(module), PyObject *args)
{
const char *name;
Py_ssize_t size;
PyObject *globals, *locals, *fromlist;
int level;
if (!PyArg_ParseTuple(args, "z#OOOi",
&name, &size, &globals, &locals, &fromlist, &level)) {
return NULL;
}
NULLABLE(globals);
NULLABLE(locals);
NULLABLE(fromlist);

return PyImport_ImportModuleLevel(name, globals, locals, fromlist, level);
}


/* Test PyImport_ImportModuleLevelObject() */
static PyObject *
pyimport_importmodulelevelobject(PyObject *Py_UNUSED(module), PyObject *args)
{
PyObject *name, *globals, *locals, *fromlist;
int level;
if (!PyArg_ParseTuple(args, "OOOOi",
&name, &globals, &locals, &fromlist, &level)) {
return NULL;
}
NULLABLE(name);
NULLABLE(globals);
NULLABLE(locals);
NULLABLE(fromlist);

return PyImport_ImportModuleLevelObject(name, globals, locals, fromlist, level);
}


/* Test PyImport_ImportFrozenModule() */
static PyObject *
pyimport_importfrozenmodule(PyObject *Py_UNUSED(module), PyObject *args)
{
const char *name;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "z#", &name, &size)) {
return NULL;
}

RETURN_INT(PyImport_ImportFrozenModule(name));
}


/* Test PyImport_ImportFrozenModuleObject() */
static PyObject *
pyimport_importfrozenmoduleobject(PyObject *Py_UNUSED(module), PyObject *name)
{
NULLABLE(name);
RETURN_INT(PyImport_ImportFrozenModuleObject(name));
}


/* Test PyImport_ExecCodeModule() */
static PyObject *
pyimport_executecodemodule(PyObject *Py_UNUSED(module), PyObject *args)
{
const char *name;
Py_ssize_t size;
PyObject *code;
if (!PyArg_ParseTuple(args, "z#O", &name, &size, &code)) {
return NULL;
}
NULLABLE(code);

return PyImport_ExecCodeModule(name, code);
}


/* Test PyImport_ExecCodeModuleEx() */
static PyObject *
pyimport_executecodemoduleex(PyObject *Py_UNUSED(module), PyObject *args)
{
const char *name;
Py_ssize_t size;
PyObject *code;
const char *pathname;
if (!PyArg_ParseTuple(args, "z#Oz#", &name, &size, &code, &pathname, &size)) {
return NULL;
}
NULLABLE(code);

return PyImport_ExecCodeModuleEx(name, code, pathname);
}


/* Test PyImport_ExecCodeModuleWithPathnames() */
static PyObject *
pyimport_executecodemodulewithpathnames(PyObject *Py_UNUSED(module), PyObject *args)
{
const char *name;
Py_ssize_t size;
PyObject *code;
const char *pathname;
const char *cpathname;
if (!PyArg_ParseTuple(args, "z#Oz#z#", &name, &size, &code, &pathname, &size, &cpathname, &size)) {
return NULL;
}
NULLABLE(code);

return PyImport_ExecCodeModuleWithPathnames(name, code,
pathname, cpathname);
}


/* Test PyImport_ExecCodeModuleObject() */
static PyObject *
pyimport_executecodemoduleobject(PyObject *Py_UNUSED(module), PyObject *args)
{
PyObject *name, *code, *pathname, *cpathname;
if (!PyArg_ParseTuple(args, "OOOO", &name, &code, &pathname, &cpathname)) {
return NULL;
}
NULLABLE(name);
NULLABLE(code);
NULLABLE(pathname);
NULLABLE(cpathname);

return PyImport_ExecCodeModuleObject(name, code, pathname, cpathname);
}


static PyMethodDef test_methods[] = {
{"PyImport_GetMagicNumber", pyimport_getmagicnumber, METH_NOARGS},
{"PyImport_GetMagicTag", pyimport_getmagictag, METH_NOARGS},
{"PyImport_GetModuleDict", pyimport_getmoduledict, METH_NOARGS},
{"PyImport_GetModule", pyimport_getmodule, METH_O},
{"PyImport_AddModuleObject", pyimport_addmoduleobject, METH_O},
{"PyImport_AddModule", pyimport_addmodule, METH_VARARGS},
{"PyImport_AddModuleRef", pyimport_addmoduleref, METH_VARARGS},
{"PyImport_Import", pyimport_import, METH_O},
{"PyImport_ImportModule", pyimport_importmodule, METH_VARARGS},
{"PyImport_ImportModuleNoBlock", pyimport_importmodulenoblock, METH_VARARGS},
{"PyImport_ImportModuleEx", pyimport_importmoduleex, METH_VARARGS},
{"PyImport_ImportModuleLevel", pyimport_importmodulelevel, METH_VARARGS},
{"PyImport_ImportModuleLevelObject", pyimport_importmodulelevelobject, METH_VARARGS},
{"PyImport_ImportFrozenModule", pyimport_importfrozenmodule, METH_VARARGS},
{"PyImport_ImportFrozenModuleObject", pyimport_importfrozenmoduleobject, METH_O},
{"PyImport_ExecCodeModule", pyimport_executecodemodule, METH_VARARGS},
{"PyImport_ExecCodeModuleEx", pyimport_executecodemoduleex, METH_VARARGS},
{"PyImport_ExecCodeModuleWithPathnames", pyimport_executecodemodulewithpathnames, METH_VARARGS},
{"PyImport_ExecCodeModuleObject", pyimport_executecodemoduleobject, METH_VARARGS},
{NULL},
};


int
_PyTestLimitedCAPI_Init_Import(PyObject *module)
{
return PyModule_AddFunctions(module, test_methods);
}
1 change: 1 addition & 0 deletions Modules/_testlimitedcapi/parts.h
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ int _PyTestLimitedCAPI_Init_Dict(PyObject *module);
int _PyTestLimitedCAPI_Init_Eval(PyObject *module);
int _PyTestLimitedCAPI_Init_Float(PyObject *module);
int _PyTestLimitedCAPI_Init_HeaptypeRelative(PyObject *module);
int _PyTestLimitedCAPI_Init_Import(PyObject *module);
int _PyTestLimitedCAPI_Init_Object(PyObject *module);
int _PyTestLimitedCAPI_Init_List(PyObject *module);
int _PyTestLimitedCAPI_Init_Long(PyObject *module);
1 change: 1 addition & 0 deletions PCbuild/_testlimitedcapi.vcxproj
Original file line number Diff line number Diff line change
@@ -103,6 +103,7 @@
<ClCompile Include="..\Modules\_testlimitedcapi\eval.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\float.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\heaptype_relative.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\import.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\list.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\long.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\object.c" />
1 change: 1 addition & 0 deletions PCbuild/_testlimitedcapi.vcxproj.filters
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@
<ClCompile Include="..\Modules\_testlimitedcapi\eval.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\float.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\heaptype_relative.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\import.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\list.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\long.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\object.c" />