Skip to content

Commit b89548d

Browse files
committed
Add test, refine docs, add whatsnew, separate run_presite in pylifecycle.c
1 parent f192e38 commit b89548d

File tree

4 files changed

+66
-26
lines changed

4 files changed

+66
-26
lines changed

Doc/using/cmdline.rst

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -553,9 +553,10 @@ Miscellaneous options
553553
container system. See also :envvar:`PYTHON_CPU_COUNT`.
554554
If *n* is ``default``, nothing is overridden.
555555
* :samp:`-X presite={package.module}` specifies a module that should be
556-
imported before ``site.py`` is executed. Python needs to be
557-
:ref:`built in debug mode <debug-build>` for this option to exist.
558-
See also :envvar:`PYTHON_PRESITE <PYTHON_PRESITE=package.module>`.
556+
imported before ``site.py`` is executed and before the :mod:`__main__`
557+
module exists. Therefore, the imported module isn't :mod:`__main__`.
558+
Python needs to be :ref:`built in debug mode <debug-build>` for this
559+
option to exist. See also :envvar:`PYTHON_PRESITE`.
559560

560561
It also allows passing arbitrary values and retrieving them through the
561562
:data:`sys._xoptions` dictionary.
@@ -1099,19 +1100,22 @@ Debug-mode variables
10991100

11001101
Need Python configured with the :option:`--with-trace-refs` build option.
11011102

1102-
.. envvar:: PYTHONDUMPREFSFILE=FILENAME
1103+
.. envvar:: PYTHONDUMPREFSFILE
11031104

11041105
If set, Python will dump objects and reference counts still alive
1105-
after shutting down the interpreter into a file called *FILENAME*.
1106+
after shutting down the interpreter into a file under the path given
1107+
as the value to this environment variable.
11061108

11071109
Need Python configured with the :option:`--with-trace-refs` build option.
11081110

11091111
.. versionadded:: 3.11
11101112

1111-
.. envvar:: PYTHON_PRESITE=package.module
1113+
.. envvar:: PYTHON_PRESITE
11121114

11131115
If this variable is set to a module, that module will be imported
1114-
early in the interpreter lifecycle, before ``site.py`` is executed.
1116+
early in the interpreter lifecycle, before ``site.py`` is executed,
1117+
and before the :mod:`__main__` module is created. Therefore, the
1118+
imported module is not treated as :mod:`__main__`.
11151119

11161120
See also the :option:`-X presite <-X>` command-line option,
11171121
which takes precedence over this variable.

Doc/whatsnew/3.13.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,3 +1348,13 @@ removed, although there is currently no date scheduled for their removal.
13481348

13491349
* Remove undocumented ``PY_TIMEOUT_MAX`` constant from the limited C API.
13501350
(Contributed by Victor Stinner in :gh:`110014`.)
1351+
1352+
1353+
Regression Test Changes
1354+
=======================
1355+
1356+
* Python built with :file:`configure` :option:`--with-pydebug` now
1357+
supports a :option:`-X presite=package.module <-X>` command-line
1358+
option. If used, it specifies a module that should be imported early
1359+
in the lifecycle of the interpreter, before ``site.py`` is executed.
1360+
(Contributed by Łukasz Langa in :gh:`110769`.)

Lib/test/test_embed.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,22 @@ def test_no_memleak(self):
18201820
self.assertEqual(refs, 0, out)
18211821
self.assertEqual(blocks, 0, out)
18221822

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+
18231839

18241840
class StdPrinterTests(EmbeddingTestsMixin, unittest.TestCase):
18251841
# Test PyStdPrinter_Type which is used by _PySys_SetPreliminaryStderr():

Python/pylifecycle.c

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,34 @@ pyinit_main_reconfigure(PyThreadState *tstate)
10761076
}
10771077

10781078

1079+
static void
1080+
run_presite(PyThreadState *tstate)
1081+
{
1082+
PyInterpreterState *interp = tstate->interp;
1083+
const PyConfig *config = _PyInterpreterState_GetConfig(interp);
1084+
1085+
if (config->run_presite) {
1086+
PyObject *presite_modname = PyUnicode_FromWideChar(
1087+
config->run_presite,
1088+
wcslen(config->run_presite)
1089+
);
1090+
if (presite_modname == NULL) {
1091+
fprintf(stderr, "Could not convert pre-site module name to unicode\n");
1092+
Py_DECREF(presite_modname);
1093+
}
1094+
else {
1095+
PyObject *presite = PyImport_Import(presite_modname);
1096+
if (presite == NULL) {
1097+
fprintf(stderr, "pre-site import failed:\n");
1098+
_PyErr_Print(tstate);
1099+
}
1100+
Py_XDECREF(presite);
1101+
Py_DECREF(presite_modname);
1102+
}
1103+
}
1104+
}
1105+
1106+
10791107
static PyStatus
10801108
init_interp_main(PyThreadState *tstate)
10811109
{
@@ -1158,25 +1186,7 @@ init_interp_main(PyThreadState *tstate)
11581186
}
11591187

11601188
#ifdef Py_DEBUG
1161-
if (config->run_presite) {
1162-
PyObject *presite_modname = PyUnicode_FromWideChar(
1163-
config->run_presite,
1164-
wcslen(config->run_presite)
1165-
);
1166-
if (presite_modname == NULL) {
1167-
fprintf(stderr, "Could not convert module name to unicode\n");
1168-
Py_DECREF(presite_modname);
1169-
}
1170-
else {
1171-
PyObject *presite = PyImport_Import(presite_modname);
1172-
if (presite == NULL) {
1173-
fprintf(stderr, "pre-site import failed:\n");
1174-
_PyErr_Print(tstate);
1175-
}
1176-
Py_XDECREF(presite);
1177-
Py_DECREF(presite_modname);
1178-
}
1179-
}
1189+
run_presite(tstate);
11801190
#endif
11811191

11821192
status = add_main_module(interp);

0 commit comments

Comments
 (0)