diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index b447e4253a85618..d1b23dfc52b2b99 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -418,6 +418,29 @@ always available. Unless explicitly noted otherwise, all variables are read-only .. versionadded:: 3.11 +.. data:: _wasi_info + + An object containing information about the build on the WebAssembly WASI + platform. The object is provisional and may change in the future. + + .. attribute:: _wasi_info.wasi_version + + The WASI target version as a string: ``'p1'``, ``'p2'``, or ``'p3'``. + + .. attribute:: _wasi_info.wasi_sdk_version + + The full WASI SDK version as a string, such as ``'34.0'``. + + .. attribute:: _wasi_info.cooperative_threads + + ``True`` if wasi-libc was compiled with cooperative multithreading + support, ``False`` otherwise. + + .. availability:: WASI. + + .. versionadded:: next + + .. data:: pycache_prefix If this is set (not ``None``), Python will write bytecode-cache ``.pyc`` diff --git a/Include/internal/mimalloc/mimalloc/internal.h b/Include/internal/mimalloc/mimalloc/internal.h index a7daa3a40a4c0bc..423693f33e1a65a 100644 --- a/Include/internal/mimalloc/mimalloc/internal.h +++ b/Include/internal/mimalloc/mimalloc/internal.h @@ -23,10 +23,6 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_trace_message(...) #endif -#if defined(__EMSCRIPTEN__) && !defined(__wasi__) -#define __wasi__ -#endif - #if defined(__cplusplus) #define mi_decl_externc extern "C" #else @@ -34,7 +30,7 @@ terms of the MIT license. A copy of the license can be found in the file #endif // pthreads -#if !defined(_WIN32) && !defined(__wasi__) +#if !defined(_WIN32) && !defined(__wasm__) #define MI_USE_PTHREADS #include #endif diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index c74ca05ca66c9ce..af99437821d2c36 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -824,6 +824,16 @@ def test_emscripten_info(self): self.assertIsInstance(sys._emscripten_info.pthreads, bool) self.assertIsInstance(sys._emscripten_info.shared_memory, bool) + @unittest.skipUnless(support.is_wasi, "only available on WASI") + def test_wasi_info(self): + info = sys._wasi_info + self.assertIn(info.wasi_version, {'p1', 'p2', 'p3'}) + self.assertIn('.', info.wasi_sdk_version) + sdk_major, _, sdk_minor = info.wasi_sdk_version.partition('.') + self.assertGreaterEqual(int(sdk_major), 1) + self.assertGreaterEqual(int(sdk_minor), 0) + self.assertIsInstance(info.cooperative_threads, bool) + def test_43581(self): # Can't use sys.stdout, as this is a StringIO object when # the test runs under regrtest. diff --git a/Misc/NEWS.d/next/Library/2026-10-08-11-58-52.gh-issue-158628.NJxwuw.rst b/Misc/NEWS.d/next/Library/2026-10-08-11-58-52.gh-issue-158628.NJxwuw.rst new file mode 100644 index 000000000000000..eb1e0f1d3271f8a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-08-11-58-52.gh-issue-158628.NJxwuw.rst @@ -0,0 +1 @@ +Implement :data:`sys._wasi_info` for exposing WASI-specific system details. diff --git a/Platforms/WASI/README.md b/Platforms/WASI/README.md index a62efbda5366544..e56645b4db24c1c 100644 --- a/Platforms/WASI/README.md +++ b/Platforms/WASI/README.md @@ -279,10 +279,16 @@ posix.uname_result( ### C code -WASI SDK defines several built-in macros. You can dump a full list of built-ins -with ``/path/to/wasi-sdk/bin/clang -dM -E - < /dev/null``. +The following built-in macros identify WebAssembly targets and environments. +For WASI SDK, you can dump a full list of built-ins with +`/path/to/wasi-sdk/bin/clang -dM -E - < /dev/null`. -* WebAssembly ``__wasm__`` (also ``__wasm``) -* wasm32 ``__wasm32__`` (also ``__wasm32``) -* wasm64 ``__wasm64__`` -* WASI ``__wasi__`` +#### Shared with Emscripten + +- WebAssembly target: `__wasm__` (also `__wasm`) +- wasm32 target: `__wasm32__` (also `__wasm32`) +- wasm64 target: `__wasm64__` + +#### Unique to WASI + +- WASI environment: `__wasi__` diff --git a/Python/marshal.c b/Python/marshal.c index 6aa99bb4693117a..977bd80c337976b 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -44,7 +44,7 @@ module marshal */ #if defined(MS_WINDOWS) # define MAX_MARSHAL_STACK_DEPTH 1000 -#elif defined(__wasi__) +#elif defined(__wasm__) # define MAX_MARSHAL_STACK_DEPTH 1500 // TARGET_OS_IPHONE covers any non-macOS Apple platform. // It won't be defined on older macOS SDKs diff --git a/Python/sysmodule.c b/Python/sysmodule.c index afc90d9bf5d7dd6..a284c8322eac701 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -64,6 +64,10 @@ extern const char *PyWin_DLLVersionString; # include #endif +#ifdef __wasi__ +# include +#endif + #ifdef HAVE_FCNTL_H # include #endif @@ -3837,6 +3841,49 @@ make_abi_info(void) } +#ifdef __wasi__ + +static PyObject * +make_wasi_info(void) +{ +#if defined(__wasip1__) + const char *wasi_version = "p1"; +#elif defined(__wasip2__) + const char *wasi_version = "p2"; +#elif defined(__wasip3__) + const char *wasi_version = "p3"; +#else +# error "Unknown WASI target version" +#endif + + // The SDK version is only defined for SDK builds of wasi-libc. +#ifdef __wasi_sdk_version__ + const char *wasi_sdk_version = __wasi_sdk_version__; +#else +# error "Unknown WASI SDK version" +#endif + +#ifdef __wasi_cooperative_threads__ + PyObject *cooperative_threads = Py_True; +#else + PyObject *cooperative_threads = Py_False; +#endif + + PyObject *wasi_info = Py_BuildValue( + "{s:s,s:s,s:O}", + "wasi_version", wasi_version, + "wasi_sdk_version", wasi_sdk_version, + "cooperative_threads", cooperative_threads); + if (wasi_info == NULL) { + return NULL; + } + PyObject *ns = _PyNamespace_New(wasi_info); + Py_DECREF(wasi_info); + return ns; +} + +#endif // __wasi__ + #ifdef __EMSCRIPTEN__ PyDoc_STRVAR(emscripten_info__doc__, @@ -4084,6 +4131,10 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) SET_SYS("abi_info", make_abi_info()); +#ifdef __wasi__ + SET_SYS("_wasi_info", make_wasi_info()); +#endif + /* initialize asyncgen_hooks */ if (_PyStructSequence_InitBuiltin(interp, &AsyncGenHooksType, &asyncgen_hooks_desc) < 0)