[PATCH] windows: switch the console encoding into an encoding actually used (issue2926)

Adrian Buehlmann adrian at cadifra.com
Thu Jul 28 22:53:50 UTC 2011


On 2011-07-28 22:52, Andrei Polushin wrote:
> # HG changeset patch
> # User Andrei Polushin <polushin at gmail.com>
> # Date 1311886282 -25200
> # Branch stable
> # Node ID 61ace80f43d6144bef600d7ebe05f75f80fd0fe3
> # Parent  56848e2bb0c5a43b580dd2ca7ce1e781d4e75b2b
> windows: switch the console encoding into an encoding actually used (issue2926)
> 
> The encoding of the console is switched temporarily, for the time the Mercurial
> is running, and restored to the previous value on exit.
> This solution is backward compatible, it changes almost nothing, i.e. neither
> stdout/pipe encoding, nor internal string handling are affected anyway.
> 
> One problem still remains: `hg log | more' doesn't produce readable output on
> OEM console, I've found no way to change the console encoding when redirected.
> 
> One problem possibly introduced: killing hg process may not restore previous
> console encoding. I'm unable to reproduce the problem, however.
> 
> diff -r 56848e2bb0c5 -r 61ace80f43d6 mercurial/osutil.c
> --- a/mercurial/osutil.c	Fri Jul 22 20:31:15 2011 -0300
> +++ b/mercurial/osutil.c	Fri Jul 29 03:51:22 2011 +0700
> @@ -402,6 +402,36 @@
>  }
>  
>  #ifdef _WIN32
> +static UINT inputcp;
> +static UINT outputcp;
> +
> +static void restoreconsoleencoding(void)
> +{
> +	SetConsoleCP(inputcp);
> +	SetConsoleOutputCP(outputcp);
> +}
> +
> +static PyObject *forceconsoleencoding(PyObject *self, PyObject *args)
> +{
> +	int cp;
> +
> +	if (!PyArg_ParseTuple(args, "i", &cp))
> +		return NULL;
> +
> +	if (!inputcp && !outputcp && IsValidCodePage(cp)) {
> +		inputcp = GetConsoleCP();
> +		outputcp = GetConsoleOutputCP();
> +
> +		SetConsoleCP(cp);
> +		SetConsoleOutputCP(cp);
> +
> +		atexit(restoreconsoleencoding);
> +		return Py_True;
> +	}
> +
> +	return Py_False;
> +}
> +
>  static PyObject *posixfile(PyObject *self, PyObject *args, PyObject *kwds)
>  {
>  	static char *kwlist[] = {"name", "mode", "buffering", NULL};
> @@ -536,6 +566,8 @@
>  	{"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
>  	 "list a directory\n"},
>  #ifdef _WIN32
> +	{"forceconsoleencoding", forceconsoleencoding, METH_VARARGS,
> +	 "Temporarily switch the console encoding, restored on exit.\n"},
>  	{"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
>  	 "Open a file with POSIX-like semantics.\n"
>  "On error, this function may raise either a WindowsError or an IOError."},
> diff -r 56848e2bb0c5 -r 61ace80f43d6 mercurial/windows.py
> --- a/mercurial/windows.py	Fri Jul 22 20:31:15 2011 -0300
> +++ b/mercurial/windows.py	Fri Jul 29 03:51:22 2011 +0700
> @@ -8,6 +8,16 @@
>  from i18n import _
>  import osutil
>  import errno, msvcrt, os, re, sys
> +import codecs, encoding
> +
> +# Temporarily switch the console encoding into an encoding actually used.
> +try:
> +    cp = codecs.lookup(encoding.encoding).name
> +    if cp.startswith('cp'):
> +        cp = int(cp[2:])
> +        osutil.forceconsoleencoding(cp)
> +except LookupError, ValueError:
> +    pass

Is there a reason why this can't be done by using Python's ctypes
instead of C code? (see win32.py)


More information about the Mercurial-devel mailing list