Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed the staticfiles management commands collectstatic and findstati…

…c to not raise encoding related exceptions when handlings filenames with non-ASCII characters.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15538 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 64a0a33c33079fa8ea79f1935d2a56281427e0f0 1 parent 6eacbfd
@jezdez jezdez authored
View
26 django/contrib/staticfiles/management/commands/collectstatic.py
@@ -6,6 +6,7 @@
from django.conf import settings
from django.core.files.storage import get_storage_class
from django.core.management.base import CommandError, NoArgsCommand
+from django.utils.encoding import smart_str
from django.contrib.staticfiles import finders
@@ -64,7 +65,7 @@ def handle_noargs(self, **options):
# Warn before doing anything more.
if options.get('interactive'):
- confirm = raw_input("""
+ confirm = raw_input(u"""
You have requested to collect static files at the destination
location as specified in your settings file ('%s').
@@ -90,17 +91,18 @@ def handle_noargs(self, **options):
actual_count = len(self.copied_files) + len(self.symlinked_files)
unmodified_count = len(self.unmodified_files)
if self.verbosity >= 1:
- self.stdout.write("\n%s static file%s %s to '%s'%s.\n"
+ self.stdout.write(smart_str(u"\n%s static file%s %s to '%s'%s.\n"
% (actual_count, actual_count != 1 and 's' or '',
symlink and 'symlinked' or 'copied',
settings.STATIC_ROOT,
unmodified_count and ' (%s unmodified)'
- % unmodified_count or ''))
+ % unmodified_count or '')))
def log(self, msg, level=2):
"""
Small log helper
"""
+ msg = smart_str(msg)
if not msg.endswith("\n"):
msg += "\n"
if self.verbosity >= level:
@@ -135,13 +137,13 @@ def delete_file(self, path, prefixed_path, source_storage, **options):
(not symlink and full_path and os.path.islink(full_path))):
if prefixed_path not in self.unmodified_files:
self.unmodified_files.append(prefixed_path)
- self.log("Skipping '%s' (not modified)" % path)
+ self.log(u"Skipping '%s' (not modified)" % path)
return False
# Then delete the existing file if really needed
if options['dry_run']:
- self.log("Pretending to delete '%s'" % path)
+ self.log(u"Pretending to delete '%s'" % path)
else:
- self.log("Deleting '%s'" % path)
+ self.log(u"Deleting '%s'" % path)
self.storage.delete(prefixed_path)
return True
@@ -151,7 +153,7 @@ def link_file(self, path, prefixed_path, source_storage, **options):
"""
# Skip this file if it was already copied earlier
if prefixed_path in self.symlinked_files:
- return self.log("Skipping '%s' (already linked earlier)" % path)
+ return self.log(u"Skipping '%s' (already linked earlier)" % path)
# Delete the target file if needed or break
if not self.delete_file(path, prefixed_path, source_storage, **options):
return
@@ -159,9 +161,9 @@ def link_file(self, path, prefixed_path, source_storage, **options):
source_path = source_storage.path(path)
# Finally link the file
if options['dry_run']:
- self.log("Pretending to link '%s'" % source_path, level=1)
+ self.log(u"Pretending to link '%s'" % source_path, level=1)
else:
- self.log("Linking '%s'" % source_path, level=1)
+ self.log(u"Linking '%s'" % source_path, level=1)
full_path = self.storage.path(prefixed_path)
try:
os.makedirs(os.path.dirname(full_path))
@@ -177,7 +179,7 @@ def copy_file(self, path, prefixed_path, source_storage, **options):
"""
# Skip this file if it was already copied earlier
if prefixed_path in self.copied_files:
- return self.log("Skipping '%s' (already copied earlier)" % path)
+ return self.log(u"Skipping '%s' (already copied earlier)" % path)
# Delete the target file if needed or break
if not self.delete_file(path, prefixed_path, source_storage, **options):
return
@@ -185,9 +187,9 @@ def copy_file(self, path, prefixed_path, source_storage, **options):
source_path = source_storage.path(path)
# Finally start copying
if options['dry_run']:
- self.log("Pretending to copy '%s'" % source_path, level=1)
+ self.log(u"Pretending to copy '%s'" % source_path, level=1)
else:
- self.log("Copying '%s'" % source_path, level=1)
+ self.log(u"Copying '%s'" % source_path, level=1)
if self.local:
full_path = self.storage.path(prefixed_path)
try:
View
11 django/contrib/staticfiles/management/commands/findstatic.py
@@ -1,6 +1,7 @@
import os
from optparse import make_option
from django.core.management.base import LabelCommand
+from django.utils.encoding import smart_str, smart_unicode
from django.contrib.staticfiles import finders
@@ -16,11 +17,15 @@ class Command(LabelCommand):
def handle_label(self, path, **options):
verbosity = int(options.get('verbosity', 1))
result = finders.find(path, all=options['all'])
+ path = smart_unicode(path)
if result:
if not isinstance(result, (list, tuple)):
result = [result]
- output = '\n '.join((os.path.realpath(path) for path in result))
- self.stdout.write("Found %r here:\n %s\n" % (path, output))
+ output = u'\n '.join(
+ (smart_unicode(os.path.realpath(path)) for path in result))
+ self.stdout.write(
+ smart_str(u"Found '%s' here:\n %s\n" % (path, output)))
else:
if verbosity >= 1:
- self.stdout.write("No matching file found for %r.\n" % path)
+ self.stderr.write(
+ smart_str("No matching file found for '%s'.\n" % path))
View
1  tests/regressiontests/staticfiles_tests/apps/test/static/test/speçial.txt
@@ -0,0 +1 @@
+speçial in the app dir
View
19 tests/regressiontests/staticfiles_tests/tests.py
@@ -1,3 +1,5 @@
+# -*- encoding: utf-8 -*-
+import codecs
import os
import posixpath
import shutil
@@ -11,6 +13,7 @@
from django.core.files.storage import default_storage
from django.core.management import call_command
from django.test import TestCase
+from django.utils.encoding import smart_unicode
from django.utils._os import rmtree_errorhandler
@@ -72,8 +75,8 @@ def tearDown(self):
settings.INSTALLED_APPS = self.old_installed_apps
def assertFileContains(self, filepath, text):
- self.assertTrue(text in self._get_file(filepath),
- "'%s' not in '%s'" % (text, filepath))
+ self.assertTrue(text in self._get_file(smart_unicode(filepath)),
+ u"'%s' not in '%s'" % (text, filepath))
def assertFileNotFound(self, filepath):
self.assertRaises(IOError, self._get_file, filepath)
@@ -108,7 +111,7 @@ def run_collectstatic(self, **kwargs):
def _get_file(self, filepath):
assert filepath, 'filepath is empty.'
filepath = os.path.join(settings.STATIC_ROOT, filepath)
- f = open(filepath)
+ f = codecs.open(filepath, "r", "utf-8")
try:
return f.read()
finally:
@@ -140,10 +143,16 @@ def test_staticfiles_dirs_priority(self):
def test_app_files(self):
"""
- Can find a file in an app media/ directory.
+ Can find a file in an app static/ directory.
"""
self.assertFileContains('test/file1.txt', 'file1 in the app dir')
+ def test_nonascii_filenames(self):
+ """
+ Can find a file with non-ASCII character in an app static/ directory.
+ """
+ self.assertFileContains(u'test/speçial.txt', u'speçial in the app dir')
+
class TestFindStatic(BuildStaticTestCase, TestDefaults):
"""
@@ -156,7 +165,7 @@ def _get_file(self, filepath):
call_command('findstatic', filepath, all=False, verbosity='0')
sys.stdout.seek(0)
lines = [l.strip() for l in sys.stdout.readlines()]
- contents = open(lines[1].strip()).read()
+ contents = codecs.open(lines[1].strip(), "r", "utf-8").read()
finally:
sys.stdout = _stdout
return contents
Please sign in to comment.
Something went wrong with that request. Please try again.