From ad3156a58fc073f130ceaa96a9257a64d63e3d39 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 12 Jul 2019 20:10:15 +0530 Subject: [PATCH] Fix a regression caused by py3 porting that is preventing calibre from starting up on windows machines with non UTF-8 locales. Fixes #1836360 [no RUN ver 3.45.0 or 3.45.1](https://bugs.launchpad.net/calibre/+bug/1836360) os.path.expanduser is broken in python2. When passed a unicode object it concatenates it to a bytestring, which will lead to UnicodeDecodeError if the bytestring happens to not be in the default encoding, ususally UTF-8 --- src/calibre/startup.py | 22 ++++++++++++++++++++-- src/calibre/utils/filenames.py | 17 ++--------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/calibre/startup.py b/src/calibre/startup.py index b6c662ef6d..7508b24395 100644 --- a/src/calibre/startup.py +++ b/src/calibre/startup.py @@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en' Perform various initialization tasks. ''' -import locale, sys +import locale, sys, os # Default translation is NOOP from polyglot.builtins import builtins, is_py3, unicode_type @@ -79,7 +79,25 @@ if not _run_once: if len(sys.argv) > 1 and not isinstance(sys.argv[1], unicode_type): sys.argv[1:] = winutil.argv()[1-len(sys.argv):] - # + if not ispy3: + # Python2's expanduser is broken for non-ASCII usernames + # and unicode paths + + def expanduser(path): + if isinstance(path, bytes): + path = path.decode('mbcs') + if path[:1] != '~': + return path + i, n = 1, len(path) + while i < n and path[i] not in '/\\': + i += 1 + userhome = winutil.special_folder_path(winutil.CSIDL_PROFILE) + if i != 1: # ~user + userhome = os.path.join(os.path.dirname(userhome), path[1:i]) + + return userhome + path[i:] + os.path.expanduser = expanduser + # Ensure that all temp files/dirs are created under a calibre tmp dir from calibre.ptempfile import base_dir try: diff --git a/src/calibre/utils/filenames.py b/src/calibre/utils/filenames.py index 1d2417e6d9..93236af4f5 100644 --- a/src/calibre/utils/filenames.py +++ b/src/calibre/utils/filenames.py @@ -12,7 +12,7 @@ from math import ceil from calibre import force_unicode, isbytestring, prints, sanitize_file_name from calibre.constants import ( - filesystem_encoding, iswindows, plugins, preferred_encoding, isosx, ispy3 + filesystem_encoding, iswindows, plugins, preferred_encoding, isosx ) from calibre.utils.localization import get_udc from polyglot.builtins import iteritems, itervalues, unicode_type, range @@ -545,20 +545,7 @@ def remove_dir_if_empty(path, ignore_metadata_caches=False): raise -if iswindows and not ispy3: - # Python's expanduser is broken for non-ASCII usernames - def expanduser(path): - if isinstance(path, bytes): - path = path.decode(filesystem_encoding) - if path[:1] != '~': - return path - i, n = 1, len(path) - while i < n and path[i] not in '/\\': - i += 1 - userhome = plugins['winutil'][0].special_folder_path(plugins['winutil'][0].CSIDL_PROFILE) - return userhome + path[i:] -else: - expanduser = os.path.expanduser +expanduser = os.path.expanduser def format_permissions(st_mode):