Guess output encoding from sys.stdout.encoding

Rather than using the locale settings. #1419
This commit is contained in:
Adrian Sampson 2015-04-13 11:11:16 -07:00
parent c834599b42
commit a0ff517d17
3 changed files with 22 additions and 10 deletions

View file

@ -72,14 +72,23 @@ class UserError(Exception):
# Utilities.
def _encoding():
"""Tries to guess the encoding used by the terminal."""
def _out_encoding():
"""Get the encoding to use for *outputting* strings to the console.
"""
# Configured override?
encoding = config['terminal_encoding'].get()
if encoding:
return encoding
# Determine from locale settings.
# Python's guessed output stream encoding, or UTF-8 as a fallback
# (e.g., when piped to a file).
return sys.stdout.encoding or 'utf8'
def _arg_encoding():
"""Get the encoding for command-line arguments (and other OS
locale-sensitive strings).
"""
try:
return locale.getdefaultlocale()[1] or 'utf8'
except ValueError:
@ -92,7 +101,7 @@ def decargs(arglist):
"""Given a list of command-line argument bytestrings, attempts to
decode them to Unicode strings.
"""
return [s.decode(_encoding()) for s in arglist]
return [s.decode(_arg_encoding()) for s in arglist]
def print_(*strings):
@ -100,8 +109,8 @@ def print_(*strings):
is not in the terminal's encoding's character set, just silently
replaces it.
If the arguments are strings then they're expected to share the same type:
either bytes or unicode.
If the arguments are strings then they're expected to share the same
type: either bytes or unicode.
"""
if strings:
if isinstance(strings[0], unicode):
@ -111,7 +120,7 @@ def print_(*strings):
else:
txt = u''
if isinstance(txt, unicode):
txt = txt.encode(_encoding(), 'replace')
txt = txt.encode(_out_encoding(), 'replace')
print(txt)
@ -126,7 +135,7 @@ def input_(prompt=None):
# http://bugs.python.org/issue1927
if prompt:
if isinstance(prompt, unicode):
prompt = prompt.encode(_encoding(), 'replace')
prompt = prompt.encode(_out_encoding(), 'replace')
print(prompt, end=' ')
try:

View file

@ -21,6 +21,9 @@ Little fixes and improvements:
* :doc:`/plugins/replaygain`: Fix a number of issues with the new
``bs1770gain`` backend on Windows. Also, fix missing debug output in import
mode. :bug:`1398`
* Beets should now be better at guessing the appropriate output encoding on
Windows. (Specifically, the console output encoding is guessed separately
from the encoding for command-line arguments.) :bug:`1419`
1.3.11 (April 5, 2015)
----------------------

View file

@ -51,7 +51,7 @@ from beets.library import Library, Item, Album
from beets import importer
from beets.autotag.hooks import AlbumInfo, TrackInfo
from beets.mediafile import MediaFile, Image
from beets.ui import _encoding
from beets.ui import _arg_encoding
# TODO Move AutotagMock here
from test import _common
@ -121,7 +121,7 @@ def has_program(cmd, args=['--version']):
full_cmd = [cmd] + args
for i, elem in enumerate(full_cmd):
if isinstance(elem, unicode):
full_cmd[i] = elem.encode(_encoding())
full_cmd[i] = elem.encode(_arg_encoding())
try:
with open(os.devnull, 'wb') as devnull:
subprocess.check_call(full_cmd, stderr=devnull,