Fixed #10200 -- Raised CommandError when errors happen in loaddata.

This commit is contained in:
Claude Paroz 2012-06-07 10:31:08 +02:00
parent 4464bbba15
commit 6fd1950a4e
3 changed files with 81 additions and 129 deletions

View File

@ -7,7 +7,7 @@ import traceback
from django.conf import settings
from django.core import serializers
from django.core.management.base import BaseCommand
from django.core.management.base import BaseCommand, CommandError
from django.core.management.color import no_style
from django.db import (connections, router, transaction, DEFAULT_DB_ALIAS,
IntegrityError, DatabaseError)
@ -36,11 +36,10 @@ class Command(BaseCommand):
connection = connections[using]
if not len(fixture_labels):
self.stderr.write(
raise CommandError(
"No database fixture specified. Please provide the path of at "
"least one fixture in the command line."
)
return
verbosity = int(options.get('verbosity'))
show_traceback = options.get('traceback')
@ -126,13 +125,9 @@ class Command(BaseCommand):
if verbosity >= 2:
self.stdout.write("Loading '%s' fixtures..." % fixture_name)
else:
self.stderr.write(
raise CommandError(
"Problem installing fixture '%s': %s is not a known serialization format." %
(fixture_name, format))
if commit:
transaction.rollback(using=using)
transaction.leave_transaction_management(using=using)
return
if os.path.isabs(fixture_name):
fixture_dirs = [fixture_name]
@ -167,12 +162,8 @@ class Command(BaseCommand):
else:
try:
if label_found:
self.stderr.write("Multiple fixtures named '%s' in %s. Aborting." %
raise CommandError("Multiple fixtures named '%s' in %s. Aborting." %
(fixture_name, humanize(fixture_dir)))
if commit:
transaction.rollback(using=using)
transaction.leave_transaction_management(using=using)
return
fixture_count += 1
objects_in_fixture = 0
@ -191,13 +182,13 @@ class Command(BaseCommand):
try:
obj.save(using=using)
except (DatabaseError, IntegrityError) as e:
msg = "Could not load %(app_label)s.%(object_name)s(pk=%(pk)s): %(error_msg)s" % {
e.args = ("Could not load %(app_label)s.%(object_name)s(pk=%(pk)s): %(error_msg)s" % {
'app_label': obj.object._meta.app_label,
'object_name': obj.object._meta.object_name,
'pk': obj.object.pk,
'error_msg': e
}
raise e.__class__, e.__class__(msg), sys.exc_info()[2]
},)
raise
loaded_object_count += loaded_objects_in_fixture
fixture_object_count += objects_in_fixture
@ -208,13 +199,9 @@ class Command(BaseCommand):
# If the fixture we loaded contains 0 objects, assume that an
# error was encountered during fixture loading.
if objects_in_fixture == 0:
self.stderr.write(
raise CommandError(
"No fixture data found for '%s'. (File format may be invalid.)" %
(fixture_name))
if commit:
transaction.rollback(using=using)
transaction.leave_transaction_management(using=using)
return
# Since we disabled constraint checks, we must manually check for
# any invalid keys that might have been added
@ -223,19 +210,13 @@ class Command(BaseCommand):
except (SystemExit, KeyboardInterrupt):
raise
except Exception:
except Exception as e:
if commit:
transaction.rollback(using=using)
transaction.leave_transaction_management(using=using)
if show_traceback:
traceback.print_exc()
else:
self.stderr.write(
"Problem installing fixture '%s': %s" %
(full_path, ''.join(traceback.format_exception(sys.exc_type,
sys.exc_value, sys.exc_traceback))))
return
if not isinstance(e, CommandError):
e.args = ("Problem installing fixture '%s': %s" % (full_path, e),)
raise
# If we found even one object in a fixture, we need to reset the
# database sequences.

View File

@ -4,7 +4,7 @@ import StringIO
from django.contrib.sites.models import Site
from django.core import management
from django.db import connection
from django.db import connection, IntegrityError
from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature
from .models import Article, Book, Spy, Tag, Visa
@ -232,11 +232,9 @@ class FixtureLoadingTests(TestCase):
def test_ambiguous_compressed_fixture(self):
# The name "fixture5" is ambigous, so loading it will raise an error
new_io = StringIO.StringIO()
management.call_command('loaddata', 'fixture5', verbosity=0, stderr=new_io, commit=False)
output = new_io.getvalue().strip().split('\n')
self.assertEqual(len(output), 1)
self.assertTrue(output[0].startswith("Multiple fixtures named 'fixture5'"))
with self.assertRaisesRegexp(management.CommandError,
"Multiple fixtures named 'fixture5'"):
management.call_command('loaddata', 'fixture5', verbosity=0, commit=False)
def test_db_loading(self):
# Load db fixtures 1 and 2. These will load using the 'default' database identifier implicitly
@ -258,10 +256,9 @@ class FixtureLoadingTests(TestCase):
# is closed at the end of each test.
if connection.vendor == 'mysql':
connection.cursor().execute("SET sql_mode = 'TRADITIONAL'")
new_io = StringIO.StringIO()
management.call_command('loaddata', 'invalid.json', verbosity=0, stderr=new_io, commit=False)
output = new_io.getvalue().strip().split('\n')
self.assertRegexpMatches(output[-1], "Error: Could not load fixtures.Article\(pk=1\): .*$")
with self.assertRaisesRegexp(IntegrityError,
"Could not load fixtures.Article\(pk=1\): .*$"):
management.call_command('loaddata', 'invalid.json', verbosity=0, commit=False)
def test_loading_using(self):
# Load db fixtures 1 and 2. These will load using the 'default' database identifier explicitly
@ -316,11 +313,9 @@ class FixtureTransactionTests(TransactionTestCase):
# Try to load fixture 2 using format discovery; this will fail
# because there are two fixture2's in the fixtures directory
new_io = StringIO.StringIO()
management.call_command('loaddata', 'fixture2', verbosity=0, stderr=new_io)
output = new_io.getvalue().strip().split('\n')
self.assertEqual(len(output), 1)
self.assertTrue(output[0].startswith("Multiple fixtures named 'fixture2'"))
with self.assertRaisesRegexp(management.CommandError,
"Multiple fixtures named 'fixture2'"):
management.call_command('loaddata', 'fixture2', verbosity=0)
# object list is unaffected
self.assertQuerysetEqual(Article.objects.all(), [

View File

@ -9,7 +9,7 @@ from io import BytesIO
from django.core import management
from django.core.management.base import CommandError
from django.core.management.commands.dumpdata import sort_dependencies
from django.db import transaction
from django.db import transaction, IntegrityError
from django.db.models import signals
from django.test import (TestCase, TransactionTestCase, skipIfDBFeature,
skipUnlessDBFeature)
@ -116,17 +116,14 @@ class TestFixtures(TestCase):
Test for ticket #4371 -- Loading data of an unknown format should fail
Validate that error conditions are caught correctly
"""
stderr = BytesIO()
with self.assertRaisesRegexp(management.CommandError,
"Problem installing fixture 'bad_fixture1': "
"unkn is not a known serialization format."):
management.call_command(
'loaddata',
'bad_fixture1.unkn',
verbosity=0,
commit=False,
stderr=stderr,
)
self.assertEqual(
stderr.getvalue(),
"Problem installing fixture 'bad_fixture1': unkn is not a known serialization format.\n"
)
def test_invalid_data(self):
@ -135,17 +132,13 @@ class TestFixtures(TestCase):
using explicit filename.
Validate that error conditions are caught correctly
"""
stderr = BytesIO()
with self.assertRaisesRegexp(management.CommandError,
"No fixture data found for 'bad_fixture2'. \(File format may be invalid.\)"):
management.call_command(
'loaddata',
'bad_fixture2.xml',
verbosity=0,
commit=False,
stderr=stderr,
)
self.assertEqual(
stderr.getvalue(),
"No fixture data found for 'bad_fixture2'. (File format may be invalid.)\n"
)
def test_invalid_data_no_ext(self):
@ -154,17 +147,13 @@ class TestFixtures(TestCase):
without file extension.
Validate that error conditions are caught correctly
"""
stderr = BytesIO()
with self.assertRaisesRegexp(management.CommandError,
"No fixture data found for 'bad_fixture2'. \(File format may be invalid.\)"):
management.call_command(
'loaddata',
'bad_fixture2',
verbosity=0,
commit=False,
stderr=stderr,
)
self.assertEqual(
stderr.getvalue(),
"No fixture data found for 'bad_fixture2'. (File format may be invalid.)\n"
)
def test_empty(self):
@ -172,35 +161,27 @@ class TestFixtures(TestCase):
Test for ticket #4371 -- Loading a fixture file with no data returns an error.
Validate that error conditions are caught correctly
"""
stderr = BytesIO()
with self.assertRaisesRegexp(management.CommandError,
"No fixture data found for 'empty'. \(File format may be invalid.\)"):
management.call_command(
'loaddata',
'empty',
verbosity=0,
commit=False,
stderr=stderr,
)
self.assertEqual(
stderr.getvalue(),
"No fixture data found for 'empty'. (File format may be invalid.)\n"
)
def test_error_message(self):
"""
(Regression for #9011 - error message is correct)
"""
stderr = BytesIO()
with self.assertRaisesRegexp(management.CommandError,
"^No fixture data found for 'bad_fixture2'. \(File format may be invalid.\)$"):
management.call_command(
'loaddata',
'bad_fixture2',
'animal',
verbosity=0,
commit=False,
stderr=stderr,
)
self.assertEqual(
stderr.getvalue(),
"No fixture data found for 'bad_fixture2'. (File format may be invalid.)\n"
)
def test_pg_sequence_resetting_checks(self):
@ -357,16 +338,13 @@ class TestFixtures(TestCase):
"""
Regression for #3615 - Ensure data with nonexistent child key references raises error
"""
stderr = BytesIO()
with self.assertRaisesRegexp(IntegrityError,
"Problem installing fixture"):
management.call_command(
'loaddata',
'forward_ref_bad_data.json',
verbosity=0,
commit=False,
stderr=stderr,
)
self.assertTrue(
stderr.getvalue().startswith('Problem installing fixture')
)
_cur_dir = os.path.dirname(os.path.abspath(__file__))
@ -392,15 +370,13 @@ class TestFixtures(TestCase):
"""
Regression for #7043 - Error is quickly reported when no fixtures is provided in the command line.
"""
stderr = BytesIO()
with self.assertRaisesRegexp(management.CommandError,
"No database fixture specified. Please provide the path of "
"at least one fixture in the command line."):
management.call_command(
'loaddata',
verbosity=0,
commit=False,
stderr=stderr,
)
self.assertEqual(
stderr.getvalue(), 'No database fixture specified. Please provide the path of at least one fixture in the command line.\n'
)
def test_loaddata_not_existant_fixture_file(self):