diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py --- a/mercurial/pycompat.py +++ b/mercurial/pycompat.py @@ -13,6 +13,7 @@ from __future__ import absolute_import import getopt import inspect import json +import locale import os import shlex import sys @@ -93,6 +94,26 @@ def rapply(f, xs): return _rapply(f, xs) +# Passing the '' locale means that the locale should be set according to the +# user settings (environment variables). +# Python sometimes avoids setting the global locale settings. When interfacing +# with C code (e.g. the curses module or the Subversion bindings), the global +# locale settings must be initialized correctly. Python 2 does not initialize +# the global locale settings on interpreter startup. Python 3 sometimes +# initializes LC_CTYPE, but not consistently at least on Windows. Therefore we +# explicitly initialize it to get consistent behavior if it's not already +# initialized. Since CPython commit 177d921c8c03d30daa32994362023f777624b10d, +# LC_CTYPE is always initialized. If we require Python 3.8+, we should re-check +# if we can remove this code. +if locale.setlocale(locale.LC_CTYPE, None) == 'C': + try: + locale.setlocale(locale.LC_CTYPE, '') + except locale.Error: + # The likely case is that the locale from the environment variables is + # unknown. + pass + + if ispy3: import builtins import codecs