From c91667338a4e774e2819ccf4da852dc7b759bc19 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Sat, 8 Dec 2012 11:13:52 +0100 Subject: Fixed #19357 -- Allow non-ASCII chars in filesystem paths Thanks kujiu for the report and Aymeric Augustin for the review. --- django/utils/_os.py | 23 ++++++++++++++++++++++- django/utils/translation/trans_real.py | 7 ++++--- 2 files changed, 26 insertions(+), 4 deletions(-) (limited to 'django/utils') diff --git a/django/utils/_os.py b/django/utils/_os.py index 1ea12aed8a..6c1cd17a83 100644 --- a/django/utils/_os.py +++ b/django/utils/_os.py @@ -1,6 +1,8 @@ import os import stat +import sys from os.path import join, normcase, normpath, abspath, isabs, sep, dirname + from django.utils.encoding import force_text from django.utils import six @@ -10,6 +12,9 @@ except NameError: class WindowsError(Exception): pass +if not six.PY3: + fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() + # Under Python 2, define our own abspath function that can handle joining # unicode paths to a current working directory that has non-ASCII characters @@ -29,6 +34,23 @@ else: path = join(os.getcwdu(), path) return normpath(path) +def upath(path): + """ + Always return a unicode path. + """ + if not six.PY3: + return path.decode(fs_encoding) + return path + +def npath(path): + """ + Always return a native path, that is unicode on Python 3 and bytestring on + Python 2. + """ + if not six.PY3 and not isinstance(path, bytes): + return path.encode(fs_encoding) + return path + def safe_join(base, *paths): """ Joins one or more path components to the base path component intelligently. @@ -74,4 +96,3 @@ def rmtree_errorhandler(func, path, exc_info): os.chmod(path, stat.S_IWRITE) # use the original function to repeat the operation func(path) - diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index 1bcef2d8de..cf6270cc0c 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -10,6 +10,7 @@ from threading import local from django.utils.importlib import import_module from django.utils.encoding import force_str, force_text +from django.utils._os import upath from django.utils.safestring import mark_safe, SafeData from django.utils import six from django.utils.six import StringIO @@ -109,7 +110,7 @@ def translation(language): from django.conf import settings - globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale') + globalpath = os.path.join(os.path.dirname(upath(sys.modules[settings.__module__].__file__)), 'locale') def _fetch(lang, fallback=None): @@ -151,7 +152,7 @@ def translation(language): for appname in reversed(settings.INSTALLED_APPS): app = import_module(appname) - apppath = os.path.join(os.path.dirname(app.__file__), 'locale') + apppath = os.path.join(os.path.dirname(upath(app.__file__)), 'locale') if os.path.isdir(apppath): res = _merge(apppath) @@ -337,7 +338,7 @@ def all_locale_paths(): """ from django.conf import settings globalpath = os.path.join( - os.path.dirname(sys.modules[settings.__module__].__file__), 'locale') + os.path.dirname(upath(sys.modules[settings.__module__].__file__)), 'locale') return [globalpath] + list(settings.LOCALE_PATHS) def check_for_language(lang_code): -- cgit v1.3