Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
4ad95be
Define PyMODEXPORT_FUNC
encukou May 21, 2025
c53650d
Add new state to module object
encukou May 21, 2025
9564e20
Make sure the module def matches the state
encukou May 21, 2025
05a87c3
Add simple test case
encukou May 21, 2025
57c4f1e
Add new slot definitions
encukou May 21, 2025
956c59a
Modules are bigger sue me
encukou May 23, 2025
14a66d2
Add a test for PyModule_FromSlotsAndSpec
encukou May 21, 2025
72a27f5
Add PyModule_FromSlotsAndSpec (empty for now)
encukou Oct 24, 2025
b54293b
Add module test
encukou May 21, 2025
fcc68f8
Fill in enough of a PyModuleDef to pass to common machinery
encukou May 21, 2025
3ab607e
Pass in a spec
encukou May 21, 2025
35d7d51
Rename field which can now be NULL
encukou May 22, 2025
6fbbc18
Common implementation for PyModule_From{Def,Slots}AndSpec
encukou May 22, 2025
7207e07
Add test for Py_mod_name slot
encukou May 22, 2025
8d4d264
Handle Py_mod_name
encukou May 22, 2025
bd61e5b
Test repeated slot
encukou May 22, 2025
d638abf
Test Py_mod_name with a def
encukou May 22, 2025
b24e6a6
Py_mod_doc
encukou May 22, 2025
756cbff
Disallow NULL slot value
encukou May 22, 2025
320de14
Test repeats and NULL for all new slots
encukou May 22, 2025
4d88cf3
Add PyModule_GetSize
encukou May 22, 2025
a1d3c15
Test size
encukou May 22, 2025
7fcee67
Handle size
encukou May 22, 2025
9fd1e7e
Test new slots with PyModuleDef
encukou May 22, 2025
fd95984
Py_mod_methods
encukou May 22, 2025
748e18f
GC hooks
encukou May 22, 2025
1101f55
Py_mod_token
encukou May 22, 2025
488eae7
Py_mod_exec
encukou May 22, 2025
f9d0dde
Clean up slot-handling a bit
encukou May 22, 2025
020dcc6
Py_mod_create
encukou May 22, 2025
cf7409e
Use PyModule_Exec in exec_builtin_or_dynamic
encukou May 22, 2025
d1673de
PyModExport
encukou May 22, 2025
c3dd935
_PyModule_IsExtension: Check md_exec
encukou May 22, 2025
1de2c50
Small style/doc fixups
encukou May 22, 2025
e486cdc
Handle NULL slots & bad spec; some light refactoring
encukou May 23, 2025
31a5cc5
Allow non-Module instances
encukou May 23, 2025
3dcadbb
Tests for the export hook
encukou May 23, 2025
bd1c352
`state_` in slot names
encukou May 23, 2025
56525fa
Test PyModule_Exec with PyModuleDef-defined module
encukou Jun 7, 2025
4b93132
Test PyModule_GetToken, token setting, and default tokens
encukou Jun 17, 2025
bb2dd7d
Add PyType_GetModuleByToken
encukou Jun 17, 2025
36cc311
Fix refcounting
encukou Jun 17, 2025
37905ae
Rename and test PyModule_GetStateSize
encukou Jun 19, 2025
1df228a
Rename new internal module members
encukou Jun 19, 2025
71e043f
Share storage between def and token
encukou Jun 19, 2025
dd3c25f
Lose the spec argument
encukou Oct 9, 2025
391281d
Put `const` in signatures
encukou Oct 9, 2025
058e0db
test_cext: Remove the 'create_moduledef.c' workaround
encukou Oct 21, 2025
e6ff4b9
Make helpers static
encukou Oct 24, 2025
b651cef
Add comment to assertion
encukou Oct 24, 2025
4d4c6b7
Mark test PyModuleDefs as GIL-friendly
encukou Oct 24, 2025
54c496e
Add vcxproj entries for test files
encukou Oct 24, 2025
fdc49ed
Add to Limited API
encukou Oct 26, 2025
dab2207
gh-140633: AppleFrameworkLoader: Ignore AttributeError when setting _…
encukou Oct 26, 2025
4f7bccb
test_cext: Define PyInit_* function which asserts that it wasn't called
encukou Oct 26, 2025
628942c
Add a blurb
encukou Oct 26, 2025
08ee616
Make tokens `const` to pass check for C globals
encukou Oct 27, 2025
ffe3322
One more cast
encukou Oct 27, 2025
0855bdd
test_import: Move modexport tests to their own class
encukou Oct 27, 2025
0af8cae
Merge in the main branch
encukou Oct 27, 2025
895a046
Remove redundant comment
encukou Oct 27, 2025
25fe913
Rename _PyImport_GetModInitFunc2 to _PyImport_GetModuleExportHooks
encukou Oct 28, 2025
1939ad2
Merge in the main branch
encukou Oct 28, 2025
821a2b2
Merge in the main branch
encukou Oct 28, 2025
ab04b28
Update outdated comment
encukou Oct 28, 2025
d9013b1
Add a _PyModule_CAST macro
encukou Oct 28, 2025
788835e
Better argument naming in headers
encukou Oct 28, 2025
fde9850
Move comment to top
encukou Oct 28, 2025
0465b0d
'noop', not 'trivial
encukou Oct 28, 2025
268840a
PyLong_AsInt
encukou Oct 28, 2025
3e13677
Add spaces inside curly braces
encukou Oct 28, 2025
fdff39b
PyErr_FormatUnraisable, not PyErr_WriteUnraisable
encukou Oct 28, 2025
7c29575
Use NDEBUG
encukou Oct 28, 2025
b163b28
Wrap in do-while
encukou Oct 28, 2025
6ddcb01
PyErr_SetString instead of PyErr_Format
encukou Oct 28, 2025
2013284
Repr in error messages
encukou Oct 28, 2025
52af397
PEP 7 whitespace
encukou Oct 28, 2025
01d52ba
Make sure Victor's edits are credited
encukou Oct 28, 2025
ba6e602
Correct logic
encukou Oct 29, 2025
d26e9b7
Merge in the main branch
encukou Oct 29, 2025
26b57f2
Get the spaces just right
encukou Nov 3, 2025
66e8309
Merge branch 'main' into modexport-rebased
encukou Nov 3, 2025
928f23b
_PyModule_GetDefOrNull never raises
encukou Nov 3, 2025
4f3712f
Merge in the main branch
encukou Nov 4, 2025
55ae793
Remove _PyModule_GetGCHooks; get the hooks directly via internal API
encukou Nov 4, 2025
1e6b18c
Style fixes
vstinner Nov 4, 2025
4d58846
Remove unused variables
encukou Nov 4, 2025
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
Prev Previous commit
Next Next commit
Handle NULL slots & bad spec; some light refactoring
  • Loading branch information
