| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent d0d472b commit 0eeb817
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -716,7 +716,7 @@ PyConfig | |||
| 716 | 716 | ||
| 717 | 717 | Set to ``1`` by the :envvar:`PYTHONDUMPREFS` environment variable. | |
| 718 | 718 | ||
| 719 | - Need a special build of Python with the ``Py_TRACE_REFS`` macro defined: | ||
| 719 | + Needs a special build of Python with the ``Py_TRACE_REFS`` macro defined: | ||
| 720 | 720 | see the :option:`configure --with-trace-refs option <--with-trace-refs>`. | |
| 721 | 721 | ||
| 722 | 722 | Default: ``0``. | |
@@ -1048,7 +1048,7 @@ PyConfig | |||
| 1048 | 1048 | Incremented by the :option:`-d` command line option. Set to the | |
| 1049 | 1049 | :envvar:`PYTHONDEBUG` environment variable value. | |
| 1050 | 1050 | ||
| 1051 | - Need a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro | ||
| 1051 | + Needs a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro | ||
| 1052 | 1052 | must be defined). | |
| 1053 | 1053 | ||
| 1054 | 1054 | Default: ``0``. | |
@@ -1100,6 +1100,7 @@ PyConfig | |||
| 1100 | 1100 | ||
| 1101 | 1101 | Set by the :option:`-X pycache_prefix=PATH <-X>` command line option and | |
| 1102 | 1102 | the :envvar:`PYTHONPYCACHEPREFIX` environment variable. | |
| 1103 | + The command-line option takes precedence. | ||
| 1103 | 1104 | ||
| 1104 | 1105 | If ``NULL``, :data:`sys.pycache_prefix` is set to ``None``. | |
| 1105 | 1106 | ||
@@ -1143,13 +1144,27 @@ PyConfig | |||
| 1143 | 1144 | ||
| 1144 | 1145 | Default: ``NULL``. | |
| 1145 | 1146 | ||
| 1147 | + .. c:member:: wchar_t* run_presite | ||
| 1148 | + | ||
| 1149 | + ``package.module`` path to module that should be imported before | ||
| 1150 | + ``site.py`` is run. | ||
| 1151 | + | ||
| 1152 | + Set by the :option:`-X presite=package.module <-X>` command-line | ||
| 1153 | + option and the :envvar:`PYTHON_PRESITE` environment variable. | ||
| 1154 | + The command-line option takes precedence. | ||
| 1155 | + | ||
| 1156 | + Needs a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro | ||
| 1157 | + must be defined). | ||
| 1158 | + | ||
| 1159 | + Default: ``NULL``. | ||
| 1160 | + | ||
| 1146 | 1161 | .. c:member:: int show_ref_count | |
| 1147 | 1162 | ||
| 1148 | 1163 | Show total reference count at exit (excluding immortal objects)? | |
| 1149 | 1164 | ||
| 1150 | 1165 | Set to ``1`` by :option:`-X showrefcount <-X>` command line option. | |
| 1151 | 1166 | ||
| 1152 | - Need a :ref:`debug build of Python <debug-build>` (the ``Py_REF_DEBUG`` | ||
| 1167 | + Needs a :ref:`debug build of Python <debug-build>` (the ``Py_REF_DEBUG`` | ||
| 1153 | 1168 | macro must be defined). | |
| 1154 | 1169 | ||
| 1155 | 1170 | Default: ``0``. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -552,6 +552,12 @@ Miscellaneous options | |||
| 552 | 552 | This option may be useful for users who need to limit CPU resources of a | |
| 553 | 553 | container system. See also :envvar:`PYTHON_CPU_COUNT`. | |
| 554 | 554 | If *n* is ``default``, nothing is overridden. | |
| 555 | + * :samp:`-X presite={package.module}` specifies a module that should be | ||
| 556 | + imported before the :mod:`site` module is executed and before the | ||
| 557 | + :mod:`__main__` module exists. Therefore, the imported module isn't | ||
| 558 | + :mod:`__main__`. This can be used to execute code early during Python | ||
| 559 | + initialization. Python needs to be :ref:`built in debug mode <debug-build>` | ||
| 560 | + for this option to exist. See also :envvar:`PYTHON_PRESITE`. | ||
| 555 | 561 | ||
| 556 | 562 | It also allows passing arbitrary values and retrieving them through the | |
| 557 | 563 | :data:`sys._xoptions` dictionary. | |
@@ -602,6 +608,9 @@ Miscellaneous options | |||
| 602 | 608 | .. versionadded:: 3.13 | |
| 603 | 609 | The ``-X cpu_count`` option. | |
| 604 | 610 | ||
| 611 | + .. versionadded:: 3.13 | ||
| 612 | + The ``-X presite`` option. | ||
| 613 | + | ||
| 605 | 614 | ||
| 606 | 615 | Options you shouldn't use | |
| 607 | 616 | ~~~~~~~~~~~~~~~~~~~~~~~~~ | |
@@ -1091,13 +1100,33 @@ Debug-mode variables | |||
| 1091 | 1100 | If set, Python will dump objects and reference counts still alive after | |
| 1092 | 1101 | shutting down the interpreter. | |
| 1093 | 1102 | ||
| 1094 | - Need Python configured with the :option:`--with-trace-refs` build option. | ||
| 1103 | + Needs Python configured with the :option:`--with-trace-refs` build option. | ||
| 1095 | 1104 | ||
| 1096 | - .. envvar:: PYTHONDUMPREFSFILE=FILENAME | ||
| 1105 | + .. envvar:: PYTHONDUMPREFSFILE | ||
| 1097 | 1106 | ||
| 1098 | 1107 | If set, Python will dump objects and reference counts still alive | |
| 1099 | - after shutting down the interpreter into a file called *FILENAME*. | ||
| 1108 | + after shutting down the interpreter into a file under the path given | ||
| 1109 | + as the value to this environment variable. | ||
| 1100 | 1110 | ||
| 1101 | - Need Python configured with the :option:`--with-trace-refs` build option. | ||
| 1111 | + Needs Python configured with the :option:`--with-trace-refs` build option. | ||
| 1102 | 1112 | ||
| 1103 | 1113 | .. versionadded:: 3.11 | |
| 1114 | + | ||
| 1115 | + .. envvar:: PYTHON_PRESITE | ||
| 1116 | + | ||
| 1117 | + If this variable is set to a module, that module will be imported | ||
| 1118 | + early in the interpreter lifecycle, before the :mod:`site` module is | ||
| 1119 | + executed, and before the :mod:`__main__` module is created. | ||
| 1120 | + Therefore, the imported module is not treated as :mod:`__main__`. | ||
| 1121 | + | ||
| 1122 | + This can be used to execute code early during Python initialization. | ||
| 1123 | + | ||
| 1124 | + To import a submodule, use ``package.module`` as the value, like in | ||
| 1125 | + an import statement. | ||
| 1126 | + | ||
| 1127 | + See also the :option:`-X presite <-X>` command-line option, | ||
| 1128 | + which takes precedence over this variable. | ||
| 1129 | + | ||
| 1130 | + Needs Python configured with the :option:`--with-pydebug` build option. | ||
| 1131 | + | ||
| 1132 | + .. versionadded:: 3.13 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1356,3 +1356,13 @@ removed, although there is currently no date scheduled for their removal. | |||
| 1356 | 1356 | ||
| 1357 | 1357 | * Remove undocumented ``PY_TIMEOUT_MAX`` constant from the limited C API. | |
| 1358 | 1358 | (Contributed by Victor Stinner in :gh:`110014`.) | |
| 1359 | + | ||
| 1360 | + | ||
| 1361 | + Regression Test Changes | ||
| 1362 | + ======================= | ||
| 1363 | + | ||
| 1364 | + * Python built with :file:`configure` :option:`--with-pydebug` now | ||
| 1365 | + supports a :option:`-X presite=package.module <-X>` command-line | ||
| 1366 | + option. If used, it specifies a module that should be imported early | ||
| 1367 | + in the lifecycle of the interpreter, before ``site.py`` is executed. | ||
| 1368 | + (Contributed by Łukasz Langa in :gh:`110769`.) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -225,6 +225,12 @@ typedef struct PyConfig { | |||
| 225 | 225 | // If non-zero, turns on statistics gathering. | |
| 226 | 226 | int _pystats; | |
| 227 | 227 | #endif | |
| 228 | + | ||
| 229 | + #ifdef Py_DEBUG | ||
| 230 | + // If not empty, import a non-__main__ module before site.py is executed. | ||
| 231 | + // PYTHON_PRESITE=package.module or -X presite=package.module | ||
| 232 | + wchar_t *run_presite; | ||
| 233 | + #endif | ||
| 228 | 234 | } PyConfig; | |
| 229 | 235 | ||
| 230 | 236 | PyAPI_FUNC(void) PyConfig_InitPythonConfig(PyConfig *config); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -515,6 +515,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): | |||
| 515 | 515 | } | |
| 516 | 516 | if Py_STATS: | |
| 517 | 517 | CONFIG_COMPAT['_pystats'] = 0 | |
| 518 | + if support.Py_DEBUG: | ||
| 519 | + CONFIG_COMPAT['run_presite'] = None | ||
| 518 | 520 | if MS_WINDOWS: | |
| 519 | 521 | CONFIG_COMPAT.update({ | |
| 520 | 522 | 'legacy_windows_stdio': 0, | |
@@ -1818,6 +1820,22 @@ def test_no_memleak(self): | |||
| 1818 | 1820 | self.assertEqual(refs, 0, out) | |
| 1819 | 1821 | self.assertEqual(blocks, 0, out) | |
| 1820 | 1822 | ||
| 1823 | + @unittest.skipUnless(support.Py_DEBUG, | ||
| 1824 | + '-X presite requires a Python debug build') | ||
| 1825 | + def test_presite(self): | ||
| 1826 | + cmd = [sys.executable, "-I", "-X", "presite=test.reperf", "-c", "print('cmd')"] | ||
| 1827 | + proc = subprocess.run( | ||
| 1828 | + cmd, | ||
| 1829 | + stdout=subprocess.PIPE, | ||
| 1830 | + stderr=subprocess.STDOUT, | ||
| 1831 | + text=True, | ||
| 1832 | + ) | ||
| 1833 | + self.assertEqual(proc.returncode, 0) | ||
| 1834 | + out = proc.stdout.strip() | ||
| 1835 | + self.assertIn("10 times sub", out) | ||
| 1836 | + self.assertIn("CPU seconds", out) | ||
| 1837 | + self.assertIn("cmd", out) | ||
| 1838 | + | ||
| 1821 | 1839 | ||
| 1822 | 1840 | class StdPrinterTests(EmbeddingTestsMixin, unittest.TestCase): | |
| 1823 | 1841 | # Test PyStdPrinter_Type which is used by _PySys_SetPreliminaryStderr(): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + Add :envvar:`PYTHON_PRESITE=package.module` to import a module early in the | ||
| 2 | + interpreter lifecycle before ``site.py`` is executed. Python needs to be | ||
| 3 | + :ref:`built in debug mode <debug-build>` for this option to exist. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -117,6 +117,9 @@ static const PyConfigSpec PYCONFIG_SPEC[] = { | |||
| 117 | 117 | SPEC(_is_python_build, UINT), | |
| 118 | 118 | #ifdef Py_STATS | |
| 119 | 119 | SPEC(_pystats, UINT), | |
| 120 | + #endif | ||
| 121 | + #ifdef Py_DEBUG | ||
| 122 | + SPEC(run_presite, WSTR_OPT), | ||
| 120 | 123 | #endif | |
| 121 | 124 | {NULL, 0, 0}, | |
| 122 | 125 | }; | |
@@ -241,6 +244,11 @@ The following implementation-specific options are available:\n\ | |||
| 241 | 244 | \n\ | |
| 242 | 245 | -X pystats: Enable pystats collection at startup." | |
| 243 | 246 | #endif | |
| 247 | + #ifdef Py_DEBUG | ||
| 248 | + "\n\ | ||
| 249 | + \n\ | ||
| 250 | + -X presite=package.module: import this module before site.py is run." | ||
| 251 | + #endif | ||
| 244 | 252 | ; | |
| 245 | 253 | ||
| 246 | 254 | /* Envvars that don't have equivalent command-line options are listed first */ | |
@@ -297,6 +305,9 @@ static const char usage_envvars[] = | |||
| 297 | 305 | #ifdef Py_STATS | |
| 298 | 306 | "PYTHONSTATS : turns on statistics gathering\n" | |
| 299 | 307 | #endif | |
| 308 | + #ifdef Py_DEBUG | ||
| 309 | + "PYTHON_PRESITE=pkg.mod : import this module before site.py is run\n" | ||
| 310 | + #endif | ||
| 300 | 311 | ; | |
| 301 | 312 | ||
| 302 | 313 | #if defined(MS_WINDOWS) | |
@@ -790,6 +801,9 @@ PyConfig_Clear(PyConfig *config) | |||
| 790 | 801 | CLEAR(config->run_module); | |
| 791 | 802 | CLEAR(config->run_filename); | |
| 792 | 803 | CLEAR(config->check_hash_pycs_mode); | |
| 804 | + #ifdef Py_DEBUG | ||
| 805 | + CLEAR(config->run_presite); | ||
| 806 | + #endif | ||
| 793 | 807 | ||
| 794 | 808 | _PyWideStringList_Clear(&config->orig_argv); | |
| 795 | 809 | #undef CLEAR | |
@@ -1806,6 +1820,36 @@ config_init_pycache_prefix(PyConfig *config) | |||
| 1806 | 1820 | } | |
| 1807 | 1821 | ||
| 1808 | 1822 | ||
| 1823 | + #ifdef Py_DEBUG | ||
| 1824 | + static PyStatus | ||
| 1825 | + config_init_run_presite(PyConfig *config) | ||
| 1826 | + { | ||
| 1827 | + assert(config->run_presite == NULL); | ||
| 1828 | + | ||
| 1829 | + const wchar_t *xoption = config_get_xoption(config, L"presite"); | ||
| 1830 | + if (xoption) { | ||
| 1831 | + const wchar_t *sep = wcschr(xoption, L'='); | ||
| 1832 | + if (sep && wcslen(sep) > 1) { | ||
| 1833 | + config->run_presite = _PyMem_RawWcsdup(sep + 1); | ||
| 1834 | + if (config->run_presite == NULL) { | ||
| 1835 | + return _PyStatus_NO_MEMORY(); | ||
| 1836 | + } | ||
| 1837 | + } | ||
| 1838 | + else { | ||
| 1839 | + // PYTHON_PRESITE env var ignored | ||
| 1840 | + // if "-X presite=" option is used | ||
| 1841 | + config->run_presite = NULL; | ||
| 1842 | + } | ||
| 1843 | + return _PyStatus_OK(); | ||
| 1844 | + } | ||
| 1845 | + | ||
| 1846 | + return CONFIG_GET_ENV_DUP(config, &config->run_presite, | ||
| 1847 | + L"PYTHON_PRESITE", | ||
| 1848 | + "PYTHON_PRESITE"); | ||
| 1849 | + } | ||
| 1850 | + #endif | ||
| 1851 | + | ||
| 1852 | + | ||
| 1809 | 1853 | static PyStatus | |
| 1810 | 1854 | config_read_complex_options(PyConfig *config) | |
| 1811 | 1855 | { | |
@@ -1861,6 +1905,16 @@ config_read_complex_options(PyConfig *config) | |||
| 1861 | 1905 | return status; | |
| 1862 | 1906 | } | |
| 1863 | 1907 | } | |
| 1908 | + | ||
| 1909 | + #ifdef Py_DEBUG | ||
| 1910 | + if (config->run_presite == NULL) { | ||
| 1911 | + status = config_init_run_presite(config); | ||
| 1912 | + if (_PyStatus_EXCEPTION(status)) { | ||
| 1913 | + return status; | ||
| 1914 | + } | ||
| 1915 | + } | ||
| 1916 | + #endif | ||
| 1917 | + | ||
| 1864 | 1918 | return _PyStatus_OK(); | |
| 1865 | 1919 | } | |
| 1866 | 1920 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1076,6 +1076,38 @@ pyinit_main_reconfigure(PyThreadState *tstate) | |||
| 1076 | 1076 | } | |
| 1077 | 1077 | ||
| 1078 | 1078 | ||
| 1079 | + #ifdef Py_DEBUG | ||
| 1080 | + static void | ||
| 1081 | + run_presite(PyThreadState *tstate) | ||
| 1082 | + { | ||
| 1083 | + PyInterpreterState *interp = tstate->interp; | ||
| 1084 | + const PyConfig *config = _PyInterpreterState_GetConfig(interp); | ||
| 1085 | + | ||
| 1086 | + if (!config->run_presite) { | ||
| 1087 | + return; | ||
| 1088 | + } | ||
| 1089 | + | ||
| 1090 | + PyObject *presite_modname = PyUnicode_FromWideChar( | ||
| 1091 | + config->run_presite, | ||
| 1092 | + wcslen(config->run_presite) | ||
| 1093 | + ); | ||
| 1094 | + if (presite_modname == NULL) { | ||
| 1095 | + fprintf(stderr, "Could not convert pre-site module name to unicode\n"); | ||
| 1096 | + Py_DECREF(presite_modname); | ||
| 1097 | + } | ||
| 1098 | + else { | ||
| 1099 | + PyObject *presite = PyImport_Import(presite_modname); | ||
| 1100 | + if (presite == NULL) { | ||
| 1101 | + fprintf(stderr, "pre-site import failed:\n"); | ||
| 1102 | + _PyErr_Print(tstate); | ||
| 1103 | + } | ||
| 1104 | + Py_XDECREF(presite); | ||
| 1105 | + Py_DECREF(presite_modname); | ||
| 1106 | + } | ||
| 1107 | + } | ||
| 1108 | + #endif | ||
| 1109 | + | ||
| 1110 | + | ||
| 1079 | 1111 | static PyStatus | |
| 1080 | 1112 | init_interp_main(PyThreadState *tstate) | |
| 1081 | 1113 | { | |
@@ -1157,6 +1189,10 @@ init_interp_main(PyThreadState *tstate) | |||
| 1157 | 1189 | return status; | |
| 1158 | 1190 | } | |
| 1159 | 1191 | ||
| 1192 | + #ifdef Py_DEBUG | ||
| 1193 | + run_presite(tstate); | ||
| 1194 | + #endif | ||
| 1195 | + | ||
| 1160 | 1196 | status = add_main_module(interp); | |
| 1161 | 1197 | if (_PyStatus_EXCEPTION(status)) { | |
| 1162 | 1198 | return status; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments