Code

Ticket #10200: 10200-2.diff

File 10200-2.diff, 15.8 KB (added by claudep, 23 months ago)

Raise CommandError in loaddata

Line 
1diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py
2index f44edf7..078fd6f 100644
3--- a/django/core/management/commands/loaddata.py
4+++ b/django/core/management/commands/loaddata.py
5@@ -7,7 +7,7 @@ import traceback
6 
7 from django.conf import settings
8 from django.core import serializers
9-from django.core.management.base import BaseCommand
10+from django.core.management.base import BaseCommand, CommandError
11 from django.core.management.color import no_style
12 from django.db import (connections, router, transaction, DEFAULT_DB_ALIAS,
13       IntegrityError, DatabaseError)
14@@ -36,11 +36,10 @@ class Command(BaseCommand):
15         connection = connections[using]
16 
17         if not len(fixture_labels):
18-            self.stderr.write(
19+            raise CommandError(
20                 "No database fixture specified. Please provide the path of at "
21                 "least one fixture in the command line."
22             )
23-            return
24 
25         verbosity = int(options.get('verbosity'))
26         show_traceback = options.get('traceback')
27@@ -126,13 +125,9 @@ class Command(BaseCommand):
28                         if verbosity >= 2:
29                             self.stdout.write("Loading '%s' fixtures..." % fixture_name)
30                     else:
31-                        self.stderr.write(
32+                        raise CommandError(
33                             "Problem installing fixture '%s': %s is not a known serialization format." %
34                                 (fixture_name, format))
35-                        if commit:
36-                            transaction.rollback(using=using)
37-                            transaction.leave_transaction_management(using=using)
38-                        return
39 
40                     if os.path.isabs(fixture_name):
41                         fixture_dirs = [fixture_name]
42@@ -167,12 +162,8 @@ class Command(BaseCommand):
43                             else:
44                                 try:
45                                     if label_found:
46-                                        self.stderr.write("Multiple fixtures named '%s' in %s. Aborting." %
47+                                        raise CommandError("Multiple fixtures named '%s' in %s. Aborting." %
48                                             (fixture_name, humanize(fixture_dir)))
49-                                        if commit:
50-                                            transaction.rollback(using=using)
51-                                            transaction.leave_transaction_management(using=using)
52-                                        return
53 
54                                     fixture_count += 1
55                                     objects_in_fixture = 0
56@@ -191,13 +182,13 @@ class Command(BaseCommand):
57                                             try:
58                                                 obj.save(using=using)
59                                             except (DatabaseError, IntegrityError) as e:
60-                                                msg = "Could not load %(app_label)s.%(object_name)s(pk=%(pk)s): %(error_msg)s" % {
61+                                                e.args = ("Could not load %(app_label)s.%(object_name)s(pk=%(pk)s): %(error_msg)s" % {
62                                                         'app_label': obj.object._meta.app_label,
63                                                         'object_name': obj.object._meta.object_name,
64                                                         'pk': obj.object.pk,
65                                                         'error_msg': e
66-                                                    }
67-                                                raise e.__class__, e.__class__(msg), sys.exc_info()[2]
68+                                                    },)
69+                                                raise
70 
71                                     loaded_object_count += loaded_objects_in_fixture
72                                     fixture_object_count += objects_in_fixture
73@@ -208,13 +199,9 @@ class Command(BaseCommand):
74                                 # If the fixture we loaded contains 0 objects, assume that an
75                                 # error was encountered during fixture loading.
76                                 if objects_in_fixture == 0:
77-                                    self.stderr.write(
78+                                    raise CommandError(
79                                         "No fixture data found for '%s'. (File format may be invalid.)" %
80                                             (fixture_name))
81-                                    if commit:
82-                                        transaction.rollback(using=using)
83-                                        transaction.leave_transaction_management(using=using)
84-                                    return
85 
86             # Since we disabled constraint checks, we must manually check for
87             # any invalid keys that might have been added
88@@ -223,19 +210,13 @@ class Command(BaseCommand):
89 
90         except (SystemExit, KeyboardInterrupt):
91             raise
92-        except Exception:
93+        except Exception as e:
94             if commit:
95                 transaction.rollback(using=using)
96                 transaction.leave_transaction_management(using=using)
97-            if show_traceback:
98-                traceback.print_exc()
99-            else:
100-                self.stderr.write(
101-                    "Problem installing fixture '%s': %s" %
102-                         (full_path, ''.join(traceback.format_exception(sys.exc_type,
103-                             sys.exc_value, sys.exc_traceback))))
104-            return
105-
106+            if not isinstance(e, CommandError):
107+                e.args = ("Problem installing fixture '%s': %s" % (full_path, e),)
108+            raise
109 
110         # If we found even one object in a fixture, we need to reset the
111         # database sequences.
112diff --git a/tests/modeltests/fixtures/tests.py b/tests/modeltests/fixtures/tests.py
113index 478bbe9..f5176da 100644
114--- a/tests/modeltests/fixtures/tests.py
115+++ b/tests/modeltests/fixtures/tests.py
116@@ -4,7 +4,7 @@ import StringIO
117 
118 from django.contrib.sites.models import Site
119 from django.core import management
120-from django.db import connection
121+from django.db import connection, IntegrityError
122 from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature
123 
124 from .models import Article, Book, Spy, Tag, Visa
125@@ -232,11 +232,9 @@ class FixtureLoadingTests(TestCase):
126 
127     def test_ambiguous_compressed_fixture(self):
128         # The name "fixture5" is ambigous, so loading it will raise an error
129-        new_io = StringIO.StringIO()
130-        management.call_command('loaddata', 'fixture5', verbosity=0, stderr=new_io, commit=False)
131-        output = new_io.getvalue().strip().split('\n')
132-        self.assertEqual(len(output), 1)
133-        self.assertTrue(output[0].startswith("Multiple fixtures named 'fixture5'"))
134+        with self.assertRaisesRegexp(management.CommandError,
135+                "Multiple fixtures named 'fixture5'"):
136+            management.call_command('loaddata', 'fixture5', verbosity=0, commit=False)
137 
138     def test_db_loading(self):
139         # Load db fixtures 1 and 2. These will load using the 'default' database identifier implicitly
140@@ -258,10 +256,9 @@ class FixtureLoadingTests(TestCase):
141         # is closed at the end of each test.
142         if connection.vendor == 'mysql':
143             connection.cursor().execute("SET sql_mode = 'TRADITIONAL'")
144-        new_io = StringIO.StringIO()
145-        management.call_command('loaddata', 'invalid.json', verbosity=0, stderr=new_io, commit=False)
146-        output = new_io.getvalue().strip().split('\n')
147-        self.assertRegexpMatches(output[-1], "Error: Could not load fixtures.Article\(pk=1\): .*$")
148+        with self.assertRaisesRegexp(IntegrityError,
149+                "Could not load fixtures.Article\(pk=1\): .*$"):
150+            management.call_command('loaddata', 'invalid.json', verbosity=0, commit=False)
151 
152     def test_loading_using(self):
153         # Load db fixtures 1 and 2. These will load using the 'default' database identifier explicitly
154@@ -316,11 +313,9 @@ class FixtureTransactionTests(TransactionTestCase):
155 
156         # Try to load fixture 2 using format discovery; this will fail
157         # because there are two fixture2's in the fixtures directory
158-        new_io = StringIO.StringIO()
159-        management.call_command('loaddata', 'fixture2', verbosity=0, stderr=new_io)
160-        output = new_io.getvalue().strip().split('\n')
161-        self.assertEqual(len(output), 1)
162-        self.assertTrue(output[0].startswith("Multiple fixtures named 'fixture2'"))
163+        with self.assertRaisesRegexp(management.CommandError,
164+                "Multiple fixtures named 'fixture2'"):
165+            management.call_command('loaddata', 'fixture2', verbosity=0)
166 
167         # object list is unaffected
168         self.assertQuerysetEqual(Article.objects.all(), [
169diff --git a/tests/regressiontests/fixtures_regress/tests.py b/tests/regressiontests/fixtures_regress/tests.py
170index 0e2cc3a..c0b811b 100644
171--- a/tests/regressiontests/fixtures_regress/tests.py
172+++ b/tests/regressiontests/fixtures_regress/tests.py
173@@ -9,7 +9,7 @@ from io import BytesIO
174 from django.core import management
175 from django.core.management.base import CommandError
176 from django.core.management.commands.dumpdata import sort_dependencies
177-from django.db import transaction
178+from django.db import transaction, IntegrityError
179 from django.db.models import signals
180 from django.test import (TestCase, TransactionTestCase, skipIfDBFeature,
181     skipUnlessDBFeature)
182@@ -116,18 +116,15 @@ class TestFixtures(TestCase):
183         Test for ticket #4371 -- Loading data of an unknown format should fail
184         Validate that error conditions are caught correctly
185         """
186-        stderr = BytesIO()
187-        management.call_command(
188-            'loaddata',
189-            'bad_fixture1.unkn',
190-            verbosity=0,
191-            commit=False,
192-            stderr=stderr,
193-        )
194-        self.assertEqual(
195-            stderr.getvalue(),
196-            "Problem installing fixture 'bad_fixture1': unkn is not a known serialization format.\n"
197-        )
198+        with self.assertRaisesRegexp(management.CommandError,
199+                "Problem installing fixture 'bad_fixture1': "
200+                "unkn is not a known serialization format."):
201+            management.call_command(
202+                'loaddata',
203+                'bad_fixture1.unkn',
204+                verbosity=0,
205+                commit=False,
206+            )
207 
208     def test_invalid_data(self):
209         """
210@@ -135,18 +132,14 @@ class TestFixtures(TestCase):
211         using explicit filename.
212         Validate that error conditions are caught correctly
213         """
214-        stderr = BytesIO()
215-        management.call_command(
216-            'loaddata',
217-            'bad_fixture2.xml',
218-            verbosity=0,
219-            commit=False,
220-            stderr=stderr,
221-        )
222-        self.assertEqual(
223-            stderr.getvalue(),
224-            "No fixture data found for 'bad_fixture2'. (File format may be invalid.)\n"
225-        )
226+        with self.assertRaisesRegexp(management.CommandError,
227+                "No fixture data found for 'bad_fixture2'. \(File format may be invalid.\)"):
228+            management.call_command(
229+                'loaddata',
230+                'bad_fixture2.xml',
231+                verbosity=0,
232+                commit=False,
233+            )
234 
235     def test_invalid_data_no_ext(self):
236         """
237@@ -154,54 +147,42 @@ class TestFixtures(TestCase):
238         without file extension.
239         Validate that error conditions are caught correctly
240         """
241-        stderr = BytesIO()
242-        management.call_command(
243-            'loaddata',
244-            'bad_fixture2',
245-            verbosity=0,
246-            commit=False,
247-            stderr=stderr,
248-        )
249-        self.assertEqual(
250-            stderr.getvalue(),
251-            "No fixture data found for 'bad_fixture2'. (File format may be invalid.)\n"
252-        )
253+        with self.assertRaisesRegexp(management.CommandError,
254+                "No fixture data found for 'bad_fixture2'. \(File format may be invalid.\)"):
255+            management.call_command(
256+                'loaddata',
257+                'bad_fixture2',
258+                verbosity=0,
259+                commit=False,
260+            )
261 
262     def test_empty(self):
263         """
264         Test for ticket #4371 -- Loading a fixture file with no data returns an error.
265         Validate that error conditions are caught correctly
266         """
267-        stderr = BytesIO()
268-        management.call_command(
269-            'loaddata',
270-            'empty',
271-            verbosity=0,
272-            commit=False,
273-            stderr=stderr,
274-        )
275-        self.assertEqual(
276-            stderr.getvalue(),
277-            "No fixture data found for 'empty'. (File format may be invalid.)\n"
278-        )
279+        with self.assertRaisesRegexp(management.CommandError,
280+                "No fixture data found for 'empty'. \(File format may be invalid.\)"):
281+            management.call_command(
282+                'loaddata',
283+                'empty',
284+                verbosity=0,
285+                commit=False,
286+            )
287 
288     def test_error_message(self):
289         """
290         (Regression for #9011 - error message is correct)
291         """
292-        stderr = BytesIO()
293-        management.call_command(
294-            'loaddata',
295-            'bad_fixture2',
296-            'animal',
297-            verbosity=0,
298-            commit=False,
299-            stderr=stderr,
300-        )
301-        self.assertEqual(
302-            stderr.getvalue(),
303-            "No fixture data found for 'bad_fixture2'. (File format may be invalid.)\n"
304-        )
305+        with self.assertRaisesRegexp(management.CommandError,
306+                "^No fixture data found for 'bad_fixture2'. \(File format may be invalid.\)$"):
307+            management.call_command(
308+                'loaddata',
309+                'bad_fixture2',
310+                'animal',
311+                verbosity=0,
312+                commit=False,
313+            )
314 
315     def test_pg_sequence_resetting_checks(self):
316         """
317@@ -357,17 +338,14 @@ class TestFixtures(TestCase):
318         """
319         Regression for #3615 - Ensure data with nonexistent child key references raises error
320         """
321-        stderr = BytesIO()
322-        management.call_command(
323-            'loaddata',
324-            'forward_ref_bad_data.json',
325-            verbosity=0,
326-            commit=False,
327-            stderr=stderr,
328-        )
329-        self.assertTrue(
330-            stderr.getvalue().startswith('Problem installing fixture')
331-        )
332+        with self.assertRaisesRegexp(IntegrityError,
333+                "Problem installing fixture"):
334+            management.call_command(
335+                'loaddata',
336+                'forward_ref_bad_data.json',
337+                verbosity=0,
338+                commit=False,
339+            )
340 
341     _cur_dir = os.path.dirname(os.path.abspath(__file__))
342 
343@@ -392,16 +370,14 @@ class TestFixtures(TestCase):
344         """
345         Regression for #7043 - Error is quickly reported when no fixtures is provided in the command line.
346         """
347-        stderr = BytesIO()
348-        management.call_command(
349-            'loaddata',
350-            verbosity=0,
351-            commit=False,
352-            stderr=stderr,
353-        )
354-        self.assertEqual(
355-            stderr.getvalue(), 'No database fixture specified. Please provide the path of at least one fixture in the command line.\n'
356-        )
357+        with self.assertRaisesRegexp(management.CommandError,
358+                "No database fixture specified. Please provide the path of "
359+                "at least one fixture in the command line."):
360+            management.call_command(
361+                'loaddata',
362+                verbosity=0,
363+                commit=False,
364+            )
365 
366     def test_loaddata_not_existant_fixture_file(self):
367         stdout_output = BytesIO()