def test_fixture_and_other_outputs_mixed(self): output = "Loading 'foobar' fixtures...\n" \ "Checking /tmp/what/no for fixtures...\n" \ "Installed 37 object(s) from 1 fixture(s)\n" \ "Ha ha ha ha halibut.\n" object_count, fixture_count, other_msgs = process_django_output(output) self.assertEqual(object_count, 37) self.assertEqual(fixture_count, 1) self.assertEqual(len(other_msgs), 3)
def test_multiple_fixture_output(self): # Include one line of alternate format output, from which we don't # actually bother extracting the extra information yet. output = "Installed 2 object(s) from 1 fixture(s)\n" \ "Installed 4 object(s) from 1 fixture(s)\n" \ "Installed 7 object(s) from 2 fixture(s)\n" \ "Installed 4 object(s) (of 6) from 1 fixture(s)\n" object_count, fixture_count, other_msgs = process_django_output(output) self.assertEqual(object_count, 17) self.assertEqual(fixture_count, 5) self.assertEqual(len(other_msgs), 0)
def handle(self, *fixture_labels, **options): using = options.get('database', DEFAULT_DB_ALIAS) connection = connections[using] self.style = no_style() show_traceback = options.get('traceback', False) commit = options.get('commit', True) # I'm sure there is a valid reason why Django's loaddata does this, # so I'm just going to replicate its behaviour. cursor = connection.cursor() if commit: transaction.commit_unless_managed(using=using) transaction.enter_transaction_management(using=using) transaction.managed(True, using=using) total_object_count = 0 total_fixture_count = 0 do_initial_data = False captured_outputs = [] original_verbosity = int(options.get('verbosity')) # Mark this loaddata run as a special case for syncdb loading. # Django's loaddata will be run first, ours second. if fixture_labels == ('initial_data',): # Assign a special handler type for initial data fixture_handlers = [('initial_data', 'both_for_initial', None, None)] else: # Build a list of (label, handler, type, resolved_object) tuples. fixture_handlers = associate_handlers(fixture_labels) for label, handler, type_, obj in fixture_handlers: if handler in ['django', 'both_for_initial']: captured_stdout = StringIO() # Need to assign manually; normally available to handle() via # BaseCommand.execute(), but not when we're using it this way. DjangoLoaddata.stdout = captured_stdout DjangoLoaddata.stderr = self.stderr # Capturing fixture counts from stdout requires forcing the # verbosity option to a minimum of 1. If set higher by the # user, respect that. Collect any extra messages for display. if 'verbosity' in options: options['verbosity'] = 1 if options['verbosity'] == 0 else options['verbosity'] else: options['verbosity'] = 1 # We will either be in our own transaction handling or that of # the script that called us, so disable transaction management # inside Django's loaddata options['commit'] = False try: if 'database' not in options: options.update({'database': using}) DjangoLoaddata.handle(label, **options) except Exception: if commit: transaction.rollback(using=using) transaction.leave_transaction_management(using=using) raise django_object_count, django_fixture_count, other_msgs = process_django_output(captured_stdout.getvalue()) captured_stdout.close() total_object_count += django_object_count total_fixture_count += django_fixture_count captured_outputs.extend(other_msgs) if handler in ['class_fixtures', 'both_for_initial']: if type_ == 'instance': fixtures = [label] elif type_ == 'module': fixtures = get_fixtures_from_module(label) elif type_ == 'submodule_name': # obj is a reference to an individual submodule of # the fixtures package of some app. fixtures = get_fixtures_from_module(obj) elif type_ == 'app_label': # obj is a reference to the fixtures package of the # app named in the label. Load all the fixture modules # contained within, excluding initial_data. fixtures = [] for importer, module_name, is_pkg in walk_packages(obj.__path__): if module_name == 'initial_data': continue submodule = importer.find_module(module_name).load_module(module_name) submod_fixtures = get_fixtures_from_module(submodule) for submod_fixture in submod_fixtures: # In case the user has a deeper submodule hierarchy in place # with fixtures imported from submodule to submodule, make sure no fixture # is included in the list twice through submodule discovery. if submod_fixture not in fixtures: fixtures.append(submod_fixture) elif type_ is None and label == 'initial_data': fixtures = gather_initial_data_fixtures() try: saved_set = set() for fixture in fixtures: saved_objects = fixture.load(using=using) for obj in saved_objects.items(): saved_set.add(obj) total_fixture_count += 1 total_object_count += len(saved_set) except (SystemExit, KeyboardInterrupt): raise except Exception: import traceback if commit: transaction.rollback(using=using) transaction.leave_transaction_management(using=using) if show_traceback: traceback.print_exc() else: self.stderr.write( self.style.ERROR("Problem installing class-based fixtures: %s" % ''.join(traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)))) return if commit: transaction.commit(using=using) transaction.leave_transaction_management(using=using) # Same MySQL workaround as in Django's loaddata if commit: connection.close() if total_fixture_count == 0: if original_verbosity >= 1: self.stdout.write("No fixtures found.\n") else: if original_verbosity >= 2 and captured_outputs: # Prevent printing Django's result row along with our own # when both handlers activate but only class-based fixtures # are found. if captured_outputs[-1].startswith('No fixtures found.'): captured_outputs = captured_outputs[:-1] self.stdout.write('\n'.join(captured_outputs) + '\n') if original_verbosity >= 1: # The original loaddata has another possible output format # used when less objects were loaded than were present in the # fixtures, but I don't care enough to implement it. self.stdout.write("Installed %d object(s) from %d fixture(s)\n" % (total_object_count, total_fixture_count))
def test_single_fixture_output(self): output = "Installed 2 object(s) from 1 fixture(s)\n" object_count, fixture_count, other_msgs = process_django_output(output) self.assertEqual(object_count, 2) self.assertEqual(fixture_count, 1) self.assertEqual(len(other_msgs), 0)