From 449c466e7d17292c46c08ef9a458fbdc5ddb7987 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 8 May 2010 11:10:09 +0000 Subject: Issue #8514: Add os.fsencode() function (Unix only): encode a string to bytes for use in the file system, environment variables or the command line. --- Doc/library/os.rst | 11 +++++++++++ Lib/os.py | 11 +++++++++++ Lib/subprocess.py | 14 +++----------- Misc/NEWS | 3 +++ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 577c600..1d4b1e1 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -155,6 +155,17 @@ process and user. These functions are described in :ref:`os-file-dir`. +.. function:: fsencode(value) + + Encode *value* to bytes for use in the file system, environment variables or + the command line. Uses :func:`sys.getfilesystemencoding` and + ``'surrogateescape'`` error handler for strings and returns bytes unchanged. + + Availability: Unix. + + .. versionadded:: 3.2 + + .. function:: get_exec_path(env=None) Returns the list of directories that will be searched for a named diff --git a/Lib/os.py b/Lib/os.py index 3e2ee0d..13ab18c 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -504,6 +504,17 @@ if name not in ('os2', 'nt'): return environb.get(key, default) __all__.append("getenvb") +if name != 'nt': + def fsencode(value): + """Encode value for use in the file system, environment variables + or the command line.""" + if isinstance(value, bytes): + return value + elif isinstance(value, str): + return value.encode(sys.getfilesystemencoding(), 'surrogateescape') + else: + raise TypeError("expect bytes or str, not %s" % type(value).__name__) + def _exists(name): return name in globals() diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 00d36c3..695204a 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1079,32 +1079,24 @@ class Popen(object): self._set_cloexec_flag(errpipe_write) if _posixsubprocess: - fs_encoding = sys.getfilesystemencoding() - def fs_encode(s): - """Encode s for use in the env, fs or cmdline.""" - if isinstance(s, bytes): - return s - else: - return s.encode(fs_encoding, 'surrogateescape') - # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env: - env_list = [fs_encode(k) + b'=' + fs_encode(v) + env_list = [os.fsencode(k) + b'=' + os.fsencode(v) for k, v in env.items()] else: env_list = None # Use execv instead of execve. if os.path.dirname(executable): - executable_list = (fs_encode(executable),) + executable_list = (os.fsencode(executable),) else: # This matches the behavior of os._execvpe(). path_list = os.get_exec_path(env) executable_list = (os.path.join(dir, executable) for dir in path_list) - executable_list = tuple(fs_encode(exe) + executable_list = tuple(os.fsencode(exe) for exe in executable_list) self.pid = _posixsubprocess.fork_exec( args, executable_list, diff --git a/Misc/NEWS b/Misc/NEWS index 98ec0d2..77aa054 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -351,6 +351,9 @@ C-API Library ------- +- Issue #8514: Add os.fsencode() function (Unix only): encode a string to bytes + for use in the file system, environment variables or the command line. + - Issue #8571: Fix an internal error when compressing or decompressing a chunk larger than 1GB with the zlib module's compressor and decompressor objects. -- cgit v0.12