Mercurial > hg-stable
comparison mercurial/ui.py @ 40593:7bffbbe03e90
ui: hide fin/fout/ferr attributes behind @property functions
This allows keeping references to fout/ferr/fin which are updated when these
properties are changed. See the next patch.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 03 Nov 2018 20:53:31 +0900 |
parents | d8997c5ce2ff |
children | 840cd57cde32 |
comparison
equal
deleted
inserted
replaced
40592:d8997c5ce2ff | 40593:7bffbbe03e90 |
---|---|
229 self._terminfoparams = {} | 229 self._terminfoparams = {} |
230 self._styles = {} | 230 self._styles = {} |
231 self._uninterruptible = False | 231 self._uninterruptible = False |
232 | 232 |
233 if src: | 233 if src: |
234 self.fout = src.fout | 234 self._fout = src._fout |
235 self.ferr = src.ferr | 235 self._ferr = src._ferr |
236 self.fin = src.fin | 236 self._fin = src._fin |
237 self._finoutredirected = src._finoutredirected | 237 self._finoutredirected = src._finoutredirected |
238 self.pageractive = src.pageractive | 238 self.pageractive = src.pageractive |
239 self._disablepager = src._disablepager | 239 self._disablepager = src._disablepager |
240 self._tweaked = src._tweaked | 240 self._tweaked = src._tweaked |
241 | 241 |
254 self.fixconfig() | 254 self.fixconfig() |
255 | 255 |
256 self.httppasswordmgrdb = src.httppasswordmgrdb | 256 self.httppasswordmgrdb = src.httppasswordmgrdb |
257 self._blockedtimes = src._blockedtimes | 257 self._blockedtimes = src._blockedtimes |
258 else: | 258 else: |
259 self.fout = procutil.stdout | 259 self._fout = procutil.stdout |
260 self.ferr = procutil.stderr | 260 self._ferr = procutil.stderr |
261 self.fin = procutil.stdin | 261 self._fin = procutil.stdin |
262 self._finoutredirected = False | 262 self._finoutredirected = False |
263 self.pageractive = False | 263 self.pageractive = False |
264 self._disablepager = False | 264 self._disablepager = False |
265 self._tweaked = False | 265 self._tweaked = False |
266 | 266 |
882 | 882 |
883 @util.propertycache | 883 @util.propertycache |
884 def paths(self): | 884 def paths(self): |
885 return paths(self) | 885 return paths(self) |
886 | 886 |
887 @property | |
888 def fout(self): | |
889 return self._fout | |
890 | |
891 @fout.setter | |
892 def fout(self, f): | |
893 self._fout = f | |
894 | |
895 @property | |
896 def ferr(self): | |
897 return self._ferr | |
898 | |
899 @ferr.setter | |
900 def ferr(self, f): | |
901 self._ferr = f | |
902 | |
903 @property | |
904 def fin(self): | |
905 return self._fin | |
906 | |
907 @fin.setter | |
908 def fin(self, f): | |
909 self._fin = f | |
910 | |
887 def pushbuffer(self, error=False, subproc=False, labeled=False): | 911 def pushbuffer(self, error=False, subproc=False, labeled=False): |
888 """install a buffer to capture standard output of the ui object | 912 """install a buffer to capture standard output of the ui object |
889 | 913 |
890 If error is True, the error output will be captured too. | 914 If error is True, the error output will be captured too. |
891 | 915 |
912 self._bufferapplylabels = None | 936 self._bufferapplylabels = None |
913 | 937 |
914 return "".join(self._buffers.pop()) | 938 return "".join(self._buffers.pop()) |
915 | 939 |
916 def _isbuffered(self, dest): | 940 def _isbuffered(self, dest): |
917 if dest is self.fout: | 941 if dest is self._fout: |
918 return bool(self._buffers) | 942 return bool(self._buffers) |
919 if dest is self.ferr: | 943 if dest is self._ferr: |
920 return bool(self._bufferstates and self._bufferstates[-1][0]) | 944 return bool(self._bufferstates and self._bufferstates[-1][0]) |
921 return False | 945 return False |
922 | 946 |
923 def canwritewithoutlabels(self): | 947 def canwritewithoutlabels(self): |
924 '''check if write skips the label''' | 948 '''check if write skips the label''' |
945 | 969 |
946 When labeling output for a specific command, a label of | 970 When labeling output for a specific command, a label of |
947 "cmdname.type" is recommended. For example, status issues | 971 "cmdname.type" is recommended. For example, status issues |
948 a label of "status.modified" for modified files. | 972 a label of "status.modified" for modified files. |
949 ''' | 973 ''' |
950 self._write(self.fout, *args, **opts) | 974 self._write(self._fout, *args, **opts) |
951 | 975 |
952 def write_err(self, *args, **opts): | 976 def write_err(self, *args, **opts): |
953 self._write(self.ferr, *args, **opts) | 977 self._write(self._ferr, *args, **opts) |
954 | 978 |
955 def _write(self, dest, *args, **opts): | 979 def _write(self, dest, *args, **opts): |
956 if self._isbuffered(dest): | 980 if self._isbuffered(dest): |
957 if self._bufferapplylabels: | 981 if self._bufferapplylabels: |
958 label = opts.get(r'label', '') | 982 label = opts.get(r'label', '') |
967 msg = b''.join(args) | 991 msg = b''.join(args) |
968 | 992 |
969 # opencode timeblockedsection because this is a critical path | 993 # opencode timeblockedsection because this is a critical path |
970 starttime = util.timer() | 994 starttime = util.timer() |
971 try: | 995 try: |
972 if dest is self.ferr and not getattr(self.fout, 'closed', False): | 996 if dest is self._ferr and not getattr(self._fout, 'closed', False): |
973 self.fout.flush() | 997 self._fout.flush() |
974 if self._colormode == 'win32': | 998 if self._colormode == 'win32': |
975 # windows color printing is its own can of crab, defer to | 999 # windows color printing is its own can of crab, defer to |
976 # the color module and that is it. | 1000 # the color module and that is it. |
977 color.win32print(self, dest.write, msg, **opts) | 1001 color.win32print(self, dest.write, msg, **opts) |
978 else: | 1002 else: |
980 label = opts.get(r'label', '') | 1004 label = opts.get(r'label', '') |
981 msg = self.label(msg, label) | 1005 msg = self.label(msg, label) |
982 dest.write(msg) | 1006 dest.write(msg) |
983 # stderr may be buffered under win32 when redirected to files, | 1007 # stderr may be buffered under win32 when redirected to files, |
984 # including stdout. | 1008 # including stdout. |
985 if dest is self.ferr and not getattr(self.ferr, 'closed', False): | 1009 if dest is self._ferr and not getattr(self._ferr, 'closed', False): |
986 dest.flush() | 1010 dest.flush() |
987 except IOError as err: | 1011 except IOError as err: |
988 if (dest is self.ferr | 1012 if (dest is self._ferr |
989 and err.errno in (errno.EPIPE, errno.EIO, errno.EBADF)): | 1013 and err.errno in (errno.EPIPE, errno.EIO, errno.EBADF)): |
990 # no way to report the error, so ignore it | 1014 # no way to report the error, so ignore it |
991 return | 1015 return |
992 raise error.StdioError(err) | 1016 raise error.StdioError(err) |
993 finally: | 1017 finally: |
997 def flush(self): | 1021 def flush(self): |
998 # opencode timeblockedsection because this is a critical path | 1022 # opencode timeblockedsection because this is a critical path |
999 starttime = util.timer() | 1023 starttime = util.timer() |
1000 try: | 1024 try: |
1001 try: | 1025 try: |
1002 self.fout.flush() | 1026 self._fout.flush() |
1003 except IOError as err: | 1027 except IOError as err: |
1004 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): | 1028 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): |
1005 raise error.StdioError(err) | 1029 raise error.StdioError(err) |
1006 finally: | 1030 finally: |
1007 try: | 1031 try: |
1008 self.ferr.flush() | 1032 self._ferr.flush() |
1009 except IOError as err: | 1033 except IOError as err: |
1010 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): | 1034 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): |
1011 raise error.StdioError(err) | 1035 raise error.StdioError(err) |
1012 finally: | 1036 finally: |
1013 self._blockedtimes['stdio_blocked'] += \ | 1037 self._blockedtimes['stdio_blocked'] += \ |
1253 ''' | 1277 ''' |
1254 i = self.configbool("ui", "interactive") | 1278 i = self.configbool("ui", "interactive") |
1255 if i is None: | 1279 if i is None: |
1256 # some environments replace stdin without implementing isatty | 1280 # some environments replace stdin without implementing isatty |
1257 # usually those are non-interactive | 1281 # usually those are non-interactive |
1258 return self._isatty(self.fin) | 1282 return self._isatty(self._fin) |
1259 | 1283 |
1260 return i | 1284 return i |
1261 | 1285 |
1262 def termwidth(self): | 1286 def termwidth(self): |
1263 '''how wide is the terminal in columns? | 1287 '''how wide is the terminal in columns? |
1291 | 1315 |
1292 i = self.configbool("ui", "formatted") | 1316 i = self.configbool("ui", "formatted") |
1293 if i is None: | 1317 if i is None: |
1294 # some environments replace stdout without implementing isatty | 1318 # some environments replace stdout without implementing isatty |
1295 # usually those are non-interactive | 1319 # usually those are non-interactive |
1296 return self._isatty(self.fout) | 1320 return self._isatty(self._fout) |
1297 | 1321 |
1298 return i | 1322 return i |
1299 | 1323 |
1300 def _readline(self): | 1324 def _readline(self): |
1301 # Replacing stdin/stdout temporarily is a hard problem on Python 3 | 1325 # Replacing stdin/stdout temporarily is a hard problem on Python 3 |
1302 # because they have to be text streams with *no buffering*. Instead, | 1326 # because they have to be text streams with *no buffering*. Instead, |
1303 # we use rawinput() only if call_readline() will be invoked by | 1327 # we use rawinput() only if call_readline() will be invoked by |
1304 # PyOS_Readline(), so no I/O will be made at Python layer. | 1328 # PyOS_Readline(), so no I/O will be made at Python layer. |
1305 usereadline = (self._isatty(self.fin) and self._isatty(self.fout) | 1329 usereadline = (self._isatty(self._fin) and self._isatty(self._fout) |
1306 and procutil.isstdin(self.fin) | 1330 and procutil.isstdin(self._fin) |
1307 and procutil.isstdout(self.fout)) | 1331 and procutil.isstdout(self._fout)) |
1308 if usereadline: | 1332 if usereadline: |
1309 try: | 1333 try: |
1310 # magically add command line editing support, where | 1334 # magically add command line editing support, where |
1311 # available | 1335 # available |
1312 import readline | 1336 import readline |
1324 # When stdin is in binary mode on Windows, it can cause | 1348 # When stdin is in binary mode on Windows, it can cause |
1325 # raw_input() to emit an extra trailing carriage return | 1349 # raw_input() to emit an extra trailing carriage return |
1326 if pycompat.oslinesep == b'\r\n' and line.endswith(b'\r'): | 1350 if pycompat.oslinesep == b'\r\n' and line.endswith(b'\r'): |
1327 line = line[:-1] | 1351 line = line[:-1] |
1328 else: | 1352 else: |
1329 self.fout.write(b' ') | 1353 self._fout.write(b' ') |
1330 self.fout.flush() | 1354 self._fout.flush() |
1331 line = self.fin.readline() | 1355 line = self._fin.readline() |
1332 if not line: | 1356 if not line: |
1333 raise EOFError | 1357 raise EOFError |
1334 line = line.rstrip(pycompat.oslinesep) | 1358 line = line.rstrip(pycompat.oslinesep) |
1335 | 1359 |
1336 return line | 1360 return line |
1341 """ | 1365 """ |
1342 if not self.interactive(): | 1366 if not self.interactive(): |
1343 self.write(msg, ' ', label='ui.prompt') | 1367 self.write(msg, ' ', label='ui.prompt') |
1344 self.write(default or '', "\n", label='ui.promptecho') | 1368 self.write(default or '', "\n", label='ui.promptecho') |
1345 return default | 1369 return default |
1346 self._writenobuf(self.fout, msg, label='ui.prompt') | 1370 self._writenobuf(self._fout, msg, label='ui.prompt') |
1347 self.flush() | 1371 self.flush() |
1348 try: | 1372 try: |
1349 r = self._readline() | 1373 r = self._readline() |
1350 if not r: | 1374 if not r: |
1351 r = default | 1375 r = default |
1409 self.write_err(self.label(prompt or _('password: '), 'ui.prompt')) | 1433 self.write_err(self.label(prompt or _('password: '), 'ui.prompt')) |
1410 # disable getpass() only if explicitly specified. it's still valid | 1434 # disable getpass() only if explicitly specified. it's still valid |
1411 # to interact with tty even if fin is not a tty. | 1435 # to interact with tty even if fin is not a tty. |
1412 with self.timeblockedsection('stdio'): | 1436 with self.timeblockedsection('stdio'): |
1413 if self.configbool('ui', 'nontty'): | 1437 if self.configbool('ui', 'nontty'): |
1414 l = self.fin.readline() | 1438 l = self._fin.readline() |
1415 if not l: | 1439 if not l: |
1416 raise EOFError | 1440 raise EOFError |
1417 return l.rstrip('\n') | 1441 return l.rstrip('\n') |
1418 else: | 1442 else: |
1419 return getpass.getpass('') | 1443 return getpass.getpass('') |
1535 if blockedtag is None: | 1559 if blockedtag is None: |
1536 # Long cmds tend to be because of an absolute path on cmd. Keep | 1560 # Long cmds tend to be because of an absolute path on cmd. Keep |
1537 # the tail end instead | 1561 # the tail end instead |
1538 cmdsuffix = cmd.translate(None, _keepalnum)[-85:] | 1562 cmdsuffix = cmd.translate(None, _keepalnum)[-85:] |
1539 blockedtag = 'unknown_system_' + cmdsuffix | 1563 blockedtag = 'unknown_system_' + cmdsuffix |
1540 out = self.fout | 1564 out = self._fout |
1541 if any(s[1] for s in self._bufferstates): | 1565 if any(s[1] for s in self._bufferstates): |
1542 out = self | 1566 out = self |
1543 with self.timeblockedsection(blockedtag): | 1567 with self.timeblockedsection(blockedtag): |
1544 rc = self._runsystem(cmd, environ=environ, cwd=cwd, out=out) | 1568 rc = self._runsystem(cmd, environ=environ, cwd=cwd, out=out) |
1545 if rc and onerr: | 1569 if rc and onerr: |
1680 if config is None or not self.configbool('devel', config): | 1704 if config is None or not self.configbool('devel', config): |
1681 return | 1705 return |
1682 msg = 'devel-warn: ' + msg | 1706 msg = 'devel-warn: ' + msg |
1683 stacklevel += 1 # get in develwarn | 1707 stacklevel += 1 # get in develwarn |
1684 if self.tracebackflag: | 1708 if self.tracebackflag: |
1685 util.debugstacktrace(msg, stacklevel, self.ferr, self.fout) | 1709 util.debugstacktrace(msg, stacklevel, self._ferr, self._fout) |
1686 self.log('develwarn', '%s at:\n%s' % | 1710 self.log('develwarn', '%s at:\n%s' % |
1687 (msg, ''.join(util.getstackframes(stacklevel)))) | 1711 (msg, ''.join(util.getstackframes(stacklevel)))) |
1688 else: | 1712 else: |
1689 curframe = inspect.currentframe() | 1713 curframe = inspect.currentframe() |
1690 calframe = inspect.getouterframes(curframe, 2) | 1714 calframe = inspect.getouterframes(curframe, 2) |