D12313: procutil: delete Python 2 support code
indygreg (Gregory Szorc)
phabricator at mercurial-scm.org
Wed Mar 2 23:32:01 UTC 2022
indygreg created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.
REVISION SUMMARY
This entailed deleting a function for Python 2 support and renaming the
Python 3 function to match the exported symbol name.
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D12313
AFFECTED FILES
mercurial/utils/procutil.py
CHANGE DETAILS
diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py
--- a/mercurial/utils/procutil.py
+++ b/mercurial/utils/procutil.py
@@ -80,7 +80,7 @@
def make_line_buffered(stream):
- if pycompat.ispy3 and not isinstance(stream, io.BufferedIOBase):
+ if not isinstance(stream, io.BufferedIOBase):
# On Python 3, buffered streams can be expected to subclass
# BufferedIOBase. This is definitively the case for the streams
# initialized by the interpreter. For unbuffered streams, we don't need
@@ -121,7 +121,6 @@
def _make_write_all(stream):
- assert pycompat.ispy3
if isinstance(stream, WriteAllWrapper):
return stream
if isinstance(stream, io.BufferedIOBase):
@@ -133,52 +132,32 @@
return WriteAllWrapper(stream)
-if pycompat.ispy3:
- # Python 3 implements its own I/O streams. Unlike stdio of C library,
- # sys.stdin/stdout/stderr may be None if underlying fd is closed.
-
- # TODO: .buffer might not exist if std streams were replaced; we'll need
- # a silly wrapper to make a bytes stream backed by a unicode one.
+# Python 3 implements its own I/O streams. Unlike stdio of C library,
+# sys.stdin/stdout/stderr may be None if underlying fd is closed.
- if sys.stdin is None:
- stdin = BadFile()
- else:
- stdin = sys.stdin.buffer
- if sys.stdout is None:
- stdout = BadFile()
- else:
- stdout = _make_write_all(sys.stdout.buffer)
- if sys.stderr is None:
- stderr = BadFile()
- else:
- stderr = _make_write_all(sys.stderr.buffer)
+# TODO: .buffer might not exist if std streams were replaced; we'll need
+# a silly wrapper to make a bytes stream backed by a unicode one.
- if pycompat.iswindows:
- # Work around Windows bugs.
- stdout = platform.winstdout(stdout) # pytype: disable=module-attr
- stderr = platform.winstdout(stderr) # pytype: disable=module-attr
- if isatty(stdout):
- # The standard library doesn't offer line-buffered binary streams.
- stdout = make_line_buffered(stdout)
+if sys.stdin is None:
+ stdin = BadFile()
+else:
+ stdin = sys.stdin.buffer
+if sys.stdout is None:
+ stdout = BadFile()
else:
- # Python 2 uses the I/O streams provided by the C library.
- stdin = sys.stdin
- stdout = sys.stdout
- stderr = sys.stderr
- if pycompat.iswindows:
- # Work around Windows bugs.
- stdout = platform.winstdout(stdout) # pytype: disable=module-attr
- stderr = platform.winstdout(stderr) # pytype: disable=module-attr
- if isatty(stdout):
- if pycompat.iswindows:
- # The Windows C runtime library doesn't support line buffering.
- stdout = make_line_buffered(stdout)
- else:
- # glibc determines buffering on first write to stdout - if we
- # replace a TTY destined stdout with a pipe destined stdout (e.g.
- # pager), we want line buffering.
- stdout = os.fdopen(stdout.fileno(), 'wb', 1)
+ stdout = _make_write_all(sys.stdout.buffer)
+if sys.stderr is None:
+ stderr = BadFile()
+else:
+ stderr = _make_write_all(sys.stderr.buffer)
+if pycompat.iswindows:
+ # Work around Windows bugs.
+ stdout = platform.winstdout(stdout) # pytype: disable=module-attr
+ stderr = platform.winstdout(stderr) # pytype: disable=module-attr
+if isatty(stdout):
+ # The standard library doesn't offer line-buffered binary streams.
+ stdout = make_line_buffered(stdout)
findexe = platform.findexe
_gethgcmd = platform.gethgcmd
@@ -703,7 +682,7 @@
else:
- def runbgcommandpy3(
+ def runbgcommand(
cmd,
env,
shell=False,
@@ -786,128 +765,3 @@
returncode = p.wait
if record_wait is not None:
record_wait(returncode)
-
- def runbgcommandpy2(
- cmd,
- env,
- shell=False,
- stdout=None,
- stderr=None,
- ensurestart=True,
- record_wait=None,
- stdin_bytes=None,
- ):
- """Spawn a command without waiting for it to finish.
-
-
- When `record_wait` is not None, the spawned process will not be fully
- detached and the `record_wait` argument will be called with a the
- `Subprocess.wait` function for the spawned process. This is mostly
- useful for developers that need to make sure the spawned process
- finished before a certain point. (eg: writing test)"""
- if pycompat.isdarwin:
- # avoid crash in CoreFoundation in case another thread
- # calls gui() while we're calling fork().
- gui()
-
- # double-fork to completely detach from the parent process
- # based on http://code.activestate.com/recipes/278731
- if record_wait is None:
- pid = os.fork()
- if pid:
- if not ensurestart:
- # Even though we're not waiting on the child process,
- # we still must call waitpid() on it at some point so
- # it's not a zombie/defunct. This is especially relevant for
- # chg since the parent process won't die anytime soon.
- # We use a thread to make the overhead tiny.
- def _do_wait():
- os.waitpid(pid, 0)
-
- t = threading.Thread(target=_do_wait)
- t.daemon = True
- t.start()
- return
- # Parent process
- (_pid, status) = os.waitpid(pid, 0)
- if os.WIFEXITED(status):
- returncode = os.WEXITSTATUS(status)
- else:
- returncode = -(os.WTERMSIG(status))
- if returncode != 0:
- # The child process's return code is 0 on success, an errno
- # value on failure, or 255 if we don't have a valid errno
- # value.
- #
- # (It would be slightly nicer to return the full exception info
- # over a pipe as the subprocess module does. For now it
- # doesn't seem worth adding that complexity here, though.)
- if returncode == 255:
- returncode = errno.EINVAL
- raise OSError(
- returncode,
- b'error running %r: %s'
- % (cmd, os.strerror(returncode)),
- )
- return
-
- returncode = 255
- stdin = None
-
- try:
- if record_wait is None:
- # Start a new session
- os.setsid()
- # connect stdin to devnull to make sure the subprocess can't
- # muck up that stream for mercurial.
- if stdin_bytes is None:
- stdin = open(os.devnull, b'r')
- else:
- stdin = pycompat.unnamedtempfile()
- stdin.write(stdin_bytes)
- stdin.flush()
- stdin.seek(0)
-
- if stdout is None:
- stdout = open(os.devnull, b'w')
- if stderr is None:
- stderr = open(os.devnull, b'w')
-
- p = subprocess.Popen(
- cmd,
- shell=shell,
- env=env,
- close_fds=True,
- stdin=stdin,
- stdout=stdout,
- stderr=stderr,
- )
- if record_wait is not None:
- record_wait(p.wait)
- returncode = 0
- except EnvironmentError as ex:
- returncode = ex.errno & 0xFF
- if returncode == 0:
- # This shouldn't happen, but just in case make sure the
- # return code is never 0 here.
- returncode = 255
- except Exception:
- returncode = 255
- finally:
- # mission accomplished, this child needs to exit and not
- # continue the hg process here.
- if stdin is not None:
- stdin.close()
- if record_wait is None:
- os._exit(returncode)
-
- if pycompat.ispy3:
- # This branch is more robust, because it avoids running python
- # code (hence gc finalizers, like sshpeer.__del__, which
- # blocks). But we can't easily do the equivalent in py2,
- # because of the lack of start_new_session=True flag. Given
- # that the py2 branch should die soon, the short-lived
- # duplication seems acceptable.
- runbgcommand = runbgcommandpy3
- else:
- runbgcommand = runbgcommandpy2
To: indygreg, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
More information about the Mercurial-devel
mailing list