Skip to content

Commit b8d1262

Browse files
authored
bpo-39395: putenv() and unsetenv() always available (GH-18135)
The os.putenv() and os.unsetenv() functions are now always available. On non-Windows platforms, Python now requires setenv() and unsetenv() functions to build. Remove putenv_dict from posixmodule.c: it's not longer needed.
1 parent 161e7b3 commit b8d1262

File tree

12 files changed

+52
-154
lines changed

12 files changed

+52
-154
lines changed

Doc/library/os.rst

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ process and user.
111111
to the environment made after this time are not reflected in ``os.environ``,
112112
except for changes made by modifying ``os.environ`` directly.
113113

114-
If the platform supports the :func:`putenv` function, this mapping may be used
115-
to modify the environment as well as query the environment. :func:`putenv` will
116-
be called automatically when the mapping is modified.
114+
This mapping may be used to modify the environment as well as query the
115+
environment. :func:`putenv` will be called automatically when the mapping
116+
is modified.
117117

118118
On Unix, keys and values use :func:`sys.getfilesystemencoding` and
119119
``'surrogateescape'`` error handler. Use :data:`environb` if you would like
@@ -130,14 +130,10 @@ process and user.
130130
cause memory leaks. Refer to the system documentation for
131131
:c:func:`putenv`.
132132

133-
If :func:`putenv` is not provided, a modified copy of this mapping may be
134-
passed to the appropriate process-creation functions to cause child processes
135-
to use a modified environment.
136-
137-
If the platform supports the :func:`unsetenv` function, you can delete items in
138-
this mapping to unset environment variables. :func:`unsetenv` will be called
139-
automatically when an item is deleted from ``os.environ``, and when
140-
one of the :meth:`pop` or :meth:`clear` methods is called.
133+
You can delete items in this mapping to unset environment variables.
134+
:func:`unsetenv` will be called automatically when an item is deleted from
135+
``os.environ``, and when one of the :meth:`pop` or :meth:`clear` methods is
136+
called.
141137

142138

143139
.. data:: environb
@@ -439,17 +435,18 @@ process and user.
439435
changes to the environment affect subprocesses started with :func:`os.system`,
440436
:func:`popen` or :func:`fork` and :func:`execv`.
441437

442-
.. availability:: most flavors of Unix, Windows.
438+
Assignments to items in ``os.environ`` are automatically translated into
439+
corresponding calls to :func:`putenv`; however, calls to :func:`putenv`
440+
don't update ``os.environ``, so it is actually preferable to assign to items
441+
of ``os.environ``.
443442

444443
.. note::
445444

446445
On some platforms, including FreeBSD and Mac OS X, setting ``environ`` may
447-
cause memory leaks. Refer to the system documentation for putenv.
446+
cause memory leaks. Refer to the system documentation for :c:func:`putenv`.
448447

449-
When :func:`putenv` is supported, assignments to items in ``os.environ`` are
450-
automatically translated into corresponding calls to :func:`putenv`; however,
451-
calls to :func:`putenv` don't update ``os.environ``, so it is actually
452-
preferable to assign to items of ``os.environ``.
448+
.. versionchanged:: 3.9
449+
The function is now always available.
453450

454451

455452
.. function:: setegid(egid)
@@ -638,15 +635,13 @@ process and user.
638635
environment affect subprocesses started with :func:`os.system`, :func:`popen` or
639636
:func:`fork` and :func:`execv`.
640637

641-
When :func:`unsetenv` is supported, deletion of items in ``os.environ`` is
642-
automatically translated into a corresponding call to :func:`unsetenv`; however,
643-
calls to :func:`unsetenv` don't update ``os.environ``, so it is actually
644-
preferable to delete items of ``os.environ``.
645-
646-
.. availability:: most flavors of Unix, Windows.
638+
Deletion of items in ``os.environ`` is automatically translated into a
639+
corresponding call to :func:`unsetenv`; however, calls to :func:`unsetenv`
640+
don't update ``os.environ``, so it is actually preferable to delete items of
641+
``os.environ``.
647642

648643
.. versionchanged:: 3.9
649-
The function is now also available on Windows.
644+
The function is now always available and is also available on Windows.
650645

651646

652647
.. _os-newstreams:

Doc/whatsnew/3.9.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ descriptors.
227227
The :func:`os.unsetenv` function is now also available on Windows.
228228
(Contributed by Victor Stinner in :issue:`39413`.)
229229

230+
The :func:`os.putenv` and :func:`os.unsetenv` functions are now always
231+
available.
232+
(Contributed by Victor Stinner in :issue:`39395`.)
233+
230234
poplib
231235
------
232236

@@ -331,6 +335,10 @@ Build and C API Changes
331335
Python 3.0, it has been ignored and unused.
332336
(Contributed by Jeroen Demeyer in :issue:`36974`.)
333337

