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).
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 322c215..d2047d9 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -10163,7 +10163,49 @@
#endif /* HAVE_PUTENV */
-#ifdef HAVE_UNSETENV
+#ifdef MS_WINDOWS
+/*[clinic input]
+os.unsetenv
+ name: unicode
+ /
+
+Delete an environment variable.
+[clinic start generated code]*/
+
+static PyObject *
+os_unsetenv_impl(PyObject *module, PyObject *name)
+/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
+{
+ /* PyUnicode_AsWideCharString() rejects embedded null characters */
+ wchar_t *name_str = PyUnicode_AsWideCharString(name, NULL);
+ if (name_str == NULL) {
+ return NULL;
+ }
+
+ BOOL ok = SetEnvironmentVariableW(name_str, NULL);
+ PyMem_Free(name_str);
+
+ if (!ok) {
+ return PyErr_SetFromWindowsErr(0);
+ }
+
+ /* Remove the key from posix_putenv_garbage;
+ * this will cause it to be collected. This has to
+ * happen after the real unsetenv() call because the
+ * old value was still accessible until then.
+ */
+ if (PyDict_DelItem(_posixstate(module)->posix_putenv_garbage, name)) {
+ /* really not much we can do; just leak */
+ if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
+ return NULL;
+ }
+ PyErr_Clear();
+ }
+
+ Py_RETURN_NONE;
+}
+/* repeat !defined(MS_WINDOWS) to workaround an Argument Clinic issue */
+#elif defined(HAVE_UNSETENV) && !defined(MS_WINDOWS)
/*[clinic input]
os.unsetenv
name: FSConverter