##// 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 # be unbuffered no matter if it is a tty or not.
409 # be unbuffered no matter if it is a tty or not.
410 if fn == b'ferr':
410 if fn == b'ferr':
411 newfp = fp
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)
417 else:
418 newfp = procutil.unwrap_line_buffered(fp)
412 else:
419 else:
413 # make it line buffered explicitly because the default is
420 # Python 2 uses the I/O streams provided by the C library, so
414 # decided on first write(), where fout could be a pager.
421 # make it line-buffered explicitly. Otherwise the default would
422 # be decided on first write(), where fout could be a pager.
415 if fp.isatty():
423 if fp.isatty():
416 bufsize = 1 # line buffered
424 bufsize = 1 # line buffered
417 else:
425 else:
418 bufsize = -1 # system default
426 bufsize = -1 # system default
419 newfp = os.fdopen(fp.fileno(), mode, bufsize)
427 newfp = os.fdopen(fp.fileno(), mode, bufsize)
428 if newfp is not fp:
420 setattr(ui, fn, newfp)
429 setattr(ui, fn, newfp)
421 setattr(self, cn, newfp)
430 setattr(self, cn, newfp)
422
431
@@ -440,13 +449,16 b' class chgcmdserver(commandserver.server)'
440 ui = self.ui
449 ui = self.ui
441 for (ch, fp, fd), (cn, fn, mode) in zip(self._oldios, _iochannels):
450 for (ch, fp, fd), (cn, fn, mode) in zip(self._oldios, _iochannels):
442 newfp = getattr(ui, fn)
451 newfp = getattr(ui, fn)
443 # close newfp while it's associated with client; otherwise it
452 # On Python 2, newfp and fp may be separate file objects associated
444 # would be closed when newfp is deleted
453 # with the same fd, so we must close newfp while it's associated
445 if newfp is not fp:
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 newfp.close()
458 newfp.close()
447 # restore original fd: fp is open again
459 # restore original fd: fp is open again
448 try:
460 try:
449 if newfp is fp and 'w' in mode:
461 if (pycompat.ispy3 or newfp is fp) and 'w' in mode:
450 # Discard buffered data which couldn't be flushed because
462 # Discard buffered data which couldn't be flushed because
451 # of EPIPE. The data should belong to the current session
463 # of EPIPE. The data should belong to the current session
452 # and should never persist.
464 # and should never persist.
@@ -80,6 +80,13 b' def make_line_buffered(stream):'
80 return LineBufferedWrapper(stream)
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 class WriteAllWrapper(object):
90 class WriteAllWrapper(object):
84 def __init__(self, orig):
91 def __init__(self, orig):
85 self.orig = orig
92 self.orig = orig
General Comments 0
You need to be logged in to leave comments. Login now