diff options
| author | Claude Paroz <claude@2xlibre.net> | 2012-12-08 11:13:52 +0100 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2012-12-08 11:13:52 +0100 |
| commit | c91667338a4e774e2819ccf4da852dc7b759bc19 (patch) | |
| tree | 42a700d237c85ac2b647999d02d3dcd7d8047068 /django | |
| parent | 53b879f045f0e55cc8f4bedff67b5a14f3057561 (diff) | |
Fixed #19357 -- Allow non-ASCII chars in filesystem paths
Thanks kujiu for the report and Aymeric Augustin for the review.
Diffstat (limited to 'django')
23 files changed, 82 insertions, 41 deletions
diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py index 94963b4d39..cb0c116416 100644 --- a/django/contrib/admindocs/views.py +++ b/django/contrib/admindocs/views.py @@ -14,6 +14,7 @@ from django.core import urlresolvers from django.contrib.admindocs import utils from django.contrib.sites.models import Site from django.utils.importlib import import_module +from django.utils._os import upath from django.utils import six from django.utils.translation import ugettext as _ from django.utils.safestring import mark_safe @@ -311,7 +312,7 @@ def load_all_installed_template_libraries(): try: libraries = [ os.path.splitext(p)[0] - for p in os.listdir(os.path.dirname(mod.__file__)) + for p in os.listdir(os.path.dirname(upath(mod.__file__))) if p.endswith('.py') and p[0].isalpha() ] except OSError: diff --git a/django/contrib/auth/tests/context_processors.py b/django/contrib/auth/tests/context_processors.py index 32fea8ac80..f846a828dd 100644 --- a/django/contrib/auth/tests/context_processors.py +++ b/django/contrib/auth/tests/context_processors.py @@ -9,6 +9,7 @@ from django.contrib.auth.context_processors import PermWrapper, PermLookupDict from django.db.models import Q from django.test import TestCase from django.test.utils import override_settings +from django.utils._os import upath class MockUser(object): @@ -63,7 +64,7 @@ class PermWrapperTests(TestCase): @skipIfCustomUser @override_settings( TEMPLATE_DIRS=( - os.path.join(os.path.dirname(__file__), 'templates'), + os.path.join(os.path.dirname(upath(__file__)), 'templates'), ), USE_TZ=False, # required for loading the fixture PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',), diff --git a/django/contrib/auth/tests/forms.py b/django/contrib/auth/tests/forms.py index 286652ebcc..25890683e8 100644 --- a/django/contrib/auth/tests/forms.py +++ b/django/contrib/auth/tests/forms.py @@ -11,6 +11,7 @@ from django.forms.fields import Field, EmailField from django.test import TestCase from django.test.utils import override_settings from django.utils.encoding import force_text +from django.utils._os import upath from django.utils import translation from django.utils.translation import ugettext as _ @@ -331,7 +332,7 @@ class PasswordResetFormTest(TestCase): self.assertEqual(form.cleaned_data['email'], email) def test_custom_email_subject(self): - template_path = os.path.join(os.path.dirname(__file__), 'templates') + template_path = os.path.join(os.path.dirname(upath(__file__)), 'templates') with self.settings(TEMPLATE_DIRS=(template_path,)): data = {'email': 'testclient@example.com'} form = PasswordResetForm(data) diff --git a/django/contrib/auth/tests/views.py b/django/contrib/auth/tests/views.py index b97d4a7cdf..0e83ca40a2 100644 --- a/django/contrib/auth/tests/views.py +++ b/django/contrib/auth/tests/views.py @@ -11,6 +11,7 @@ from django.http import QueryDict from django.utils.encoding import force_text from django.utils.html import escape from django.utils.http import urlquote +from django.utils._os import upath from django.test import TestCase from django.test.utils import override_settings @@ -27,7 +28,7 @@ from django.contrib.auth.tests.utils import skipIfCustomUser LANGUAGE_CODE='en', TEMPLATE_LOADERS=global_settings.TEMPLATE_LOADERS, TEMPLATE_DIRS=( - os.path.join(os.path.dirname(__file__), 'templates'), + os.path.join(os.path.dirname(upath(__file__)), 'templates'), ), USE_TZ=False, PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',), diff --git a/django/contrib/formtools/tests/__init__.py b/django/contrib/formtools/tests/__init__.py index a21ffde533..aa7d5ff7d4 100644 --- a/django/contrib/formtools/tests/__init__.py +++ b/django/contrib/formtools/tests/__init__.py @@ -14,6 +14,7 @@ from django.contrib.formtools.wizard import FormWizard from django.test import TestCase from django.test.html import parse_html from django.test.utils import override_settings +from django.utils._os import upath from django.utils import unittest from django.contrib.formtools.tests.wizard import * @@ -36,7 +37,7 @@ class TestFormPreview(preview.FormPreview): @override_settings( TEMPLATE_DIRS=( - os.path.join(os.path.dirname(__file__), 'templates'), + os.path.join(os.path.dirname(upath(__file__)), 'templates'), ), ) class PreviewTests(TestCase): @@ -214,7 +215,7 @@ class DummyRequest(http.HttpRequest): @override_settings( SECRET_KEY="123", TEMPLATE_DIRS=( - os.path.join(os.path.dirname(__file__), 'templates'), + os.path.join(os.path.dirname(upath(__file__)), 'templates'), ), ) class WizardTests(TestCase): diff --git a/django/contrib/formtools/tests/wizard/wizardtests/tests.py b/django/contrib/formtools/tests/wizard/wizardtests/tests.py index 6403a5548d..4aaea7d56e 100644 --- a/django/contrib/formtools/tests/wizard/wizardtests/tests.py +++ b/django/contrib/formtools/tests/wizard/wizardtests/tests.py @@ -9,6 +9,7 @@ from django.conf import settings from django.contrib.auth.models import User from django.contrib.formtools.wizard.views import CookieWizardView from django.contrib.formtools.tests.wizard.forms import UserForm, UserFormSet +from django.utils._os import upath class WizardTests(object): @@ -86,7 +87,7 @@ class WizardTests(object): self.assertEqual(response.context['wizard']['steps'].current, 'form2') post_data = self.wizard_step_data[1] - post_data['form2-file1'] = open(__file__, 'rb') + post_data['form2-file1'] = open(upath(__file__), 'rb') response = self.client.post(self.wizard_url, post_data) self.assertEqual(response.status_code, 200) self.assertEqual(response.context['wizard']['steps'].current, 'form3') @@ -99,7 +100,7 @@ class WizardTests(object): self.assertEqual(response.status_code, 200) all_data = response.context['form_list'] - with open(__file__, 'rb') as f: + with open(upath(__file__), 'rb') as f: self.assertEqual(all_data[1]['file1'].read(), f.read()) all_data[1]['file1'].close() del all_data[1]['file1'] @@ -118,7 +119,7 @@ class WizardTests(object): self.assertEqual(response.status_code, 200) post_data = self.wizard_step_data[1] - with open(__file__, 'rb') as post_file: + with open(upath(__file__), 'rb') as post_file: post_data['form2-file1'] = post_file response = self.client.post(self.wizard_url, post_data) self.assertEqual(response.status_code, 200) @@ -130,7 +131,7 @@ class WizardTests(object): self.assertEqual(response.status_code, 200) all_data = response.context['all_cleaned_data'] - with open(__file__, 'rb') as f: + with open(upath(__file__), 'rb') as f: self.assertEqual(all_data['file1'].read(), f.read()) all_data['file1'].close() del all_data['file1'] @@ -150,7 +151,7 @@ class WizardTests(object): post_data = self.wizard_step_data[1] post_data['form2-file1'].close() - post_data['form2-file1'] = open(__file__, 'rb') + post_data['form2-file1'] = open(upath(__file__), 'rb') response = self.client.post(self.wizard_url, post_data) self.assertEqual(response.status_code, 200) @@ -178,7 +179,7 @@ class WizardTests(object): post_data = self.wizard_step_data[1] post_data['form2-file1'].close() - post_data['form2-file1'] = open(__file__, 'rb') + post_data['form2-file1'] = open(upath(__file__), 'rb') response = self.client.post(self.wizard_url, post_data) self.assertEqual(response.status_code, 200) self.assertEqual(response.context['wizard']['steps'].current, 'form3') @@ -291,7 +292,7 @@ class WizardTestKwargs(TestCase): self.wizard_step_data[0]['form1-user'] = self.testuser.pk def test_template(self): - templates = os.path.join(os.path.dirname(__file__), 'templates') + templates = os.path.join(os.path.dirname(upath(__file__)), 'templates') with self.settings( TEMPLATE_DIRS=list(settings.TEMPLATE_DIRS) + [templates]): response = self.client.get(self.wizard_url) diff --git a/django/contrib/gis/geometry/test_data.py b/django/contrib/gis/geometry/test_data.py index b0f6e1ad57..e13e8589e6 100644 --- a/django/contrib/gis/geometry/test_data.py +++ b/django/contrib/gis/geometry/test_data.py @@ -7,13 +7,14 @@ import os from django.contrib import gis from django.utils import six +from django.utils._os import upath # This global used to store reference geometry data. GEOMETRIES = None # Path where reference test data is located. -TEST_DATA = os.path.join(os.path.dirname(gis.__file__), 'tests', 'data') +TEST_DATA = os.path.join(os.path.dirname(upath(gis.__file__)), 'tests', 'data') def tuplize(seq): diff --git a/django/contrib/gis/tests/geo3d/tests.py b/django/contrib/gis/tests/geo3d/tests.py index f7590fe84a..6b40164422 100644 --- a/django/contrib/gis/tests/geo3d/tests.py +++ b/django/contrib/gis/tests/geo3d/tests.py @@ -7,12 +7,13 @@ from django.contrib.gis.db.models import Union, Extent3D from django.contrib.gis.geos import GEOSGeometry, LineString, Point, Polygon from django.contrib.gis.utils import LayerMapping, LayerMapError from django.test import TestCase +from django.utils._os import upath from .models import (City3D, Interstate2D, Interstate3D, InterstateProj2D, InterstateProj3D, Point2D, Point3D, MultiPoint3D, Polygon2D, Polygon3D) -data_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'data')) +data_path = os.path.realpath(os.path.join(os.path.dirname(upath(__file__)), '..', 'data')) city_file = os.path.join(data_path, 'cities', 'cities.shp') vrt_file = os.path.join(data_path, 'test_vrt', 'test_vrt.vrt') diff --git a/django/contrib/gis/tests/geogapp/tests.py b/django/contrib/gis/tests/geogapp/tests.py index 2fd3560d0a..a8c607c502 100644 --- a/django/contrib/gis/tests/geogapp/tests.py +++ b/django/contrib/gis/tests/geogapp/tests.py @@ -8,6 +8,7 @@ import os from django.contrib.gis import gdal from django.contrib.gis.measure import D from django.test import TestCase +from django.utils._os import upath from .models import City, County, Zipcode @@ -61,7 +62,7 @@ class GeographyTest(TestCase): from django.contrib.gis.utils import LayerMapping # Getting the shapefile and mapping dictionary. - shp_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'data')) + shp_path = os.path.realpath(os.path.join(os.path.dirname(upath(__file__)), '..', 'data')) co_shp = os.path.join(shp_path, 'counties', 'counties.shp') co_mapping = {'name' : 'Name', 'state' : 'State', diff --git a/django/contrib/gis/tests/layermap/tests.py b/django/contrib/gis/tests/layermap/tests.py index a976954d25..470e5be216 100644 --- a/django/contrib/gis/tests/layermap/tests.py +++ b/django/contrib/gis/tests/layermap/tests.py @@ -13,13 +13,14 @@ from django.db import router from django.conf import settings from django.test import TestCase from django.utils import unittest +from django.utils._os import upath from .models import ( City, County, CountyFeat, Interstate, ICity1, ICity2, Invalid, State, city_mapping, co_mapping, cofeat_mapping, inter_mapping) -shp_path = os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir, 'data')) +shp_path = os.path.realpath(os.path.join(os.path.dirname(upath(__file__)), os.pardir, 'data')) city_shp = os.path.join(shp_path, 'cities', 'cities.shp') co_shp = os.path.join(shp_path, 'counties', 'counties.shp') inter_shp = os.path.join(shp_path, 'interstates', 'interstates.shp') diff --git a/django/contrib/sitemaps/tests/http.py b/django/contrib/sitemaps/tests/http.py index 99042fef03..4a1cf66b17 100644 --- a/django/contrib/sitemaps/tests/http.py +++ b/django/contrib/sitemaps/tests/http.py @@ -11,6 +11,7 @@ from django.core.exceptions import ImproperlyConfigured from django.test.utils import override_settings from django.utils.unittest import skipUnless from django.utils.formats import localize +from django.utils._os import upath from django.utils.translation import activate, deactivate from .base import SitemapTestsBase @@ -29,7 +30,7 @@ class HTTPSitemapTests(SitemapTestsBase): self.assertXMLEqual(response.content.decode('utf-8'), expected_content) @override_settings( - TEMPLATE_DIRS=(os.path.join(os.path.dirname(__file__), 'templates'),) + TEMPLATE_DIRS=(os.path.join(os.path.dirname(upath(__file__)), 'templates'),) ) def test_simple_sitemap_custom_index(self): "A simple sitemap index can be rendered with a custom template" @@ -64,7 +65,7 @@ class HTTPSitemapTests(SitemapTestsBase): self.assertXMLEqual(response.content.decode('utf-8'), expected_content) @override_settings( - TEMPLATE_DIRS=(os.path.join(os.path.dirname(__file__), 'templates'),) + TEMPLATE_DIRS=(os.path.join(os.path.dirname(upath(__file__)), 'templates'),) ) def test_simple_custom_sitemap(self): "A simple sitemap can be rendered with a custom template" diff --git a/django/contrib/staticfiles/storage.py b/django/contrib/staticfiles/storage.py index 9691b7849d..7e87a89f5b 100644 --- a/django/contrib/staticfiles/storage.py +++ b/django/contrib/staticfiles/storage.py @@ -19,6 +19,7 @@ from django.utils.datastructures import SortedDict from django.utils.encoding import force_bytes, force_text from django.utils.functional import LazyObject from django.utils.importlib import import_module +from django.utils._os import upath from django.contrib.staticfiles.utils import check_settings, matches_patterns @@ -296,7 +297,7 @@ class AppStaticStorage(FileSystemStorage): """ # app is the actual app module mod = import_module(app) - mod_path = os.path.dirname(mod.__file__) + mod_path = os.path.dirname(upath(mod.__file__)) location = os.path.join(mod_path, self.source_dir) super(AppStaticStorage, self).__init__(location, *args, **kwargs) diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py index bb26c20666..fab5059376 100644 --- a/django/core/management/__init__.py +++ b/django/core/management/__init__.py @@ -9,6 +9,7 @@ from django.core.exceptions import ImproperlyConfigured from django.core.management.base import BaseCommand, CommandError, handle_default_options from django.core.management.color import color_style from django.utils.importlib import import_module +from django.utils._os import upath from django.utils import six # For backwards compatibility: get_version() used to be in this module. @@ -410,10 +411,10 @@ def setup_environ(settings_mod, original_settings_path=None): # Add this project to sys.path so that it's importable in the conventional # way. For example, if this file (manage.py) lives in a directory # "myproject", this code would add "/path/to/myproject" to sys.path. - if '__init__.py' in settings_mod.__file__: - p = os.path.dirname(settings_mod.__file__) + if '__init__.py' in upath(settings_mod.__file__): + p = os.path.dirname(upath(settings_mod.__file__)) else: - p = settings_mod.__file__ + p = upath(settings_mod.__file__) project_directory, settings_filename = os.path.split(p) if project_directory == os.curdir or not project_directory: project_directory = os.getcwd() diff --git a/django/core/management/commands/compilemessages.py b/django/core/management/commands/compilemessages.py index b7392b9173..e1d8a33332 100644 --- a/django/core/management/commands/compilemessages.py +++ b/django/core/management/commands/compilemessages.py @@ -5,6 +5,7 @@ import os import sys from optparse import make_option from django.core.management.base import BaseCommand, CommandError +from django.utils._os import npath def has_bom(fn): with open(fn, 'rb') as f: @@ -41,8 +42,8 @@ def compile_messages(stderr, locale=None): # command, so that we can take advantage of shell quoting, to # quote any malicious characters/escaping. # See http://cyberelk.net/tim/articles/cmdline/ar01s02.html - os.environ['djangocompilemo'] = pf + '.mo' - os.environ['djangocompilepo'] = pf + '.po' + os.environ['djangocompilemo'] = npath(pf + '.mo') + os.environ['djangocompilepo'] = npath(pf + '.po') if sys.platform == 'win32': # Different shell-variable syntax cmd = 'msgfmt --check-format -o "%djangocompilemo%" "%djangocompilepo%"' else: diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py index f6f1b1039a..ed47b8fbf1 100644 --- a/django/core/management/commands/loaddata.py +++ b/django/core/management/commands/loaddata.py @@ -13,6 +13,7 @@ from django.db import (connections, router, transaction, DEFAULT_DB_ALIAS, IntegrityError, DatabaseError) from django.db.models import get_apps from django.utils.encoding import force_text +from django.utils._os import upath from itertools import product try: @@ -97,10 +98,10 @@ class Command(BaseCommand): if hasattr(app, '__path__'): # It's a 'models/' subpackage for path in app.__path__: - app_module_paths.append(path) + app_module_paths.append(upath(path)) else: # It's a models.py module - app_module_paths.append(app.__file__) + app_module_paths.append(upath(app.__file__)) app_fixtures = [os.path.join(os.path.dirname(path), 'fixtures') for path in app_module_paths] diff --git a/django/core/management/commands/makemessages.py b/django/core/management/commands/makemessages.py index 81c4fdf8cc..606cbe0b85 100644 --- a/django/core/management/commands/makemessages.py +++ b/django/core/management/commands/makemessages.py @@ -301,7 +301,7 @@ def make_messages(locale=None, domain='django', verbosity=1, all=False, locales = [] if locale is not None: - locales.append(locale) + locales.append(str(locale)) elif all: locale_dirs = filter(os.path.isdir, glob.glob('%s/*' % localedir)) locales = [os.path.basename(l) for l in locale_dirs] @@ -316,8 +316,8 @@ def make_messages(locale=None, domain='django', verbosity=1, all=False, if not os.path.isdir(basedir): os.makedirs(basedir) - pofile = os.path.join(basedir, '%s.po' % domain) - potfile = os.path.join(basedir, '%s.pot' % domain) + pofile = os.path.join(basedir, '%s.po' % str(domain)) + potfile = os.path.join(basedir, '%s.pot' % str(domain)) if os.path.exists(potfile): os.unlink(potfile) diff --git a/django/core/management/sql.py b/django/core/management/sql.py index ea03e9088c..e46f4ae4f5 100644 --- a/django/core/management/sql.py +++ b/django/core/management/sql.py @@ -8,6 +8,7 @@ from django.conf import settings from django.core.management.base import CommandError from django.db import models from django.db.models import get_models +from django.utils._os import upath def sql_create(app, style, connection): @@ -159,7 +160,7 @@ def _split_statements(content): def custom_sql_for_model(model, style, connection): opts = model._meta - app_dir = os.path.normpath(os.path.join(os.path.dirname(models.get_app(model._meta.app_label).__file__), 'sql')) + app_dir = os.path.normpath(os.path.join(os.path.dirname(upath(models.get_app(model._meta.app_label).__file__)), 'sql')) output = [] # Post-creation SQL should come before any initial SQL data is loaded. diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py index 9c0b7b70fd..c657fd9a54 100644 --- a/django/core/urlresolvers.py +++ b/django/core/urlresolvers.py @@ -251,9 +251,9 @@ class RegexURLResolver(LocaleRegexProvider): urlconf_repr = '<%s list>' % self.urlconf_name[0].__class__.__name__ else: urlconf_repr = repr(self.urlconf_name) - return force_str('<%s %s (%s:%s) %s>' % ( + return str('<%s %s (%s:%s) %s>') % ( self.__class__.__name__, urlconf_repr, self.app_name, - self.namespace, self.regex.pattern)) + self.namespace, self.regex.pattern) def _populate(self): lookups = MultiValueDict() diff --git a/django/db/models/loading.py b/django/db/models/loading.py index a0510acc6d..56edc36bec 100644 --- a/django/db/models/loading.py +++ b/django/db/models/loading.py @@ -5,6 +5,7 @@ from django.core.exceptions import ImproperlyConfigured from django.utils.datastructures import SortedDict from django.utils.importlib import import_module from django.utils.module_loading import module_has_submodule +from django.utils._os import upath from django.utils import six import imp @@ -244,8 +245,8 @@ class AppCache(object): # The same model may be imported via different paths (e.g. # appname.models and project.appname.models). We use the source # filename as a means to detect identity. - fname1 = os.path.abspath(sys.modules[model.__module__].__file__) - fname2 = os.path.abspath(sys.modules[model_dict[model_name].__module__].__file__) + fname1 = os.path.abspath(upath(sys.modules[model.__module__].__file__)) + fname2 = os.path.abspath(upath(sys.modules[model_dict[model_name].__module__].__file__)) # Since the filename extension could be .py the first time and # .pyc or .pyo the second time, ignore the extension when # comparing. diff --git a/django/db/utils.py b/django/db/utils.py index a91298626b..842fd354d6 100644 --- a/django/db/utils.py +++ b/django/db/utils.py @@ -5,6 +5,7 @@ from threading import local from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.utils.importlib import import_module +from django.utils._os import upath from django.utils import six @@ -27,7 +28,7 @@ def load_backend(backend_name): except ImportError as e_user: # The database backend wasn't found. Display a helpful error message # listing all possible (built-in) database backends. - backend_dir = os.path.join(os.path.dirname(__file__), 'backends') + backend_dir = os.path.join(os.path.dirname(upath(__file__)), 'backends') try: builtin_backends = [ name for _, name, ispkg in pkgutil.iter_modules([backend_dir]) 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): diff --git a/django/views/i18n.py b/django/views/i18n.py index 96643f0d7d..c1d456d667 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -8,6 +8,7 @@ from django.utils.translation import check_for_language, activate, to_locale, ge from django.utils.text import javascript_quote from django.utils.encoding import smart_text from django.utils.formats import get_format_modules, get_format +from django.utils._os import upath from django.utils import six def set_language(request): @@ -197,7 +198,7 @@ def javascript_catalog(request, domain='djangojs', packages=None): # paths of requested packages for package in packages: p = importlib.import_module(package) - path = os.path.join(os.path.dirname(p.__file__), 'locale') + path = os.path.join(os.path.dirname(upath(p.__file__)), 'locale') paths.append(path) # add the filesystem paths listed in the LOCALE_PATHS setting paths.extend(list(reversed(settings.LOCALE_PATHS))) |
