Patchwork [V2] py3: make osenvironb a proxy for, instead of a copy of os.environ where needed

login
register
mail settings
Submitter Matt Harbison
Date Sept. 19, 2018, 11:01 p.m.
Message ID <6a29fe518906d0f21b7b.1537398108@Envy>
Download mbox | patch
Permalink /patch/34838/
State Accepted
Headers show

Comments

Matt Harbison - Sept. 19, 2018, 11:01 p.m.
# HG changeset patch
# User Matt Harbison <matt_harbison@yahoo.com>
# Date 1537323243 14400
#      Tue Sep 18 22:14:03 2018 -0400
# Node ID 6a29fe518906d0f21b7bdd76323d2f71e7667241
# Parent  a5dafefc4a53294aa0bd88a27cc29baf2a1ea62c
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.
Yuya Nishihara - Sept. 20, 2018, 11:34 a.m.
On Wed, 19 Sep 2018 19:01:48 -0400, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison <matt_harbison@yahoo.com>
> # Date 1537323243 14400
> #      Tue Sep 18 22:14:03 2018 -0400
> # Node ID 6a29fe518906d0f21b7bdd76323d2f71e7667241
> # Parent  a5dafefc4a53294aa0bd88a27cc29baf2a1ea62c
> py3: make osenvironb a proxy for, instead of a copy of os.environ where needed

Queued, thanks.

Patch

diff --git a/tests/run-tests.py b/tests/run-tests.py
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -156,10 +156,33 @@  if sys.version_info > (3, 5, 0):
 
     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' %