encukou committed Oct 24, 2025
commit e486cdcd5765769200bbde2a6d463c455f4195e0
13 changes: 13 additions & 0 deletions Lib/test/test_capi/test_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,26 @@ class FakeSpec:
'Py_mod_traverse', 'Py_mod_clear', 'Py_mod_free', 'Py_mod_token',
)

# The C functions used by this module are in:
# Modules/_testcapi/module.c

class TestModFromSlotsAndSpec(unittest.TestCase):
def test_empty(self):
mod = _testcapi.module_from_slots_empty(FakeSpec())
self.assertIsInstance(mod, types.ModuleType)
self.assertEqual(mod.__name__, 'testmod')

def test_null_slots(self):
with self.assertRaises(SystemError):
_testcapi.module_from_slots_null(FakeSpec())

def test_none_spec(self):
# The spec currently must contain a name
with self.assertRaises(AttributeError):
_testcapi.module_from_slots_empty(None)
with self.assertRaises(AttributeError):
_testcapi.module_from_slots_name(None)

def test_name(self):
# Py_mod_name (and PyModuleDef.m_name) are currently ignored when
# spec is given.
Expand Down
11 changes: 11 additions & 0 deletions Modules/_testcapi/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

// Test PyModule_* API

/* unittest Cases that use these functions are in:
* Lib/test/test_capi/test_module.py
*/

static PyObject *
module_from_slots_empty(PyObject *self, PyObject *spec)
{
Expand All @@ -12,6 +16,12 @@ module_from_slots_empty(PyObject *self, PyObject *spec)
return PyModule_FromSlotsAndSpec(slots, spec);
}

static PyObject *
module_from_slots_null(PyObject *self, PyObject *spec)
{
return PyModule_FromSlotsAndSpec(NULL, spec);
}

static PyObject *
module_from_slots_name(PyObject *self, PyObject *spec)
{
Expand Down Expand Up @@ -242,6 +252,7 @@ module_from_def_slot(PyObject *self, PyObject *spec)

static PyMethodDef test_methods[] = {
{"module_from_slots_empty", module_from_slots_empty, METH_O},
{"module_from_slots_null", module_from_slots_null, METH_O},
{"module_from_slots_name", module_from_slots_name, METH_O},
{"module_from_slots_doc", module_from_slots_doc, METH_O},
{"module_from_slots_size", module_from_slots_size, METH_O},
Expand Down
23 changes: 6 additions & 17 deletions Objects/moduleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,30 +629,19 @@ PyModule_FromDefAndSpec2(PyModuleDef* def, PyObject *spec, int module_api_versio
PyObject *
PyModule_FromSlotsAndSpec(PyModuleDef_Slot *slots, PyObject *spec)
{
PyObject *result = NULL;
if (!slots) {
PyErr_BadArgument();
}
PyObject *nameobj = PyObject_GetAttrString(spec, "name");
if (nameobj == NULL) {
goto finally;
}
const char *name = PyUnicode_AsUTF8(nameobj);
if (name == NULL) {
goto finally;
PyErr_Format(
PyExc_SystemError,
"PyModule_FromSlotsAndSpec called with NULL slots");
return NULL;
}

// Fill in enough of a PyModuleDef to pass to common machinery
PyModuleDef def_like = {.m_slots = slots};

result = module_from_def_and_spec(&def_like, spec, PYTHON_API_VERSION,
NULL);
finally:
Py_XDECREF(nameobj);
return result;
return module_from_def_and_spec(&def_like, spec, PYTHON_API_VERSION,
NULL);
}


#ifdef Py_GIL_DISABLED
int
PyUnstable_Module_SetGIL(PyObject *module, void *gil)
Expand Down