Merge lp:~michael.nelson/ubuntu-webcatalog/1015515-only-one-app into lp:ubuntu-webcatalog
- 1015515-only-one-app
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Anthony Lenton | ||||
Approved revision: | 175 | ||||
Merged at revision: | 152 | ||||
Proposed branch: | lp:~michael.nelson/ubuntu-webcatalog/1015515-only-one-app | ||||
Merge into: | lp:ubuntu-webcatalog | ||||
Prerequisite: | lp:~michael.nelson/ubuntu-webcatalog/1015515-dont-create-new-app | ||||
Diff against target: |
621 lines (+467/-44) 9 files modified
src/webcatalog/migrations/0025_only_one_app_per_series_pkg_name.py (+186/-0) src/webcatalog/migrations/0026_unique_pkg_name_distroseries.py (+171/-0) src/webcatalog/models/applications.py (+1/-1) src/webcatalog/tests/__init__.py (+1/-0) src/webcatalog/tests/factory.py (+13/-3) src/webcatalog/tests/helpers.py (+37/-0) src/webcatalog/tests/test_migrations.py (+57/-0) src/webcatalog/tests/test_views.py (+0/-33) src/webcatalog/views.py (+1/-7) |
||||
To merge this branch: | bzr merge lp:~michael.nelson/ubuntu-webcatalog/1015515-only-one-app | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Anthony Lenton (community) | Approve | ||
Review via email: mp+112553@code.launchpad.net |
Commit message
package_name and distroseries are unique together on Application.
Description of the change
Overview
========
Continues on from the prereq for bug 1015515, adding a migration to ensure that duplicates are removed, before updating the unique constraint for Application.
`fab test:pg=true`
Note:
1) I'm getting "psycopg2.
2) I'm not sure whether I should comment out the migration test as per usual. If it does pass locally with psql, I'm keen to see if it fails on the vps or passes. If it passes, yay.
- 174. By Michael Nelson
-
Merged 1015515-
dont-create- new-app into 1015515- only-one- app. - 175. By Michael Nelson
-
REFACTOR: removed outdated comment and switched get_list_or_404 to get_object now that we have db restriction.
Preview Diff
1 | === added file 'src/webcatalog/migrations/0025_only_one_app_per_series_pkg_name.py' | |||
2 | --- src/webcatalog/migrations/0025_only_one_app_per_series_pkg_name.py 1970-01-01 00:00:00 +0000 | |||
3 | +++ src/webcatalog/migrations/0025_only_one_app_per_series_pkg_name.py 2012-06-28 14:07:20 +0000 | |||
4 | @@ -0,0 +1,186 @@ | |||
5 | 1 | # encoding: utf-8 | ||
6 | 2 | from south.v2 import DataMigration | ||
7 | 3 | from django.db.models import Count | ||
8 | 4 | |||
9 | 5 | class Migration(DataMigration): | ||
10 | 6 | |||
11 | 7 | def forwards(self, orm): | ||
12 | 8 | """Delete duplicate apps per distroseries. | ||
13 | 9 | |||
14 | 10 | Prefer first an sca_imported app, then the most recent. | ||
15 | 11 | """ | ||
16 | 12 | Application = orm['webcatalog.Application'] | ||
17 | 13 | dups = Application.objects.values( | ||
18 | 14 | 'package_name', 'distroseries__code_name').order_by().annotate( | ||
19 | 15 | num_dups=Count('distroseries')).filter(num_dups__gt=1) | ||
20 | 16 | for dup in dups: | ||
21 | 17 | sca_version = Application.objects.filter( | ||
22 | 18 | package_name=dup['package_name'], | ||
23 | 19 | distroseries__code_name=dup['distroseries__code_name'], | ||
24 | 20 | imported_from_sca=True) | ||
25 | 21 | if sca_version: | ||
26 | 22 | sca_version = sca_version[0] | ||
27 | 23 | dups_to_delete = Application.objects.filter( | ||
28 | 24 | package_name=dup['package_name'], | ||
29 | 25 | distroseries__code_name=dup['distroseries__code_name']) | ||
30 | 26 | dups_to_delete = dups_to_delete.exclude(id=sca_version.id) | ||
31 | 27 | dups_to_delete.delete() | ||
32 | 28 | else: | ||
33 | 29 | dup_apps = Application.objects.filter( | ||
34 | 30 | package_name=dup['package_name'], | ||
35 | 31 | distroseries__code_name=dup['distroseries__code_name'] | ||
36 | 32 | ).order_by('-id') | ||
37 | 33 | most_recent = dup_apps[0] | ||
38 | 34 | dup_apps.exclude(id=most_recent.id).delete() | ||
39 | 35 | |||
40 | 36 | def backwards(self, orm): | ||
41 | 37 | pass | ||
42 | 38 | |||
43 | 39 | |||
44 | 40 | models = { | ||
45 | 41 | 'auth.group': { | ||
46 | 42 | 'Meta': {'object_name': 'Group'}, | ||
47 | 43 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
48 | 44 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
49 | 45 | 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
50 | 46 | }, | ||
51 | 47 | 'auth.permission': { | ||
52 | 48 | 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
53 | 49 | 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | 50 | 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
55 | 51 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
56 | 52 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
57 | 53 | }, | ||
58 | 54 | 'auth.user': { | ||
59 | 55 | 'Meta': {'object_name': 'User'}, | ||
60 | 56 | 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
61 | 57 | 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
62 | 58 | 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
63 | 59 | 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
64 | 60 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
65 | 61 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
66 | 62 | 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
67 | 63 | 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
68 | 64 | 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
69 | 65 | 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
70 | 66 | 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
71 | 67 | 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
72 | 68 | 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
73 | 69 | }, | ||
74 | 70 | 'contenttypes.contenttype': { | ||
75 | 71 | 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
76 | 72 | 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
77 | 73 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | 74 | 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
79 | 75 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
80 | 76 | }, | ||
81 | 77 | 'webcatalog.application': { | ||
82 | 78 | 'Meta': {'ordering': "('-wilson_score', 'name')", 'unique_together': "(('distroseries', 'archive_id'),)", 'object_name': 'Application'}, | ||
83 | 79 | 'app_type': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), | ||
84 | 80 | 'architectures': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
85 | 81 | 'archive_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'null': 'True', 'blank': 'True'}), | ||
86 | 82 | 'categories': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
87 | 83 | 'channel': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
88 | 84 | 'comment': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
89 | 85 | 'debtags': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
90 | 86 | 'departments': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['webcatalog.Department']", 'symmetrical': 'False', 'blank': 'True'}), | ||
91 | 87 | 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
92 | 88 | 'distroseries': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.DistroSeries']"}), | ||
93 | 89 | 'icon': ('django.db.models.fields.files.ImageField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), | ||
94 | 90 | 'icon_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
95 | 91 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
96 | 92 | 'imported_from_sca': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
97 | 93 | 'is_latest': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
98 | 94 | 'keywords': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
99 | 95 | 'license': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
100 | 96 | 'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), | ||
101 | 97 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
102 | 98 | 'package_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
103 | 99 | 'popcon': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
104 | 100 | 'price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '7', 'decimal_places': '2', 'blank': 'True'}), | ||
105 | 101 | 'ratings_average': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '3', 'decimal_places': '2', 'blank': 'True'}), | ||
106 | 102 | 'ratings_histogram': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), | ||
107 | 103 | 'ratings_total': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
108 | 104 | 'section': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), | ||
109 | 105 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
110 | 106 | 'wilson_score': ('django.db.models.fields.FloatField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}) | ||
111 | 107 | }, | ||
112 | 108 | 'webcatalog.applicationmedia': { | ||
113 | 109 | 'Meta': {'ordering': "('url',)", 'unique_together': "(('application', 'url'),)", 'object_name': 'ApplicationMedia'}, | ||
114 | 110 | 'application': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Application']"}), | ||
115 | 111 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
116 | 112 | 'media_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), | ||
117 | 113 | 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) | ||
118 | 114 | }, | ||
119 | 115 | 'webcatalog.consumer': { | ||
120 | 116 | 'Meta': {'object_name': 'Consumer'}, | ||
121 | 117 | 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
122 | 118 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
123 | 119 | 'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||
124 | 120 | 'secret': ('django.db.models.fields.CharField', [], {'default': "'HQTqmfphaOwnrnRfWIzLsPUUqqthuh'", 'max_length': '255', 'blank': 'True'}), | ||
125 | 121 | 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), | ||
126 | 122 | 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'oauth_consumer'", 'unique': 'True', 'to': "orm['auth.User']"}) | ||
127 | 123 | }, | ||
128 | 124 | 'webcatalog.department': { | ||
129 | 125 | 'Meta': {'object_name': 'Department'}, | ||
130 | 126 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
131 | 127 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||
132 | 128 | 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Department']", 'null': 'True', 'blank': 'True'}), | ||
133 | 129 | 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}) | ||
134 | 130 | }, | ||
135 | 131 | 'webcatalog.distroseries': { | ||
136 | 132 | 'Meta': {'object_name': 'DistroSeries'}, | ||
137 | 133 | 'code_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20', 'db_index': 'True'}), | ||
138 | 134 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
139 | 135 | 'prerelease': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
140 | 136 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}) | ||
141 | 137 | }, | ||
142 | 138 | 'webcatalog.exhibit': { | ||
143 | 139 | 'Meta': {'object_name': 'Exhibit'}, | ||
144 | 140 | 'banner_url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), | ||
145 | 141 | 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
146 | 142 | 'display': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), | ||
147 | 143 | 'distroseries': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['webcatalog.DistroSeries']", 'symmetrical': 'False'}), | ||
148 | 144 | 'html': ('django.db.models.fields.TextField', [], {}), | ||
149 | 145 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
150 | 146 | 'package_names': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), | ||
151 | 147 | 'published': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
152 | 148 | 'sca_id': ('django.db.models.fields.IntegerField', [], {}), | ||
153 | 149 | 'weight': ('django.db.models.fields.IntegerField', [], {'default': '0'}) | ||
154 | 150 | }, | ||
155 | 151 | 'webcatalog.machine': { | ||
156 | 152 | 'Meta': {'unique_together': "(('owner', 'uuid'),)", 'object_name': 'Machine'}, | ||
157 | 153 | 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||
158 | 154 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
159 | 155 | 'logo_checksum': ('django.db.models.fields.CharField', [], {'max_length': '56', 'blank': 'True'}), | ||
160 | 156 | 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), | ||
161 | 157 | 'package_list': ('django.db.models.fields.TextField', [], {}), | ||
162 | 158 | 'packages_checksum': ('django.db.models.fields.CharField', [], {'max_length': '56'}), | ||
163 | 159 | 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}) | ||
164 | 160 | }, | ||
165 | 161 | 'webcatalog.nonce': { | ||
166 | 162 | 'Meta': {'object_name': 'Nonce'}, | ||
167 | 163 | 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Consumer']"}), | ||
168 | 164 | 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
169 | 165 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
170 | 166 | 'nonce': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), | ||
171 | 167 | 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Token']"}) | ||
172 | 168 | }, | ||
173 | 169 | 'webcatalog.reviewstatsimport': { | ||
174 | 170 | 'Meta': {'object_name': 'ReviewStatsImport'}, | ||
175 | 171 | 'distroseries': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.DistroSeries']", 'unique': 'True'}), | ||
176 | 172 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
177 | 173 | 'last_import': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}) | ||
178 | 174 | }, | ||
179 | 175 | 'webcatalog.token': { | ||
180 | 176 | 'Meta': {'object_name': 'Token'}, | ||
181 | 177 | 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Consumer']"}), | ||
182 | 178 | 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
183 | 179 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
184 | 180 | 'token': ('django.db.models.fields.CharField', [], {'default': "'sZsoIBDSOGiMtIjLpqHhOsnLNFoJrpvXhCUaZHktQQKzdYMMPU'", 'max_length': '50', 'primary_key': 'True'}), | ||
185 | 181 | 'token_secret': ('django.db.models.fields.CharField', [], {'default': "'bpTvhxNJwAHXkVNvtBgcEhuhXeTvySnFZtIQxjgENGFnrrHjMM'", 'max_length': '50'}), | ||
186 | 182 | 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) | ||
187 | 183 | } | ||
188 | 184 | } | ||
189 | 185 | |||
190 | 186 | complete_apps = ['webcatalog'] | ||
191 | 0 | 187 | ||
192 | === added file 'src/webcatalog/migrations/0026_unique_pkg_name_distroseries.py' | |||
193 | --- src/webcatalog/migrations/0026_unique_pkg_name_distroseries.py 1970-01-01 00:00:00 +0000 | |||
194 | +++ src/webcatalog/migrations/0026_unique_pkg_name_distroseries.py 2012-06-28 14:07:20 +0000 | |||
195 | @@ -0,0 +1,171 @@ | |||
196 | 1 | # encoding: utf-8 | ||
197 | 2 | from south.db import db | ||
198 | 3 | from south.v2 import SchemaMigration | ||
199 | 4 | |||
200 | 5 | |||
201 | 6 | class Migration(SchemaMigration): | ||
202 | 7 | |||
203 | 8 | def forwards(self, orm): | ||
204 | 9 | |||
205 | 10 | # Removing unique constraint on 'Application', fields ['archive_id', 'distroseries'] | ||
206 | 11 | db.delete_unique('webcatalog_application', ['archive_id', 'distroseries_id']) | ||
207 | 12 | |||
208 | 13 | # Adding unique constraint on 'Application', fields ['distroseries', 'package_name'] | ||
209 | 14 | db.create_unique('webcatalog_application', ['distroseries_id', 'package_name']) | ||
210 | 15 | |||
211 | 16 | |||
212 | 17 | def backwards(self, orm): | ||
213 | 18 | |||
214 | 19 | # Removing unique constraint on 'Application', fields ['distroseries', 'package_name'] | ||
215 | 20 | db.delete_unique('webcatalog_application', ['distroseries_id', 'package_name']) | ||
216 | 21 | |||
217 | 22 | # Adding unique constraint on 'Application', fields ['archive_id', 'distroseries'] | ||
218 | 23 | db.create_unique('webcatalog_application', ['archive_id', 'distroseries_id']) | ||
219 | 24 | |||
220 | 25 | models = { | ||
221 | 26 | 'auth.group': { | ||
222 | 27 | 'Meta': {'object_name': 'Group'}, | ||
223 | 28 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
224 | 29 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
225 | 30 | 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
226 | 31 | }, | ||
227 | 32 | 'auth.permission': { | ||
228 | 33 | 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
229 | 34 | 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
230 | 35 | 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
231 | 36 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
232 | 37 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
233 | 38 | }, | ||
234 | 39 | 'auth.user': { | ||
235 | 40 | 'Meta': {'object_name': 'User'}, | ||
236 | 41 | 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
237 | 42 | 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
238 | 43 | 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
239 | 44 | 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
240 | 45 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
241 | 46 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
242 | 47 | 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
243 | 48 | 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
244 | 49 | 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
245 | 50 | 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
246 | 51 | 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
247 | 52 | 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
248 | 53 | 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
249 | 54 | }, | ||
250 | 55 | 'contenttypes.contenttype': { | ||
251 | 56 | 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
252 | 57 | 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
253 | 58 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
254 | 59 | 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
255 | 60 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
256 | 61 | }, | ||
257 | 62 | 'webcatalog.application': { | ||
258 | 63 | 'Meta': {'ordering': "('-wilson_score', 'name')", 'unique_together': "(('distroseries', 'package_name'),)", 'object_name': 'Application'}, | ||
259 | 64 | 'app_type': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), | ||
260 | 65 | 'architectures': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
261 | 66 | 'archive_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'null': 'True', 'blank': 'True'}), | ||
262 | 67 | 'categories': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
263 | 68 | 'channel': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
264 | 69 | 'comment': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
265 | 70 | 'debtags': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
266 | 71 | 'departments': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['webcatalog.Department']", 'symmetrical': 'False', 'blank': 'True'}), | ||
267 | 72 | 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
268 | 73 | 'distroseries': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.DistroSeries']"}), | ||
269 | 74 | 'icon': ('django.db.models.fields.files.ImageField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), | ||
270 | 75 | 'icon_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
271 | 76 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
272 | 77 | 'imported_from_sca': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
273 | 78 | 'is_latest': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
274 | 79 | 'keywords': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
275 | 80 | 'license': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
276 | 81 | 'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), | ||
277 | 82 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
278 | 83 | 'package_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
279 | 84 | 'popcon': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
280 | 85 | 'price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '7', 'decimal_places': '2', 'blank': 'True'}), | ||
281 | 86 | 'ratings_average': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '3', 'decimal_places': '2', 'blank': 'True'}), | ||
282 | 87 | 'ratings_histogram': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), | ||
283 | 88 | 'ratings_total': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
284 | 89 | 'section': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), | ||
285 | 90 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
286 | 91 | 'wilson_score': ('django.db.models.fields.FloatField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}) | ||
287 | 92 | }, | ||
288 | 93 | 'webcatalog.applicationmedia': { | ||
289 | 94 | 'Meta': {'ordering': "('url',)", 'unique_together': "(('application', 'url'),)", 'object_name': 'ApplicationMedia'}, | ||
290 | 95 | 'application': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Application']"}), | ||
291 | 96 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
292 | 97 | 'media_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), | ||
293 | 98 | 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) | ||
294 | 99 | }, | ||
295 | 100 | 'webcatalog.consumer': { | ||
296 | 101 | 'Meta': {'object_name': 'Consumer'}, | ||
297 | 102 | 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
298 | 103 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
299 | 104 | 'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||
300 | 105 | 'secret': ('django.db.models.fields.CharField', [], {'default': "'CkaJaMaVaYjiDEVByNnJWMmblaoFop'", 'max_length': '255', 'blank': 'True'}), | ||
301 | 106 | 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), | ||
302 | 107 | 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'oauth_consumer'", 'unique': 'True', 'to': "orm['auth.User']"}) | ||
303 | 108 | }, | ||
304 | 109 | 'webcatalog.department': { | ||
305 | 110 | 'Meta': {'object_name': 'Department'}, | ||
306 | 111 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
307 | 112 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||
308 | 113 | 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Department']", 'null': 'True', 'blank': 'True'}), | ||
309 | 114 | 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}) | ||
310 | 115 | }, | ||
311 | 116 | 'webcatalog.distroseries': { | ||
312 | 117 | 'Meta': {'object_name': 'DistroSeries'}, | ||
313 | 118 | 'code_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20', 'db_index': 'True'}), | ||
314 | 119 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
315 | 120 | 'prerelease': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
316 | 121 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}) | ||
317 | 122 | }, | ||
318 | 123 | 'webcatalog.exhibit': { | ||
319 | 124 | 'Meta': {'object_name': 'Exhibit'}, | ||
320 | 125 | 'banner_url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), | ||
321 | 126 | 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
322 | 127 | 'display': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), | ||
323 | 128 | 'distroseries': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['webcatalog.DistroSeries']", 'symmetrical': 'False'}), | ||
324 | 129 | 'html': ('django.db.models.fields.TextField', [], {}), | ||
325 | 130 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
326 | 131 | 'package_names': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), | ||
327 | 132 | 'published': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
328 | 133 | 'sca_id': ('django.db.models.fields.IntegerField', [], {}), | ||
329 | 134 | 'weight': ('django.db.models.fields.IntegerField', [], {'default': '0'}) | ||
330 | 135 | }, | ||
331 | 136 | 'webcatalog.machine': { | ||
332 | 137 | 'Meta': {'unique_together': "(('owner', 'uuid'),)", 'object_name': 'Machine'}, | ||
333 | 138 | 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||
334 | 139 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
335 | 140 | 'logo_checksum': ('django.db.models.fields.CharField', [], {'max_length': '56', 'blank': 'True'}), | ||
336 | 141 | 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), | ||
337 | 142 | 'package_list': ('django.db.models.fields.TextField', [], {}), | ||
338 | 143 | 'packages_checksum': ('django.db.models.fields.CharField', [], {'max_length': '56'}), | ||
339 | 144 | 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}) | ||
340 | 145 | }, | ||
341 | 146 | 'webcatalog.nonce': { | ||
342 | 147 | 'Meta': {'object_name': 'Nonce'}, | ||
343 | 148 | 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Consumer']"}), | ||
344 | 149 | 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
345 | 150 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
346 | 151 | 'nonce': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), | ||
347 | 152 | 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Token']"}) | ||
348 | 153 | }, | ||
349 | 154 | 'webcatalog.reviewstatsimport': { | ||
350 | 155 | 'Meta': {'object_name': 'ReviewStatsImport'}, | ||
351 | 156 | 'distroseries': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.DistroSeries']", 'unique': 'True'}), | ||
352 | 157 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
353 | 158 | 'last_import': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}) | ||
354 | 159 | }, | ||
355 | 160 | 'webcatalog.token': { | ||
356 | 161 | 'Meta': {'object_name': 'Token'}, | ||
357 | 162 | 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Consumer']"}), | ||
358 | 163 | 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
359 | 164 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
360 | 165 | 'token': ('django.db.models.fields.CharField', [], {'default': "'XTzTOPjxjOzhqRWOpdmAPcbaAZqIKoiJKPnfuAVUpuYhCwgxhm'", 'max_length': '50', 'primary_key': 'True'}), | ||
361 | 166 | 'token_secret': ('django.db.models.fields.CharField', [], {'default': "'uZmUdXqaSKXXaCeeLbiwQjLzDPixijEGysvlXSiSpVatcifOxX'", 'max_length': '50'}), | ||
362 | 167 | 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) | ||
363 | 168 | } | ||
364 | 169 | } | ||
365 | 170 | |||
366 | 171 | complete_apps = ['webcatalog'] | ||
367 | 0 | 172 | ||
368 | === modified file 'src/webcatalog/models/applications.py' | |||
369 | --- src/webcatalog/models/applications.py 2012-06-28 14:07:20 +0000 | |||
370 | +++ src/webcatalog/models/applications.py 2012-06-28 14:07:20 +0000 | |||
371 | @@ -191,7 +191,7 @@ | |||
372 | 191 | 191 | ||
373 | 192 | class Meta: | 192 | class Meta: |
374 | 193 | app_label = 'webcatalog' | 193 | app_label = 'webcatalog' |
376 | 194 | unique_together = ('distroseries', 'archive_id') | 194 | unique_together = ('distroseries', 'package_name') |
377 | 195 | ordering = ('-wilson_score', 'name') | 195 | ordering = ('-wilson_score', 'name') |
378 | 196 | 196 | ||
379 | 197 | 197 | ||
380 | 198 | 198 | ||
381 | === modified file 'src/webcatalog/tests/__init__.py' | |||
382 | --- src/webcatalog/tests/__init__.py 2012-05-30 21:57:52 +0000 | |||
383 | +++ src/webcatalog/tests/__init__.py 2012-06-28 14:07:20 +0000 | |||
384 | @@ -24,6 +24,7 @@ | |||
385 | 24 | from .test_handlers import * | 24 | from .test_handlers import * |
386 | 25 | from .test_models import * | 25 | from .test_models import * |
387 | 26 | from .test_managers import * | 26 | from .test_managers import * |
388 | 27 | from .test_migrations import * | ||
389 | 27 | from .test_pep8 import * | 28 | from .test_pep8 import * |
390 | 28 | from .test_preflight import * | 29 | from .test_preflight import * |
391 | 29 | from .test_templatetags import * | 30 | from .test_templatetags import * |
392 | 30 | 31 | ||
393 | === modified file 'src/webcatalog/tests/factory.py' | |||
394 | --- src/webcatalog/tests/factory.py 2012-06-28 14:07:20 +0000 | |||
395 | +++ src/webcatalog/tests/factory.py 2012-06-28 14:07:20 +0000 | |||
396 | @@ -29,7 +29,10 @@ | |||
397 | 29 | from itertools import count | 29 | from itertools import count |
398 | 30 | from django.contrib.auth.models import User | 30 | from django.contrib.auth.models import User |
399 | 31 | from django.contrib.sessions.models import Session | 31 | from django.contrib.sessions.models import Session |
401 | 32 | from django.test import TestCase | 32 | from django.test import ( |
402 | 33 | TestCase, | ||
403 | 34 | TransactionTestCase, | ||
404 | 35 | ) | ||
405 | 33 | from django_openid_auth.models import UserOpenID | 36 | from django_openid_auth.models import UserOpenID |
406 | 34 | 37 | ||
407 | 35 | from webcatalog.models import ( | 38 | from webcatalog.models import ( |
408 | @@ -104,7 +107,7 @@ | |||
409 | 104 | ratings_histogram='', screenshot_url='', | 107 | ratings_histogram='', screenshot_url='', |
410 | 105 | archive_id=None, version='', is_latest=False, | 108 | archive_id=None, version='', is_latest=False, |
411 | 106 | wilson_score=0.0, debtags=[], departments=None, | 109 | wilson_score=0.0, debtags=[], departments=None, |
413 | 107 | license='', price=None): | 110 | license='', price=None, imported_from_sca=False): |
414 | 108 | if name is None: | 111 | if name is None: |
415 | 109 | name = self.get_unique_string(prefix='Readable Name') | 112 | name = self.get_unique_string(prefix='Readable Name') |
416 | 110 | if package_name is None: | 113 | if package_name is None: |
417 | @@ -124,7 +127,7 @@ | |||
418 | 124 | ratings_histogram=ratings_histogram, | 127 | ratings_histogram=ratings_histogram, |
419 | 125 | archive_id=archive_id, version=version, is_latest=is_latest, | 128 | archive_id=archive_id, version=version, is_latest=is_latest, |
420 | 126 | wilson_score=wilson_score, debtags=debtags, | 129 | wilson_score=wilson_score, debtags=debtags, |
422 | 127 | license=license, price=price) | 130 | license=license, price=price, imported_from_sca=imported_from_sca) |
423 | 128 | 131 | ||
424 | 129 | if departments is not None: | 132 | if departments is not None: |
425 | 130 | for d in departments: | 133 | for d in departments: |
426 | @@ -237,3 +240,10 @@ | |||
427 | 237 | def setUp(self): | 240 | def setUp(self): |
428 | 238 | super(TestCaseWithFactory, self).setUp() | 241 | super(TestCaseWithFactory, self).setUp() |
429 | 239 | self.factory = WebCatalogObjectFactory() | 242 | self.factory = WebCatalogObjectFactory() |
430 | 243 | |||
431 | 244 | |||
432 | 245 | class TxTestCaseWithFactory(TransactionTestCase): | ||
433 | 246 | |||
434 | 247 | def setUp(self): | ||
435 | 248 | super(TxTestCaseWithFactory, self).setUp() | ||
436 | 249 | self.factory = WebCatalogObjectFactory() | ||
437 | 240 | 250 | ||
438 | === modified file 'src/webcatalog/tests/helpers.py' | |||
439 | --- src/webcatalog/tests/helpers.py 2012-06-06 18:00:26 +0000 | |||
440 | +++ src/webcatalog/tests/helpers.py 2012-06-28 14:07:20 +0000 | |||
441 | @@ -30,6 +30,10 @@ | |||
442 | 30 | 30 | ||
443 | 31 | from contextlib import contextmanager | 31 | from contextlib import contextmanager |
444 | 32 | from django.conf import settings | 32 | from django.conf import settings |
445 | 33 | from django.core.management import call_command | ||
446 | 34 | from south.migration import Migrations | ||
447 | 35 | |||
448 | 36 | from webcatalog.tests.factory import TxTestCaseWithFactory | ||
449 | 33 | 37 | ||
450 | 34 | 38 | ||
451 | 35 | # Original snippet from http://djangosnippets.org/snippets/2156/ | 39 | # Original snippet from http://djangosnippets.org/snippets/2156/ |
452 | @@ -60,3 +64,36 @@ | |||
453 | 60 | finally: | 64 | finally: |
454 | 61 | switch_settings(**old_settings) | 65 | switch_settings(**old_settings) |
455 | 62 | # end snippet | 66 | # end snippet |
456 | 67 | |||
457 | 68 | |||
458 | 69 | class MigrationTestCase(TxTestCaseWithFactory): | ||
459 | 70 | """A Test case for testing migrations.""" | ||
460 | 71 | |||
461 | 72 | # These must be defined by subclasses. | ||
462 | 73 | start_migration = None | ||
463 | 74 | dest_migration = None | ||
464 | 75 | django_application = None | ||
465 | 76 | |||
466 | 77 | def setUp(self): | ||
467 | 78 | super(MigrationTestCase, self).setUp() | ||
468 | 79 | migrations = Migrations(self.django_application) | ||
469 | 80 | self.start_orm = migrations[self.start_migration].orm() | ||
470 | 81 | self.dest_orm = migrations[self.dest_migration].orm() | ||
471 | 82 | |||
472 | 83 | # Ensure the migration history is up-to-date with a fake migration. | ||
473 | 84 | # The other option would be to use the south setting for these tests | ||
474 | 85 | # so that the migrations are used to setup the test db. | ||
475 | 86 | call_command('migrate', self.django_application, fake=True, | ||
476 | 87 | verbosity=0) | ||
477 | 88 | # Then migrate back to the start migration. | ||
478 | 89 | call_command('migrate', self.django_application, self.start_migration, | ||
479 | 90 | verbosity=0) | ||
480 | 91 | |||
481 | 92 | def tearDown(self): | ||
482 | 93 | # Leave the db in the final state so that the test runner doesn't | ||
483 | 94 | # error when truncating the database. | ||
484 | 95 | call_command('migrate', self.django_application, verbosity=0) | ||
485 | 96 | |||
486 | 97 | def migrate_to_dest(self): | ||
487 | 98 | call_command('migrate', self.django_application, self.dest_migration, | ||
488 | 99 | verbosity=0) | ||
489 | 63 | 100 | ||
490 | === added file 'src/webcatalog/tests/test_migrations.py' | |||
491 | --- src/webcatalog/tests/test_migrations.py 1970-01-01 00:00:00 +0000 | |||
492 | +++ src/webcatalog/tests/test_migrations.py 2012-06-28 14:07:20 +0000 | |||
493 | @@ -0,0 +1,57 @@ | |||
494 | 1 | # -*- coding: utf-8 -*- | ||
495 | 2 | # This file is part of the Apps Directory | ||
496 | 3 | # Copyright (C) 2011 Canonical Ltd. | ||
497 | 4 | # | ||
498 | 5 | # This program is free software: you can redistribute it and/or modify | ||
499 | 6 | # it under the terms of the GNU Affero General Public License as | ||
500 | 7 | # published by the Free Software Foundation, either version 3 of the | ||
501 | 8 | # License, or (at your option) any later version. | ||
502 | 9 | # | ||
503 | 10 | # This program is distributed in the hope that it will be useful, | ||
504 | 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
505 | 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
506 | 13 | # GNU Affero General Public License for more details. | ||
507 | 14 | # | ||
508 | 15 | # You should have received a copy of the GNU Affero General Public License | ||
509 | 16 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
510 | 17 | |||
511 | 18 | """Temporary test cases for developing and reviewing migrations.""" | ||
512 | 19 | |||
513 | 20 | from webcatalog.tests.helpers import MigrationTestCase | ||
514 | 21 | from webcatalog.models import Application | ||
515 | 22 | |||
516 | 23 | |||
517 | 24 | class OnlyOneAppPerSeriesPkgNameTestCase(MigrationTestCase): | ||
518 | 25 | start_migration = '0024_remove_application_id_and_rename_for_purchase' | ||
519 | 26 | dest_migration = '0025_only_one_app_per_series_pkg_name' | ||
520 | 27 | django_application = 'webcatalog' | ||
521 | 28 | |||
522 | 29 | def test_latest_app_remains_when_neither_sca_imported(self): | ||
523 | 30 | oneiric = self.factory.make_distroseries(code_name='oneiric') | ||
524 | 31 | precise = self.factory.make_distroseries(code_name='precise') | ||
525 | 32 | self.factory.make_application( | ||
526 | 33 | package_name='foo', distroseries=oneiric) | ||
527 | 34 | foo_oneiric_2 = self.factory.make_application( | ||
528 | 35 | package_name='foo', distroseries=oneiric) | ||
529 | 36 | foo_precise = self.factory.make_application( | ||
530 | 37 | package_name='foo', distroseries=precise) | ||
531 | 38 | |||
532 | 39 | self.migrate_to_dest() | ||
533 | 40 | |||
534 | 41 | all_foo_apps = Application.objects.filter(package_name='foo') | ||
535 | 42 | self.assertEqual([foo_oneiric_2, foo_precise], list(all_foo_apps)) | ||
536 | 43 | |||
537 | 44 | def test_sca_imported_app_wins(self): | ||
538 | 45 | oneiric = self.factory.make_distroseries(code_name='oneiric') | ||
539 | 46 | precise = self.factory.make_distroseries(code_name='precise') | ||
540 | 47 | foo_oneiric_1 = self.factory.make_application( | ||
541 | 48 | package_name='foo', distroseries=oneiric, imported_from_sca=True) | ||
542 | 49 | self.factory.make_application( | ||
543 | 50 | package_name='foo', distroseries=oneiric) | ||
544 | 51 | foo_precise = self.factory.make_application( | ||
545 | 52 | package_name='foo', distroseries=precise) | ||
546 | 53 | |||
547 | 54 | self.migrate_to_dest() | ||
548 | 55 | |||
549 | 56 | all_foo_apps = Application.objects.filter(package_name='foo') | ||
550 | 57 | self.assertEqual([foo_oneiric_1, foo_precise], list(all_foo_apps)) | ||
551 | 0 | 58 | ||
552 | === modified file 'src/webcatalog/tests/test_views.py' | |||
553 | --- src/webcatalog/tests/test_views.py 2012-06-28 14:07:20 +0000 | |||
554 | +++ src/webcatalog/tests/test_views.py 2012-06-28 14:07:20 +0000 | |||
555 | @@ -419,29 +419,6 @@ | |||
556 | 419 | response, | 419 | response, |
557 | 420 | '<iframe src="http://example.com/video_iframe.html"') | 420 | '<iframe src="http://example.com/video_iframe.html"') |
558 | 421 | 421 | ||
559 | 422 | def test_double_entry_in_the_db_is_displayed_sainely(self): | ||
560 | 423 | """Make sure that bug:1006442 is fixed""" | ||
561 | 424 | app = self.factory.make_application() | ||
562 | 425 | self.factory.make_application( | ||
563 | 426 | package_name=app.package_name, | ||
564 | 427 | distroseries=app.distroseries | ||
565 | 428 | ) | ||
566 | 429 | response = self.client.get(self.get_app_details_url(app)) | ||
567 | 430 | |||
568 | 431 | self.assertEquals(response.status_code, 200) | ||
569 | 432 | |||
570 | 433 | def test_make_sure_doubled_entry_displays_only_one_distroseries(self): | ||
571 | 434 | app = self.factory.make_application() | ||
572 | 435 | self.factory.make_application( | ||
573 | 436 | package_name=app.package_name, | ||
574 | 437 | distroseries=app.distroseries | ||
575 | 438 | ) | ||
576 | 439 | response = self.client.get( | ||
577 | 440 | reverse('wc-package-detail', args=[app.package_name])) | ||
578 | 441 | |||
579 | 442 | ds = "Ubuntu {0}".format(app.distroseries.version) | ||
580 | 443 | self.assertContains(response, ds, 1) | ||
581 | 444 | |||
582 | 445 | 422 | ||
583 | 446 | class ApplicationDetailNoSeriesTestCase(TestCaseWithFactory): | 423 | class ApplicationDetailNoSeriesTestCase(TestCaseWithFactory): |
584 | 447 | def test_renders_latest(self): | 424 | def test_renders_latest(self): |
585 | @@ -1162,16 +1139,6 @@ | |||
586 | 1162 | 1139 | ||
587 | 1163 | self.assertEqual(200, response.status_code) | 1140 | self.assertEqual(200, response.status_code) |
588 | 1164 | 1141 | ||
589 | 1165 | def test_handles_multiple_apps_for_same_distroseries(self): | ||
590 | 1166 | ds = self.factory.make_distroseries() | ||
591 | 1167 | self.factory.make_application(package_name='skype', distroseries=ds) | ||
592 | 1168 | self.factory.make_application(package_name='skype', distroseries=ds) | ||
593 | 1169 | |||
594 | 1170 | response = self.client.get(reverse('wc-package-reviews', | ||
595 | 1171 | args=[ds.code_name, 'skype'])) | ||
596 | 1172 | |||
597 | 1173 | self.assertEqual(200, response.status_code) | ||
598 | 1174 | |||
599 | 1175 | def test_handles_api_error(self): | 1142 | def test_handles_api_error(self): |
600 | 1176 | app = self.factory.make_application() | 1143 | app = self.factory.make_application() |
601 | 1177 | self.mock_get_reviews.side_effect = APIError('500', 'error') | 1144 | self.mock_get_reviews.side_effect = APIError('500', 'error') |
602 | 1178 | 1145 | ||
603 | === modified file 'src/webcatalog/views.py' | |||
604 | --- src/webcatalog/views.py 2012-06-21 09:21:42 +0000 | |||
605 | +++ src/webcatalog/views.py 2012-06-28 14:07:20 +0000 | |||
606 | @@ -231,14 +231,8 @@ | |||
607 | 231 | 231 | ||
608 | 232 | 232 | ||
609 | 233 | def application_reviews(request, package_name, distro, ajax=False, page=1): | 233 | def application_reviews(request, package_name, distro, ajax=False, page=1): |
616 | 234 | # XXX 2012-05-25 bug=1002262 michaeln Multiple apps for distroseries. | 234 | app = get_object_or_404(Application, package_name=package_name, |
611 | 235 | # It seems that we have a few applications which are present in | ||
612 | 236 | # multiple archives for the same distroseries (skype, | ||
613 | 237 | # unity-lens-utilities, probably via a myapps PPA as well as extras?). | ||
614 | 238 | # Don't break when this happens. | ||
615 | 239 | apps = get_list_or_404(Application, package_name=package_name, | ||
617 | 240 | distroseries__code_name=distro) | 235 | distroseries__code_name=distro) |
618 | 241 | app = apps[0] | ||
619 | 242 | 236 | ||
620 | 243 | # XXX michaeln 2011-09-15 bug=851662 Better review language options. | 237 | # XXX michaeln 2011-09-15 bug=851662 Better review language options. |
621 | 244 | reviews = WebServices().get_reviews_for_package( | 238 | reviews = WebServices().get_reviews_for_package( |
Looks fine!