[PATCH 1 of 1 STABLE] color: port to using ctypes (issue2687)
Adrian Buehlmann
adrian at cadifra.com
Thu Mar 10 18:35:48 CST 2011
On 2011-03-11 01:16, Adrian Buehlmann wrote:
> # HG changeset patch
> # User Adrian Buehlmann <adrian at cadifra.com>
> # Date 1299801144 -3600
> # Branch stable
> # Node ID 131f8aa592d8977c0a3d686d83113be6bfef3cc6
> # Parent 8e94a1b4e9a48ec37c54eea39b4076ba302d085f
> color: port to using ctypes (issue2687)
>
> replacing usage of pywin32, which was removed
> for Mercurial 1.8
>
> diff --git a/hgext/color.py b/hgext/color.py
> --- a/hgext/color.py
> +++ b/hgext/color.py
> @@ -232,51 +232,89 @@ def extsetup(ui):
> _("when to colorize (boolean, always, auto, or never)"),
> _('TYPE')))
>
> -try:
> - import re, pywintypes, win32console as win32c
> +if os.name != 'nt':
> + w32effects = None
> +else:
> + import re, ctypes
> +
> + _kernel32 = ctypes.windll.kernel32
> +
> + _WORD = ctypes.c_ushort
> +
> + _INVALID_HANDLE_VALUE = -1
> +
> + class _COORD(ctypes.Structure):
> + _fields_ = [('X', ctypes.c_short),
> + ('Y', ctypes.c_short)]
> +
> + class _SMALL_RECT(ctypes.Structure):
> + _fields_ = [('Left', ctypes.c_short),
> + ('Top', ctypes.c_short),
> + ('Right', ctypes.c_short),
> + ('Bottom', ctypes.c_short)]
> +
> + class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
> + _fields_ = [('dwSize', _COORD),
> + ('dwCursorPosition', _COORD),
> + ('wAttributes', _WORD),
> + ('srWindow', _SMALL_RECT),
> + ('dwMaximumWindowSize', _COORD)]
> +
> + _STD_OUTPUT_HANDLE = 0xfffffff5L # (DWORD)-11
> + _STD_ERROR_HANDLE = 0xfffffff4L # (DWORD)-12
> +
> + _FOREGROUND_BLUE = 0x0001
> + _FOREGROUND_GREEN = 0x0002
> + _FOREGROUND_RED = 0x0004
> + _FOREGROUND_INTENSITY = 0x0008
> +
> + _BACKGROUND_BLUE = 0x0010
> + _BACKGROUND_GREEN = 0x0020
> + _BACKGROUND_RED = 0x0040
> + _BACKGROUND_INTENSITY = 0x0080
> +
> + _COMMON_LVB_REVERSE_VIDEO = 0x4000
> + _COMMON_LVB_UNDERSCORE = 0x8000
>
> # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
> w32effects = {
> 'none': -1,
> 'black': 0,
> - 'red': win32c.FOREGROUND_RED,
> - 'green': win32c.FOREGROUND_GREEN,
> - 'yellow': win32c.FOREGROUND_RED | win32c.FOREGROUND_GREEN,
> - 'blue': win32c.FOREGROUND_BLUE,
> - 'magenta': win32c.FOREGROUND_BLUE | win32c.FOREGROUND_RED,
> - 'cyan': win32c.FOREGROUND_BLUE | win32c.FOREGROUND_GREEN,
> - 'white': (win32c.FOREGROUND_RED | win32c.FOREGROUND_GREEN |
> - win32c.FOREGROUND_BLUE),
> - 'bold': win32c.FOREGROUND_INTENSITY,
> + 'red': _FOREGROUND_RED,
> + 'green': _FOREGROUND_GREEN,
> + 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
> + 'blue': _FOREGROUND_BLUE,
> + 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
> + 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
> + 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
> + 'bold': _FOREGROUND_INTENSITY,
> 'black_background': 0x100, # unused value > 0x0f
> - 'red_background': win32c.BACKGROUND_RED,
> - 'green_background': win32c.BACKGROUND_GREEN,
> - 'yellow_background': win32c.BACKGROUND_RED | win32c.BACKGROUND_GREEN,
> - 'blue_background': win32c.BACKGROUND_BLUE,
> - 'purple_background': win32c.BACKGROUND_BLUE | win32c.BACKGROUND_RED,
> - 'cyan_background': win32c.BACKGROUND_BLUE | win32c.BACKGROUND_GREEN,
> - 'white_background': (win32c.BACKGROUND_RED | win32c.BACKGROUND_GREEN |
> - win32c.BACKGROUND_BLUE),
> - 'bold_background': win32c.BACKGROUND_INTENSITY,
> - 'underline': win32c.COMMON_LVB_UNDERSCORE, # double-byte charsets only
> - 'inverse': win32c.COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
> + 'red_background': _BACKGROUND_RED,
> + 'green_background': _BACKGROUND_GREEN,
> + 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
> + 'blue_background': _BACKGROUND_BLUE,
> + 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
> + 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
> + 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
> + _BACKGROUND_BLUE),
> + 'bold_background': _BACKGROUND_INTENSITY,
> + 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
> + 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
> }
>
> - passthrough = set([win32c.FOREGROUND_INTENSITY,
> - win32c.BACKGROUND_INTENSITY,
> - win32c.COMMON_LVB_UNDERSCORE,
> - win32c.COMMON_LVB_REVERSE_VIDEO])
> + passthrough = set([_FOREGROUND_INTENSITY,
> + _BACKGROUND_INTENSITY,
> + _COMMON_LVB_UNDERSCORE,
> + _COMMON_LVB_REVERSE_VIDEO])
>
> - try:
> - stdout = win32c.GetStdHandle(win32c.STD_OUTPUT_HANDLE)
> - if stdout is None:
> - raise ImportError()
> - origattr = stdout.GetConsoleScreenBufferInfo()['Attributes']
> - except pywintypes.error:
> - # stdout may be defined but not support
> - # GetConsoleScreenBufferInfo(), when called from subprocess or
> - # redirected.
> - raise ImportError()
> + stdout = _kernel32.GetStdHandle(
> + _STD_OUTPUT_HANDLE) # don't close the handle returned
> + if stdout is None or stdout == _INVALID_HANDLE_VALUE:
> + raise ctypes.WinError()
> + csbi = _CONSOLE_SCREEN_BUFFER_INFO()
> + if not _kernel32.GetConsoleScreenBufferInfo(stdout, ctypes.byref(csbi)):
> + raise ctypes.WinError()
> + origattr = csbi.wAttributes
Gah. I'm too restrictive here:
$ hg --traceback log -r 28 -p > foo
*** failed to import extension color: [Error 6] The handle is invalid.
Traceback (most recent call last):
File "C:\Users\adi\hgrepos\hg-crew\mercurial\extensions.py", line 82, in loadall
load(ui, name, path)
File "C:\Users\adi\hgrepos\hg-crew\mercurial\extensions.py", line 67, in load
mod = importh("hgext.%s" % name)
File "C:\Users\adi\hgrepos\hg-crew\mercurial\extensions.py", line 61, in importh
mod = __import__(name)
File "C:\Users\adi\hgrepos\hg-crew\mercurial\demandimport.py", line 85, in _demandimport
return _origimport(name, globals, locals, fromlist)
File "C:\Users\adi\hgrepos\hg-crew\hgext\color.py", line 316, in <module>
raise ctypes.WinError()
WindowsError: [Error 6] The handle is invalid.
I should have read the original comment there more closely.
I'll send a corrected version.
> ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)', re.MULTILINE | re.DOTALL)
>
> def win32print(text, orig, **opts):
> @@ -309,12 +347,9 @@ try:
> for sattr in m.group(1).split(';'):
> if sattr:
> attr = mapcolor(int(sattr), attr)
> - stdout.SetConsoleTextAttribute(attr)
> + _kernel32.SetConsoleTextAttribute(stdout, attr)
> orig(m.group(2), **opts)
> m = re.match(ansire, m.group(3))
>
> # Explicity reset original attributes
> - stdout.SetConsoleTextAttribute(origattr)
> -
> -except ImportError:
> - w32effects = None
> + _kernel32.SetConsoleTextAttribute(stdout, origattr)
More information about the Mercurial-devel
mailing list