summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoritz Sichert <moritz.sichert@googlemail.com>2015-06-13 12:20:05 +0200
committerTim Graham <timograham@gmail.com>2015-06-13 19:45:05 -0400
commit98df288ddaba9787e4a370f12aba51c2b9133142 (patch)
treef4a25f41bd3e18c3078ad010421e8a0d5805ddbe
parentd58573e60d7139711e24410741ef508bf0d124d8 (diff)
Fixed #24978 -- Escaped special characters in loaddata fixture paths
-rw-r--r--django/core/management/commands/loaddata.py4
-rw-r--r--django/utils/glob.py36
-rw-r--r--tests/fixtures/fixtures/fixture?with[special]chars*.json10
-rw-r--r--tests/fixtures/tests.py4
-rw-r--r--tests/utils_tests/test_glob.py15
5 files changed, 68 insertions, 1 deletions
diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py
index 32a676d846..af108e08e1 100644
--- a/django/core/management/commands/loaddata.py
+++ b/django/core/management/commands/loaddata.py
@@ -21,6 +21,7 @@ from django.utils import lru_cache
from django.utils._os import upath
from django.utils.encoding import force_text
from django.utils.functional import cached_property
+from django.utils.glob import glob_escape
try:
import bz2
@@ -209,7 +210,8 @@ class Command(BaseCommand):
if self.verbosity >= 2:
self.stdout.write("Checking %s for fixtures..." % humanize(fixture_dir))
fixture_files_in_dir = []
- for candidate in glob.iglob(os.path.join(fixture_dir, fixture_name + '*')):
+ path = os.path.join(fixture_dir, fixture_name)
+ for candidate in glob.iglob(glob_escape(path) + '*'):
if os.path.basename(candidate) in targets:
# Save the fixture_dir and fixture_name for future error messages.
fixture_files_in_dir.append((candidate, fixture_dir, fixture_name))
diff --git a/django/utils/glob.py b/django/utils/glob.py
new file mode 100644
index 0000000000..a3138b09dc
--- /dev/null
+++ b/django/utils/glob.py
@@ -0,0 +1,36 @@
+from __future__ import unicode_literals
+
+import os.path
+import re
+
+from django.utils import six
+
+# backport of Python 3.4's glob.escape
+
+try:
+ from glob import escape as glob_escape
+except ImportError:
+ _magic_check = re.compile('([*?[])')
+
+ if six.PY3:
+ _magic_check_bytes = re.compile(b'([*?[])')
+
+ def glob_escape(pathname):
+ """
+ Escape all special characters.
+ """
+ drive, pathname = os.path.splitdrive(pathname)
+ if isinstance(pathname, bytes):
+ pathname = _magic_check_bytes.sub(br'[\1]', pathname)
+ else:
+ pathname = _magic_check.sub(r'[\1]', pathname)
+ return drive + pathname
+
+ else:
+ def glob_escape(pathname):
+ """
+ Escape all special characters.
+ """
+ drive, pathname = os.path.splitdrive(pathname)
+ pathname = _magic_check.sub(r'[\1]', pathname)
+ return drive + pathname
diff --git a/tests/fixtures/fixtures/fixture?with[special]chars*.json b/tests/fixtures/fixtures/fixture?with[special]chars*.json
new file mode 100644
index 0000000000..b6b7ad2a7c
--- /dev/null
+++ b/tests/fixtures/fixtures/fixture?with[special]chars*.json
@@ -0,0 +1,10 @@
+[
+ {
+ "pk": "1",
+ "model": "fixtures.article",
+ "fields": {
+ "headline": "How To Deal With Special Characters",
+ "pub_date": "2006-06-16 12:00:00"
+ }
+ }
+]
diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py
index 544b70473b..d87f1942ff 100644
--- a/tests/fixtures/tests.py
+++ b/tests/fixtures/tests.py
@@ -224,6 +224,10 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase):
"Unknown model in excludes: fixtures.FooModel"):
self._dumpdata_assert(['fixtures', 'sites'], '', exclude_list=['fixtures.FooModel'])
+ def test_load_fixture_with_special_characters(self):
+ management.call_command('loaddata', 'fixture?with[special]chars*', verbosity=0)
+ self.assertQuerysetEqual(Article.objects.all(), ['<Article: How To Deal With Special Characters>'])
+
def test_dumpdata_with_filtering_manager(self):
spy1 = Spy.objects.create(name='Paul')
spy2 = Spy.objects.create(name='Alex', cover_blown=True)
diff --git a/tests/utils_tests/test_glob.py b/tests/utils_tests/test_glob.py
new file mode 100644
index 0000000000..7e72815ef8
--- /dev/null
+++ b/tests/utils_tests/test_glob.py
@@ -0,0 +1,15 @@
+from __future__ import unicode_literals
+
+from django.test import SimpleTestCase
+from django.utils.glob import glob_escape
+
+
+class TestUtilsGlob(SimpleTestCase):
+ def test_glob_escape(self):
+ filename = '/my/file?/name[with special chars*'
+ expected = '/my/file[?]/name[[]with special chars[*]'
+ filename_b = b'/my/file?/name[with special chars*'
+ expected_b = b'/my/file[?]/name[[]with special chars[*]'
+
+ self.assertEqual(glob_escape(filename), expected)
+ self.assertEqual(glob_escape(filename_b), expected_b)