##// END OF EJS Templates
py3: make color use absolute_import
Pulkit Goyal -
r28968:a5d449a7 default
parent child Browse files
Show More
@@ -1,655 +1,664 b''
1 1 # color.py color output for Mercurial commands
2 2 #
3 3 # Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 '''colorize output from some commands
9 9
10 10 The color extension colorizes output from several Mercurial commands.
11 11 For example, the diff command shows additions in green and deletions
12 12 in red, while the status command shows modified files in magenta. Many
13 13 other commands have analogous colors. It is possible to customize
14 14 these colors.
15 15
16 16 Effects
17 17 -------
18 18
19 19 Other effects in addition to color, like bold and underlined text, are
20 20 also available. By default, the terminfo database is used to find the
21 21 terminal codes used to change color and effect. If terminfo is not
22 22 available, then effects are rendered with the ECMA-48 SGR control
23 23 function (aka ANSI escape codes).
24 24
25 25 The available effects in terminfo mode are 'blink', 'bold', 'dim',
26 26 'inverse', 'invisible', 'italic', 'standout', and 'underline'; in
27 27 ECMA-48 mode, the options are 'bold', 'inverse', 'italic', and
28 28 'underline'. How each is rendered depends on the terminal emulator.
29 29 Some may not be available for a given terminal type, and will be
30 30 silently ignored.
31 31
32 32 Labels
33 33 ------
34 34
35 35 Text receives color effects depending on the labels that it has. Many
36 36 default Mercurial commands emit labelled text. You can also define
37 37 your own labels in templates using the label function, see :hg:`help
38 38 templates`. A single portion of text may have more than one label. In
39 39 that case, effects given to the last label will override any other
40 40 effects. This includes the special "none" effect, which nullifies
41 41 other effects.
42 42
43 43 Labels are normally invisible. In order to see these labels and their
44 44 position in the text, use the global --color=debug option. The same
45 45 anchor text may be associated to multiple labels, e.g.
46 46
47 47 [log.changeset changeset.secret|changeset: 22611:6f0a53c8f587]
48 48
49 49 The following are the default effects for some default labels. Default
50 50 effects may be overridden from your configuration file::
51 51
52 52 [color]
53 53 status.modified = blue bold underline red_background
54 54 status.added = green bold
55 55 status.removed = red bold blue_background
56 56 status.deleted = cyan bold underline
57 57 status.unknown = magenta bold underline
58 58 status.ignored = black bold
59 59
60 60 # 'none' turns off all effects
61 61 status.clean = none
62 62 status.copied = none
63 63
64 64 qseries.applied = blue bold underline
65 65 qseries.unapplied = black bold
66 66 qseries.missing = red bold
67 67
68 68 diff.diffline = bold
69 69 diff.extended = cyan bold
70 70 diff.file_a = red bold
71 71 diff.file_b = green bold
72 72 diff.hunk = magenta
73 73 diff.deleted = red
74 74 diff.inserted = green
75 75 diff.changed = white
76 76 diff.tab =
77 77 diff.trailingwhitespace = bold red_background
78 78
79 79 # Blank so it inherits the style of the surrounding label
80 80 changeset.public =
81 81 changeset.draft =
82 82 changeset.secret =
83 83
84 84 resolve.unresolved = red bold
85 85 resolve.resolved = green bold
86 86
87 87 bookmarks.active = green
88 88
89 89 branches.active = none
90 90 branches.closed = black bold
91 91 branches.current = green
92 92 branches.inactive = none
93 93
94 94 tags.normal = green
95 95 tags.local = black bold
96 96
97 97 rebase.rebased = blue
98 98 rebase.remaining = red bold
99 99
100 100 shelve.age = cyan
101 101 shelve.newest = green bold
102 102 shelve.name = blue bold
103 103
104 104 histedit.remaining = red bold
105 105
106 106 Custom colors
107 107 -------------
108 108
109 109 Because there are only eight standard colors, this module allows you
110 110 to define color names for other color slots which might be available
111 111 for your terminal type, assuming terminfo mode. For instance::
112 112
113 113 color.brightblue = 12
114 114 color.pink = 207
115 115 color.orange = 202
116 116
117 117 to set 'brightblue' to color slot 12 (useful for 16 color terminals
118 118 that have brighter colors defined in the upper eight) and, 'pink' and
119 119 'orange' to colors in 256-color xterm's default color cube. These
120 120 defined colors may then be used as any of the pre-defined eight,
121 121 including appending '_background' to set the background to that color.
122 122
123 123 Modes
124 124 -----
125 125
126 126 By default, the color extension will use ANSI mode (or win32 mode on
127 127 Windows) if it detects a terminal. To override auto mode (to enable
128 128 terminfo mode, for example), set the following configuration option::
129 129
130 130 [color]
131 131 mode = terminfo
132 132
133 133 Any value other than 'ansi', 'win32', 'terminfo', or 'auto' will
134 134 disable color.
135 135
136 136 Note that on some systems, terminfo mode may cause problems when using
137 137 color with the pager extension and less -R. less with the -R option
138 138 will only display ECMA-48 color codes, and terminfo mode may sometimes
139 139 emit codes that less doesn't understand. You can work around this by
140 140 either using ansi mode (or auto mode), or by using less -r (which will
141 141 pass through all terminal control codes, not just color control
142 142 codes).
143 143
144 144 On some systems (such as MSYS in Windows), the terminal may support
145 145 a different color mode than the pager (activated via the "pager"
146 146 extension). It is possible to define separate modes depending on whether
147 147 the pager is active::
148 148
149 149 [color]
150 150 mode = auto
151 151 pagermode = ansi
152 152
153 153 If ``pagermode`` is not defined, the ``mode`` will be used.
154 154 '''
155 155
156 import os
156 from __future__ import absolute_import
157 157
158 from mercurial import cmdutil, commands, dispatch, extensions, subrepo, util
159 from mercurial import ui as uimod
158 import os
159 from mercurial import (
160 cmdutil,
161 commands,
162 dispatch,
163 extensions,
164 subrepo,
165 ui as uimod,
166 util,
167 )
160 168 from mercurial.i18n import _
161 169
162 170 cmdtable = {}
163 171 command = cmdutil.command(cmdtable)
164 172 # Note for extension authors: ONLY specify testedwith = 'internal' for
165 173 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
166 174 # be specifying the version(s) of Mercurial they are tested with, or
167 175 # leave the attribute unspecified.
168 176 testedwith = 'internal'
169 177
170 178 # start and stop parameters for effects
171 179 _effects = {'none': 0, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33,
172 180 'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37, 'bold': 1,
173 181 'italic': 3, 'underline': 4, 'inverse': 7, 'dim': 2,
174 182 'black_background': 40, 'red_background': 41,
175 183 'green_background': 42, 'yellow_background': 43,
176 184 'blue_background': 44, 'purple_background': 45,
177 185 'cyan_background': 46, 'white_background': 47}
178 186
179 187 def _terminfosetup(ui, mode):
180 188 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
181 189
182 190 global _terminfo_params
183 191 # If we failed to load curses, we go ahead and return.
184 192 if not _terminfo_params:
185 193 return
186 194 # Otherwise, see what the config file says.
187 195 if mode not in ('auto', 'terminfo'):
188 196 return
189 197
190 198 _terminfo_params.update((key[6:], (False, int(val)))
191 199 for key, val in ui.configitems('color')
192 200 if key.startswith('color.'))
193 201
194 202 try:
195 203 curses.setupterm()
196 204 except curses.error as e:
197 205 _terminfo_params = {}
198 206 return
199 207
200 208 for key, (b, e) in _terminfo_params.items():
201 209 if not b:
202 210 continue
203 211 if not curses.tigetstr(e):
204 212 # Most terminals don't support dim, invis, etc, so don't be
205 213 # noisy and use ui.debug().
206 214 ui.debug("no terminfo entry for %s\n" % e)
207 215 del _terminfo_params[key]
208 216 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
209 217 # Only warn about missing terminfo entries if we explicitly asked for
210 218 # terminfo mode.
211 219 if mode == "terminfo":
212 220 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
213 221 "ECMA-48 color\n"))
214 222 _terminfo_params = {}
215 223
216 224 def _modesetup(ui, coloropt):
217 225 global _terminfo_params
218 226
219 227 if coloropt == 'debug':
220 228 return 'debug'
221 229
222 230 auto = (coloropt == 'auto')
223 231 always = not auto and util.parsebool(coloropt)
224 232 if not always and not auto:
225 233 return None
226 234
227 235 formatted = always or (os.environ.get('TERM') != 'dumb' and ui.formatted())
228 236
229 237 mode = ui.config('color', 'mode', 'auto')
230 238
231 239 # If pager is active, color.pagermode overrides color.mode.
232 240 if getattr(ui, 'pageractive', False):
233 241 mode = ui.config('color', 'pagermode', mode)
234 242
235 243 realmode = mode
236 244 if mode == 'auto':
237 245 if os.name == 'nt':
238 246 term = os.environ.get('TERM')
239 247 # TERM won't be defined in a vanilla cmd.exe environment.
240 248
241 249 # UNIX-like environments on Windows such as Cygwin and MSYS will
242 250 # set TERM. They appear to make a best effort attempt at setting it
243 251 # to something appropriate. However, not all environments with TERM
244 252 # defined support ANSI. Since "ansi" could result in terminal
245 253 # gibberish, we error on the side of selecting "win32". However, if
246 254 # w32effects is not defined, we almost certainly don't support
247 255 # "win32", so don't even try.
248 256 if (term and 'xterm' in term) or not w32effects:
249 257 realmode = 'ansi'
250 258 else:
251 259 realmode = 'win32'
252 260 else:
253 261 realmode = 'ansi'
254 262
255 263 def modewarn():
256 264 # only warn if color.mode was explicitly set and we're in
257 265 # an interactive terminal
258 266 if mode == realmode and ui.interactive():
259 267 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
260 268
261 269 if realmode == 'win32':
262 270 _terminfo_params = {}
263 271 if not w32effects:
264 272 modewarn()
265 273 return None
266 274 _effects.update(w32effects)
267 275 elif realmode == 'ansi':
268 276 _terminfo_params = {}
269 277 elif realmode == 'terminfo':
270 278 _terminfosetup(ui, mode)
271 279 if not _terminfo_params:
272 280 ## FIXME Shouldn't we return None in this case too?
273 281 modewarn()
274 282 realmode = 'ansi'
275 283 else:
276 284 return None
277 285
278 286 if always or (auto and formatted):
279 287 return realmode
280 288 return None
281 289
282 290 try:
283 291 import curses
284 292 # Mapping from effect name to terminfo attribute name or color number.
285 293 # This will also force-load the curses module.
286 294 _terminfo_params = {'none': (True, 'sgr0'),
287 295 'standout': (True, 'smso'),
288 296 'underline': (True, 'smul'),
289 297 'reverse': (True, 'rev'),
290 298 'inverse': (True, 'rev'),
291 299 'blink': (True, 'blink'),
292 300 'dim': (True, 'dim'),
293 301 'bold': (True, 'bold'),
294 302 'invisible': (True, 'invis'),
295 303 'italic': (True, 'sitm'),
296 304 'black': (False, curses.COLOR_BLACK),
297 305 'red': (False, curses.COLOR_RED),
298 306 'green': (False, curses.COLOR_GREEN),
299 307 'yellow': (False, curses.COLOR_YELLOW),
300 308 'blue': (False, curses.COLOR_BLUE),
301 309 'magenta': (False, curses.COLOR_MAGENTA),
302 310 'cyan': (False, curses.COLOR_CYAN),
303 311 'white': (False, curses.COLOR_WHITE)}
304 312 except ImportError:
305 313 _terminfo_params = {}
306 314
307 315 _styles = {'grep.match': 'red bold',
308 316 'grep.linenumber': 'green',
309 317 'grep.rev': 'green',
310 318 'grep.change': 'green',
311 319 'grep.sep': 'cyan',
312 320 'grep.filename': 'magenta',
313 321 'grep.user': 'magenta',
314 322 'grep.date': 'magenta',
315 323 'bookmarks.active': 'green',
316 324 'branches.active': 'none',
317 325 'branches.closed': 'black bold',
318 326 'branches.current': 'green',
319 327 'branches.inactive': 'none',
320 328 'diff.changed': 'white',
321 329 'diff.deleted': 'red',
322 330 'diff.diffline': 'bold',
323 331 'diff.extended': 'cyan bold',
324 332 'diff.file_a': 'red bold',
325 333 'diff.file_b': 'green bold',
326 334 'diff.hunk': 'magenta',
327 335 'diff.inserted': 'green',
328 336 'diff.tab': '',
329 337 'diff.trailingwhitespace': 'bold red_background',
330 338 'changeset.public' : '',
331 339 'changeset.draft' : '',
332 340 'changeset.secret' : '',
333 341 'diffstat.deleted': 'red',
334 342 'diffstat.inserted': 'green',
335 343 'histedit.remaining': 'red bold',
336 344 'ui.prompt': 'yellow',
337 345 'log.changeset': 'yellow',
338 346 'patchbomb.finalsummary': '',
339 347 'patchbomb.from': 'magenta',
340 348 'patchbomb.to': 'cyan',
341 349 'patchbomb.subject': 'green',
342 350 'patchbomb.diffstats': '',
343 351 'rebase.rebased': 'blue',
344 352 'rebase.remaining': 'red bold',
345 353 'resolve.resolved': 'green bold',
346 354 'resolve.unresolved': 'red bold',
347 355 'shelve.age': 'cyan',
348 356 'shelve.newest': 'green bold',
349 357 'shelve.name': 'blue bold',
350 358 'status.added': 'green bold',
351 359 'status.clean': 'none',
352 360 'status.copied': 'none',
353 361 'status.deleted': 'cyan bold underline',
354 362 'status.ignored': 'black bold',
355 363 'status.modified': 'blue bold',
356 364 'status.removed': 'red bold',
357 365 'status.unknown': 'magenta bold underline',
358 366 'tags.normal': 'green',
359 367 'tags.local': 'black bold'}
360 368
361 369
362 370 def _effect_str(effect):
363 371 '''Helper function for render_effects().'''
364 372
365 373 bg = False
366 374 if effect.endswith('_background'):
367 375 bg = True
368 376 effect = effect[:-11]
369 377 attr, val = _terminfo_params[effect]
370 378 if attr:
371 379 return curses.tigetstr(val)
372 380 elif bg:
373 381 return curses.tparm(curses.tigetstr('setab'), val)
374 382 else:
375 383 return curses.tparm(curses.tigetstr('setaf'), val)
376 384
377 385 def render_effects(text, effects):
378 386 'Wrap text in commands to turn on each effect.'
379 387 if not text:
380 388 return text
381 389 if not _terminfo_params:
382 390 start = [str(_effects[e]) for e in ['none'] + effects.split()]
383 391 start = '\033[' + ';'.join(start) + 'm'
384 392 stop = '\033[' + str(_effects['none']) + 'm'
385 393 else:
386 394 start = ''.join(_effect_str(effect)
387 395 for effect in ['none'] + effects.split())
388 396 stop = _effect_str('none')
389 397 return ''.join([start, text, stop])
390 398
391 399 def extstyles():
392 400 for name, ext in extensions.extensions():
393 401 _styles.update(getattr(ext, 'colortable', {}))
394 402
395 403 def valideffect(effect):
396 404 'Determine if the effect is valid or not.'
397 405 good = False
398 406 if not _terminfo_params and effect in _effects:
399 407 good = True
400 408 elif effect in _terminfo_params or effect[:-11] in _terminfo_params:
401 409 good = True
402 410 return good
403 411
404 412 def configstyles(ui):
405 413 for status, cfgeffects in ui.configitems('color'):
406 414 if '.' not in status or status.startswith('color.'):
407 415 continue
408 416 cfgeffects = ui.configlist('color', status)
409 417 if cfgeffects:
410 418 good = []
411 419 for e in cfgeffects:
412 420 if valideffect(e):
413 421 good.append(e)
414 422 else:
415 423 ui.warn(_("ignoring unknown color/effect %r "
416 424 "(configured in color.%s)\n")
417 425 % (e, status))
418 426 _styles[status] = ' '.join(good)
419 427
420 428 class colorui(uimod.ui):
421 429 _colormode = 'ansi'
422 430 def write(self, *args, **opts):
423 431 if self._colormode is None:
424 432 return super(colorui, self).write(*args, **opts)
425 433
426 434 label = opts.get('label', '')
427 435 if self._buffers and not opts.get('prompt', False):
428 436 if self._bufferapplylabels:
429 437 self._buffers[-1].extend(self.label(a, label) for a in args)
430 438 else:
431 439 self._buffers[-1].extend(args)
432 440 elif self._colormode == 'win32':
433 441 for a in args:
434 442 win32print(a, super(colorui, self).write, **opts)
435 443 else:
436 444 return super(colorui, self).write(
437 445 *[self.label(a, label) for a in args], **opts)
438 446
439 447 def write_err(self, *args, **opts):
440 448 if self._colormode is None:
441 449 return super(colorui, self).write_err(*args, **opts)
442 450
443 451 label = opts.get('label', '')
444 452 if self._bufferstates and self._bufferstates[-1][0]:
445 453 return self.write(*args, **opts)
446 454 if self._colormode == 'win32':
447 455 for a in args:
448 456 win32print(a, super(colorui, self).write_err, **opts)
449 457 else:
450 458 return super(colorui, self).write_err(
451 459 *[self.label(a, label) for a in args], **opts)
452 460
453 461 def showlabel(self, msg, label):
454 462 if label and msg:
455 463 if msg[-1] == '\n':
456 464 return "[%s|%s]\n" % (label, msg[:-1])
457 465 else:
458 466 return "[%s|%s]" % (label, msg)
459 467 else:
460 468 return msg
461 469
462 470 def label(self, msg, label):
463 471 if self._colormode is None:
464 472 return super(colorui, self).label(msg, label)
465 473
466 474 if self._colormode == 'debug':
467 475 return self.showlabel(msg, label)
468 476
469 477 effects = []
470 478 for l in label.split():
471 479 s = _styles.get(l, '')
472 480 if s:
473 481 effects.append(s)
474 482 elif valideffect(l):
475 483 effects.append(l)
476 484 effects = ' '.join(effects)
477 485 if effects:
478 486 return '\n'.join([render_effects(s, effects)
479 487 for s in msg.split('\n')])
480 488 return msg
481 489
482 490 def uisetup(ui):
483 491 if ui.plain():
484 492 return
485 493 if not isinstance(ui, colorui):
486 494 colorui.__bases__ = (ui.__class__,)
487 495 ui.__class__ = colorui
488 496 def colorcmd(orig, ui_, opts, cmd, cmdfunc):
489 497 mode = _modesetup(ui_, opts['color'])
490 498 colorui._colormode = mode
491 499 if mode and mode != 'debug':
492 500 extstyles()
493 501 configstyles(ui_)
494 502 return orig(ui_, opts, cmd, cmdfunc)
495 503 def colorgit(orig, gitsub, commands, env=None, stream=False, cwd=None):
496 504 if gitsub.ui._colormode and len(commands) and commands[0] == "diff":
497 505 # insert the argument in the front,
498 506 # the end of git diff arguments is used for paths
499 507 commands.insert(1, '--color')
500 508 return orig(gitsub, commands, env, stream, cwd)
501 509 extensions.wrapfunction(dispatch, '_runcommand', colorcmd)
502 510 extensions.wrapfunction(subrepo.gitsubrepo, '_gitnodir', colorgit)
503 511
504 512 def extsetup(ui):
505 513 commands.globalopts.append(
506 514 ('', 'color', 'auto',
507 515 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
508 516 # and should not be translated
509 517 _("when to colorize (boolean, always, auto, never, or debug)"),
510 518 _('TYPE')))
511 519
512 520 @command('debugcolor', [], 'hg debugcolor')
513 521 def debugcolor(ui, repo, **opts):
514 522 global _styles
515 523 _styles = {}
516 524 for effect in _effects.keys():
517 525 _styles[effect] = effect
518 526 ui.write(('color mode: %s\n') % ui._colormode)
519 527 ui.write(_('available colors:\n'))
520 528 for label, colors in _styles.items():
521 529 ui.write(('%s\n') % colors, label=label)
522 530
523 531 if os.name != 'nt':
524 532 w32effects = None
525 533 else:
526 import re, ctypes
534 import ctypes
535 import re
527 536
528 537 _kernel32 = ctypes.windll.kernel32
529 538
530 539 _WORD = ctypes.c_ushort
531 540
532 541 _INVALID_HANDLE_VALUE = -1
533 542
534 543 class _COORD(ctypes.Structure):
535 544 _fields_ = [('X', ctypes.c_short),
536 545 ('Y', ctypes.c_short)]
537 546
538 547 class _SMALL_RECT(ctypes.Structure):
539 548 _fields_ = [('Left', ctypes.c_short),
540 549 ('Top', ctypes.c_short),
541 550 ('Right', ctypes.c_short),
542 551 ('Bottom', ctypes.c_short)]
543 552
544 553 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
545 554 _fields_ = [('dwSize', _COORD),
546 555 ('dwCursorPosition', _COORD),
547 556 ('wAttributes', _WORD),
548 557 ('srWindow', _SMALL_RECT),
549 558 ('dwMaximumWindowSize', _COORD)]
550 559
551 560 _STD_OUTPUT_HANDLE = 0xfffffff5L # (DWORD)-11
552 561 _STD_ERROR_HANDLE = 0xfffffff4L # (DWORD)-12
553 562
554 563 _FOREGROUND_BLUE = 0x0001
555 564 _FOREGROUND_GREEN = 0x0002
556 565 _FOREGROUND_RED = 0x0004
557 566 _FOREGROUND_INTENSITY = 0x0008
558 567
559 568 _BACKGROUND_BLUE = 0x0010
560 569 _BACKGROUND_GREEN = 0x0020
561 570 _BACKGROUND_RED = 0x0040
562 571 _BACKGROUND_INTENSITY = 0x0080
563 572
564 573 _COMMON_LVB_REVERSE_VIDEO = 0x4000
565 574 _COMMON_LVB_UNDERSCORE = 0x8000
566 575
567 576 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
568 577 w32effects = {
569 578 'none': -1,
570 579 'black': 0,
571 580 'red': _FOREGROUND_RED,
572 581 'green': _FOREGROUND_GREEN,
573 582 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
574 583 'blue': _FOREGROUND_BLUE,
575 584 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
576 585 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
577 586 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
578 587 'bold': _FOREGROUND_INTENSITY,
579 588 'black_background': 0x100, # unused value > 0x0f
580 589 'red_background': _BACKGROUND_RED,
581 590 'green_background': _BACKGROUND_GREEN,
582 591 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
583 592 'blue_background': _BACKGROUND_BLUE,
584 593 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
585 594 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
586 595 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
587 596 _BACKGROUND_BLUE),
588 597 'bold_background': _BACKGROUND_INTENSITY,
589 598 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
590 599 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
591 600 }
592 601
593 602 passthrough = set([_FOREGROUND_INTENSITY,
594 603 _BACKGROUND_INTENSITY,
595 604 _COMMON_LVB_UNDERSCORE,
596 605 _COMMON_LVB_REVERSE_VIDEO])
597 606
598 607 stdout = _kernel32.GetStdHandle(
599 608 _STD_OUTPUT_HANDLE) # don't close the handle returned
600 609 if stdout is None or stdout == _INVALID_HANDLE_VALUE:
601 610 w32effects = None
602 611 else:
603 612 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
604 613 if not _kernel32.GetConsoleScreenBufferInfo(
605 614 stdout, ctypes.byref(csbi)):
606 615 # stdout may not support GetConsoleScreenBufferInfo()
607 616 # when called from subprocess or redirected
608 617 w32effects = None
609 618 else:
610 619 origattr = csbi.wAttributes
611 620 ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)',
612 621 re.MULTILINE | re.DOTALL)
613 622
614 623 def win32print(text, orig, **opts):
615 624 label = opts.get('label', '')
616 625 attr = origattr
617 626
618 627 def mapcolor(val, attr):
619 628 if val == -1:
620 629 return origattr
621 630 elif val in passthrough:
622 631 return attr | val
623 632 elif val > 0x0f:
624 633 return (val & 0x70) | (attr & 0x8f)
625 634 else:
626 635 return (val & 0x07) | (attr & 0xf8)
627 636
628 637 # determine console attributes based on labels
629 638 for l in label.split():
630 639 style = _styles.get(l, '')
631 640 for effect in style.split():
632 641 try:
633 642 attr = mapcolor(w32effects[effect], attr)
634 643 except KeyError:
635 644 # w32effects could not have certain attributes so we skip
636 645 # them if not found
637 646 pass
638 647 # hack to ensure regexp finds data
639 648 if not text.startswith('\033['):
640 649 text = '\033[m' + text
641 650
642 651 # Look for ANSI-like codes embedded in text
643 652 m = re.match(ansire, text)
644 653
645 654 try:
646 655 while m:
647 656 for sattr in m.group(1).split(';'):
648 657 if sattr:
649 658 attr = mapcolor(int(sattr), attr)
650 659 _kernel32.SetConsoleTextAttribute(stdout, attr)
651 660 orig(m.group(2), **opts)
652 661 m = re.match(ansire, m.group(3))
653 662 finally:
654 663 # Explicitly reset original attributes
655 664 _kernel32.SetConsoleTextAttribute(stdout, origattr)
@@ -1,180 +1,179 b''
1 1 #require test-repo
2 2
3 3 $ cd "$TESTDIR"/..
4 4
5 5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
6 hgext/color.py not using absolute_import
7 6 hgext/eol.py not using absolute_import
8 7 hgext/extdiff.py not using absolute_import
9 8 hgext/factotum.py not using absolute_import
10 9 hgext/fetch.py not using absolute_import
11 10 hgext/fsmonitor/pywatchman/__init__.py not using absolute_import
12 11 hgext/fsmonitor/pywatchman/__init__.py requires print_function
13 12 hgext/fsmonitor/pywatchman/capabilities.py not using absolute_import
14 13 hgext/fsmonitor/pywatchman/pybser.py not using absolute_import
15 14 hgext/gpg.py not using absolute_import
16 15 hgext/graphlog.py not using absolute_import
17 16 hgext/hgcia.py not using absolute_import
18 17 hgext/hgk.py not using absolute_import
19 18 hgext/highlight/__init__.py not using absolute_import
20 19 hgext/highlight/highlight.py not using absolute_import
21 20 hgext/histedit.py not using absolute_import
22 21 hgext/largefiles/__init__.py not using absolute_import
23 22 hgext/largefiles/basestore.py not using absolute_import
24 23 hgext/largefiles/lfcommands.py not using absolute_import
25 24 hgext/largefiles/lfutil.py not using absolute_import
26 25 hgext/largefiles/localstore.py not using absolute_import
27 26 hgext/largefiles/overrides.py not using absolute_import
28 27 hgext/largefiles/proto.py not using absolute_import
29 28 hgext/largefiles/remotestore.py not using absolute_import
30 29 hgext/largefiles/reposetup.py not using absolute_import
31 30 hgext/largefiles/uisetup.py not using absolute_import
32 31 hgext/largefiles/wirestore.py not using absolute_import
33 32 hgext/mq.py not using absolute_import
34 33 hgext/rebase.py not using absolute_import
35 34 hgext/share.py not using absolute_import
36 35 hgext/win32text.py not using absolute_import
37 36 i18n/check-translation.py not using absolute_import
38 37 i18n/polib.py not using absolute_import
39 38 setup.py not using absolute_import
40 39 tests/heredoctest.py requires print_function
41 40 tests/md5sum.py not using absolute_import
42 41 tests/readlink.py not using absolute_import
43 42 tests/readlink.py requires print_function
44 43 tests/run-tests.py not using absolute_import
45 44 tests/svn-safe-append.py not using absolute_import
46 45 tests/test-atomictempfile.py not using absolute_import
47 46 tests/test-demandimport.py not using absolute_import
48 47
49 48 #if py3exe
50 49 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs $PYTHON3 contrib/check-py3-compat.py
51 50 contrib/check-code.py: invalid syntax: (unicode error) 'unicodeescape' codec can't decode bytes in position *-*: malformed \N character escape (<unknown>, line *) (glob)
52 51 doc/hgmanpage.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
53 52 hgext/automv.py: error importing module: <SyntaxError> invalid syntax (commands.py, line *) (line *) (glob)
54 53 hgext/blackbox.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
55 54 hgext/bugzilla.py: error importing module: <ImportError> No module named 'urlparse' (line *) (glob)
56 55 hgext/censor.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
57 56 hgext/chgserver.py: error importing module: <ImportError> No module named 'SocketServer' (line *) (glob)
58 57 hgext/children.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
59 58 hgext/churn.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
60 59 hgext/clonebundles.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
61 60 hgext/color.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
62 61 hgext/convert/bzr.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
63 62 hgext/convert/common.py: error importing module: <ImportError> No module named 'cPickle' (line *) (glob)
64 63 hgext/convert/convcmd.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
65 64 hgext/convert/cvs.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
66 65 hgext/convert/cvsps.py: error importing module: <ImportError> No module named 'cPickle' (line *) (glob)
67 66 hgext/convert/darcs.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
68 67 hgext/convert/filemap.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
69 68 hgext/convert/git.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
70 69 hgext/convert/gnuarch.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
71 70 hgext/convert/hg.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
72 71 hgext/convert/monotone.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
73 72 hgext/convert/p*.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
74 73 hgext/convert/subversion.py: error importing module: <ImportError> No module named 'cPickle' (line *) (glob)
75 74 hgext/convert/transport.py: error importing module: <ImportError> No module named 'svn.client' (line *) (glob)
76 75 hgext/eol.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
77 76 hgext/extdiff.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
78 77 hgext/factotum.py: error importing: <ImportError> No module named 'httplib' (error at url.py:*) (glob)
79 78 hgext/fetch.py: error importing module: <SyntaxError> invalid syntax (commands.py, line *) (line *) (glob)
80 79 hgext/fsmonitor/watchmanclient.py: error importing module: <SystemError> Parent module 'hgext.fsmonitor' not loaded, cannot perform relative import (line *) (glob)
81 80 hgext/gpg.py: error importing module: <SyntaxError> invalid syntax (commands.py, line *) (line *) (glob)
82 81 hgext/graphlog.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
83 82 hgext/hgcia.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
84 83 hgext/hgk.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
85 84 hgext/histedit.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
86 85 hgext/keyword.py: error importing: <ImportError> No module named 'BaseHTTPServer' (error at common.py:*) (glob)
87 86 hgext/largefiles/basestore.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
88 87 hgext/largefiles/lfcommands.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
89 88 hgext/largefiles/lfutil.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
90 89 hgext/largefiles/localstore.py: error importing module: <ImportError> No module named 'lfutil' (line *) (glob)
91 90 hgext/largefiles/overrides.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
92 91 hgext/largefiles/proto.py: error importing: <ImportError> No module named 'httplib' (error at httppeer.py:*) (glob)
93 92 hgext/largefiles/remotestore.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at wireproto.py:*) (glob)
94 93 hgext/largefiles/reposetup.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
95 94 hgext/largefiles/uisetup.py: error importing module: <SyntaxError> invalid syntax (archival.py, line *) (line *) (glob)
96 95 hgext/largefiles/wirestore.py: error importing module: <ImportError> No module named 'lfutil' (line *) (glob)
97 96 hgext/mq.py: error importing module: <SyntaxError> invalid syntax (commands.py, line *) (line *) (glob)
98 97 hgext/notify.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
99 98 hgext/pager.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
100 99 hgext/patchbomb.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
101 100 hgext/purge.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
102 101 hgext/rebase.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
103 102 hgext/record.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
104 103 hgext/relink.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
105 104 hgext/schemes.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
106 105 hgext/share.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
107 106 hgext/shelve.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
108 107 hgext/strip.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
109 108 hgext/transplant.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
110 109 mercurial/archival.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
111 110 mercurial/branchmap.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
112 111 mercurial/bundle*.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
113 112 mercurial/bundlerepo.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
114 113 mercurial/changegroup.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
115 114 mercurial/changelog.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
116 115 mercurial/cmdutil.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
117 116 mercurial/commands.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
118 117 mercurial/commandserver.py: error importing module: <ImportError> No module named 'SocketServer' (line *) (glob)
119 118 mercurial/context.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
120 119 mercurial/copies.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
121 120 mercurial/crecord.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
122 121 mercurial/dirstate.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
123 122 mercurial/discovery.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
124 123 mercurial/dispatch.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
125 124 mercurial/exchange.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
126 125 mercurial/extensions.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
127 126 mercurial/filelog.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
128 127 mercurial/filemerge.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
129 128 mercurial/fileset.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
130 129 mercurial/formatter.py: error importing module: <ImportError> No module named 'cPickle' (line *) (glob)
131 130 mercurial/graphmod.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
132 131 mercurial/help.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
133 132 mercurial/hg.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
134 133 mercurial/hgweb/common.py: error importing module: <ImportError> No module named 'BaseHTTPServer' (line *) (glob)
135 134 mercurial/hgweb/hgweb_mod.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
136 135 mercurial/hgweb/hgwebdir_mod.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
137 136 mercurial/hgweb/protocol.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
138 137 mercurial/hgweb/request.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
139 138 mercurial/hgweb/server.py: error importing module: <ImportError> No module named 'BaseHTTPServer' (line *) (glob)
140 139 mercurial/hgweb/webcommands.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
141 140 mercurial/hgweb/webutil.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
142 141 mercurial/hgweb/wsgicgi.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
143 142 mercurial/hook.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
144 143 mercurial/httpclient/_readers.py: error importing module: <ImportError> No module named 'httplib' (line *) (glob)
145 144 mercurial/httpconnection.py: error importing: <ImportError> No module named 'httplib' (error at __init__.py:*) (glob)
146 145 mercurial/httppeer.py: error importing module: <ImportError> No module named 'httplib' (line *) (glob)
147 146 mercurial/keepalive.py: error importing module: <ImportError> No module named 'httplib' (line *) (glob)
148 147 mercurial/localrepo.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
149 148 mercurial/mail.py: error importing module: <AttributeError> module 'email' has no attribute 'Header' (line *) (glob)
150 149 mercurial/manifest.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
151 150 mercurial/merge.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
152 151 mercurial/namespaces.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
153 152 mercurial/patch.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
154 153 mercurial/pure/mpatch.py: error importing module: <ImportError> cannot import name 'pycompat' (line *) (glob)
155 154 mercurial/pure/parsers.py: error importing module: <ImportError> No module named 'mercurial.pure.node' (line *) (glob)
156 155 mercurial/repair.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
157 156 mercurial/revlog.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
158 157 mercurial/revset.py: error importing module: <AttributeError> 'dict' object has no attribute 'iteritems' (line *) (glob)
159 158 mercurial/scmutil.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
160 159 mercurial/scmwindows.py: error importing module: <ImportError> No module named '_winreg' (line *) (glob)
161 160 mercurial/simplemerge.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
162 161 mercurial/sshpeer.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at wireproto.py:*) (glob)
163 162 mercurial/sshserver.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
164 163 mercurial/statichttprepo.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
165 164 mercurial/store.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
166 165 mercurial/streamclone.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
167 166 mercurial/subrepo.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
168 167 mercurial/templatefilters.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
169 168 mercurial/templatekw.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
170 169 mercurial/templater.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
171 170 mercurial/ui.py: error importing: <ImportError> No module named 'cPickle' (error at formatter.py:*) (glob)
172 171 mercurial/unionrepo.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
173 172 mercurial/url.py: error importing module: <ImportError> No module named 'httplib' (line *) (glob)
174 173 mercurial/verify.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
175 174 mercurial/win*.py: error importing module: <ImportError> No module named 'msvcrt' (line *) (glob)
176 175 mercurial/windows.py: error importing module: <ImportError> No module named '_winreg' (line *) (glob)
177 176 mercurial/wireproto.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
178 177 tests/readlink.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
179 178
180 179 #endif
General Comments 0
You need to be logged in to leave comments. Login now