Index: Lib/os.py =================================================================== --- Lib/os.py (révision 80702) +++ Lib/os.py (copie de travail) @@ -355,8 +355,9 @@ return last_exc = saved_exc = None saved_tb = None + file = fsencode(file) for dir in get_exec_path(env): - fullname = path.join(dir, file) + fullname = path.join(fsencode(dir), file) try: exec_func(fullname, *argrest) except error as e: @@ -387,29 +388,30 @@ from _abcoll import MutableMapping # Can't use collections (bootstrap) class _Environ(MutableMapping): - def __init__(self, environ, keymap, putenv, unsetenv): - self.keymap = keymap + def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv): + self.encodekey = encodekey + self.decodekey = decodekey + self.encodevalue = encodevalue + self.decodevalue = decodevalue self.putenv = putenv self.unsetenv = unsetenv - self.data = data = {} - for key, value in environ.items(): - data[keymap(key)] = str(value) + self.data = data def __getitem__(self, key): - return self.data[self.keymap(key)] + value = self.data[self.encodekey(key)] + return self.decodevalue(value) def __setitem__(self, key, value): - value = str(value) self.putenv(key, value) - self.data[self.keymap(key)] = value + self.data[self.encodekey(key)] = self.encodevalue(value) def __delitem__(self, key): self.unsetenv(key) - del self.data[self.keymap(key)] + del self.data[self.encodekey(key)] def __iter__(self): for key in self.data: - yield key + yield self.decodekey(key) def __len__(self): return len(self.data) @@ -439,22 +441,56 @@ else: __all__.append("unsetenv") +def fsdecode(value): + """ + file system to unicode + """ + if isinstance(value, str): + return value + else: + return value.decode(sys.getfilesystemencoding(), 'surrogateescape') + +if name in ('os2', 'nt', 'ce'): + fsencode = fsdecode +else: + def fsencode(value): + """ + unicode to file system + """ + if isinstance(value, bytes): + return value + else: + return value.encode(sys.getfilesystemencoding(), 'surrogateescape') + if name in ('os2', 'nt'): # Where Env Var Names Must Be UPPERCASE - _keymap = lambda key: str(key.upper()) + def _keymap(key): + return fsencode(key).upper() else: # Where Env Var Names Can Be Mixed Case - _keymap = lambda key: str(key) + _keymap = fsencode -environ = _Environ(environ, _keymap, _putenv, _unsetenv) +data = {} +for key, value in environ.items(): + data[_keymap(key)] = fsencode(value) +# unicode environ +environ = _Environ(data, _keymap, fsdecode, fsencode, fsdecode, _putenv, _unsetenv) def getenv(key, default=None): """Get an environment variable, return None if it doesn't exist. The optional second argument can specify an alternate default.""" - if isinstance(key, bytes): - key = key.decode(sys.getfilesystemencoding(), "surrogateescape") return environ.get(key, default) __all__.append("getenv") +if name not in ('os2', 'nt'): + # bytes environ + environb = _Environ(data, _keymap, fsencode, fsencode, fsencode, _putenv, _unsetenv) + + def getenvb(key, default=None): + """Get an environment variable, return None if it doesn't exist. + The optional second argument can specify an alternate default.""" + return environb.get(key, default) + __all__.append("getenvb") + def _exists(name): return name in globals() Index: Lib/test/test_os.py =================================================================== --- Lib/test/test_os.py (révision 80702) +++ Lib/test/test_os.py (copie de travail) @@ -439,7 +439,22 @@ # Supplied PATH environment variable self.assertSequenceEqual(test_path, os.get_exec_path(test_env)) + @unittest.skipIf(sys.platform == "win32", "POSIX specific test") + def test_environb(self): + # os.environ -> os.environb + value = 'euro\u20ac' + os.environ['unicode'] = value + self.assertEquals(os.environ['unicode'], value) + value_bytes = os.fsencode(value) + self.assertEquals(os.environb[b'unicode'], value_bytes) + # os.environb -> os.environ + value = b'\xff' + os.environb[b'bytes'] = value + self.assertEquals(os.environb['bytes'], value) + value_str = os.fsdecode(value) + self.assertEquals(os.environ['bytes'], value_str) + class WalkTests(unittest.TestCase): """Tests for os.walk().""" Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (révision 80702) +++ Modules/posixmodule.c (copie de travail) @@ -493,14 +493,12 @@ char *p = strchr(*e, '='); if (p == NULL) continue; - k = PyUnicode_Decode(*e, (int)(p-*e), - Py_FileSystemDefaultEncoding, "surrogateescape"); + k = PyBytes_FromStringAndSize(*e, (int)(p-*e)); if (k == NULL) { PyErr_Clear(); continue; } - v = PyUnicode_Decode(p+1, strlen(p+1), - Py_FileSystemDefaultEncoding, "surrogateescape"); + v = PyBytes_FromStringAndSize(p+1, strlen(p+1)); if (v == NULL) { PyErr_Clear(); Py_DECREF(k);