| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 5a549e8 commit 00db9e8
13 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1525,7 +1525,10 @@ sharedmods: $(SHAREDMODS) pybuilddir.txt | |||
| 1525 | 1525 | $(MKDIR_P) $$target; \ | |
| 1526 | 1526 | for mod in X $(SHAREDMODS); do \ | |
| 1527 | 1527 | if test $$mod != X; then \ | |
| 1528 | - $(LN) -sf ../../$$mod $$target/`basename $$mod`; \ | ||
| 1528 | + rel=`echo $$mod | sed 's,^Modules/,,'`; \ | ||
| 1529 | + dest=$$target/$$rel; \ | ||
| 1530 | + $(MKDIR_P) `dirname $$dest`; \ | ||
| 1531 | + $(LN) -sf `pwd`/$$mod $$dest; \ | ||
| 1529 | 1532 | fi; \ | |
| 1530 | 1533 | done | |
| 1531 | 1534 | ||
@@ -2394,11 +2397,13 @@ sharedinstall: all | |||
| 2394 | 2397 | done | |
| 2395 | 2398 | @for i in X $(SHAREDMODS); do \ | |
| 2396 | 2399 | if test $$i != X; then \ | |
| 2397 | - echo $(INSTALL_SHARED) $$i $(DESTSHARED)/`basename $$i`; \ | ||
| 2398 | - $(INSTALL_SHARED) $$i $(DESTDIR)$(DESTSHARED)/`basename $$i`; \ | ||
| 2400 | + rel=`echo $$i | sed 's,^Modules/,,'`; \ | ||
| 2401 | + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(DESTSHARED)/`dirname $$rel`; \ | ||
| 2402 | + echo $(INSTALL_SHARED) $$i $(DESTSHARED)/$$rel; \ | ||
| 2403 | + $(INSTALL_SHARED) $$i $(DESTDIR)$(DESTSHARED)/$$rel; \ | ||
| 2399 | 2404 | if test -d "$$i.dSYM"; then \ | |
| 2400 | - echo $(DSYMUTIL_PATH) $(DESTDIR)$(DESTSHARED)/`basename $$i`; \ | ||
| 2401 | - $(DSYMUTIL_PATH) $(DESTDIR)$(DESTSHARED)/`basename $$i`; \ | ||
| 2405 | + echo $(DSYMUTIL_PATH) $(DESTDIR)$(DESTSHARED)/$$rel; \ | ||
| 2406 | + $(DSYMUTIL_PATH) $(DESTDIR)$(DESTSHARED)/$$rel; \ | ||
| 2402 | 2407 | fi; \ | |
| 2403 | 2408 | fi; \ | |
| 2404 | 2409 | done | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,9 @@ | |||
| 1 | + The :mod:`math` module is now built as an extension *package*: | ||
| 2 | + ``math/__init__`` and ``math/integer``. :mod:`math.integer` is therefore a | ||
| 3 | + real extension submodule instead of the ``_math_integer`` extension module | ||
| 4 | + disguised as one. :file:`Modules/makesetup` now accepts dotted module names | ||
| 5 | + (a package initializer is written with an explicit ``__init__`` leaf, e.g. | ||
| 6 | + ``math.__init__``) and maps each to a sub-directory path and the matching | ||
| 7 | + ``PyInit_`` symbol. This works both for the usual shared build and for | ||
| 8 | + builds where ``math`` is compiled into the interpreter as a builtin module | ||
| 9 | + (Windows and WebAssembly). | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -155,8 +155,8 @@ PYTHONPATH=$(COREPYTHONPATH) | |||
| 155 | 155 | #array arraymodule.c | |
| 156 | 156 | #binascii binascii.c | |
| 157 | 157 | #cmath cmathmodule.c | |
| 158 | - #math mathmodule.c | ||
| 159 | - #_math_integer mathintegermodule.c | ||
| 158 | + #math.__init__ mathmodule.c | ||
| 159 | + #math.integer mathintegermodule.c | ||
| 160 | 160 | #mmap mmapmodule.c | |
| 161 | 161 | #select selectmodule.c | |
| 162 | 162 | #_sysconfig _sysconfig.c | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -37,7 +37,7 @@ | |||
| 37 | 37 | @MODULE__HEAPQ_TRUE@_heapq _heapqmodule.c | |
| 38 | 38 | @MODULE__JSON_TRUE@_json _json.c | |
| 39 | 39 | @MODULE__LSPROF_TRUE@_lsprof _lsprof.c rotatingtree.c | |
| 40 | - @MODULE__MATH_INTEGER_TRUE@_math_integer mathintegermodule.c | ||
| 40 | + @MODULE_MATH_INTEGER_TRUE@math.integer mathintegermodule.c | ||
| 41 | 41 | @MODULE__PICKLE_TRUE@_pickle _pickle.c | |
| 42 | 42 | @MODULE__QUEUE_TRUE@_queue _queuemodule.c | |
| 43 | 43 | @MODULE__RANDOM_TRUE@_random _randommodule.c | |
@@ -52,7 +52,7 @@ | |||
| 52 | 52 | @MODULE__ZONEINFO_TRUE@_zoneinfo _zoneinfo.c | |
| 53 | 53 | ||
| 54 | 54 | # needs libm | |
| 55 | - @MODULE_MATH_TRUE@math mathmodule.c | ||
| 55 | + @MODULE_MATH_TRUE@math.__init__ mathmodule.c | ||
| 56 | 56 | @MODULE_CMATH_TRUE@cmath cmathmodule.c | |
| 57 | 57 | @MODULE__STATISTICS_TRUE@_statistics _statisticsmodule.c | |
| 58 | 58 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -87,6 +87,32 @@ esac | |||
| 87 | 87 | NL='\ | |
| 88 | 88 | ' | |
| 89 | 89 | ||
| 90 | + # Map a module name as written in Setup to its three distinct attributes. | ||
| 91 | + # Submodules use dotted names (math.integer); a package's initializer is | ||
| 92 | + # written with an explicit __init__ leaf (math.__init__). | ||
| 93 | + # mod_regname: import/registration name math.integer -> math.integer | ||
| 94 | + # math.__init__ -> math | ||
| 95 | + # mod_path: path under srcdir (no ext) math.integer -> math/integer | ||
| 96 | + # math.__init__ -> math/__init__ | ||
| 97 | + # mod_sym: static PyInit_<sym> symbol math.integer -> math_integer | ||
| 98 | + # math.__init__ -> math | ||
| 99 | + # mod_sym (the static inittab symbol) uses the full dotted name so it stays | ||
| 100 | + # unique across packages; shared submodules instead export | ||
| 101 | + # PyInit_<last component> (see Py_BUILD_CORE_BUILTIN). | ||
| 102 | + mod_regname() { | ||
| 103 | + case $1 in | ||
| 104 | + *.__init__) echo "${1%.__init__}";; | ||
| 105 | + *) echo "$1";; | ||
| 106 | + esac | ||
| 107 | + } | ||
| 108 | + mod_path() { | ||
| 109 | + echo "$1" | tr '.' '/' | ||
| 110 | + } | ||
| 111 | + mod_sym() { | ||
| 112 | + reg=`mod_regname "$1"` | ||
| 113 | + echo "$reg" | tr '.' '_' | ||
| 114 | + } | ||
| 115 | + | ||
| 90 | 116 | # Main loop | |
| 91 | 117 | for i in ${*-Setup} | |
| 92 | 118 | do | |
@@ -183,21 +209,35 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | | |||
| 183 | 209 | \$\(*_RPATH\)) libs="$libs $arg";; | |
| 184 | 210 | \$*) libs="$libs $arg" | |
| 185 | 211 | cpps="$cpps $arg";; | |
| 186 | - *.*) echo 1>&2 "bad word $arg in $line" | ||
| 187 | - exit 1;; | ||
| 188 | 212 | -u) skip=libs; libs="$libs -u";; | |
| 189 | 213 | [a-zA-Z_]*) | |
| 190 | - mods="$mods $arg" | ||
| 191 | - mods_upper=$(echo $mods | tr '[a-z]' '[A-Z]');; | ||
| 214 | + # Module name, possibly dotted (math.integer) or a | ||
| 215 | + # package initializer (math.__init__). Only identifier | ||
| 216 | + # characters and dots are allowed. | ||
| 217 | + case $arg in | ||
| 218 | + *[!a-zA-Z0-9_.]*) | ||
| 219 | + echo 1>&2 "bad word $arg in $line" | ||
| 220 | + exit 1;; | ||
| 221 | + esac | ||
| 222 | + mods="$mods $arg";; | ||
| 192 | 223 | *) echo 1>&2 "bad word $arg in $line" | |
| 193 | 224 | exit 1;; | |
| 194 | 225 | esac | |
| 195 | 226 | done | |
| 227 | + regmods= | ||
| 228 | + for mod in $mods | ||
| 229 | + do | ||
| 230 | + regmods="$regmods `mod_regname $mod`" | ||
| 231 | + done | ||
| 232 | + # MODULE_<NAME>_* variables are keyed by the registration name with | ||
| 233 | + # dots replaced by underscores (math.integer -> MODULE_MATH_INTEGER, | ||
| 234 | + # math.__init__ -> MODULE_MATH). | ||
| 235 | + mods_upper=`echo $regmods | tr 'a-z' 'A-Z' | tr '.' '_'` | ||
| 196 | 236 | if test -z "$cpps" -a -z "$libs"; then | |
| 197 | 237 | cpps="\$(MODULE_${mods_upper}_CFLAGS)" | |
| 198 | 238 | libs="\$(MODULE_${mods_upper}_LDFLAGS)" | |
| 199 | 239 | fi | |
| 200 | - for mod in $mods | ||
| 240 | + for mod in $regmods | ||
| 201 | 241 | do | |
| 202 | 242 | case $CONFIGURED in | |
| 203 | 243 | *,${mod},*) | |
@@ -211,14 +251,14 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | | |||
| 211 | 251 | case $doconfig in | |
| 212 | 252 | yes) | |
| 213 | 253 | LIBS="$LIBS $libs" | |
| 214 | - MODS="$MODS $mods" | ||
| 215 | - BUILT="$BUILT $mods" | ||
| 254 | + MODS="$MODS $regmods" | ||
| 255 | + BUILT="$BUILT $regmods" | ||
| 216 | 256 | ;; | |
| 217 | 257 | no) | |
| 218 | - BUILT="$BUILT $mods" | ||
| 258 | + BUILT="$BUILT $regmods" | ||
| 219 | 259 | ;; | |
| 220 | 260 | disabled) | |
| 221 | - DISABLED="$DISABLED $mods" | ||
| 261 | + DISABLED="$DISABLED $regmods" | ||
| 222 | 262 | continue | |
| 223 | 263 | ;; | |
| 224 | 264 | esac | |
@@ -269,15 +309,17 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | | |||
| 269 | 309 | esac | |
| 270 | 310 | for mod in $mods | |
| 271 | 311 | do | |
| 272 | - file="$srcdir/$mod\$(EXT_SUFFIX)" | ||
| 312 | + file="$srcdir/`mod_path $mod`\$(EXT_SUFFIX)" | ||
| 273 | 313 | case $doconfig in | |
| 274 | 314 | no) | |
| 275 | 315 | SHAREDMODS="$SHAREDMODS $file" | |
| 276 | - BUILT_SHARED="$BUILT_SHARED $mod" | ||
| 316 | + BUILT_SHARED="$BUILT_SHARED `mod_regname $mod`" | ||
| 277 | 317 | ;; | |
| 278 | 318 | esac | |
| 279 | 319 | rule="$file: $objs \$(MODULE_${mods_upper}_LDEPS)" | |
| 280 | - rule="$rule; \$(BLDSHARED) $objs $libs \$(LIBPYTHON) -o $file" | ||
| 320 | + # Submodules/packages land in a sub-directory (math/integer, | ||
| 321 | + # math/__init__); create it before linking. | ||
| 322 | + rule="$rule; \$(MKDIR_P) \$(@D); \$(BLDSHARED) $objs $libs \$(LIBPYTHON) -o $file" | ||
| 281 | 323 | echo "$rule" >>$rulesf | |
| 282 | 324 | done | |
| 283 | 325 | done | |
@@ -299,8 +341,11 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | | |||
| 299 | 341 | INITBITS= | |
| 300 | 342 | for mod in $MODS | |
| 301 | 343 | do | |
| 302 | - EXTDECLS="${EXTDECLS}extern PyObject* PyInit_$mod(void);$NL" | ||
| 303 | - INITBITS="${INITBITS} {\"$mod\", PyInit_$mod},$NL" | ||
| 344 | + # $mod is the registration name (e.g. math.integer); the C init | ||
| 345 | + # symbol is named after its last component only (PyInit_integer). | ||
| 346 | + modsym=`mod_sym $mod` | ||
| 347 | + EXTDECLS="${EXTDECLS}extern PyObject* PyInit_$modsym(void);$NL" | ||
| 348 | + INITBITS="${INITBITS} {\"$mod\", PyInit_$modsym},$NL" | ||
| 304 | 349 | done | |
| 305 | 350 | ||
| 306 | 351 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1287,8 +1287,17 @@ static struct PyModuleDef math_integer_module = { | |||
| 1287 | 1287 | .m_slots = math_integer_slots, | |
| 1288 | 1288 | }; | |
| 1289 | 1289 | ||
| 1290 | + /* Shared, the dynamic loader looks up PyInit_integer (the last component of | ||
| 1291 | + * the name). Built into the interpreter (Py_BUILD_CORE_BUILTIN), the inittab | ||
| 1292 | + * uses PyInit_math_integer instead, so the static symbol stays unique. */ | ||
| 1293 | + #ifdef Py_BUILD_CORE_BUILTIN | ||
| 1294 | + # define MATH_INTEGER_PYINIT PyInit_math_integer | ||
| 1295 | + #else | ||
| 1296 | + # define MATH_INTEGER_PYINIT PyInit_integer | ||
| 1297 | + #endif | ||
| 1298 | + | ||
| 1290 | 1299 | PyMODINIT_FUNC | |
| 1291 | - PyInit__math_integer(void) | ||
| 1300 | + MATH_INTEGER_PYINIT(void) | ||
| 1292 | 1301 | { | |
| 1293 | 1302 | return PyModuleDef_Init(&math_integer_module); | |
| 1294 | 1303 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3188,7 +3188,26 @@ math_exec(PyObject *module) | |||
| 3188 | 3188 | return -1; | |
| 3189 | 3189 | } | |
| 3190 | 3190 | ||
| 3191 | - PyObject *intmath = PyImport_ImportModule("_math_integer"); | ||
| 3191 | + /* math is a package. A shared build gets __path__ from the math/ | ||
| 3192 | + * directory; a builtin build (e.g. Windows, WebAssembly) does not, so set | ||
| 3193 | + * an empty one to mark math as a package and find the builtin submodule. */ | ||
| 3194 | + PyObject *path; | ||
| 3195 | + if (PyObject_GetOptionalAttrString(module, "__path__", &path) < 0) { | ||
| 3196 | + return -1; | ||
| 3197 | + } | ||
| 3198 | + if (path == NULL) { | ||
| 3199 | + path = PyList_New(0); | ||
| 3200 | + if (path == NULL || PyModule_Add(module, "__path__", path) < 0) { | ||
| 3201 | + return -1; | ||
| 3202 | + } | ||
| 3203 | + } | ||
| 3204 | + else { | ||
| 3205 | + Py_DECREF(path); | ||
| 3206 | + } | ||
| 3207 | + | ||
| 3208 | + /* Importing the math.integer submodule sets sys.modules['math.integer'] | ||
| 3209 | + * and the parent's 'integer' attribute automatically. */ | ||
| 3210 | + PyObject *intmath = PyImport_ImportModule("math.integer"); | ||
| 3192 | 3211 | if (!intmath) { | |
| 3193 | 3212 | return -1; | |
| 3194 | 3213 | } | |
@@ -3206,13 +3225,9 @@ math_exec(PyObject *module) | |||
| 3206 | 3225 | IMPORT_FROM_INTMATH(isqrt); | |
| 3207 | 3226 | IMPORT_FROM_INTMATH(lcm); | |
| 3208 | 3227 | IMPORT_FROM_INTMATH(perm); | |
| 3209 | - if (_PyImport_SetModuleString("math.integer", intmath) < 0) { | ||
| 3210 | - Py_DECREF(intmath); | ||
| 3211 | - return -1; | ||
| 3212 | - } | ||
| 3213 | - if (PyModule_Add(module, "integer", intmath) < 0) { | ||
| 3214 | - return -1; | ||
| 3215 | - } | ||
| 3228 | + /* sys.modules['math.integer'] and the parent 'integer' attribute were | ||
| 3229 | + * set by the import machinery above. */ | ||
| 3230 | + Py_DECREF(intmath); | ||
| 3216 | 3231 | return 0; | |
| 3217 | 3232 | } | |
| 3218 | 3233 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,7 +13,7 @@ extern PyObject* PyInit_errno(void); | |||
| 13 | 13 | extern PyObject* PyInit_faulthandler(void); | |
| 14 | 14 | extern PyObject* PyInit__tracemalloc(void); | |
| 15 | 15 | extern PyObject* PyInit_gc(void); | |
| 16 | - extern PyObject* PyInit__math_integer(void); | ||
| 16 | + extern PyObject* PyInit_math_integer(void); | ||
| 17 | 17 | extern PyObject* PyInit_math(void); | |
| 18 | 18 | extern PyObject* PyInit_nt(void); | |
| 19 | 19 | extern PyObject* PyInit__operator(void); | |
@@ -101,8 +101,8 @@ struct _inittab _PyImport_Inittab[] = { | |||
| 101 | 101 | {"errno", PyInit_errno}, | |
| 102 | 102 | {"faulthandler", PyInit_faulthandler}, | |
| 103 | 103 | {"gc", PyInit_gc}, | |
| 104 | - {"_math_integer", PyInit__math_integer}, | ||
| 105 | 104 | {"math", PyInit_math}, | |
| 105 | + {"math.integer", PyInit_math_integer}, | ||
| 106 | 106 | {"nt", PyInit_nt}, /* Use the NT os functions, not posix */ | |
| 107 | 107 | {"_operator", PyInit__operator}, | |
| 108 | 108 | {"_signal", PyInit__signal}, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -147,6 +147,18 @@ def __bool__(self) -> bool: | |||
| 147 | 147 | return self.value in {"builtin", "shared"} | |
| 148 | 148 | ||
| 149 | 149 | ||
| 150 | + def registration_name(setup_token: str) -> str: | ||
| 151 | + """Map a Setup module token to its import/registration name. | ||
| 152 | + | ||
| 153 | + Submodules use dotted names (math.integer); an extension package's | ||
| 154 | + initializer is written with an explicit __init__ leaf (math.__init__), | ||
| 155 | + whose registration name is the package itself (math). | ||
| 156 | + """ | ||
| 157 | + if setup_token.endswith(".__init__"): | ||
| 158 | + return setup_token[: -len(".__init__")] | ||
| 159 | + return setup_token | ||
| 160 | + | ||
| 161 | + | ||
| 150 | 162 | class ModuleInfo(NamedTuple): | |
| 151 | 163 | name: str | |
| 152 | 164 | state: ModuleState | |
@@ -380,13 +392,22 @@ def get_sysconfig_modules(self) -> Iterable[ModuleInfo]: | |||
| 380 | 392 | else: | |
| 381 | 393 | modbuiltin = set(sys.builtin_module_names) | |
| 382 | 394 | ||
| 395 | + # MODULE_<NAME>_STATE keys flatten dotted registration names to | ||
| 396 | + # underscores (math.integer -> MODULE_MATH_INTEGER_STATE). Recover | ||
| 397 | + # the real, possibly dotted, name from the MOD*_NAMES lists. | ||
| 398 | + realnames = {} | ||
| 399 | + for var in ("MODBUILT_NAMES", "MODSHARED_NAMES", "MODDISABLED_NAMES"): | ||
| 400 | + for name in (sysconfig.get_config_var(var) or "").split(): | ||
| 401 | + realnames[name.replace(".", "_")] = name | ||
| 402 | + | ||
| 383 | 403 | for key, value in sysconfig.get_config_vars().items(): | |
| 384 | 404 | if not key.startswith("MODULE_") or not key.endswith("_STATE"): | |
| 385 | 405 | continue | |
| 386 | 406 | if value not in {"yes", "disabled", "missing", "n/a"}: | |
| 387 | 407 | raise ValueError(f"Unsupported value '{value}' for {key}") | |
| 388 | 408 | ||
| 389 | 409 | modname = key[7:-6].lower() | |
| 410 | + modname = realnames.get(modname, modname) | ||
| 390 | 411 | if modname in moddisabled: | |
| 391 | 412 | # Setup "*disabled*" rule | |
| 392 | 413 | state = ModuleState.DISABLED_SETUP | |
@@ -427,12 +448,12 @@ def parse_setup_file(self, setup_file: pathlib.Path) -> Iterable[ModuleInfo]: | |||
| 427 | 448 | if state == ModuleState.DISABLED: | |
| 428 | 449 | # *disabled* can disable multiple modules per line | |
| 429 | 450 | for item in items: | |
| 430 | - modinfo = ModuleInfo(item, state) | ||
| 451 | + modinfo = ModuleInfo(registration_name(item), state) | ||
| 431 | 452 | logger.debug("Found %s in %s", modinfo, setup_file) | |
| 432 | 453 | yield modinfo | |
| 433 | 454 | elif state in {ModuleState.SHARED, ModuleState.BUILTIN}: | |
| 434 | 455 | # *shared* and *static*, first item is the name of the module. | |
| 435 | - modinfo = ModuleInfo(items[0], state) | ||
| 456 | + modinfo = ModuleInfo(registration_name(items[0]), state) | ||
| 436 | 457 | logger.debug("Found %s in %s", modinfo, setup_file) | |
| 437 | 458 | yield modinfo | |
| 438 | 459 | ||
@@ -456,7 +477,16 @@ def get_spec(self, modinfo: ModuleInfo) -> ModuleSpec: | |||
| 456 | 477 | def get_location(self, modinfo: ModuleInfo) -> pathlib.Path | None: | |
| 457 | 478 | """Get shared library location in build directory""" | |
| 458 | 479 | if modinfo.state == ModuleState.SHARED: | |
| 459 | - return self.builddir / f"{modinfo.name}{self.ext_suffix}" | ||
| 480 | + # Dotted submodule names map onto sub-directories | ||
| 481 | + # (math.integer -> math/integer.so). An extension *package* is | ||
| 482 | + # registered under its bare name but lives in <name>/__init__.so. | ||
| 483 | + stem = modinfo.name.replace(".", "/") | ||
| 484 | + location = self.builddir / f"{stem}{self.ext_suffix}" | ||
| 485 | + if not location.exists(): | ||
| 486 | + pkg_init = self.builddir / stem / f"__init__{self.ext_suffix}" | ||
| 487 | + if pkg_init.exists(): | ||
| 488 | + return pkg_init | ||
| 489 | + return location | ||
| 460 | 490 | else: | |
| 461 | 491 | return None | |
| 462 | 492 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments