[PATCH 1 of 3] ui: keep the I/O streams as attributes rather than using the globals
Idan Kamara
idankk86 at gmail.com
Tue Jun 7 08:55:44 CDT 2011
# HG changeset patch
# User Idan Kamara <idankk86 at gmail.com>
# Date 1307443149 -10800
# Node ID 717b9ae1694d3e125f865dc89743166533914240
# Parent 3c7907dc95ca4f0e127631df180215d21af4d00a
ui: keep the I/O streams as attributes rather than using the globals
This should be the preferred way to control I/O, rather than replacing
sys.stdin/out/err.
diff -r 3c7907dc95ca -r 717b9ae1694d mercurial/hgweb/protocol.py
--- a/mercurial/hgweb/protocol.py Mon Jun 06 21:02:48 2011 +0200
+++ b/mercurial/hgweb/protocol.py Tue Jun 07 13:39:09 2011 +0300
@@ -12,9 +12,10 @@
HGTYPE = 'application/mercurial-0.1'
class webproto(object):
- def __init__(self, req):
+ def __init__(self, req, ui):
self.req = req
self.response = ''
+ self.ui = ui
def getargs(self, args):
knownargs = self._args()
data = {}
@@ -46,8 +47,12 @@
for s in util.filechunkiter(self.req, limit=length):
fp.write(s)
def redirect(self):
- self.oldio = sys.stdout, sys.stderr
- sys.stderr = sys.stdout = cStringIO.StringIO()
+ self.oldio = self.ui.fout, self.ui.ferr
+ self.ui.ferr = self.ui.fout = cStringIO.StringIO()
+ def restore(self):
+ val = self.ui.fout.getvalue()
+ self.ui.ferr, self.ui.fout = self.oldio
+ return val
def groupchunks(self, cg):
z = zlib.compressobj()
while True:
@@ -66,7 +71,7 @@
return cmd in wireproto.commands
def call(repo, req, cmd):
- p = webproto(req)
+ p = webproto(req, repo.ui)
rsp = wireproto.dispatch(repo, p, cmd)
if isinstance(rsp, str):
req.respond(HTTP_OK, HGTYPE, length=len(rsp))
@@ -75,14 +80,13 @@
req.respond(HTTP_OK, HGTYPE)
return rsp.gen
elif isinstance(rsp, wireproto.pushres):
- val = sys.stdout.getvalue()
- sys.stdout, sys.stderr = p.oldio
+ val = p.restore()
req.respond(HTTP_OK, HGTYPE)
return ['%d\n%s' % (rsp.res, val)]
elif isinstance(rsp, wireproto.pusherr):
# drain the incoming bundle
req.drain()
- sys.stdout, sys.stderr = p.oldio
+ p.restore()
rsp = '0\n%s\n' % rsp.res
req.respond(HTTP_OK, HGTYPE, length=len(rsp))
return [rsp]
diff -r 3c7907dc95ca -r 717b9ae1694d mercurial/sshserver.py
--- a/mercurial/sshserver.py Mon Jun 06 21:02:48 2011 +0200
+++ b/mercurial/sshserver.py Tue Jun 07 13:39:09 2011 +0300
@@ -14,11 +14,11 @@
self.ui = ui
self.repo = repo
self.lock = None
- self.fin = sys.stdin
- self.fout = sys.stdout
+ self.fin = ui.fin
+ self.fout = ui.fout
hook.redirect(True)
- sys.stdout = sys.stderr
+ ui.fout = repo.ui.fout = ui.ferr
# Prevent insertion/deletion of CRs
util.setbinary(self.fin)
diff -r 3c7907dc95ca -r 717b9ae1694d mercurial/ui.py
--- a/mercurial/ui.py Mon Jun 06 21:02:48 2011 +0200
+++ b/mercurial/ui.py Tue Jun 07 13:39:09 2011 +0300
@@ -21,6 +21,10 @@
self._trustgroups = set()
if src:
+ self.fout = src.fout
+ self.ferr = src.ferr
+ self.fin = src.fin
+
self._tcfg = src._tcfg.copy()
self._ucfg = src._ucfg.copy()
self._ocfg = src._ocfg.copy()
@@ -29,6 +33,10 @@
self.environ = src.environ
self.fixconfig()
else:
+ self.fout = sys.stdout
+ self.ferr = sys.stderr
+ self.fin = sys.stdin
+
# shared read-only environment
self.environ = os.environ
# we always trust global config files
@@ -435,26 +443,26 @@
self._buffers[-1].extend([str(a) for a in args])
else:
for a in args:
- sys.stdout.write(str(a))
+ self.fout.write(str(a))
def write_err(self, *args, **opts):
try:
- if not getattr(sys.stdout, 'closed', False):
- sys.stdout.flush()
+ if not getattr(self.fout, 'closed', False):
+ self.fout.flush()
for a in args:
- sys.stderr.write(str(a))
+ self.ferr.write(str(a))
# stderr may be buffered under win32 when redirected to files,
# including stdout.
- if not getattr(sys.stderr, 'closed', False):
- sys.stderr.flush()
+ if not getattr(self.ferr, 'closed', False):
+ self.ferr.flush()
except IOError, inst:
if inst.errno not in (errno.EPIPE, errno.EIO):
raise
def flush(self):
- try: sys.stdout.flush()
+ try: self.fout.flush()
except: pass
- try: sys.stderr.flush()
+ try: self.ferr.flush()
except: pass
def interactive(self):
@@ -475,7 +483,7 @@
if i is None:
# some environments replace stdin without implementing isatty
# usually those are non-interactive
- return util.isatty(sys.stdin)
+ return util.isatty(self.fin)
return i
@@ -513,12 +521,12 @@
if i is None:
# some environments replace stdout without implementing isatty
# usually those are non-interactive
- return util.isatty(sys.stdout)
+ return util.isatty(self.fout)
return i
def _readline(self, prompt=''):
- if util.isatty(sys.stdin):
+ if util.isatty(self.fin):
try:
# magically add command line editing support, where
# available
@@ -528,7 +536,14 @@
# windows sometimes raises something other than ImportError
except Exception:
pass
+
+ # instead of trying to emulate raw_input, swap our in/out
+ # with sys.stdin/out
+ old = sys.stdout, sys.stdin
+ sys.stdout, sys.stdin = self.fout, self.fin
line = raw_input(prompt)
+ sys.stdout, sys.stdin = old
+
# When stdin is in binary mode on Windows, it can cause
# raw_input() to emit an extra trailing carriage return
if os.linesep == '\r\n' and line and line[-1] == '\r':
diff -r 3c7907dc95ca -r 717b9ae1694d tests/test-ui-color.py
--- a/tests/test-ui-color.py Mon Jun 06 21:02:48 2011 +0200
+++ b/tests/test-ui-color.py Tue Jun 07 13:39:09 2011 +0300
@@ -19,13 +19,13 @@
ui_ = ui.ui()
ui_.setconfig('ui', 'formatted', 'True')
+# we're not interested in the output, so write that to devnull
+ui_.fout = open(os.devnull, 'w')
+
# call some arbitrary command just so we go through
# color's wrapped _runcommand twice.
-# we're not interested in the output, so write that to devnull
def runcmd():
- sys.stdout = open(os.devnull, 'w')
dispatch.dispatch(dispatch.request(['version', '-q'], ui_))
- sys.stdout = sys.__stdout__
runcmd()
print "colored? " + str(issubclass(ui_.__class__, color.colorui))
More information about the Mercurial-devel
mailing list