py3: make osenvironb a proxy for, instead of a copy of os.environ where needed
authorMatt Harbison <matt_harbison@yahoo.com>
Tue, 18 Sep 2018 22:14:03 -0400
changeset 39714 491fc3f4be67
parent 39713 a5dafefc4a53
child 39715 d8a7690ccc74
py3: make osenvironb a proxy for, instead of a copy of os.environ where needed Without this, TESTDIR and a few other variables weren't defined in the *.t test. I didn't bother implementing all of the view functions for simplicity. All that is actually used is __{get,set}item__(), get() and pop(), but the rest seems easy enough to add for futureproofing.
tests/run-tests.py
--- a/tests/run-tests.py	Tue May 22 16:16:11 2018 +0200
+++ b/tests/run-tests.py	Tue Sep 18 22:14:03 2018 -0400
@@ -156,10 +156,33 @@
 
     osenvironb = getattr(os, 'environb', None)
     if osenvironb is None:
-        # Windows lacks os.environb, for instance.
-        osenvironb = {
-            _bytespath(k): _bytespath(v) for k, v in os.environ.items()
-        }
+        # Windows lacks os.environb, for instance.  A proxy over the real thing
+        # instead of a copy allows the environment to be updated via bytes on
+        # all platforms.
+        class environbytes(object):
+            def __init__(self, strenv):
+                self.__len__ = strenv.__len__
+                self.clear = strenv.clear
+                self._strenv = strenv
+            def __getitem__(self, k):
+                v = self._strenv.__getitem__(_strpath(k))
+                return _bytespath(v)
+            def __setitem__(self, k, v):
+                self._strenv.__setitem__(_strpath(k), _strpath(v))
+            def __delitem__(self, k):
+                self._strenv.__delitem__(_strpath(k))
+            def __contains__(self, k):
+                return self._strenv.__contains__(_strpath(k))
+            def __iter__(self):
+                return iter([_bytespath(k) for k in iter(self._strenv)])
+            def get(self, k, default=None):
+                v = self._strenv.get(_strpath(k), _strpath(default))
+                return _bytespath(v)
+            def pop(self, k, default=None):
+                v = self._strenv.pop(_strpath(k), _strpath(default))
+                return _bytespath(v)
+
+        osenvironb = environbytes(os.environ)
 
 elif sys.version_info >= (3, 0, 0):
     print('%s is only supported on Python 3.5+ and 2.7, not %s' %