Skip to content

Commit 56cd371

Browse files
authored
bpo-39413: Implement os.unsetenv() on Windows (GH-18104)
The os.unsetenv() function is now also available on Windows. It is implemented with SetEnvironmentVariableW(name, NULL).
1 parent 59e2d26 commit 56cd371

File tree

6 files changed

+92
-12
lines changed

6 files changed

+92
-12
lines changed

Doc/library/os.rst

+3
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,9 @@ process and user.
645645

646646
.. availability:: most flavors of Unix, Windows.
647647

648+
.. versionchanged:: 3.9
649+
The function is now also available on Windows.
650+
648651

649652
.. _os-newstreams:
650653

Doc/whatsnew/3.9.rst

+3
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ Exposed the Linux-specific :func:`os.pidfd_open` (:issue:`38692`) and
216216
:data:`os.P_PIDFD` (:issue:`38713`) for process management with file
217217
descriptors.
218218

219+
The :func:`os.unsetenv` function is now also available on Windows.
220+
(Contributed by Victor Stinner in :issue:`39413`.)
221+
219222
poplib
220223
------
221224

Lib/test/test_os.py

+3-8
Original file line numberDiff line numberDiff line change
@@ -956,14 +956,9 @@ def test_environb(self):
956956
# On OS X < 10.6, unsetenv() doesn't return a value (bpo-13415).
957957
@support.requires_mac_ver(10, 6)
958958
def test_unset_error(self):
959-
if sys.platform == "win32":
960-
# an environment variable is limited to 32,767 characters
961-
key = 'x' * 50000
962-
self.assertRaises(ValueError, os.environ.__delitem__, key)
963-
else:
964-
# "=" is not allowed in a variable name
965-
key = 'key='
966-
self.assertRaises(OSError, os.environ.__delitem__, key)
959+
# "=" is not allowed in a variable name
960+
key = 'key='
961+
self.assertRaises(OSError, os.environ.__delitem__, key)
967962

968963
def test_key_type(self):
969964
missing = 'missingkey'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The :func:`os.unsetenv` function is now also available on Windows.

Modules/clinic/posixmodule.c.h

+39-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/posixmodule.c

+43-1
Original file line numberDiff line numberDiff line change
@@ -10163,7 +10163,49 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
1016310163
#endif /* HAVE_PUTENV */
1016410164

1016510165

10166-
#ifdef HAVE_UNSETENV
10166+
#ifdef MS_WINDOWS
10167+
/*[clinic input]
10168+
os.unsetenv
10169+
name: unicode
10170+
/
10171+
10172+
Delete an environment variable.
10173+
[clinic start generated code]*/
10174+
10175+
static PyObject *
10176+
os_unsetenv_impl(PyObject *module, PyObject *name)
10177+
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
10178+
{
10179+
/* PyUnicode_AsWideCharString() rejects embedded null characters */
10180+
wchar_t *name_str = PyUnicode_AsWideCharString(name, NULL);
10181+
if (name_str == NULL) {
10182+
return NULL;
10183+
}
10184+
10185+
BOOL ok = SetEnvironmentVariableW(name_str, NULL);
10186+
PyMem_Free(name_str);
10187+
10188+
if (!ok) {
10189+
return PyErr_SetFromWindowsErr(0);
10190+
}
10191+
10192+
/* Remove the key from posix_putenv_garbage;
10193+
* this will cause it to be collected. This has to
10194+
* happen after the real unsetenv() call because the
10195+
* old value was still accessible until then.
10196+
*/
10197+
if (PyDict_DelItem(_posixstate(module)->posix_putenv_garbage, name)) {
10198+
/* really not much we can do; just leak */
10199+
if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
10200+
return NULL;
10201+
}
10202+
PyErr_Clear();
10203+
}
10204+
10205+
Py_RETURN_NONE;
10206+
}
10207+
/* repeat !defined(MS_WINDOWS) to workaround an Argument Clinic issue */
10208+
#elif defined(HAVE_UNSETENV) && !defined(MS_WINDOWS)
1016710209
/*[clinic input]
1016810210
os.unsetenv
1016910211
name: FSConverter

0 commit comments

Comments
 (0)