summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-01-21 15:13:09 (GMT)
committerGitHub <noreply@github.com>2020-01-21 15:13:09 (GMT)
commit56cd3710a1ea3ba872d345ea1bebc86ed08bc8b8 (patch)
tree53e622226ec54c95227e9c36011b7326fb918899
parent59e2d26b258c12f18d8d2e789ef741703d6c52d5 (diff)
downloadcpython-56cd3710a1ea3ba872d345ea1bebc86ed08bc8b8.zip
cpython-56cd3710a1ea3ba872d345ea1bebc86ed08bc8b8.tar.gz
cpython-56cd3710a1ea3ba872d345ea1bebc86ed08bc8b8.tar.bz2
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).
-rw-r--r--Doc/library/os.rst3
-rw-r--r--Doc/whatsnew/3.9.rst3
-rw-r--r--Lib/test/test_os.py11
-rw-r--r--Misc/NEWS.d/next/Library/2020-01-21-15-48-35.bpo-39413.7XYDM8.rst1
-rw-r--r--Modules/clinic/posixmodule.c.h42
-rw-r--r--Modules/posixmodule.c44
6 files changed, 92 insertions, 12 deletions
diff --git a/Doc/library/os.rst b/Doc/library/os.rst
index 4fec647..de3e560 100644
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -645,6 +645,9 @@ process and user.
.. availability:: most flavors of Unix, Windows.
+ .. versionchanged:: 3.9
+ The function is now also available on Windows.
+
.. _os-newstreams:
diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst
index f40685c..ab27c48 100644
--- a/Doc/whatsnew/3.9.rst
+++ b/Doc/whatsnew/3.9.rst
@@ -216,6 +216,9 @@ Exposed the Linux-specific :func:`os.pidfd_open` (:issue:`38692`) and
:data:`os.P_PIDFD` (:issue:`38713`) for process management with file
descriptors.
+The :func:`os.unsetenv` function is now also available on Windows.
+(Contributed by Victor Stinner in :issue:`39413`.)
+
poplib
------
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 82c441c..50535da 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -956,14 +956,9 @@ class EnvironTests(mapping_tests.BasicTestMappingProtocol):
# On OS X < 10.6, unsetenv() doesn't return a value (bpo-13415).
@support.requires_mac_ver(10, 6)
def test_unset_error(self):
- if sys.platform == "win32":
- # an environment variable is limited to 32,767 characters
- key = 'x' * 50000
- self.assertRaises(ValueError, os.environ.__delitem__, key)
- else:
- # "=" is not allowed in a variable name
- key = 'key='
- self.assertRaises(OSError, os.environ.__delitem__, key)
+ # "=" is not allowed in a variable name
+ key = 'key='
+ self.assertRaises(OSError, os.environ.__delitem__, key)
def test_key_type(self):
missing = 'missingkey'
diff --git a/Misc/NEWS.d/next/Library/2020-01-21-15-48-35.bpo-39413.7XYDM8.rst b/Misc/NEWS.d/next/Library/2020-01-21-15-48-35.bpo-39413.7XYDM8.rst
new file mode 100644
index 0000000..a185ab5
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-01-21-15-48-35.bpo-39413.7XYDM8.rst
@@ -0,0 +1 @@
+The :func:`os.unsetenv` function is now also available on Windows.
diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h
index aa4756a..661d91a 100644
--- a/Modules/clinic/posixmodule.c.h
+++ b/Modules/clinic/posixmodule.c.h
@@ -6125,7 +6125,43 @@ exit:
#endif /* defined(HAVE_PUTENV) && !defined(MS_WINDOWS) */
-#if defined(HAVE_UNSETENV)
+#if defined(MS_WINDOWS)
+
+PyDoc_STRVAR(os_unsetenv__doc__,
+"unsetenv($module, name, /)\n"
+"--\n"
+"\n"
+"Delete an environment variable.");
+
+#define OS_UNSETENV_METHODDEF \
+ {"unsetenv", (PyCFunction)os_unsetenv, METH_O, os_unsetenv__doc__},
+
+static PyObject *
+os_unsetenv_impl(PyObject *module, PyObject *name);
+
+static PyObject *
+os_unsetenv(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ PyObject *name;
+
+ if (!PyUnicode_Check(arg)) {
+ _PyArg_BadArgument("unsetenv", "argument", "str", arg);
+ goto exit;
+ }
+ if (PyUnicode_READY(arg) == -1) {
+ goto exit;
+ }
+ name = arg;
+ return_value = os_unsetenv_impl(module, name);
+
+exit:
+ return return_value;
+}
+
+#endif /* defined(MS_WINDOWS) */
+
+#if (defined(HAVE_UNSETENV) && !defined(MS_WINDOWS))
PyDoc_STRVAR(os_unsetenv__doc__,
"unsetenv($module, name, /)\n"
@@ -6157,7 +6193,7 @@ exit:
return return_value;
}
-#endif /* defined(HAVE_UNSETENV) */
+#endif /* (defined(HAVE_UNSETENV) && !defined(MS_WINDOWS)) */
PyDoc_STRVAR(os_strerror__doc__,
"strerror($module, code, /)\n"
@@ -8773,4 +8809,4 @@ exit:
#ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF
#define OS__REMOVE_DLL_DIRECTORY_METHODDEF
#endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */
-/*[clinic end generated code: output=51ba5b9536420cea input=a9049054013a1b77]*/
+/*[clinic end generated code: output=6e739a2715712e88 input=a9049054013a1b77]*/
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 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
#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