338+
* On non-Windows platforms, the :c:func:`setenv` and :c:func:`unsetenv`
339+
functions are now required to build Python.
340+
(Contributed by Victor Stinner in :issue:`39395`.)
341+
334342

335343
Deprecated
336344
==========

Lib/os.py

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -654,17 +654,15 @@ def get_exec_path(env=None):
654654
return path_list.split(pathsep)
655655

656656

657-
# Change environ to automatically call putenv(), unsetenv if they exist.
657+
# Change environ to automatically call putenv() and unsetenv()
658658
from _collections_abc import MutableMapping
659659

660660
class _Environ(MutableMapping):
661-
def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv):
661+
def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue):
662662
self.encodekey = encodekey
663663
self.decodekey = decodekey
664664
self.encodevalue = encodevalue
665665
self.decodevalue = decodevalue
666-
self.putenv = putenv
667-
self.unsetenv = unsetenv
668666
self._data = data
669667

670668
def __getitem__(self, key):
@@ -678,12 +676,12 @@ def __getitem__(self, key):
678676
def __setitem__(self, key, value):
679677
key = self.encodekey(key)
680678
value = self.encodevalue(value)
681-
self.putenv(key, value)
679+
putenv(key, value)
682680
self._data[key] = value
683681

684682
def __delitem__(self, key):
685683
encodedkey = self.encodekey(key)
686-
self.unsetenv(encodedkey)
684+
unsetenv(encodedkey)
687685
try:
688686
del self._data[encodedkey]
689687
except KeyError:
@@ -712,22 +710,6 @@ def setdefault(self, key, value):
712710
self[key] = value
713711
return self[key]
714712

715-
try:
716-
_putenv = putenv
717-
except NameError:
718-
_putenv = lambda key, value: None
719-
else:
720-
if "putenv" not in __all__:
721-
__all__.append("putenv")
722-
723-
try:
724-
_unsetenv = unsetenv
725-
except NameError:
726-
_unsetenv = lambda key: _putenv(key, "")
727-
else:
728-
if "unsetenv" not in __all__:
729-
__all__.append("unsetenv")
730-
731713
def _createenviron():
732714
if name == 'nt':
733715
# Where Env Var Names Must Be UPPERCASE
@@ -755,8 +737,7 @@ def decode(value):
755737
data = environ
756738
return _Environ(data,
757739
encodekey, decode,
758-
encode, decode,
759-
_putenv, _unsetenv)
740+
encode, decode)
760741

761742
# unicode environ
762743
environ = _createenviron()
@@ -781,8 +762,7 @@ def _check_bytes(value):
781762
# bytes environ
782763
environb = _Environ(environ._data,
783764
_check_bytes, bytes,
784-
_check_bytes, bytes,
785-
_putenv, _unsetenv)
765+
_check_bytes, bytes)
786766
del _check_bytes
787767

788768
def getenvb(key, default=None):

Lib/test/test_os.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -953,8 +953,6 @@ def test_environb(self):
953953
value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape')
954954
self.assertEqual(os.environ['bytes'], value_str)
955955

956-
@unittest.skipUnless(hasattr(os, 'putenv'), "Test needs os.putenv()")
957-
@unittest.skipUnless(hasattr(os, 'unsetenv'), "Test needs os.unsetenv()")
958956
def test_putenv_unsetenv(self):
959957
name = "PYTHONTESTVAR"
960958
value = "testvalue"
@@ -975,8 +973,6 @@ def test_putenv_unsetenv(self):
975973

976974
# On OS X < 10.6, unsetenv() doesn't return a value (bpo-13415).
977975
@support.requires_mac_ver(10, 6)
978-
@unittest.skipUnless(hasattr(os, 'putenv'), "Test needs os.putenv()")
979-
@unittest.skipUnless(hasattr(os, 'unsetenv'), "Test needs os.unsetenv()")
980976
def test_putenv_unsetenv_error(self):
981977
# Empty variable name is invalid.
982978
# "=" and null character are not allowed in a variable name.

Lib/test/test_posix.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,6 @@ def test_environ(self):
969969
self.assertEqual(type(k), item_type)
970970
self.assertEqual(type(v), item_type)
971971

972-
@unittest.skipUnless(hasattr(os, "putenv"), "requires os.putenv()")
973972
def test_putenv(self):
974973
with self.assertRaises(ValueError):
975974
os.putenv('FRUIT\0VEGETABLE', 'cabbage')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
On non-Windows platforms, the :c:func:`setenv` and :c:func:`unsetenv` functions
2+
are now required to build Python.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The :func:`os.putenv` and :func:`os.unsetenv` functions are now always
2+
available.

Modules/clinic/posixmodule.c.h

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)