Merge lp:~ricardokirkner/locolander/add-author into lp:locolander
- add-author
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Ricardo Kirkner |
Approved revision: | 24 |
Merged at revision: | 19 |
Proposed branch: | lp:~ricardokirkner/locolander/add-author |
Merge into: | lp:locolander |
Prerequisite: | lp:~ricardokirkner/locolander/celery-stack |
Diff against target: |
291 lines (+159/-26) 7 files modified
locolander/locolanderweb/admin.py (+8/-0) locolander/locolanderweb/migrations/0004_auto__add_field_mergerequest_author.py (+87/-0) locolander/locolanderweb/models.py (+1/-0) locolander/locolanderweb/tests/test_base.py (+5/-2) locolander/locolanderweb/tests/test_models.py (+5/-1) locolander/repos/launchpad.py (+11/-0) locolander/repos/tests/test_launchpad.py (+42/-23) |
To merge this branch: | bzr merge lp:~ricardokirkner/locolander/add-author |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Natalia Bidart | Approve | ||
Review via email: mp+174570@code.launchpad.net |
Commit message
added author to MergeRequest model
Description of the change
- 20. By Ricardo Kirkner
-
expose locolanderweb models in admin
- 21. By Ricardo Kirkner
-
merged trunk
- 22. By Ricardo Kirkner
-
regenerated migration
Natalia Bidart (nataliabidart) wrote : | # |
Code looks good! One detail: in a branch of mine you made me remove the datetime(
Leaving my approve vote, if you think the mp.date_created is a merge error, please revert before landing.
Ricardo Kirkner (ricardokirkner) wrote : | # |
> Code looks good! One detail: in a branch of mine you made me remove the
> datetime(
> precision from mp.date_created, any reason for you to revert that?
>
> Leaving my approve vote, if you think the mp.date_created is a merge error,
> please revert before landing.
It is an artifact from my pre-merged branch. Fixed, thanks!
- 23. By Ricardo Kirkner
-
merged trunk
- 24. By Ricardo Kirkner
-
reverted unwanted changes
Preview Diff
1 | === added file 'locolander/locolanderweb/admin.py' |
2 | --- locolander/locolanderweb/admin.py 1970-01-01 00:00:00 +0000 |
3 | +++ locolander/locolanderweb/admin.py 2013-07-20 18:17:23 +0000 |
4 | @@ -0,0 +1,8 @@ |
5 | +from django.contrib import admin |
6 | + |
7 | +from locolanderweb.models import MergeRequest, Project, RunLog |
8 | + |
9 | + |
10 | +admin.site.register(Project) |
11 | +admin.site.register(MergeRequest) |
12 | +admin.site.register(RunLog) |
13 | |
14 | === added file 'locolander/locolanderweb/migrations/0004_auto__add_field_mergerequest_author.py' |
15 | --- locolander/locolanderweb/migrations/0004_auto__add_field_mergerequest_author.py 1970-01-01 00:00:00 +0000 |
16 | +++ locolander/locolanderweb/migrations/0004_auto__add_field_mergerequest_author.py 2013-07-20 18:17:23 +0000 |
17 | @@ -0,0 +1,87 @@ |
18 | +# -*- coding: utf-8 -*- |
19 | +from south.db import db |
20 | +from south.v2 import SchemaMigration |
21 | + |
22 | + |
23 | +class Migration(SchemaMigration): |
24 | + |
25 | + def forwards(self, orm): |
26 | + # Adding field 'MergeRequest.author' |
27 | + db.add_column(u'locolanderweb_mergerequest', 'author', |
28 | + self.gf('django.db.models.fields.TextField')(default=''), |
29 | + keep_default=False) |
30 | + |
31 | + |
32 | + def backwards(self, orm): |
33 | + # Deleting field 'MergeRequest.author' |
34 | + db.delete_column(u'locolanderweb_mergerequest', 'author') |
35 | + |
36 | + |
37 | + models = { |
38 | + u'auth.group': { |
39 | + 'Meta': {'object_name': 'Group'}, |
40 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
41 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), |
42 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) |
43 | + }, |
44 | + u'auth.permission': { |
45 | + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, |
46 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
47 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), |
48 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
49 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) |
50 | + }, |
51 | + u'auth.user': { |
52 | + 'Meta': {'object_name': 'User'}, |
53 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
54 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), |
55 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
56 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), |
57 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
58 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
59 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
60 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
61 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
62 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
63 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
64 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), |
65 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) |
66 | + }, |
67 | + u'contenttypes.contenttype': { |
68 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, |
69 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
70 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
71 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
72 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) |
73 | + }, |
74 | + u'locolanderweb.mergerequest': { |
75 | + 'Meta': {'object_name': 'MergeRequest'}, |
76 | + 'author': ('django.db.models.fields.TextField', [], {'default': "''"}), |
77 | + 'commit_message': ('django.db.models.fields.TextField', [], {}), |
78 | + 'date_completed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), |
79 | + 'date_created': ('django.db.models.fields.DateTimeField', [], {}), |
80 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
81 | + 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['locolanderweb.Project']"}), |
82 | + 'reviewers': ('django.db.models.fields.TextField', [], {}), |
83 | + 'source': ('django.db.models.fields.TextField', [], {}), |
84 | + 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '128'}), |
85 | + 'target': ('django.db.models.fields.TextField', [], {}) |
86 | + }, |
87 | + u'locolanderweb.project': { |
88 | + 'Meta': {'object_name': 'Project'}, |
89 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
90 | + 'name': ('django.db.models.fields.TextField', [], {}), |
91 | + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), |
92 | + 'url': ('django.db.models.fields.CharField', [], {'max_length': '256'}) |
93 | + }, |
94 | + u'locolanderweb.runlog': { |
95 | + 'Meta': {'object_name': 'RunLog'}, |
96 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
97 | + 'merge_request': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['locolanderweb.MergeRequest']"}), |
98 | + 'raw': ('django.db.models.fields.TextField', [], {}), |
99 | + 'return_code': ('django.db.models.fields.IntegerField', [], {}), |
100 | + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}) |
101 | + } |
102 | + } |
103 | + |
104 | + complete_apps = ['locolanderweb'] |
105 | |
106 | === modified file 'locolander/locolanderweb/models.py' |
107 | --- locolander/locolanderweb/models.py 2013-07-06 23:19:29 +0000 |
108 | +++ locolander/locolanderweb/models.py 2013-07-20 18:17:23 +0000 |
109 | @@ -55,6 +55,7 @@ |
110 | source = models.TextField() |
111 | target = models.TextField() |
112 | commit_message = models.TextField() |
113 | + author = models.TextField(default='') |
114 | reviewers = models.TextField() |
115 | date_created = models.DateTimeField() |
116 | date_completed = models.DateTimeField(null=True, blank=True) |
117 | |
118 | === modified file 'locolander/locolanderweb/tests/test_base.py' |
119 | --- locolander/locolanderweb/tests/test_base.py 2013-07-06 23:19:29 +0000 |
120 | +++ locolander/locolanderweb/tests/test_base.py 2013-07-20 18:17:23 +0000 |
121 | @@ -46,7 +46,8 @@ |
122 | def make_merge_request( |
123 | self, project=None, status=STATUS_PENDING, |
124 | source=None, target=None, commit_message=None, |
125 | - reviewers=None, date_created=None, date_completed=None): |
126 | + author=None, reviewers=None, date_created=None, |
127 | + date_completed=None): |
128 | if project is None: |
129 | project = self.make_project() |
130 | if source is None: |
131 | @@ -55,13 +56,15 @@ |
132 | target = 'http://foo.target' |
133 | if commit_message is None: |
134 | commit_message = 'Foo bar commit message.' |
135 | + if author is None: |
136 | + author = 'Some Person <some@domain>' |
137 | if reviewers is None: |
138 | reviewers = ['mengano', 'fulano'] |
139 | if date_created is None: |
140 | date_created = datetime.utcnow() |
141 | return MergeRequest.objects.create( |
142 | project=project, status=status, source=source, target=target, |
143 | - commit_message=commit_message, reviewers=reviewers, |
144 | + commit_message=commit_message, author=author, reviewers=reviewers, |
145 | date_created=date_created, date_completed=date_completed) |
146 | |
147 | def make_run_log(self, merge_request=None, return_code=0, raw=None): |
148 | |
149 | === modified file 'locolander/locolanderweb/tests/test_models.py' |
150 | --- locolander/locolanderweb/tests/test_models.py 2013-07-13 16:00:06 +0000 |
151 | +++ locolander/locolanderweb/tests/test_models.py 2013-07-20 18:17:23 +0000 |
152 | @@ -120,7 +120,8 @@ |
153 | self.obj = MergeRequest.objects.create( |
154 | project=self.project, |
155 | source='source', target='target', commit_message='commit', |
156 | - reviewers='fulano, mengano', date_created=self.created) |
157 | + author='Some Person <some@domain>', reviewers='fulano, mengano', |
158 | + date_created=self.created) |
159 | |
160 | def test_status_default(self): |
161 | self.assertEqual(self.obj.status, STATUS_PENDING) |
162 | @@ -139,6 +140,9 @@ |
163 | def test_commit_message(self): |
164 | self.assertEqual(self.obj.commit_message, 'commit') |
165 | |
166 | + def test_author(self): |
167 | + self.assertEqual(self.obj.author, 'Some Person <some@domain>') |
168 | + |
169 | def test_reviewers(self): |
170 | self.assertEqual(self.obj.reviewers, 'fulano, mengano') |
171 | |
172 | |
173 | === modified file 'locolander/repos/launchpad.py' |
174 | --- locolander/repos/launchpad.py 2013-07-13 16:00:06 +0000 |
175 | +++ locolander/repos/launchpad.py 2013-07-20 18:17:23 +0000 |
176 | @@ -5,6 +5,8 @@ |
177 | import os |
178 | import re |
179 | |
180 | +import bzrlib.plugin |
181 | +from bzrlib.branch import Branch |
182 | from launchpadlib.launchpad import Launchpad |
183 | |
184 | from repos import errors |
185 | @@ -29,6 +31,14 @@ |
186 | self.launchpad = Launchpad.login_anonymously( |
187 | 'locolander', 'production', CACHE_DIR) |
188 | self.lp_projects = self.launchpad.projects |
189 | + # load bzr plugins so that lp: namespace is recognized |
190 | + bzrlib.plugin.load_plugins() |
191 | + |
192 | + def get_author(self, branch_url): |
193 | + branch = Branch.open(branch_url) |
194 | + tip = branch.repository.get_revision( |
195 | + branch.get_rev_id(branch.revno())) |
196 | + return tip.committer |
197 | |
198 | def approved_requests_for_project_url(self, project_url): |
199 | """Return approved merge proposals.""" |
200 | @@ -56,5 +66,6 @@ |
201 | 'target': mp.target_branch.bzr_identity, |
202 | 'reviewers': mp.reviewer.name, # csv |
203 | 'commit_message': mp.commit_message, |
204 | + 'author': self.get_author(mp.source_branch.bzr_identity), |
205 | }) |
206 | return approved |
207 | |
208 | === modified file 'locolander/repos/tests/test_launchpad.py' |
209 | --- locolander/repos/tests/test_launchpad.py 2013-07-06 22:26:19 +0000 |
210 | +++ locolander/repos/tests/test_launchpad.py 2013-07-20 18:17:23 +0000 |
211 | @@ -3,11 +3,16 @@ |
212 | from datetime import datetime |
213 | from unittest import TestCase |
214 | |
215 | +import bzrlib.branch |
216 | from mock import Mock, patch |
217 | |
218 | from repos import errors, launchpad |
219 | |
220 | |
221 | +# fake bzrlib Branch object |
222 | +FakeBranch = Mock(spec=bzrlib.branch.Branch) |
223 | + |
224 | + |
225 | class FakeMP(object): |
226 | """Fake launchpadlib Merge Proposal object.""" |
227 | |
228 | @@ -71,26 +76,40 @@ |
229 | with self.assertRaises(errors.RepositoryDoesNotExist): |
230 | self.lp.approved_requests_for_project_url('lp:not-found') |
231 | |
232 | - def test_valid_project_without_approved_mp(self): |
233 | - mps = self.lp.approved_requests_for_project_url('lp:test-project') |
234 | - self.assertEqual(len(mps), 1) |
235 | - mp = mps[0] |
236 | - self.assertIsInstance(mp, dict) |
237 | - |
238 | - expected_keys = ['date_created', 'source', 'target', 'reviewers', |
239 | - 'commit_message'] |
240 | - for key in expected_keys: |
241 | - self.assertIn(key, mp) |
242 | - self.assertEqual(mp['commit_message'], 'approved mp') |
243 | - |
244 | - def test_valid_project_return_approved_mp(self): |
245 | - mps = self.lp.approved_requests_for_project_url('lp:test-project') |
246 | - self.assertEqual(len(mps), 1) |
247 | - mp = mps[0] |
248 | - self.assertIsInstance(mp, dict) |
249 | - |
250 | - expected_keys = ['date_created', 'source', 'target', 'reviewers', |
251 | - 'commit_message'] |
252 | - for key in expected_keys: |
253 | - self.assertIn(key, mp) |
254 | - self.assertEqual(mp['commit_message'], 'approved mp') |
255 | + @patch('repos.launchpad.Branch.open') |
256 | + def test_valid_project_without_approved_mp(self, mock_open): |
257 | + mps = self.lp.approved_requests_for_project_url('lp:test-project') |
258 | + self.assertEqual(len(mps), 1) |
259 | + mp = mps[0] |
260 | + self.assertIsInstance(mp, dict) |
261 | + |
262 | + expected_keys = ['date_created', 'source', 'target', 'reviewers', |
263 | + 'commit_message', 'author'] |
264 | + for key in expected_keys: |
265 | + self.assertIn(key, mp) |
266 | + self.assertEqual(mp['commit_message'], 'approved mp') |
267 | + |
268 | + @patch('repos.launchpad.Branch.open') |
269 | + def test_valid_project_return_approved_mp(self, mock_open): |
270 | + mps = self.lp.approved_requests_for_project_url('lp:test-project') |
271 | + self.assertEqual(len(mps), 1) |
272 | + mp = mps[0] |
273 | + self.assertIsInstance(mp, dict) |
274 | + |
275 | + expected_keys = ['date_created', 'source', 'target', 'reviewers', |
276 | + 'commit_message', 'author'] |
277 | + for key in expected_keys: |
278 | + self.assertIn(key, mp) |
279 | + self.assertEqual(mp['commit_message'], 'approved mp') |
280 | + |
281 | + @patch('repos.launchpad.Branch.open') |
282 | + def test_get_author(self, mock_open): |
283 | + mock_revision = Mock() |
284 | + mock_revision.committer = 'The Author <some@email.com>' |
285 | + mock_repository = Mock() |
286 | + mock_repository.get_revision.return_value = mock_revision |
287 | + mock_open.return_value.repository = mock_repository |
288 | + |
289 | + author = self.lp.get_author('lp:test-project') |
290 | + |
291 | + self.assertEqual(author, 'The Author <some@email.com>') |
Changes for the new author field looks good, but there seem to be a mixup in the diff since the next branch has 0 diff lines, and this one includes all the celery tasks things.