| | 20 | |
| | 21 | class SingleZipReader(zipfile.ZipFile): |
| | 22 | def __init__(self, *args, **kwargs): |
| | 23 | zipfile.ZipFile.__init__(self, *args, **kwargs) |
| | 24 | if settings.DEBUG: |
| | 25 | assert len(self.namelist()) == 1, "Zip-compressed fixtures must contain only one file." |
| | 26 | |
| | 27 | def read(self): |
| | 28 | return zipfile.ZipFile.read(self, self.namelist()[0]) |
| | 29 | |
| | 30 | def humanize(dirname): |
| | 31 | if dirname: |
| | 32 | return "'%s'" % dirname |
| | 33 | return 'absolute path' |
| | 34 | |
| | 35 | def find_fixture_data(fixture_labels, verbosity, using, stdout): |
| | 36 | app_module_paths = [] |
| | 37 | for app in get_apps(): |
| | 38 | if hasattr(app, '__path__'): |
| | 39 | # It's a 'models/' subpackage |
| | 40 | app_module_paths.extend(app.__path__) |
| | 41 | else: |
| | 42 | # It's a models.py module |
| | 43 | app_module_paths.append(app.__file__) |
| | 44 | app_fixtures = [ |
| | 45 | os.path.join(os.path.dirname(path), 'fixtures') |
| | 46 | for path in app_module_paths |
| | 47 | ] |
| | 48 | |
| | 49 | compression_types = { |
| | 50 | None: file, |
| | 51 | 'gz': gzip.GzipFile, |
| | 52 | 'zip': SingleZipReader |
| | 53 | } |
| | 54 | if has_bz2: |
| | 55 | compression_types['bz2'] = bz2.BZ2File |
| | 56 | |
| | 57 | objs = [] |
| | 58 | models = set() |
| | 59 | fixture_count = 0 |
| | 60 | found_object_count = 0 |
| | 61 | fixture_object_count = 0 |
| | 62 | |
| | 63 | for fixture_label in fixture_labels: |
| | 64 | parts = fixture_label.split('.') |
| | 65 | |
| | 66 | if len(parts) > 1 and parts[-1] in compression_types: |
| | 67 | compression_formats = [parts[-1]] |
| | 68 | parts = parts[:-1] |
| | 69 | else: |
| | 70 | compression_formats = compression_types.keys() |
| | 71 | |
| | 72 | if len(parts) == 1: |
| | 73 | fixture_name = parts[0] |
| | 74 | formats = serializers.get_public_serializer_formats() |
| | 75 | else: |
| | 76 | fixture_name, format = '.'.join(parts[:-1]), parts[-1] |
| | 77 | if format in serializers.get_public_serializer_formats(): |
| | 78 | formats = [format] |
| | 79 | else: |
| | 80 | formats = [] |
| | 81 | |
| | 82 | if formats: |
| | 83 | if verbosity >= 2: |
| | 84 | stdout.write("Loading '%s' fixtures...\n" % fixture_name) |
| | 85 | else: |
| | 86 | raise CommandError("Problem installing fixture '%s': %s is not a " |
| | 87 | "known serialization format." % (fixture_name, format)) |
| | 88 | |
| | 89 | if os.path.isabs(fixture_name): |
| | 90 | fixture_dirs = [fixture_name] |
| | 91 | else: |
| | 92 | fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + [''] |
| | 93 | |
| | 94 | for fixture_dir in fixture_dirs: |
| | 95 | if verbosity >= 2: |
| | 96 | stdout.write("Checking %s for fixtures...\n" % humanize(fixture_dir)) |
| | 97 | |
| | 98 | label_found = False |
| | 99 | for combo in product([using, None], formats, compression_formats): |
| | 100 | database, format, compression_format = combo |
| | 101 | file_name = '.'.join( |
| | 102 | p for p in [ |
| | 103 | fixture_name, database, format, compression_format |
| | 104 | ] |
| | 105 | if p |
| | 106 | ) |
| | 107 | |
| | 108 | if verbosity >= 3: |
| | 109 | stdout.write("Trying %s for %s fixture '%s'...\n" % \ |
| | 110 | (humanize(fixture_dir), file_name, fixture_name)) |
| | 111 | full_path = os.path.join(fixture_dir, file_name) |
| | 112 | open_method = compression_types[compression_format] |
| | 113 | try: |
| | 114 | fixture = open_method(full_path, 'r') |
| | 115 | except IOError: |
| | 116 | if verbosity >= 2: |
| | 117 | stdout.write("No %s fixture '%s' in %s.\n" % \ |
| | 118 | (format, fixture_name, humanize(fixture_dir))) |
| | 119 | continue |
| | 120 | |
| | 121 | if label_found: |
| | 122 | fixture.close() |
| | 123 | raise CommandError("Multiple fixtures named '%s' in %s." |
| | 124 | " Aborting" % (fixture_name, humanize(fixture_dir))) |
| | 125 | fixture_count += 1 |
| | 126 | objects_in_fixture = 0 |
| | 127 | found_objects_in_fixture = 0 |
| | 128 | if verbosity >= 2: |
| | 129 | stdout.write("Installing %s fixture '%s' from %s.\n" % \ |
| | 130 | (format, fixture_name, humanize(fixture_dir))) |
| | 131 | objects = serializers.deserialize(format, fixture, using=using) |
| | 132 | for obj in objects: |
| | 133 | objects_in_fixture += 1 |
| | 134 | if router.allow_syncdb(using, obj.object.__class__): |
| | 135 | found_objects_in_fixture += 1 |
| | 136 | models.add(obj.object.__class__) |
| | 137 | objs.append(obj) |
| | 138 | found_object_count += found_objects_in_fixture |
| | 139 | fixture_object_count += objects_in_fixture |
| | 140 | label_found = True |
| | 141 | fixture.close() |
| | 142 | |
| | 143 | # If the fixture we loaded contains 0 objects, assume that an |
| | 144 | # error was encountered during fixture loading. |
| | 145 | if objects_in_fixture == 0: |
| | 146 | raise CommandError("No fixture data found for '%s'. " |
| | 147 | "(File format may be invalid.)" % fixture_name) |
| | 148 | return objs, models, fixture_count, fixture_object_count |
| | 149 | |
| 68 | | class SingleZipReader(zipfile.ZipFile): |
| 69 | | def __init__(self, *args, **kwargs): |
| 70 | | zipfile.ZipFile.__init__(self, *args, **kwargs) |
| 71 | | if settings.DEBUG: |
| 72 | | assert len(self.namelist()) == 1, "Zip-compressed fixtures must contain only one file." |
| 73 | | def read(self): |
| 74 | | return zipfile.ZipFile.read(self, self.namelist()[0]) |
| 75 | | |
| 76 | | compression_types = { |
| 77 | | None: file, |
| 78 | | 'gz': gzip.GzipFile, |
| 79 | | 'zip': SingleZipReader |
| 80 | | } |
| 81 | | if has_bz2: |
| 82 | | compression_types['bz2'] = bz2.BZ2File |
| 83 | | |
| 84 | | app_module_paths = [] |
| 85 | | for app in get_apps(): |
| 86 | | if hasattr(app, '__path__'): |
| 87 | | # It's a 'models/' subpackage |
| 88 | | for path in app.__path__: |
| 89 | | app_module_paths.append(path) |
| 90 | | else: |
| 91 | | # It's a models.py module |
| 92 | | app_module_paths.append(app.__file__) |
| 93 | | |
| 94 | | app_fixtures = [os.path.join(os.path.dirname(path), 'fixtures') for path in app_module_paths] |
| 95 | | for fixture_label in fixture_labels: |
| 96 | | parts = fixture_label.split('.') |
| 97 | | |
| 98 | | if len(parts) > 1 and parts[-1] in compression_types: |
| 99 | | compression_formats = [parts[-1]] |
| 100 | | parts = parts[:-1] |
| 101 | | else: |
| 102 | | compression_formats = compression_types.keys() |
| 103 | | |
| 104 | | if len(parts) == 1: |
| 105 | | fixture_name = parts[0] |
| 106 | | formats = serializers.get_public_serializer_formats() |
| 107 | | else: |
| 108 | | fixture_name, format = '.'.join(parts[:-1]), parts[-1] |
| 109 | | if format in serializers.get_public_serializer_formats(): |
| 110 | | formats = [format] |
| 111 | | else: |
| 112 | | formats = [] |
| 113 | | |
| 114 | | if formats: |
| 115 | | if verbosity >= 2: |
| 116 | | self.stdout.write("Loading '%s' fixtures...\n" % fixture_name) |
| 117 | | else: |
| 118 | | self.stderr.write( |
| 119 | | self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format.\n" % |
| 120 | | (fixture_name, format))) |
| 121 | | if commit: |
| 122 | | transaction.rollback(using=using) |
| 123 | | transaction.leave_transaction_management(using=using) |
| 124 | | return |
| 125 | | |
| 126 | | if os.path.isabs(fixture_name): |
| 127 | | fixture_dirs = [fixture_name] |
| 128 | | else: |
| 129 | | fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + [''] |
| 130 | | |
| 131 | | for fixture_dir in fixture_dirs: |
| 132 | | if verbosity >= 2: |
| 133 | | self.stdout.write("Checking %s for fixtures...\n" % humanize(fixture_dir)) |
| 134 | | |
| 135 | | label_found = False |
| 136 | | for combo in product([using, None], formats, compression_formats): |
| 137 | | database, format, compression_format = combo |
| 138 | | file_name = '.'.join( |
| 139 | | p for p in [ |
| 140 | | fixture_name, database, format, compression_format |
| 141 | | ] |
| 142 | | if p |
| 143 | | ) |
| 144 | | |
| 145 | | if verbosity >= 3: |
| 146 | | self.stdout.write("Trying %s for %s fixture '%s'...\n" % \ |
| 147 | | (humanize(fixture_dir), file_name, fixture_name)) |
| 148 | | full_path = os.path.join(fixture_dir, file_name) |
| 149 | | open_method = compression_types[compression_format] |
| 150 | | try: |
| 151 | | fixture = open_method(full_path, 'r') |
| 152 | | if label_found: |
| 153 | | fixture.close() |
| 154 | | self.stderr.write(self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting.\n" % |
| 155 | | (fixture_name, humanize(fixture_dir)))) |
| 156 | | if commit: |
| 157 | | transaction.rollback(using=using) |
| 158 | | transaction.leave_transaction_management(using=using) |
| 159 | | return |
| 160 | | else: |
| 161 | | fixture_count += 1 |
| 162 | | objects_in_fixture = 0 |
| 163 | | loaded_objects_in_fixture = 0 |
| 164 | | if verbosity >= 2: |
| 165 | | self.stdout.write("Installing %s fixture '%s' from %s.\n" % \ |
| 166 | | (format, fixture_name, humanize(fixture_dir))) |
| 167 | | try: |
| 168 | | objects = serializers.deserialize(format, fixture, using=using) |
| 169 | | for obj in objects: |
| 170 | | objects_in_fixture += 1 |
| 171 | | if router.allow_syncdb(using, obj.object.__class__): |
| 172 | | loaded_objects_in_fixture += 1 |
| 173 | | models.add(obj.object.__class__) |
| 174 | | obj.save(using=using) |
| 175 | | loaded_object_count += loaded_objects_in_fixture |
| 176 | | fixture_object_count += objects_in_fixture |
| 177 | | label_found = True |
| 178 | | except (SystemExit, KeyboardInterrupt): |
| 179 | | raise |
| 180 | | except Exception: |
| 181 | | import traceback |
| 182 | | fixture.close() |
| 183 | | if commit: |
| 184 | | transaction.rollback(using=using) |
| 185 | | transaction.leave_transaction_management(using=using) |
| 186 | | if show_traceback: |
| 187 | | traceback.print_exc() |
| 188 | | else: |
| 189 | | self.stderr.write( |
| 190 | | self.style.ERROR("Problem installing fixture '%s': %s\n" % |
| 191 | | (full_path, ''.join(traceback.format_exception(sys.exc_type, |
| 192 | | sys.exc_value, sys.exc_traceback))))) |
| 193 | | return |
| 194 | | fixture.close() |
| 195 | | |
| 196 | | # If the fixture we loaded contains 0 objects, assume that an |
| 197 | | # error was encountered during fixture loading. |
| 198 | | if objects_in_fixture == 0: |
| 199 | | self.stderr.write( |
| 200 | | self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)\n" % |
| 201 | | (fixture_name))) |
| 202 | | if commit: |
| 203 | | transaction.rollback(using=using) |
| 204 | | transaction.leave_transaction_management(using=using) |
| 205 | | return |
| 206 | | |
| 207 | | except Exception, e: |
| 208 | | if verbosity >= 2: |
| 209 | | self.stdout.write("No %s fixture '%s' in %s.\n" % \ |
| 210 | | (format, fixture_name, humanize(fixture_dir))) |
| | 189 | try: |
| | 190 | objs, models, fixture_count, fixture_object_count = find_fixture_data( |
| | 191 | fixture_labels, |
| | 192 | verbosity=verbosity, |
| | 193 | using=using, |
| | 194 | stdout=self.stdout |
| | 195 | ) |
| | 196 | except CommandError, e: |
| | 197 | if commit: |
| | 198 | transaction.rollback(using=using) |
| | 199 | transaction.leave_transaction_management(using=using) |
| | 200 | # For reasons I don't understand CommandErrors are never raised. |
| | 201 | self.stderr.write(e.args[0] + "\n") |
| | 202 | return |
| | 203 | for obj in objs: |
| | 204 | obj.save(using=using) |