mirror of
https://github.com/python/cpython.git
synced 2025-07-19 01:05:26 +00:00
[3.13] gh-126925: Modify how iOS test results are gathered (GH-127592) (#127754)
Adds a `use_system_log` config item to enable stdout/stderr redirection for
Apple platforms. This log streaming is then used by a new iOS test runner
script, allowing the display of test suite output at runtime. The iOS test
runner script can be used by any Python project, not just the CPython test
suite.
(cherry picked from commit 2041a95e68
)
This commit is contained in:
parent
b56100c77a
commit
075c41d5f5
16 changed files with 782 additions and 58 deletions
|
@ -129,6 +129,10 @@ static const PyConfigSpec PYCONFIG_SPEC[] = {
|
|||
#ifdef Py_DEBUG
|
||||
SPEC(run_presite, WSTR_OPT),
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
SPEC(use_system_logger, BOOL),
|
||||
#endif
|
||||
|
||||
{NULL, 0, 0},
|
||||
};
|
||||
|
||||
|
@ -744,6 +748,9 @@ config_check_consistency(const PyConfig *config)
|
|||
assert(config->cpu_count != 0);
|
||||
// config->use_frozen_modules is initialized later
|
||||
// by _PyConfig_InitImportConfig().
|
||||
#ifdef __APPLE__
|
||||
assert(config->use_system_logger >= 0);
|
||||
#endif
|
||||
#ifdef Py_STATS
|
||||
assert(config->_pystats >= 0);
|
||||
#endif
|
||||
|
@ -846,6 +853,9 @@ _PyConfig_InitCompatConfig(PyConfig *config)
|
|||
config->_is_python_build = 0;
|
||||
config->code_debug_ranges = 1;
|
||||
config->cpu_count = -1;
|
||||
#ifdef __APPLE__
|
||||
config->use_system_logger = 0;
|
||||
#endif
|
||||
#ifdef Py_GIL_DISABLED
|
||||
config->enable_gil = _PyConfig_GIL_DEFAULT;
|
||||
#endif
|
||||
|
@ -874,6 +884,9 @@ config_init_defaults(PyConfig *config)
|
|||
#ifdef MS_WINDOWS
|
||||
config->legacy_windows_stdio = 0;
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
config->use_system_logger = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -909,6 +922,9 @@ PyConfig_InitIsolatedConfig(PyConfig *config)
|
|||
#ifdef MS_WINDOWS
|
||||
config->legacy_windows_stdio = 0;
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
config->use_system_logger = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -43,7 +43,9 @@
|
|||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# include <AvailabilityMacros.h>
|
||||
# include <mach-o/loader.h>
|
||||
# include <os/log.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
|
@ -73,6 +75,9 @@ static PyStatus init_sys_streams(PyThreadState *tstate);
|
|||
#ifdef __ANDROID__
|
||||
static PyStatus init_android_streams(PyThreadState *tstate);
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
static PyStatus init_apple_streams(PyThreadState *tstate);
|
||||
#endif
|
||||
static void wait_for_thread_shutdown(PyThreadState *tstate);
|
||||
static void finalize_subinterpreters(void);
|
||||
static void call_ll_exitfuncs(_PyRuntimeState *runtime);
|
||||
|
@ -1253,6 +1258,14 @@ init_interp_main(PyThreadState *tstate)
|
|||
return status;
|
||||
}
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
if (config->use_system_logger) {
|
||||
status = init_apple_streams(tstate);
|
||||
if (_PyStatus_EXCEPTION(status)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Py_DEBUG
|
||||
run_presite(tstate);
|
||||
|
@ -2920,6 +2933,75 @@ done:
|
|||
|
||||
#endif // __ANDROID__
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
static PyObject *
|
||||
apple_log_write_impl(PyObject *self, PyObject *args)
|
||||
{
|
||||
int logtype = 0;
|
||||
const char *text = NULL;
|
||||
if (!PyArg_ParseTuple(args, "iy", &logtype, &text)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Call the underlying Apple logging API. The os_log unified logging APIs
|
||||
// were introduced in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0;
|
||||
// this call is a no-op on older versions.
|
||||
#if TARGET_OS_IPHONE || (TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12)
|
||||
// Pass the user-provided text through explicit %s formatting
|
||||
// to avoid % literals being interpreted as a formatting directive.
|
||||
os_log_with_type(OS_LOG_DEFAULT, logtype, "%s", text);
|
||||
#endif
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef apple_log_write_method = {
|
||||
"apple_log_write", apple_log_write_impl, METH_VARARGS
|
||||
};
|
||||
|
||||
|
||||
static PyStatus
|
||||
init_apple_streams(PyThreadState *tstate)
|
||||
{
|
||||
PyStatus status = _PyStatus_OK();
|
||||
PyObject *_apple_support = NULL;
|
||||
PyObject *apple_log_write = NULL;
|
||||
PyObject *result = NULL;
|
||||
|
||||
_apple_support = PyImport_ImportModule("_apple_support");
|
||||
if (_apple_support == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
apple_log_write = PyCFunction_New(&apple_log_write_method, NULL);
|
||||
if (apple_log_write == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Initialize the logging streams, sending stdout -> Default; stderr -> Error
|
||||
result = PyObject_CallMethod(
|
||||
_apple_support, "init_streams", "Oii",
|
||||
apple_log_write, OS_LOG_TYPE_DEFAULT, OS_LOG_TYPE_ERROR);
|
||||
if (result == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
error:
|
||||
_PyErr_Print(tstate);
|
||||
status = _PyStatus_ERR("failed to initialize Apple log streams");
|
||||
|
||||
done:
|
||||
Py_XDECREF(result);
|
||||
Py_XDECREF(apple_log_write);
|
||||
Py_XDECREF(_apple_support);
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
|
||||
static void
|
||||
_Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp,
|
||||
|
|
1
Python/stdlib_module_names.h
generated
1
Python/stdlib_module_names.h
generated
|
@ -6,6 +6,7 @@ static const char* _Py_stdlib_module_names[] = {
|
|||
"_abc",
|
||||
"_aix_support",
|
||||
"_android_support",
|
||||
"_apple_support",
|
||||
"_ast",
|
||||
"_asyncio",
|
||||
"_bisect",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue