[Python-checkins] bpo-39406: Implement os.putenv() with setenv() if available (GH-18128)

Victor Stinner webhook-mailer at python.org
Wed Jan 22 16:48:20 EST 2020


https://github.com/python/cpython/commit/b477d19a6b7751b0c933b239dae4fc96dbcde9c4
commit: b477d19a6b7751b0c933b239dae4fc96dbcde9c4
branch: master
author: Victor Stinner <vstinner at python.org>
committer: GitHub <noreply at github.com>
date: 2020-01-22T22:48:16+01:00
summary:

bpo-39406: Implement os.putenv() with setenv() if available (GH-18128)

If setenv() C function is available, os.putenv() is now implemented
with setenv() instead of putenv(), so Python doesn't have to handle
the environment variable memory.

files:
A Misc/NEWS.d/next/Library/2020-01-22-21-18-58.bpo-39406.HMpe8x.rst
M Modules/clinic/posixmodule.c.h
M Modules/posixmodule.c
M configure
M configure.ac
M pyconfig.h.in

diff --git a/Misc/NEWS.d/next/Library/2020-01-22-21-18-58.bpo-39406.HMpe8x.rst b/Misc/NEWS.d/next/Library/2020-01-22-21-18-58.bpo-39406.HMpe8x.rst
new file mode 100644
index 0000000000000..56a5316043238
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-01-22-21-18-58.bpo-39406.HMpe8x.rst
@@ -0,0 +1,3 @@
+If ``setenv()`` C function is available, :func:`os.putenv` is now
+implemented with ``setenv()`` instead of ``putenv()``, so Python doesn't
+have to handle the environment variable memory.
diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h
index aa4756a620aae..13a69cd5f0e4d 100644
--- a/Modules/clinic/posixmodule.c.h
+++ b/Modules/clinic/posixmodule.c.h
@@ -6034,7 +6034,7 @@ os_posix_fadvise(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 
 #endif /* (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) */
 
-#if defined(HAVE_PUTENV) && defined(MS_WINDOWS)
+#if defined(MS_WINDOWS)
 
 PyDoc_STRVAR(os_putenv__doc__,
 "putenv($module, name, value, /)\n"
@@ -6080,9 +6080,9 @@ os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     return return_value;
 }
 
-#endif /* defined(HAVE_PUTENV) && defined(MS_WINDOWS) */
+#endif /* defined(MS_WINDOWS) */
 
-#if defined(HAVE_PUTENV) && !defined(MS_WINDOWS)
+#if ((defined(HAVE_SETENV) || defined(HAVE_PUTENV)) && !defined(MS_WINDOWS))
 
 PyDoc_STRVAR(os_putenv__doc__,
 "putenv($module, name, value, /)\n"
@@ -6123,7 +6123,7 @@ os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     return return_value;
 }
 
-#endif /* defined(HAVE_PUTENV) && !defined(MS_WINDOWS) */
+#endif /* ((defined(HAVE_SETENV) || defined(HAVE_PUTENV)) && !defined(MS_WINDOWS)) */
 
 #if defined(HAVE_UNSETENV)
 
@@ -8773,4 +8773,4 @@ os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nar
 #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=6f42d8be634f5942 input=a9049054013a1b77]*/
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 71b99fd836f15..6a687529df0c0 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -819,19 +819,20 @@ dir_fd_converter(PyObject *o, void *p)
     }
 }
 
-/* Windows: _wputenv(env) copies the *env* string and doesn't require the
-   caller to manage the variable memory. */
-#if defined(HAVE_PUTENV) && !defined(MS_WINDOWS)
+/* Windows _wputenv() and setenv() copy the arguments and so don't require
+   the caller to manage the variable memory. Only Unix putenv() requires
+   putenv_dict. */
+#if defined(HAVE_PUTENV) && !defined(MS_WINDOWS) && !defined(HAVE_SETENV)
 #  define PY_PUTENV_DICT
 #endif
 
 typedef struct {
     PyObject *billion;
 #ifdef PY_PUTENV_DICT
-    /* putenv() and _wputenv() requires that the caller manages the environment
-       variable memory. Use a Python dictionary for that: name => env, where
-       env is a string like "name=value". On Windows, dict keys and values are
-       Unicode strings. On Unix, they are bytes strings. */
+    /* putenv() requires that the caller manages the environment variable
+       memory. Use a Python dictionary for that: name => env, where env is a
+       string like "name=value". On Windows, dict keys and values are Unicode
+       strings. On Unix, they are bytes strings. */
     PyObject *putenv_dict;
 #endif
     PyObject *DirEntryType;
@@ -10081,8 +10082,6 @@ posix_putenv_dict_setitem(PyObject *name, PyObject *value)
 #endif  /* PY_PUTENV_DICT */
 
 
-#ifdef HAVE_PUTENV
-
 #ifdef MS_WINDOWS
 /*[clinic input]
 os.putenv
@@ -10132,8 +10131,6 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
         posix_error();
         goto error;
     }
-    /* _wputenv(env) copies the *env* string and doesn't require the caller
-       to manage the variable memory. */
     Py_DECREF(unicode);
 
     Py_RETURN_NONE;
@@ -10142,7 +10139,8 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
     Py_DECREF(unicode);
     return NULL;
 }
-#else /* MS_WINDOWS */
+/* repeat !defined(MS_WINDOWS) to workaround an Argument Clinic issue */
+#elif (defined(HAVE_SETENV) || defined(HAVE_PUTENV)) && !defined(MS_WINDOWS)
 /*[clinic input]
 os.putenv
 
@@ -10157,8 +10155,6 @@ static PyObject *
 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
 {
-    PyObject *bytes = NULL;
-    char *env;
     const char *name_string = PyBytes_AS_STRING(name);
     const char *value_string = PyBytes_AS_STRING(value);
 
@@ -10166,22 +10162,28 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
         return NULL;
     }
-    bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
+
+#ifdef HAVE_SETENV
+    if (setenv(name_string, value_string, 1)) {
+        return posix_error();
+    }
+#else
+    PyObject *bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
     if (bytes == NULL) {
         return NULL;
     }
 
-    env = PyBytes_AS_STRING(bytes);
+    char *env = PyBytes_AS_STRING(bytes);
     if (putenv(env)) {
         Py_DECREF(bytes);
         return posix_error();
     }
 
     posix_putenv_dict_setitem(name, bytes);
+#endif
     Py_RETURN_NONE;
 }
-#endif /* MS_WINDOWS */
-#endif /* HAVE_PUTENV */
+#endif  /* defined(HAVE_SETENV) || defined(HAVE_PUTENV) */
 
 
 #ifdef HAVE_UNSETENV
diff --git a/configure b/configure
index c8253b1455f65..e96683622b304 100755
--- a/configure
+++ b/configure
@@ -782,7 +782,6 @@ infodir
 docdir
 oldincludedir
 includedir
-runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -896,7 +895,6 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
-runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1149,15 +1147,6 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
-  -runstatedir | --runstatedir | --runstatedi | --runstated \
-  | --runstate | --runstat | --runsta | --runst | --runs \
-  | --run | --ru | --r)
-    ac_prev=runstatedir ;;
-  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
-  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
-  | --run=* | --ru=* | --r=*)
-    runstatedir=$ac_optarg ;;
-
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1295,7 +1284,7 @@ fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir runstatedir
+		libdir localedir mandir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1448,7 +1437,6 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
-  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -10303,6 +10291,7 @@ fi
 
 
 
+
 if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
 	if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
@@ -11561,7 +11550,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
  posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
  pthread_condattr_setclock pthread_init pthread_kill putenv pwrite pwritev pwritev2 \
  readlink readlinkat readv realpath renameat \
- sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \
+ sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid setenv seteuid \
  setgid sethostname \
  setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \
  sched_get_priority_max sched_setaffinity sched_setscheduler sched_setparam \
diff --git a/configure.ac b/configure.ac
index bcef99c496225..36c165b2f2e42 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3600,7 +3600,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
  posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
  pthread_condattr_setclock pthread_init pthread_kill putenv pwrite pwritev pwritev2 \
  readlink readlinkat readv realpath renameat \
- sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \
+ sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid setenv seteuid \
  setgid sethostname \
  setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \
  sched_get_priority_max sched_setaffinity sched_setscheduler sched_setparam \
diff --git a/pyconfig.h.in b/pyconfig.h.in
index e053be15a1180..1918fab8bdbe7 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -895,6 +895,9 @@
 /* Define to 1 if you have the `setegid' function. */
 #undef HAVE_SETEGID
 
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
 /* Define to 1 if you have the `seteuid' function. */
 #undef HAVE_SETEUID
 



More information about the Python-checkins mailing list