Patchwork [1,of,5] 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, 12:03 p.m.
Message ID <6cf61fcd3fad06f14668.1537358633@Envy>
Download mbox | patch
Permalink /patch/34826/
State Accepted
Headers show

Comments

Matt Harbison - Sept. 19, 2018, 12:03 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 6cf61fcd3fad06f14668a4cc56cc7c5351561219
# Parent  fa681452b249f5d59dd77c925ce15b027758e8fe
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. 19, 2018, 1 p.m.
On Wed, 19 Sep 2018 08:03:53 -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 6cf61fcd3fad06f14668a4cc56cc7c5351561219
> # Parent  fa681452b249f5d59dd77c925ce15b027758e8fe
> py3: make osenvironb a proxy for, instead of a copy of os.environ where needed

> +            @staticmethod
> +            def _strpathornone(b):
> +                if b is None:
> +                    return None
> +                return _strpath(b)
> +            @staticmethod
> +            def _bytespathornone(s):
> +                if s is None:
> +                    return None
> +                return _bytespath(s)

I think these functions can be removed since _bytespath/_strpath() handles None.

> +        osenvironb = envdict()

My two cents. envdict(os.environ) will look cleaner.

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,44 @@  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 envdict(object):
+            def __init__(self):
+                self.__len__ = os.environ.__len__
+                self.clear = os.environ.clear
+
+            @staticmethod
+            def _strpathornone(b):
+                if b is None:
+                    return None
+                return _strpath(b)
+            @staticmethod
+            def _bytespathornone(s):
+                if s is None:
+                    return None
+                return _bytespath(s)
+
+            def __getitem__(self, k):
+                v = os.environ.__getitem__(_strpath(k))
+                return _bytespath(v)
+            def __setitem__(self, k, v):
+                os.environ.__setitem__(_strpath(k), _strpath(v))
+            def __delitem__(self, k):
+                os.environ.__delitem__(_strpath(k))
+            def __contains__(self, k):
+                return os.environ.__contains__(_strpath(k))
+            def __iter__(self):
+                return iter([_bytespath(k) for k in iter(os.environ)])
+            def get(self, k, default=None):
+                v = os.environ.get(_strpath(k), envdict._strpathornone(default))
+                return envdict._bytespathornone(v)
+            def pop(self, k, default=None):
+                v = os.environ.pop(_strpath(k), envdict._strpathornone(default))
+                return envdict._bytespathornone(v)
+
+        osenvironb = envdict()
 
 elif sys.version_info >= (3, 0, 0):
     print('%s is only supported on Python 3.5+ and 2.7, not %s' %