Commit 449c466e authored by Victor Stinner's avatar Victor Stinner

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.
parent 4cda46ab
...@@ -155,6 +155,17 @@ process and user. ...@@ -155,6 +155,17 @@ process and user.
These functions are described in :ref:`os-file-dir`. 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) .. function:: get_exec_path(env=None)
Returns the list of directories that will be searched for a named Returns the list of directories that will be searched for a named
......
...@@ -504,6 +504,17 @@ if name not in ('os2', 'nt'): ...@@ -504,6 +504,17 @@ if name not in ('os2', 'nt'):
return environb.get(key, default) return environb.get(key, default)
__all__.append("getenvb") __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): def _exists(name):
return name in globals() return name in globals()
......
...@@ -1079,32 +1079,24 @@ class Popen(object): ...@@ -1079,32 +1079,24 @@ class Popen(object):
self._set_cloexec_flag(errpipe_write) self._set_cloexec_flag(errpipe_write)
if _posixsubprocess: 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 # We must avoid complex work that could involve
# malloc or free in the child process to avoid # malloc or free in the child process to avoid
# potential deadlocks, thus we do all this here. # potential deadlocks, thus we do all this here.
# and pass it to fork_exec() # and pass it to fork_exec()
if env: 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()] for k, v in env.items()]
else: else:
env_list = None # Use execv instead of execve. env_list = None # Use execv instead of execve.
if os.path.dirname(executable): if os.path.dirname(executable):
executable_list = (fs_encode(executable),) executable_list = (os.fsencode(executable),)
else: else:
# This matches the behavior of os._execvpe(). # This matches the behavior of os._execvpe().
path_list = os.get_exec_path(env) path_list = os.get_exec_path(env)
executable_list = (os.path.join(dir, executable) executable_list = (os.path.join(dir, executable)
for dir in path_list) for dir in path_list)
executable_list = tuple(fs_encode(exe) executable_list = tuple(os.fsencode(exe)
for exe in executable_list) for exe in executable_list)
self.pid = _posixsubprocess.fork_exec( self.pid = _posixsubprocess.fork_exec(
args, executable_list, args, executable_list,
......
...@@ -351,6 +351,9 @@ C-API ...@@ -351,6 +351,9 @@ C-API
Library 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 - Issue #8571: Fix an internal error when compressing or decompressing a
chunk larger than 1GB with the zlib module's compressor and decompressor chunk larger than 1GB with the zlib module's compressor and decompressor
objects. objects.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment