Issue #8513: os.get_exec_path() supports b'PATH' key and bytes value.
subprocess.Popen() and os._execvpe() support bytes program name. Add
os.supports_bytes_environ flag: True if the native OS type of the environment
is bytes (eg. False on Windows).
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 37abe22..6a63717 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -370,7 +370,7 @@
 
     def setUp(self):
         self.__save = dict(os.environ)
-        if os.name not in ('os2', 'nt'):
+        if os.supports_bytes_environ:
             self.__saveb = dict(os.environb)
         for key, value in self._reference().items():
             os.environ[key] = value
@@ -378,7 +378,7 @@
     def tearDown(self):
         os.environ.clear()
         os.environ.update(self.__save)
-        if os.name not in ('os2', 'nt'):
+        if os.supports_bytes_environ:
             os.environb.clear()
             os.environb.update(self.__saveb)
 
@@ -445,7 +445,21 @@
         # Supplied PATH environment variable
         self.assertSequenceEqual(test_path, os.get_exec_path(test_env))
 
-    @unittest.skipIf(sys.platform == "win32", "POSIX specific test")
+        if os.supports_bytes_environ:
+            # env cannot contain 'PATH' and b'PATH' keys
+            self.assertRaises(ValueError,
+                os.get_exec_path, {'PATH': '1', b'PATH': b'2'})
+
+            # bytes key and/or value
+            self.assertSequenceEqual(os.get_exec_path({b'PATH': b'abc'}),
+                ['abc'])
+            self.assertSequenceEqual(os.get_exec_path({b'PATH': 'abc'}),
+                ['abc'])
+            self.assertSequenceEqual(os.get_exec_path({'PATH': b'abc'}),
+                ['abc'])
+
+    @unittest.skipUnless(os.supports_bytes_environ,
+                         "os.environb required for this test.")
     def test_environb(self):
         # os.environ -> os.environb
         value = 'euro\u20ac'
@@ -669,22 +683,54 @@
 
     @unittest.skipUnless(hasattr(os, '_execvpe'),
                          "No internal os._execvpe function to test.")
-    def test_internal_execvpe(self):
-        program_path = os.sep+'absolutepath'
-        program = 'executable'
-        fullpath = os.path.join(program_path, program)
-        arguments = ['progname', 'arg1', 'arg2']
+    def _test_internal_execvpe(self, test_type):
+        program_path = os.sep + 'absolutepath'
+        if test_type is bytes:
+            program = b'executable'
+            fullpath = os.path.join(os.fsencode(program_path), program)
+            native_fullpath = fullpath
+            arguments = [b'progname', 'arg1', 'arg2']
+        else:
+            program = 'executable'
+            arguments = ['progname', 'arg1', 'arg2']
+            fullpath = os.path.join(program_path, program)
+            if os.name != "nt":
+                native_fullpath = os.fsencode(fullpath)
+            else:
+                native_fullpath = fullpath
         env = {'spam': 'beans'}
 
+        # test os._execvpe() with an absolute path
         with _execvpe_mockup() as calls:
-            self.assertRaises(RuntimeError, os._execvpe, fullpath, arguments)
+            self.assertRaises(RuntimeError,
+                os._execvpe, fullpath, arguments)
             self.assertEqual(len(calls), 1)
             self.assertEqual(calls[0], ('execv', fullpath, (arguments,)))
 
+        # test os._execvpe() with a relative path:
+        # os.get_exec_path() returns defpath
         with _execvpe_mockup(defpath=program_path) as calls:
-            self.assertRaises(OSError, os._execvpe, program, arguments, env=env)
+            self.assertRaises(OSError,
+                os._execvpe, program, arguments, env=env)
             self.assertEqual(len(calls), 1)
-            self.assertEqual(calls[0], ('execve', fullpath, (arguments, env)))
+            self.assertSequenceEqual(calls[0],
+                ('execve', native_fullpath, (arguments, env)))
+
+        # test os._execvpe() with a relative path:
+        # os.get_exec_path() reads the 'PATH' variable
+        with _execvpe_mockup() as calls:
+            env_path = env.copy()
+            env_path['PATH'] = program_path
+            self.assertRaises(OSError,
+                os._execvpe, program, arguments, env=env_path)
+            self.assertEqual(len(calls), 1)
+            self.assertSequenceEqual(calls[0],
+                ('execve', native_fullpath, (arguments, env_path)))
+
+    def test_internal_execvpe_str(self):
+        self._test_internal_execvpe(str)
+        if os.name != "nt":
+            self._test_internal_execvpe(bytes)
 
 
 class Win32ErrorTests(unittest.TestCase):