Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions Doc/data/stable_abi.dat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 10 additions & 7 deletions Include/exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
inside the Python core, they are private to the core.
If in an extension module, it may be declared with
external linkage depending on the platform.
PyMODEXPORT_FUNC: Like PyMODINIT_FUNC, but for a slots array

As a number of platforms support/require "__declspec(dllimport/dllexport)",
we support a HAVE_DECLSPEC_DLL macro to save duplication.
Expand Down Expand Up @@ -62,9 +63,9 @@
/* module init functions inside the core need no external linkage */
/* except for Cygwin to handle embedding */
# if defined(__CYGWIN__)
# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*
# define _PyINIT_FUNC_DECLSPEC Py_EXPORTED_SYMBOL
# else /* __CYGWIN__ */
# define PyMODINIT_FUNC PyObject*
# define _PyINIT_FUNC_DECLSPEC
# endif /* __CYGWIN__ */
# else /* Py_BUILD_CORE */
/* Building an extension module, or an embedded situation */
Expand All @@ -78,9 +79,9 @@
# define PyAPI_DATA(RTYPE) extern Py_IMPORTED_SYMBOL RTYPE
/* module init functions outside the core must be exported */
# if defined(__cplusplus)
# define PyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL PyObject*
# define _PyINIT_FUNC_DECLSPEC extern "C" Py_EXPORTED_SYMBOL
# else /* __cplusplus */
# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*
# define _PyINIT_FUNC_DECLSPEC Py_EXPORTED_SYMBOL
# endif /* __cplusplus */
# endif /* Py_BUILD_CORE */
# endif /* HAVE_DECLSPEC_DLL */
Expand All @@ -93,13 +94,15 @@
#ifndef PyAPI_DATA
# define PyAPI_DATA(RTYPE) extern Py_EXPORTED_SYMBOL RTYPE
#endif
#ifndef PyMODINIT_FUNC
#ifndef _PyINIT_FUNC_DECLSPEC
# if defined(__cplusplus)
# define PyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL PyObject*
# define _PyINIT_FUNC_DECLSPEC extern "C" Py_EXPORTED_SYMBOL
# else /* __cplusplus */
# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*
# define _PyINIT_FUNC_DECLSPEC Py_EXPORTED_SYMBOL
# endif /* __cplusplus */
#endif

#define PyMODINIT_FUNC _PyINIT_FUNC_DECLSPEC PyObject*
#define PyMODEXPORT_FUNC _PyINIT_FUNC_DECLSPEC PyModuleDef_Slot*

#endif /* Py_EXPORTS_H */
16 changes: 12 additions & 4 deletions Include/internal/pycore_importdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ typedef enum ext_module_origin {
_Py_ext_module_origin_DYNAMIC = 3,
} _Py_ext_module_origin;

struct hook_prefixes {
const char *const init_prefix;
const char *const export_prefix;
};

