diff --git a/direct/src/showutil/FreezeTool.py b/direct/src/showutil/FreezeTool.py index 38c50fa11b..a8a967f93a 100644 --- a/direct/src/showutil/FreezeTool.py +++ b/direct/src/showutil/FreezeTool.py @@ -30,6 +30,8 @@ isDebugBuild = (python.lower().endswith('_d')) # These are modules that Python always tries to import up-front. They # must be frozen in any main.exe. +# NB. if encodings are removed, be sure to remove them from the shortcut in +# deploy-stub.c. startupModules = [ 'encodings', 'encodings.aliases', 'encodings.undefined', 'encodings.ascii', 'encodings.cp1252', 'encodings.latin_1', 'encodings.utf_8', diff --git a/pandatool/src/deploy-stub/deploy-stub.c b/pandatool/src/deploy-stub/deploy-stub.c index d35d3f59a9..51d7da88a9 100644 --- a/pandatool/src/deploy-stub/deploy-stub.c +++ b/pandatool/src/deploy-stub/deploy-stub.c @@ -38,6 +38,32 @@ static struct _inittab extensions[] = { #endif #endif +#if defined(_WIN32) && PY_VERSION_HEX < 0x03060000 +static int supports_code_page(UINT cp) { + /* Shortcut, because we know that these encodings are bundled by default-- + * see FreezeTool.py and Python's encodings/aliases.py */ + if (cp != 0 && cp != 1252 && cp != 367 && cp != 437 && cp != 850 && cp != 819) { + const struct _frozen *moddef; + char codec[100]; + + /* Check if the codec was frozen into the program. We can't check this + * using _PyCodec_Lookup, since Python hasn't been initialized yet. */ + PyOS_snprintf(codec, sizeof(codec), "encodings.cp%u", (unsigned int)cp); + + moddef = PyImport_FrozenModules; + while (moddef->name) { + if (strcmp(moddef->name, codec) == 0) { + return 1; + } + ++moddef; + } + return 0; + } + + return 1; +} +#endif + /* Main program */ #ifdef WIN_UNICODE @@ -64,6 +90,19 @@ int Py_FrozenMain(int argc, char **argv) } #endif +#if defined(MS_WINDOWS) && PY_VERSION_HEX >= 0x03040000 && PY_VERSION_HEX < 0x03060000 + if (!supports_code_page(GetConsoleOutputCP()) || + !supports_code_page(GetConsoleCP())) { + /* Revert to the active codepage, and tell Python to use the 'mbcs' + * encoding (which always uses the active codepage). In 99% of cases, + * this will be the same thing anyway. */ + UINT acp = GetACP(); + SetConsoleCP(acp); + SetConsoleOutputCP(acp); + Py_SetStandardStreamEncoding("mbcs", NULL); + } +#endif + Py_FrozenFlag = 1; /* Suppress errors from getpath.c */ Py_NoSiteFlag = 1; Py_NoUserSiteDirectory = 1; @@ -112,6 +151,33 @@ int Py_FrozenMain(int argc, char **argv) PyWinFreeze_ExeInit(); #endif +#if defined(MS_WINDOWS) && PY_VERSION_HEX < 0x03040000 + if (!supports_code_page(GetConsoleOutputCP()) || + !supports_code_page(GetConsoleCP())) { + /* Same hack as before except for Python 2.7, which doesn't seem to have + * a way to set the encoding ahead of time, and setting PYTHONIOENCODING + * doesn't seem to work. Fortunately, Python 2.7 doesn't usually start + * causing codec errors until the first print statement. */ + PyObject *sys_stream; + UINT acp = GetACP(); + SetConsoleCP(acp); + SetConsoleOutputCP(acp); + + sys_stream = PySys_GetObject("stdin"); + if (sys_stream && PyFile_Check(sys_stream)) { + PyFile_SetEncodingAndErrors(sys_stream, "mbcs", NULL); + } + sys_stream = PySys_GetObject("stdout"); + if (sys_stream && PyFile_Check(sys_stream)) { + PyFile_SetEncodingAndErrors(sys_stream, "mbcs", NULL); + } + sys_stream = PySys_GetObject("stderr"); + if (sys_stream && PyFile_Check(sys_stream)) { + PyFile_SetEncodingAndErrors(sys_stream, "mbcs", NULL); + } + } +#endif + if (Py_VerboseFlag) fprintf(stderr, "Python %s\n%s\n", Py_GetVersion(), Py_GetCopyright());