Patchwork D299: pycompat: introduce a wrapper for __builtins__.{raw_,}input()

login
register
mail settings
Submitter phabricator
Date Aug. 11, 2017, 7:52 p.m.
Message ID <8d9ee9a1c28a50df3b180c9ba0ac330c@localhost.localdomain>
Download mbox | patch
Permalink /patch/22900/
State Not Applicable
Headers show

Comments

phabricator - Aug. 11, 2017, 7:52 p.m.
durin42 updated this revision to Diff 801.
durin42 marked an inline comment as done.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D299?vs=682&id=801

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

AFFECTED FILES
  hgext/hgk.py
  mercurial/pycompat.py
  mercurial/ui.py

CHANGE DETAILS




To: durin42, #hg-reviewers
Cc: yuja, mercurial-devel

Patch

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1217,18 +1217,10 @@ 
         self.write(prompt, prompt=True)
         self.flush()
 
-        # instead of trying to emulate raw_input, swap (self.fin,
-        # self.fout) with (sys.stdin, sys.stdout)
-        oldin = sys.stdin
-        oldout = sys.stdout
-        sys.stdin = self.fin
-        sys.stdout = self.fout
         # prompt ' ' must exist; otherwise readline may delete entire line
         # - http://bugs.python.org/issue12833
         with self.timeblockedsection('stdio'):
-            line = raw_input(' ')
-        sys.stdin = oldin
-        sys.stdout = oldout
+            line = pycompat.bytesinput(self.fin, self.fout, r' ')
 
         # When stdin is in binary mode on Windows, it can cause
         # raw_input() to emit an extra trailing carriage return
diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
--- a/mercurial/pycompat.py
+++ b/mercurial/pycompat.py
@@ -70,6 +70,18 @@ 
     stdout = sys.stdout.buffer
     stderr = sys.stderr.buffer
 
+    class noclosetextio(io.TextIOWrapper):
+        def __del__(self):
+            """Override __del__ so it doesn't close the underlying stream."""
+
+    def bytesinput(fin, fout, *args, **kwargs):
+        sin, sout = sys.stdin, sys.stdout
+        try:
+            sys.stdin, sys.stdout = noclosetextio(fin), noclosetextio(fout)
+            return bytestr(input(*args, **kwargs))
+        finally:
+            sys.stdin, sys.stdout = sin, sout
+
     # Since Python 3 converts argv to wchar_t type by Py_DecodeLocale() on Unix,
     # we can use os.fsencode() to get back bytes argv.
     #
@@ -304,6 +316,15 @@ 
     stdin = sys.stdin
     stdout = sys.stdout
     stderr = sys.stderr
+
+    def bytesinput(fin, fout, *args, **kwargs):
+        sin, sout = sys.stdin, sys.stdout
+        try:
+            sys.stdin, sys.stdout = fin, fout
+            return raw_input(*args, **kwargs)
+        finally:
+            sys.stdin, sys.stdout = sin, sout
+
     if getattr(sys, 'argv', None) is not None:
         sysargv = sys.argv
     sysplatform = sys.platform
diff --git a/hgext/hgk.py b/hgext/hgk.py
--- a/hgext/hgk.py
+++ b/hgext/hgk.py
@@ -48,6 +48,7 @@ 
     commands,
     obsolete,
     patch,
+    pycompat,
     registrar,
     scmutil,
 )
@@ -96,7 +97,7 @@ 
     while True:
         if opts['stdin']:
             try:
-                line = raw_input().split(' ')
+                line = pycompat.bytesinput(sys.stdin, sys.stdout).split(' ')
                 node1 = line[0]
                 if len(line) > 1:
                     node2 = line[1]
@@ -177,7 +178,7 @@ 
     prefix = ""
     if opts['stdin']:
         try:
-            (type, r) = raw_input().split(' ')
+            (type, r) = pycompat.bytesinput(sys.stdin, sys.stdout).split(' ')
             prefix = "    "
         except EOFError:
             return
@@ -195,7 +196,8 @@ 
         catcommit(ui, repo, n, prefix)
         if opts['stdin']:
             try:
-                (type, r) = raw_input().split(' ')
+                (type, r) = pycompat.bytesinput(
+                    sys.stdin, sys.stdout).split(' ')
             except EOFError:
                 break
         else: