Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 0 additions & 3 deletions Include/internal/pycore_pylifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,6 @@ extern int _Py_LegacyLocaleDetected(int warn);
// Export for 'readline' shared extension
PyAPI_FUNC(char*) _Py_SetLocaleFromEnv(int category);

// Export for special main.c string compiling with source tracebacks
int _PyRun_SimpleStringFlagsWithName(const char *command, const char* name, PyCompilerFlags *flags);


/* interpreter config */

Expand Down
15 changes: 8 additions & 7 deletions Include/internal/pycore_pythonrun.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,18 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif

extern int _PyRun_SimpleFileObject(
extern PyObject* _PyRun_SimpleFile(
FILE *fp,
PyObject *filename,
int closeit,
PyCompilerFlags *flags);

extern int _PyRun_AnyFileObject(
extern PyObject* _PyRun_AnyFile(
FILE *fp,
PyObject *filename,
int closeit,
PyCompilerFlags *flags);

extern int _PyRun_InteractiveLoopObject(
FILE *fp,
PyObject *filename,
PyCompilerFlags *flags);

extern int _PyObject_SupportedAsScript(PyObject *);
extern const char* _Py_SourceAsString(
PyObject *cmd,
Expand All @@ -39,6 +34,12 @@ extern PyObject * _Py_CompileStringObjectWithModule(
PyCompilerFlags *flags, int optimize,
PyObject *module);

// Export for special main.c string compiling with source tracebacks
extern PyObject* _PyRun_SimpleString(
const char *command,
PyObject* name,
PyCompilerFlags *flags);


/* Stack size, in "pointers". This must be large enough, so
* no two calls to check recursion depth are more than this far
Expand Down
68 changes: 62 additions & 6 deletions Lib/test/test_embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
if not os.path.isfile(os.path.join(STDLIB_INSTALL, 'os.py')):
STDLIB_INSTALL = None

CODE_EXITCODE_123 = 'raise SystemExit(123)'


def debug_build(program):
program = os.path.basename(program)
name = os.path.splitext(program)[0]
Expand Down Expand Up @@ -140,12 +143,16 @@ def run_embedded_interpreter(self, *args, env=None,
env = env.copy()
env['SYSTEMROOT'] = os.environ['SYSTEMROOT']

p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
env=env,
cwd=cwd)
kwargs = dict(
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
env=env,
cwd=cwd,
)
if input is not None:
kwargs['stdin'] = subprocess.PIPE
p = subprocess.Popen(cmd, **kwargs)
try:
(out, err) = p.communicate(input=input, timeout=timeout)
except:
Expand Down Expand Up @@ -590,6 +597,55 @@ def _nogil_filtered_err(err: str, mod_name: str) -> str:
]
return "\n".join(filtered_err_lines)

def check_program_exitcode(self, *args, check_stderr=True, **kwargs):
out, err = self.run_embedded_interpreter(*args, **kwargs)
self.assertEqual(out.rstrip(), 'ok! Py_RunMain() returned 123')
if check_stderr:
self.assertEqual(err, '')

def test_init_run_main_code_exitcode(self):
code = CODE_EXITCODE_123
self.check_program_exitcode("test_init_run_main_code_exitcode", code)

def test_init_run_main_script_exitcode(self):
with tempfile.TemporaryDirectory() as tmpdir:
filename = os.path.join(tmpdir, 'script.py')
with open(filename, 'w') as fp:
fp.write(CODE_EXITCODE_123)

self.check_program_exitcode("test_init_run_main_script_exitcode",
filename)

def test_init_run_main_interactive_exitcode(self):
code = CODE_EXITCODE_123
self.check_program_exitcode("test_init_run_main_interactive_exitcode",
input=code,
check_stderr=False)

def test_init_run_main_startup_exitcode(self):
with tempfile.TemporaryDirectory() as tmpdir:
filename = os.path.join(tmpdir, 'startup.py')
with open(filename, 'x') as fp:
fp.write(CODE_EXITCODE_123)

env = dict(os.environ)
env['PYTHONSTARTUP'] = filename
self.check_program_exitcode("test_init_run_main_interactive_exitcode",
env=env,
check_stderr=False)

def test_init_run_main_module_exitcode(self):
with tempfile.TemporaryDirectory() as tmpdir:
modname = '_testembed_testmodule'
filename = os.path.join(tmpdir, modname + '.py')
with open(filename, 'x', encoding='utf8') as fp:
fp.write(CODE_EXITCODE_123)

env = dict(os.environ)
env['PYTHONPATH'] = tmpdir
self.check_program_exitcode("test_init_run_main_module_exitcode",
modname, env=env)


def config_dev_mode(preconfig, config):
preconfig['allocator'] = PYMEM_ALLOCATOR_DEBUG
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix :c:func:`Py_RunMain` to return an exit code, rather than calling
:c:func:`Py_Exit`, when running a script, a command, or the REPL. Patch by
Victor Stinner.
27 changes: 0 additions & 27 deletions Modules/_testcapi/run.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,6 @@ run_simplefile(PyObject *mod, PyObject *args)
assert(_Py_IsValidFD(fd));
fclose(fp);

if (res == -1 && PyErr_Occurred()) {
return NULL;
}
assert(!PyErr_Occurred());
return PyLong_FromLong(res);
}
Expand Down Expand Up @@ -203,9 +200,6 @@ run_simplefileex(PyObject *mod, PyObject *args)
return NULL;
}

if (res == -1 && PyErr_Occurred()) {
return NULL;
}
assert(!PyErr_Occurred());
return PyLong_FromLong(res);
}
Expand Down Expand Up @@ -243,9 +237,6 @@ run_simplefileexflags(PyObject *mod, PyObject *args)
return NULL;
}

if (res == -1 && PyErr_Occurred()) {
return NULL;
}
assert(!PyErr_Occurred());
return PyLong_FromLong(res);
}
Expand All @@ -272,9 +263,6 @@ run_anyfile(PyObject *mod, PyObject *args)
assert(_Py_IsValidFD(fd));
fclose(fp);

if (res == -1 && PyErr_Occurred()) {
return NULL;
}
assert(!PyErr_Occurred());
return PyLong_FromLong(res);
}
Expand Down Expand Up @@ -310,9 +298,6 @@ run_anyfileflags(PyObject *mod, PyObject *args)
assert(_Py_IsValidFD(fd));
fclose(fp);

if (res == -1 && PyErr_Occurred()) {
return NULL;
}
assert(!PyErr_Occurred());
return PyLong_FromLong(res);
}
Expand Down Expand Up @@ -342,9 +327,6 @@ run_anyfileex(PyObject *mod, PyObject *args)
return NULL;
}

if (res == -1 && PyErr_Occurred()) {
return NULL;
}
assert(!PyErr_Occurred());
return PyLong_FromLong(res);
}
Expand Down Expand Up @@ -382,9 +364,6 @@ run_anyfileexflags(PyObject *mod, PyObject *args)
return NULL;
}

if (res == -1 && PyErr_Occurred()) {
return NULL;
}
assert(!PyErr_Occurred());
return PyLong_FromLong(res);
}
Expand Down Expand Up @@ -664,9 +643,6 @@ run_simplestring(PyObject *mod, PyObject *args)
}

int res = PyRun_SimpleString(str);
if (res == -1 && PyErr_Occurred()) {
return NULL;
}
assert(!PyErr_Occurred());
return PyLong_FromLong(res);
}
Expand All @@ -689,9 +665,6 @@ run_simplestringflags(PyObject *mod, PyObject *args)
}

int res = PyRun_SimpleStringFlags(str, pflags);
if (res == -1 && PyErr_Occurred()) {
return NULL;
}
assert(!PyErr_Occurred());
return PyLong_FromLong(res);
}
Expand Down
Loading
Loading