| 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) |