/* Input for loading an extension module. */
struct _Py_ext_module_loader_info {
PyObject *filename;
Expand All @@ -40,7 +45,7 @@ struct _Py_ext_module_loader_info {
* depending on if it's builtin or not. */
PyObject *path;
_Py_ext_module_origin origin;
const char *hook_prefix;
const struct hook_prefixes *hook_prefixes;
const char *newcontext;
};
extern void _Py_ext_module_loader_info_clear(
Expand All @@ -62,7 +67,9 @@ extern int _Py_ext_module_loader_info_init_from_spec(
PyObject *spec);
#endif

/* The result from running an extension module's init function. */
/* The result from running an extension module's init function.
* Not used for modules defined via PyModExport (slots array).
*/
struct _Py_ext_module_loader_result {
PyModuleDef *def;
PyObject *module;
Expand All @@ -89,10 +96,11 @@ extern void _Py_ext_module_loader_result_apply_error(

/* The module init function. */
typedef PyObject *(*PyModInitFunction)(void);
typedef PyModuleDef_Slot *(*PyModExportFunction)(void);
#ifdef HAVE_DYNAMIC_LOADING
extern PyModInitFunction _PyImport_GetModInitFunc(
extern int _PyImport_GetModuleExportHooks(
struct _Py_ext_module_loader_info *info,
FILE *fp);
FILE *fp, PyModInitFunction *modinit, PyModExportFunction *modexport);
#endif
extern int _PyImport_RunModInitFunc(
PyModInitFunction p0,
Expand Down
36 changes: 28 additions & 8 deletions Include/internal/pycore_moduleobject.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#ifndef Py_INTERNAL_MODULEOBJECT_H
#define Py_INTERNAL_MODULEOBJECT_H

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -16,32 +19,49 @@ extern int _PyModule_IsPossiblyShadowing(PyObject *);

extern int _PyModule_IsExtension(PyObject *obj);

typedef int (*_Py_modexecfunc)(PyObject *);

typedef struct {
PyObject_HEAD
PyObject *md_dict;
PyModuleDef *md_def;
void *md_state;
PyObject *md_weaklist;
// for logging purposes after md_dict is cleared
PyObject *md_name;
bool md_token_is_def; /* if true, `md_token` is the PyModuleDef */
#ifdef Py_GIL_DISABLED
void *md_gil;
#endif
Py_ssize_t md_state_size;
traverseproc md_state_traverse;
inquiry md_state_clear;
freefunc md_state_free;
void *md_token;
_Py_modexecfunc md_exec; /* only set if md_token_is_def is true */
} PyModuleObject;

static inline PyModuleDef* _PyModule_GetDef(PyObject *mod) {
assert(PyModule_Check(mod));
return ((PyModuleObject *)mod)->md_def;
#define _PyModule_CAST(op) \
(assert(PyModule_Check(op)), _Py_CAST(PyModuleObject*, (op)))

static inline PyModuleDef *_PyModule_GetDefOrNull(PyObject *arg) {
PyModuleObject *mod = _PyModule_CAST(arg);
if (mod->md_token_is_def) {
return (PyModuleDef *)mod->md_token;
}
return NULL;
}

static inline PyModuleDef *_PyModule_GetToken(PyObject *arg) {
PyModuleObject *mod = _PyModule_CAST(arg);
return mod->md_token;
}

static inline void* _PyModule_GetState(PyObject* mod) {
assert(PyModule_Check(mod));
return ((PyModuleObject *)mod)->md_state;
return _PyModule_CAST(mod)->md_state;
}

static inline PyObject* _PyModule_GetDict(PyObject *mod) {
assert(PyModule_Check(mod));
PyObject *dict = ((PyModuleObject *)mod) -> md_dict;
PyObject *dict = _PyModule_CAST(mod)->md_dict;
// _PyModule_GetDict(mod) must not be used after calling module_clear(mod)
assert(dict != NULL);
return dict; // borrowed reference
Expand Down
17 changes: 16 additions & 1 deletion Include/moduleobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,19 @@ struct PyModuleDef_Slot {
#endif
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15)
# define Py_mod_abi 5
# define Py_mod_name 6
# define Py_mod_doc 7
# define Py_mod_state_size 8
# define Py_mod_methods 9
# define Py_mod_state_traverse 10
# define Py_mod_state_clear 11
# define Py_mod_state_free 12
# define Py_mod_token 13
#endif


#ifndef Py_LIMITED_API
#define _Py_mod_LAST_SLOT 5
#define _Py_mod_LAST_SLOT 13
#endif

#endif /* New in 3.5 */
Expand All @@ -109,6 +117,13 @@ struct PyModuleDef_Slot {
PyAPI_FUNC(int) PyUnstable_Module_SetGIL(PyObject *module, void *gil);
#endif

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15)
PyAPI_FUNC(PyObject *) PyModule_FromSlotsAndSpec(const PyModuleDef_Slot *,
PyObject *spec);
PyAPI_FUNC(int) PyModule_Exec(PyObject *mod);
PyAPI_FUNC(int) PyModule_GetStateSize(PyObject *mod, Py_ssize_t *result);
PyAPI_FUNC(int) PyModule_GetToken(PyObject *, void **result);
#endif

#ifndef _Py_OPAQUE_PYOBJECT
struct PyModuleDef {
Expand Down
5 changes: 5 additions & 0 deletions Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,11 @@ PyAPI_FUNC(PyObject *) PyType_GetModuleByDef(PyTypeObject *, PyModuleDef *);
PyAPI_FUNC(int) PyType_Freeze(PyTypeObject *type);
#endif

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15)
PyAPI_FUNC(PyObject *) PyType_GetModuleByToken(PyTypeObject *type,
const void *token);
#endif

#ifdef __cplusplus
}
#endif
Expand Down
Loading
Loading