https://github.com/python/cpython/commit/35e9d41a9cc3999672ba7440847b16ec71bd9ddd
commit: 35e9d41a9cc3999672ba7440847b16ec71bd9ddd
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2025-10-11T22:58:43+02:00
summary:
gh-139482: Add `posix._clearenv()` function (#139965)
files:
A Misc/NEWS.d/next/Library/2025-10-11-20-03-13.gh-issue-139482.du2Stg.rst
M Lib/os.py
M Lib/test/test_os/test_os.py
M Modules/clinic/posixmodule.c.h
M Modules/posixmodule.c
M configure
M configure.ac
M pyconfig.h.in
diff --git a/Lib/os.py b/Lib/os.py
index 710d6f8cfcdf74..328d13c303b580 100644
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -58,6 +58,11 @@ def _get_exports_list(module):
__all__.append('_exit')
except ImportError:
pass
+ try:
+ from posix import _clearenv
+ __all__.append('_clearenv')
+ except ImportError:
+ pass
import posixpath as path
try:
@@ -768,6 +773,12 @@ def __ror__(self, other):
new.update(self)
return new
+ if _exists("_clearenv"):
+ def clear(self):
+ _clearenv()
+ self._data.clear()
+
+
def _create_environ_mapping():
if name == 'nt':
# Where Env Var Names Must Be UPPERCASE
diff --git a/Lib/test/test_os/test_os.py b/Lib/test/test_os/test_os.py
index e074858fe2ad99..86880a6d281315 100644
--- a/Lib/test/test_os/test_os.py
+++ b/Lib/test/test_os/test_os.py
@@ -1494,6 +1494,14 @@ def test_reload_environ(self):
self.assertNotIn(b'test_env', os.environb)
self.assertNotIn('test_env', os.environ)
+ def test_clearenv(self):
+ os.environ['REMOVEME'] = '1'
+ os.environ.clear()
+ self.assertEqual(os.environ, {})
+
+ self.assertRaises(TypeError, os.environ.clear, None)
+
+
class WalkTests(unittest.TestCase):
"""Tests for os.walk()."""
is_fwalk = False
diff --git
a/Misc/NEWS.d/next/Library/2025-10-11-20-03-13.gh-issue-139482.du2Stg.rst
b/Misc/NEWS.d/next/Library/2025-10-11-20-03-13.gh-issue-139482.du2Stg.rst
new file mode 100644
index 00000000000000..4edd3d238bf2d9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-10-11-20-03-13.gh-issue-139482.du2Stg.rst
@@ -0,0 +1,3 @@
+Optimize :data:`os.environ.clear() <os.environ>` by calling
+:manpage:`clearenv(3)` when this function is available.
+Patch by Victor Stinner.
diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h
index 3d9863ad179d3c..71f87ac8ec7cf4 100644
--- a/Modules/clinic/posixmodule.c.h
+++ b/Modules/clinic/posixmodule.c.h
@@ -9539,6 +9539,27 @@ os_unsetenv(PyObject *module, PyObject *arg)
#endif /* !defined(MS_WINDOWS) */
+#if defined(HAVE_CLEARENV)
+
+PyDoc_STRVAR(os__clearenv__doc__,
+"_clearenv($module, /)\n"
+"--\n"
+"\n");
+
+#define OS__CLEARENV_METHODDEF \
+ {"_clearenv", (PyCFunction)os__clearenv, METH_NOARGS, os__clearenv__doc__},
+
+static PyObject *
+os__clearenv_impl(PyObject *module);
+
+static PyObject *
+os__clearenv(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return os__clearenv_impl(module);
+}
+
+#endif /* defined(HAVE_CLEARENV) */
+
PyDoc_STRVAR(os_strerror__doc__,
"strerror($module, code, /)\n"
"--\n"
@@ -13292,6 +13313,10 @@ os__emscripten_log(PyObject *module, PyObject *const
*args, Py_ssize_t nargs, Py
#define OS_UNSETENV_METHODDEF
#endif /* !defined(OS_UNSETENV_METHODDEF) */
+#ifndef OS__CLEARENV_METHODDEF
+ #define OS__CLEARENV_METHODDEF
+#endif /* !defined(OS__CLEARENV_METHODDEF) */
+
#ifndef OS_WCOREDUMP_METHODDEF
#define OS_WCOREDUMP_METHODDEF
#endif /* !defined(OS_WCOREDUMP_METHODDEF) */
@@ -13447,4 +13472,4 @@ os__emscripten_log(PyObject *module, PyObject *const
*args, Py_ssize_t nargs, Py
#ifndef OS__EMSCRIPTEN_LOG_METHODDEF
#define OS__EMSCRIPTEN_LOG_METHODDEF
#endif /* !defined(OS__EMSCRIPTEN_LOG_METHODDEF) */
-/*[clinic end generated code: output=47ace1528820858b input=a9049054013a1b77]*/
+/*[clinic end generated code: output=67f0df7cd5a7de20 input=a9049054013a1b77]*/
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 8278902cbeb349..38ddc3ec4ffc3d 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -13201,6 +13201,25 @@ os_unsetenv_impl(PyObject *module, PyObject *name)
#endif /* !MS_WINDOWS */
+#ifdef HAVE_CLEARENV
+/*[clinic input]
+os._clearenv
+[clinic start generated code]*/
+
+static PyObject *
+os__clearenv_impl(PyObject *module)
+/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
+{
+ errno = 0;
+ int err = clearenv();
+ if (err) {
+ return posix_error();
+ }
+ Py_RETURN_NONE;
+}
+#endif
+
+
/*[clinic input]
os.strerror
@@ -17167,6 +17186,7 @@ static PyMethodDef posix_methods[] = {
OS_POSIX_FADVISE_METHODDEF
OS_PUTENV_METHODDEF
OS_UNSETENV_METHODDEF
+ OS__CLEARENV_METHODDEF
OS_STRERROR_METHODDEF
OS_FCHDIR_METHODDEF
OS_FSYNC_METHODDEF
diff --git a/configure b/configure
index d80340e3015bee..211f84399064a0 100755
--- a/configure
+++ b/configure
@@ -19225,6 +19225,12 @@ if test "x$ac_cv_func_chown" = xyes
then :
printf "%s\n" "#define HAVE_CHOWN 1" >>confdefs.h
+fi
+ac_fn_c_check_func "$LINENO" "clearenv" "ac_cv_func_clearenv"
+if test "x$ac_cv_func_clearenv" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLEARENV 1" >>confdefs.h
+
fi
ac_fn_c_check_func "$LINENO" "clock" "ac_cv_func_clock"
if test "x$ac_cv_func_clock" = xyes
diff --git a/configure.ac b/configure.ac
index 1e0c0f71b7c281..35bf153a8987b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5226,7 +5226,8 @@ fi
# checks for library functions
AC_CHECK_FUNCS([ \
- accept4 alarm bind_textdomain_codeset chmod chown clock closefrom
close_range confstr \
+ accept4 alarm bind_textdomain_codeset chmod chown clearenv \
+ clock closefrom close_range confstr \
copy_file_range ctermid dladdr dup dup3 execv explicit_bzero explicit_memset
\
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
@@ -8173,7 +8174,7 @@ PY_STDLIB_MOD([xxlimited_35], [test "$TEST_MODULES" =
yes], [test "$ac_cv_func_d
# Determine JIT stencils header files based on target platform
JIT_STENCILS_H=""
-AS_VAR_IF([enable_experimental_jit], [no],
+AS_VAR_IF([enable_experimental_jit], [no],
[],
[case "$host" in
aarch64-apple-darwin*)
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 60bff4a9f26356..72870411bc086a 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -141,6 +141,9 @@
/* Define if you have the 'chroot' function. */
#undef HAVE_CHROOT
+/* Define to 1 if you have the 'clearenv' function. */
+#undef HAVE_CLEARENV
+
/* Define to 1 if you have the 'clock' function. */
#undef HAVE_CLOCK
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]