##// END OF EJS Templates
chgserver: backport py3 buffered I/O workarounds from procutil...
Yuya Nishihara -
r46452:b56feaa9 default
parent child Browse files
Show More
@@ -409,14 +409,23 b' class chgcmdserver(commandserver.server)'
409 409 # be unbuffered no matter if it is a tty or not.
410 410 if fn == b'ferr':
411 411 newfp = fp
412 elif pycompat.ispy3:
413 # On Python 3, the standard library doesn't offer line-buffered
414 # binary streams, so wrap/unwrap it.
415 if fp.isatty():
416 newfp = procutil.make_line_buffered(fp)
412 417 else:
413 # make it line buffered explicitly because the default is
414 # decided on first write(), where fout could be a pager.
418 newfp = procutil.unwrap_line_buffered(fp)
419 else:
420 # Python 2 uses the I/O streams provided by the C library, so
421 # make it line-buffered explicitly. Otherwise the default would
422 # be decided on first write(), where fout could be a pager.
415 423 if fp.isatty():
416 424 bufsize = 1 # line buffered
417 425 else:
418 426 bufsize = -1 # system default
419 427 newfp = os.fdopen(fp.fileno(), mode, bufsize)
428 if newfp is not fp:
420 429 setattr(ui, fn, newfp)
421 430 setattr(self, cn, newfp)
422 431
@@ -440,13 +449,16 b' class chgcmdserver(commandserver.server)'
440 449 ui = self.ui
441 450 for (ch, fp, fd), (cn, fn, mode) in zip(self._oldios, _iochannels):
442 451 newfp = getattr(ui, fn)
443 # close newfp while it's associated with client; otherwise it
444 # would be closed when newfp is deleted
445 if newfp is not fp:
452 # On Python 2, newfp and fp may be separate file objects associated
453 # with the same fd, so we must close newfp while it's associated
454 # with the client. Otherwise the new associated fd would be closed
455 # when newfp gets deleted. On Python 3, newfp is just a wrapper
456 # around fp even if newfp is not fp, so deleting newfp is safe.
457 if not (pycompat.ispy3 or newfp is fp):
446 458 newfp.close()
447 459 # restore original fd: fp is open again
448 460 try:
449 if newfp is fp and 'w' in mode:
461 if (pycompat.ispy3 or newfp is fp) and 'w' in mode:
450 462 # Discard buffered data which couldn't be flushed because
451 463 # of EPIPE. The data should belong to the current session
452 464 # and should never persist.
@@ -80,6 +80,13 b' def make_line_buffered(stream):'
80 80 return LineBufferedWrapper(stream)
81 81
82 82
83 def unwrap_line_buffered(stream):
84 if isinstance(stream, LineBufferedWrapper):
85 assert not isinstance(stream.orig, LineBufferedWrapper)
86 return stream.orig
87 return stream
88
89
83 90 class WriteAllWrapper(object):
84 91 def __init__(self, orig):
85 92 self.orig = orig
General Comments 0
You need to be logged in to leave comments. Login now