Commit 6fd1950a authored by Claude Paroz's avatar Claude Paroz
Browse files

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

parent 4464bbba
Loading
Loading
Loading
Loading
+12 −31
Original line number Diff line number Diff line
@@ -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.
+10 −15
Original line number Diff line number Diff line
@@ -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(), [
+59 −83
Original line number Diff line number Diff line
@@ -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):