49 procutil, |
54 procutil, |
50 resourceutil, |
55 resourceutil, |
51 stringutil, |
56 stringutil, |
52 urlutil, |
57 urlutil, |
53 ) |
58 ) |
|
59 |
|
60 # The **opts args of the various write() methods can be basically anything, but |
|
61 # there's no way to express it as "anything but str". So type it to be the |
|
62 # handful of known types that are used. |
|
63 _MsgOpts = Union[bytes, bool, List["_PromptChoice"]] |
|
64 _PromptChoice = Tuple[bytes, bytes] |
54 |
65 |
55 urlreq = util.urlreq |
66 urlreq = util.urlreq |
56 |
67 |
57 # for use with str.translate(None, _keepalnum), to keep just alphanumerics |
68 # for use with str.translate(None, _keepalnum), to keep just alphanumerics |
58 _keepalnum = b''.join( |
69 _keepalnum = b''.join( |
1202 def canbatchlabeledwrites(self): |
1213 def canbatchlabeledwrites(self): |
1203 '''check if write calls with labels are batchable''' |
1214 '''check if write calls with labels are batchable''' |
1204 # Windows color printing is special, see ``write``. |
1215 # Windows color printing is special, see ``write``. |
1205 return self._colormode != b'win32' |
1216 return self._colormode != b'win32' |
1206 |
1217 |
1207 def write(self, *args, **opts): |
1218 def write(self, *args: bytes, **opts: _MsgOpts) -> None: |
1208 """write args to output |
1219 """write args to output |
1209 |
1220 |
1210 By default, this method simply writes to the buffer or stdout. |
1221 By default, this method simply writes to the buffer or stdout. |
1211 Color mode can be set on the UI class to have the output decorated |
1222 Color mode can be set on the UI class to have the output decorated |
1212 with color modifier before being written to stdout. |
1223 with color modifier before being written to stdout. |
1260 finally: |
1271 finally: |
1261 self._blockedtimes[b'stdio_blocked'] += ( |
1272 self._blockedtimes[b'stdio_blocked'] += ( |
1262 util.timer() - starttime |
1273 util.timer() - starttime |
1263 ) * 1000 |
1274 ) * 1000 |
1264 |
1275 |
1265 def write_err(self, *args, **opts): |
1276 def write_err(self, *args: bytes, **opts: _MsgOpts) -> None: |
1266 self._write(self._ferr, *args, **opts) |
1277 self._write(self._ferr, *args, **opts) |
1267 |
1278 |
1268 def _write(self, dest, *args, **opts): |
1279 def _write(self, dest, *args: bytes, **opts: _MsgOpts) -> None: |
1269 # update write() as well if you touch this code |
1280 # update write() as well if you touch this code |
1270 if self._isbuffered(dest): |
1281 if self._isbuffered(dest): |
1271 label = opts.get('label', b'') |
1282 label = opts.get('label', b'') |
1272 if label and self._bufferapplylabels: |
1283 if label and self._bufferapplylabels: |
1273 self._buffers[-1].extend(self.label(a, label) for a in args) |
1284 self._buffers[-1].extend(self.label(a, label) for a in args) |
1274 else: |
1285 else: |
1275 self._buffers[-1].extend(args) |
1286 self._buffers[-1].extend(args) |
1276 else: |
1287 else: |
1277 self._writenobuf(dest, *args, **opts) |
1288 self._writenobuf(dest, *args, **opts) |
1278 |
1289 |
1279 def _writenobuf(self, dest, *args, **opts): |
1290 def _writenobuf(self, dest, *args: bytes, **opts: _MsgOpts) -> None: |
1280 # update write() as well if you touch this code |
1291 # update write() as well if you touch this code |
1281 if not opts.get('keepprogressbar', False): |
1292 if not opts.get('keepprogressbar', False): |
1282 self._progclear() |
1293 self._progclear() |
1283 msg = b''.join(args) |
1294 msg = b''.join(args) |
1284 |
1295 |
1333 ) + args |
1344 ) + args |
1334 _writemsgwith(self._write, dest, *args, **opts) |
1345 _writemsgwith(self._write, dest, *args, **opts) |
1335 if timestamp: |
1346 if timestamp: |
1336 dest.flush() |
1347 dest.flush() |
1337 |
1348 |
1338 def _writemsgnobuf(self, dest, *args, **opts): |
1349 def _writemsgnobuf(self, dest, *args: bytes, **opts: _MsgOpts) -> None: |
1339 _writemsgwith(self._writenobuf, dest, *args, **opts) |
1350 _writemsgwith(self._writenobuf, dest, *args, **opts) |
1340 |
1351 |
1341 def flush(self): |
1352 def flush(self) -> None: |
1342 # opencode timeblockedsection because this is a critical path |
1353 # opencode timeblockedsection because this is a critical path |
1343 starttime = util.timer() |
1354 starttime = util.timer() |
1344 try: |
1355 try: |
1345 try: |
1356 try: |
1346 self._fout.flush() |
1357 self._fout.flush() |
1695 # usually those are non-interactive |
1706 # usually those are non-interactive |
1696 return self._isatty(self._fout) |
1707 return self._isatty(self._fout) |
1697 |
1708 |
1698 return i |
1709 return i |
1699 |
1710 |
1700 def _readline(self, prompt=b' ', promptopts=None): |
1711 def _readline( |
|
1712 self, |
|
1713 prompt: bytes = b' ', |
|
1714 promptopts: Optional[Dict[str, _MsgOpts]] = None, |
|
1715 ) -> bytes: |
1701 # Replacing stdin/stdout temporarily is a hard problem on Python 3 |
1716 # Replacing stdin/stdout temporarily is a hard problem on Python 3 |
1702 # because they have to be text streams with *no buffering*. Instead, |
1717 # because they have to be text streams with *no buffering*. Instead, |
1703 # we use rawinput() only if call_readline() will be invoked by |
1718 # we use rawinput() only if call_readline() will be invoked by |
1704 # PyOS_Readline(), so no I/O will be made at Python layer. |
1719 # PyOS_Readline(), so no I/O will be made at Python layer. |
1705 usereadline = ( |
1720 usereadline = ( |
1777 return r |
1792 return r |
1778 except EOFError: |
1793 except EOFError: |
1779 raise error.ResponseExpected() |
1794 raise error.ResponseExpected() |
1780 |
1795 |
1781 @staticmethod |
1796 @staticmethod |
1782 def extractchoices(prompt): |
1797 def extractchoices(prompt: bytes) -> Tuple[bytes, List[_PromptChoice]]: |
1783 """Extract prompt message and list of choices from specified prompt. |
1798 """Extract prompt message and list of choices from specified prompt. |
1784 |
1799 |
1785 This returns tuple "(message, choices)", and "choices" is the |
1800 This returns tuple "(message, choices)", and "choices" is the |
1786 list of tuple "(response character, text without &)". |
1801 list of tuple "(response character, text without &)". |
1787 |
1802 |
1809 ampidx = s.index(b'&') |
1824 ampidx = s.index(b'&') |
1810 return s[ampidx + 1 : ampidx + 2].lower(), s.replace(b'&', b'', 1) |
1825 return s[ampidx + 1 : ampidx + 2].lower(), s.replace(b'&', b'', 1) |
1811 |
1826 |
1812 return (msg, [choicetuple(s) for s in choices]) |
1827 return (msg, [choicetuple(s) for s in choices]) |
1813 |
1828 |
1814 def promptchoice(self, prompt, default=0): |
1829 def promptchoice(self, prompt: bytes, default: int = 0) -> int: |
1815 """Prompt user with a message, read response, and ensure it matches |
1830 """Prompt user with a message, read response, and ensure it matches |
1816 one of the provided choices. The prompt is formatted as follows: |
1831 one of the provided choices. The prompt is formatted as follows: |
1817 |
1832 |
1818 "would you like fries with that (Yn)? $$ &Yes $$ &No" |
1833 "would you like fries with that (Yn)? $$ &Yes $$ &No" |
1819 |
1834 |
1829 if r.lower() in resps: |
1844 if r.lower() in resps: |
1830 return resps.index(r.lower()) |
1845 return resps.index(r.lower()) |
1831 # TODO: shouldn't it be a warning? |
1846 # TODO: shouldn't it be a warning? |
1832 self._writemsg(self._fmsgout, _(b"unrecognized response\n")) |
1847 self._writemsg(self._fmsgout, _(b"unrecognized response\n")) |
1833 |
1848 |
1834 def getpass(self, prompt=None, default=None): |
1849 def getpass( |
|
1850 self, prompt: Optional[bytes] = None, default: Optional[bytes] = None |
|
1851 ) -> Optional[bytes]: |
1835 if not self.interactive(): |
1852 if not self.interactive(): |
1836 return default |
1853 return default |
1837 try: |
1854 try: |
1838 self._writemsg( |
1855 self._writemsg( |
1839 self._fmsgerr, |
1856 self._fmsgerr, |
1852 else: |
1869 else: |
1853 return util.get_password() |
1870 return util.get_password() |
1854 except EOFError: |
1871 except EOFError: |
1855 raise error.ResponseExpected() |
1872 raise error.ResponseExpected() |
1856 |
1873 |
1857 def status(self, *msg, **opts): |
1874 def status(self, *msg: bytes, **opts: _MsgOpts) -> None: |
1858 """write status message to output (if ui.quiet is False) |
1875 """write status message to output (if ui.quiet is False) |
1859 |
1876 |
1860 This adds an output label of "ui.status". |
1877 This adds an output label of "ui.status". |
1861 """ |
1878 """ |
1862 if not self.quiet: |
1879 if not self.quiet: |
1863 self._writemsg(self._fmsgout, type=b'status', *msg, **opts) |
1880 self._writemsg(self._fmsgout, type=b'status', *msg, **opts) |
1864 |
1881 |
1865 def warn(self, *msg, **opts): |
1882 def warn(self, *msg: bytes, **opts: _MsgOpts) -> None: |
1866 """write warning message to output (stderr) |
1883 """write warning message to output (stderr) |
1867 |
1884 |
1868 This adds an output label of "ui.warning". |
1885 This adds an output label of "ui.warning". |
1869 """ |
1886 """ |
1870 self._writemsg(self._fmsgerr, type=b'warning', *msg, **opts) |
1887 self._writemsg(self._fmsgerr, type=b'warning', *msg, **opts) |
1871 |
1888 |
1872 def error(self, *msg, **opts): |
1889 def error(self, *msg: bytes, **opts: _MsgOpts) -> None: |
1873 """write error message to output (stderr) |
1890 """write error message to output (stderr) |
1874 |
1891 |
1875 This adds an output label of "ui.error". |
1892 This adds an output label of "ui.error". |
1876 """ |
1893 """ |
1877 self._writemsg(self._fmsgerr, type=b'error', *msg, **opts) |
1894 self._writemsg(self._fmsgerr, type=b'error', *msg, **opts) |
1878 |
1895 |
1879 def note(self, *msg, **opts): |
1896 def note(self, *msg: bytes, **opts: _MsgOpts) -> None: |
1880 """write note to output (if ui.verbose is True) |
1897 """write note to output (if ui.verbose is True) |
1881 |
1898 |
1882 This adds an output label of "ui.note". |
1899 This adds an output label of "ui.note". |
1883 """ |
1900 """ |
1884 if self.verbose: |
1901 if self.verbose: |
1885 self._writemsg(self._fmsgout, type=b'note', *msg, **opts) |
1902 self._writemsg(self._fmsgout, type=b'note', *msg, **opts) |
1886 |
1903 |
1887 def debug(self, *msg, **opts): |
1904 def debug(self, *msg: bytes, **opts: _MsgOpts) -> None: |
1888 """write debug message to output (if ui.debugflag is True) |
1905 """write debug message to output (if ui.debugflag is True) |
1889 |
1906 |
1890 This adds an output label of "ui.debug". |
1907 This adds an output label of "ui.debug". |
1891 """ |
1908 """ |
1892 if self.debugflag: |
1909 if self.debugflag: |
2146 for logger in activeloggers: |
2163 for logger in activeloggers: |
2147 logger.log(self, event, msg, opts) |
2164 logger.log(self, event, msg, opts) |
2148 finally: |
2165 finally: |
2149 self._loggers = registeredloggers |
2166 self._loggers = registeredloggers |
2150 |
2167 |
2151 def label(self, msg, label): |
2168 def label(self, msg: bytes, label: bytes) -> bytes: |
2152 """style msg based on supplied label |
2169 """style msg based on supplied label |
2153 |
2170 |
2154 If some color mode is enabled, this will add the necessary control |
2171 If some color mode is enabled, this will add the necessary control |
2155 characters to apply such color. In addition, 'debug' color mode adds |
2172 characters to apply such color. In addition, 'debug' color mode adds |
2156 markup showing which label affects a piece of text. |
2173 markup showing which label affects a piece of text. |
2160 """ |
2177 """ |
2161 if self._colormode is not None: |
2178 if self._colormode is not None: |
2162 return color.colorlabel(self, msg, label) |
2179 return color.colorlabel(self, msg, label) |
2163 return msg |
2180 return msg |
2164 |
2181 |
2165 def develwarn(self, msg, stacklevel=1, config=None): |
2182 def develwarn( |
|
2183 self, msg: bytes, stacklevel: int = 1, config: Optional[bytes] = None |
|
2184 ) -> None: |
2166 """issue a developer warning message |
2185 """issue a developer warning message |
2167 |
2186 |
2168 Use 'stacklevel' to report the offender some layers further up in the |
2187 Use 'stacklevel' to report the offender some layers further up in the |
2169 stack. |
2188 stack. |
2170 """ |
2189 """ |
2285 if name == b'stderr': |
2306 if name == b'stderr': |
2286 return ui.ferr, ui.ferr |
2307 return ui.ferr, ui.ferr |
2287 raise error.Abort(b'invalid ui.message-output destination: %s' % name) |
2308 raise error.Abort(b'invalid ui.message-output destination: %s' % name) |
2288 |
2309 |
2289 |
2310 |
2290 def _writemsgwith(write, dest, *args, **opts): |
2311 def _writemsgwith(write, dest, *args: bytes, **opts: _MsgOpts) -> None: |
2291 """Write ui message with the given ui._write*() function |
2312 """Write ui message with the given ui._write*() function |
2292 |
2313 |
2293 The specified message type is translated to 'ui.<type>' label if the dest |
2314 The specified message type is translated to 'ui.<type>' label if the dest |
2294 isn't a structured channel, so that the message will be colorized. |
2315 isn't a structured channel, so that the message will be colorized. |
2295 """ |
2316 """ |