Merge lp:~michael.nelson/launchpad/470181-ppa-inline-style into lp:launchpad/db-devel

Proposed by Michael Nelson
Status: Merged
Approved by: Michael Nelson
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~michael.nelson/launchpad/470181-ppa-inline-style
Merge into: lp:launchpad/db-devel
Diff against target: 607 lines (+268/-38)
11 files modified
Makefile (+3/-1)
lib/canonical/launchpad/webapp/publisher.py (+0/-16)
lib/devscripts/ec2test/instance.py (+19/-4)
lib/devscripts/ec2test/tests/test_ec2instance.py (+185/-0)
lib/lp/code/model/directbranchcommit.py (+17/-3)
lib/lp/code/tests/test_directbranchcommit.py (+1/-1)
lib/lp/soyuz/templates/archive-index.pt (+1/-1)
lib/lp/translations/doc/translations-export-to-branch.txt (+11/-3)
lib/lp/translations/scripts/translations_to_branch.py (+13/-6)
lib/lp/translations/utilities/gettext_po_exporter.py (+15/-2)
utilities/rocketfuel-setup (+3/-1)
To merge this branch: bzr merge lp:~michael.nelson/launchpad/470181-ppa-inline-style
Reviewer Review Type Date Requested Status
Abel Deuring (community) Approve
Review via email: mp+15325@code.launchpad.net

Commit message

Fixes bug 470181 by adding a missing class required for correct styling of the inline text area editor.

To post a comment you must log in.
Revision history for this message
Michael Nelson (michael.nelson) wrote :

= Summary =

This is a fix for bug 470181.

I'm not 100%, but it seems as though since we integrated the multiline editor on the PPA index page, a subsequent requirement has been added (via lazr-js) of a lazr-multiline-edit class.

This branch simply adds that class to fix the bug.

== Demo and Q/A ==

View https://launchpad.dev/~cprov/+archive/ppa before merging this branch to see the issue (or view a ppa on edge).

Then reload the same page after merging to see it fixed.

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/lp/soyuz/templates/archive-index.pt

Revision history for this message
Abel Deuring (adeuring) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2009-11-17 20:43:28 +0000
3+++ Makefile 2009-11-27 16:21:25 +0000
4@@ -335,6 +335,8 @@
5 launchpad.pot:
6 bin/i18nextract.py
7
8+# Called by the rocketfuel-setup script. You probably don't want to run this
9+# on its own.
10 install: reload-apache
11
12 copy-certificates:
13@@ -353,7 +355,7 @@
14 a2ensite local-launchpad
15
16 reload-apache: enable-apache-launchpad
17- /etc/init.d/apache2 reload
18+ /etc/init.d/apache2 restart
19
20 static:
21 $(PY) scripts/make-static.py
22
23=== modified file 'lib/canonical/launchpad/webapp/publisher.py'
24--- lib/canonical/launchpad/webapp/publisher.py 2009-11-14 22:44:07 +0000
25+++ lib/canonical/launchpad/webapp/publisher.py 2009-11-27 16:21:25 +0000
26@@ -38,8 +38,6 @@
27 from zope.security.checker import ProxyFactory, NamesChecker
28 from zope.traversing.browser.interfaces import IAbsoluteURL
29
30-from canonical.cachedproperty import cachedproperty
31-from canonical.config import config
32 from canonical.launchpad.layers import setFirstLayer, WebServiceLayer
33 from canonical.launchpad.webapp.vhosts import allvhosts
34 from canonical.launchpad.webapp.interfaces import (
35@@ -232,7 +230,6 @@
36 many templates not set via zcml, or you want to do
37 rendering from Python.
38 - isBetaUser <-- whether the logged-in user is a beta tester
39- - striped_class<-- a tr class for an alternating row background
40 """
41
42 def __init__(self, context, request):
43@@ -285,19 +282,6 @@
44 else:
45 return self.render()
46
47- @cachedproperty
48- def striped_class(self):
49- """Return a generator which yields alternating CSS classes.
50-
51- This is to be used for HTML tables in which the row colors should be
52- alternated.
53- """
54- def bg_stripe_generator():
55- while True:
56- yield 'white'
57- yield 'shaded'
58- return bg_stripe_generator()
59-
60 def _getErrorMessage(self):
61 """Property getter for `error_message`."""
62 return self._error_message
63
64=== modified file 'lib/devscripts/ec2test/instance.py'
65--- lib/devscripts/ec2test/instance.py 2009-11-23 02:36:18 +0000
66+++ lib/devscripts/ec2test/instance.py 2009-11-27 16:21:25 +0000
67@@ -19,11 +19,9 @@
68 import traceback
69
70 from bzrlib.errors import BzrCommandError
71-from bzrlib.plugins.launchpad.account import get_lp_login
72
73 import paramiko
74
75-from devscripts.ec2test.credentials import EC2Credentials
76 from devscripts.ec2test.session import EC2SessionName
77
78
79@@ -194,6 +192,17 @@
80 to allow access to the instance.
81 :param credentials: An `EC2Credentials` object.
82 """
83+ # This import breaks in the test environment. Do it here so
84+ # that unit tests (which don't use this factory) can still
85+ # import EC2Instance.
86+ from bzrlib.plugins.launchpad.account import get_lp_login
87+
88+ # XXX JeroenVermeulen 2009-11-27 bug=489073: EC2Credentials
89+ # imports boto, which isn't necessarily installed in our test
90+ # environment. Doing the import here so that unit tests (which
91+ # don't use this factory) can still import EC2Instance.
92+ from devscripts.ec2test.credentials import EC2Credentials
93+
94 assert isinstance(name, EC2SessionName)
95 if instance_type not in AVAILABLE_INSTANCE_TYPES:
96 raise ValueError('unknown instance_type %s' % (instance_type,))
97@@ -388,6 +397,10 @@
98 self._ensure_ec2test_user_has_keys()
99 return self._connect('ec2test')
100
101+ def _report_traceback(self):
102+ """Print traceback."""
103+ traceback.print_exc()
104+
105 def set_up_and_run(self, postmortem, shutdown, func, *args, **kw):
106 """Start, run `func` and then maybe shut down.
107
108@@ -405,16 +418,17 @@
109 # We ignore the value of the 'shutdown' argument and always shut down
110 # unless `func` returns normally.
111 really_shutdown = True
112+ retval = None
113 try:
114 self.start()
115 try:
116- return func(*args, **kw)
117+ retval = func(*args, **kw)
118 except Exception:
119 # When running in postmortem mode, it is really helpful to see
120 # if there are any exceptions before it waits in the console
121 # (in the finally block), and you can't figure out why it's
122 # broken.
123- traceback.print_exc()
124+ self._report_traceback()
125 else:
126 really_shutdown = shutdown
127 finally:
128@@ -427,6 +441,7 @@
129 finally:
130 if really_shutdown:
131 self.shutdown()
132+ return retval
133
134 def _copy_single_file(self, sftp, local_path, remote_dir):
135 """Copy `local_path` to `remote_dir` on this instance.
136
137=== added file 'lib/devscripts/ec2test/tests/test_ec2instance.py'
138--- lib/devscripts/ec2test/tests/test_ec2instance.py 1970-01-01 00:00:00 +0000
139+++ lib/devscripts/ec2test/tests/test_ec2instance.py 2009-11-27 16:21:25 +0000
140@@ -0,0 +1,185 @@
141+# Copyright 2009 Canonical Ltd. This software is licensed under the
142+# GNU Affero General Public License version 3 (see the file LICENSE).
143+# pylint: disable-msg=E0702
144+
145+"""Test handling of EC2 machine images."""
146+
147+__metaclass__ = type
148+
149+from unittest import TestCase, TestLoader
150+
151+from devscripts.ec2test.instance import EC2Instance
152+
153+
154+class Stub:
155+ """Generic recipient of invocations.
156+
157+ Use this to:
158+ - Stub methods that should do nothing.
159+ - Inject failures into methods.
160+ - Record whether a method is being called.
161+ """
162+ # XXX JeroenVermeulen 2009-11-26: This probably exists somewhere
163+ # already. Or if not, maybe it should. But with a name that won't
164+ # turn Stuart Bishop's IRC client into a disco simulator.
165+
166+ call_count = 0
167+
168+ def __init__(self, return_value=None, simulated_failure=None):
169+ """Define what to do when this stub gets invoked.
170+
171+ :param return_value: Something to return from the invocation.
172+ :parma simulated_failure: Something to raise in the invocation.
173+ """
174+ assert return_value is None or simulated_failure is None, (
175+ "Stub can raise an exception or return a value, but not both.")
176+ self.return_value = return_value
177+ self.simulated_failure = simulated_failure
178+
179+ def __call__(self, *args, **kwargs):
180+ """Catch a call.
181+
182+ Records the fact that an invocation was made in
183+ `call_count`.
184+
185+ If you passed a `simulated_failure` to the constructor, that
186+ object is raised.
187+
188+ :return: The `return_value` you passed to the constructor.
189+ """
190+ self.call_count += 1
191+
192+ if self.simulated_failure is not None:
193+ raise self.simulated_failure
194+
195+ return self.return_value
196+
197+
198+class FakeAccount:
199+ """Helper for setting up an `EC2Instance` without EC2."""
200+ acquire_private_key = Stub()
201+ acquire_security_group = Stub()
202+
203+
204+class FakeOutput:
205+ """Pretend stdout/stderr output from EC2 instance."""
206+ output = "Fake output."
207+
208+
209+class FakeBotoInstance:
210+ """Helper for setting up an `EC2Instance` without EC2."""
211+ id = 0
212+ state = 'running'
213+ public_dns_name = 'fake-instance'
214+
215+ update = Stub()
216+ stop = Stub()
217+ get_console_output = FakeOutput
218+
219+
220+class FakeReservation:
221+ """Helper for setting up an `EC2Instance` without EC2."""
222+ def __init__(self):
223+ self.instances = [FakeBotoInstance()]
224+
225+
226+class FakeImage:
227+ """Helper for setting up an `EC2Instance` without EC2."""
228+ run = Stub(return_value=FakeReservation())
229+
230+
231+class FakeFailure(Exception):
232+ """A pretend failure from the test runner."""
233+
234+
235+class TestEC2Instance(TestCase):
236+ """Test running of an `EC2Instance` without EC2."""
237+
238+ def _makeInstance(self):
239+ """Set up an `EC2Instance`, with stubbing where needed.
240+
241+ `EC2Instance.shutdown` is replaced with a `Stub`, so check its
242+ call_count to see whether it's been invoked.
243+ """
244+ session_name = None
245+ image = FakeImage()
246+ instance_type = 'c1.xlarge'
247+ demo_networks = None
248+ account = FakeAccount()
249+ from_scratch = None
250+ user_key = None
251+ login = None
252+
253+ instance = EC2Instance(
254+ session_name, image, instance_type, demo_networks, account,
255+ from_scratch, user_key, login)
256+
257+ instance.shutdown = Stub()
258+ instance._report_traceback = Stub()
259+ instance.log = Stub()
260+
261+ return instance
262+
263+ def _runInstance(self, instance, runnee=None, headless=False):
264+ """Set up and run an `EC2Instance` (but without EC2)."""
265+ if runnee is None:
266+ runnee = Stub()
267+
268+ instance.set_up_and_run(False, not headless, runnee)
269+
270+ def test_EC2Instance_test_baseline(self):
271+ # The EC2 instances we set up have neither started nor been shut
272+ # down. After running, they have started.
273+ # Not a very useful test, except it establishes the basic
274+ # assumptions for the other tests.
275+ instance = self._makeInstance()
276+ runnee = Stub()
277+
278+ self.assertEqual(0, runnee.call_count)
279+ self.assertEqual(0, instance.shutdown.call_count)
280+
281+ self._runInstance(instance, runnee=runnee)
282+
283+ self.assertEqual(1, runnee.call_count)
284+
285+ def test_set_up_and_run_headful(self):
286+ # A non-headless run executes all tests in the instance, then
287+ # shuts down.
288+ instance = self._makeInstance()
289+
290+ self._runInstance(instance, headless=False)
291+
292+ self.assertEqual(1, instance.shutdown.call_count)
293+
294+ def test_set_up_and_run_headless(self):
295+ # An asynchronous, headless run kicks off the tests on the
296+ # instance but does not shut it down.
297+ instance = self._makeInstance()
298+
299+ self._runInstance(instance, headless=True)
300+
301+ self.assertEqual(0, instance.shutdown.call_count)
302+
303+ def test_set_up_and_run_headful_failure(self):
304+ # If the test runner barfs, the instance swallows the exception
305+ # and shuts down.
306+ instance = self._makeInstance()
307+ runnee = Stub(simulated_failure=FakeFailure("Headful barfage."))
308+
309+ self._runInstance(instance, runnee=runnee, headless=False)
310+
311+ self.assertEqual(1, instance.shutdown.call_count)
312+
313+ def test_set_up_and_run_headless_failure(self):
314+ # If the instance's test runner fails to set up for a headless
315+ # run, the instance swallows the exception and shuts down.
316+ instance = self._makeInstance()
317+ runnee = Stub(simulated_failure=FakeFailure("Headless boom."))
318+
319+ self._runInstance(instance, runnee=runnee, headless=True)
320+
321+ self.assertEqual(1, instance.shutdown.call_count)
322+
323+
324+def test_suite():
325+ return TestLoader().loadTestsFromName(__name__)
326
327=== modified file 'lib/lp/code/model/directbranchcommit.py'
328--- lib/lp/code/model/directbranchcommit.py 2009-09-09 20:03:19 +0000
329+++ lib/lp/code/model/directbranchcommit.py 2009-11-27 16:21:25 +0000
330@@ -74,6 +74,8 @@
331 self.db_branch = db_branch
332 self.to_mirror = to_mirror
333
334+ self.last_scanned_id = self.db_branch.last_scanned_id
335+
336 if committer is None:
337 committer = db_branch.owner
338 self.committer = committer
339@@ -172,12 +174,18 @@
340 assert self.is_locked, "Getting revision on un-locked branch."
341 last_revision = None
342 last_revision = self.bzrbranch.last_revision()
343- if last_revision != self.db_branch.last_scanned_id:
344+ if last_revision != self.last_scanned_id:
345 raise ConcurrentUpdateError(
346 "Branch has been changed. Not committing.")
347
348- def commit(self, commit_message):
349- """Commit to branch."""
350+ def commit(self, commit_message, txn=None):
351+ """Commit to branch.
352+
353+ :param commit_message: Message for branch's commit log.
354+ :param txn: Transaction to commit. Can be helpful in avoiding
355+ long idle times in database transactions. May be committed
356+ more than once.
357+ """
358 assert self.is_open, "Committing closed DirectBranchCommit."
359 assert self.is_locked, "Not locked at commit time."
360
361@@ -185,6 +193,9 @@
362 try:
363 self._checkForRace()
364
365+ if txn:
366+ txn.commit()
367+
368 rev_id = self.revision_tree.get_revision_id()
369 if rev_id == NULL_REVISION:
370 if list(self.transform_preview.iter_changes()) == []:
371@@ -193,6 +204,9 @@
372 self.bzrbranch, commit_message)
373 IMasterObject(self.db_branch).requestMirror()
374
375+ if txn:
376+ txn.commit()
377+
378 finally:
379 self.unlock()
380 self.is_open = False
381
382=== modified file 'lib/lp/code/tests/test_directbranchcommit.py'
383--- lib/lp/code/tests/test_directbranchcommit.py 2009-10-02 09:48:30 +0000
384+++ lib/lp/code/tests/test_directbranchcommit.py 2009-11-27 16:21:25 +0000
385@@ -37,7 +37,7 @@
386
387 self.committer = DirectBranchCommit(self.db_branch)
388 if update_last_scanned_id:
389- self.db_branch.last_scanned_id = (
390+ self.committer.last_scanned_id = (
391 self.committer.bzrbranch.last_revision())
392
393 def _tearDownCommitter(self):
394
395=== modified file 'lib/lp/soyuz/templates/archive-index.pt'
396--- lib/lp/soyuz/templates/archive-index.pt 2009-11-04 13:56:17 +0000
397+++ lib/lp/soyuz/templates/archive-index.pt 2009-11-27 16:21:25 +0000
398@@ -30,7 +30,7 @@
399 This archive has been disabled.
400 </p>
401
402- <div id="edit-description"
403+ <div id="edit-description" class="lazr-multiline-edit"
404 tal:content="structure view/archive_description_html"
405 />
406 </div>
407
408=== modified file 'lib/lp/translations/doc/translations-export-to-branch.txt'
409--- lib/lp/translations/doc/translations-export-to-branch.txt 2009-10-20 06:03:46 +0000
410+++ lib/lp/translations/doc/translations-export-to-branch.txt 2009-11-27 16:21:25 +0000
411@@ -45,7 +45,7 @@
412 ... if self.simulate_race:
413 ... raise ConcurrentUpdateError("Simulated race condition.")
414 ...
415- ... def commit(self, message=None):
416+ ... def commit(self, message=None, txn=None):
417 ... self._checkForRace()
418 ... self.logger.info("Committed %d file(s)." % self.written_files)
419 ...
420@@ -129,11 +129,11 @@
421
422 >>> transaction.commit()
423 >>> script = MockExportTranslationsToBranch(
424- ... 'export-to-branch', test_args=['-vv'])
425+ ... 'export-to-branch', test_args=[])
426 >>> script.main()
427 INFO Exporting to translations branches.
428 INFO Exporting Gazblachko trunk series.
429- DEBUG No previous translations commit found.
430+ DEBUG ...
431 INFO Writing file 'po/main/nl.po':
432 INFO # ...
433 msgid ""
434@@ -143,6 +143,7 @@
435 msgid "maingazpot msgid"
436 msgstr "maingazpot msgstr"
437 <BLANKLINE>
438+ DEBUG ...
439 INFO Writing file 'po/module/nl.po':
440 INFO # ...
441 msgid ""
442@@ -152,6 +153,8 @@
443 <BLANKLINE>
444 msgid "gazmod msgid"
445 msgstr "gazmod msgstr"
446+ <BLANKLINE>
447+ DEBUG ...
448 INFO Committed 2 file(s).
449 INFO Unlock.
450 INFO Processed 1 item(s); 0 failure(s).
451@@ -186,6 +189,7 @@
452 >>> script.main()
453 INFO Exporting to translations branches.
454 INFO Exporting Gazblachko trunk series.
455+ DEBUG ....
456 DEBUG Last commit was at ....
457 INFO Unlock.
458 INFO Processed 1 item(s); 0 failure(s).
459@@ -197,6 +201,7 @@
460 >>> script.main()
461 INFO Exporting to translations branches.
462 INFO Exporting Gazblachko trunk series.
463+ DEBUG ....
464 DEBUG Last commit was at ...
465 INFO Writing file 'po/main/nl.po':
466 INFO ...
467@@ -228,11 +233,14 @@
468 >>> script.main()
469 INFO Exporting to translations branches.
470 INFO Exporting Gazblachko trunk series.
471+ DEBUG ....
472 DEBUG No previous translations commit found.
473+ DEBUG ....
474 INFO Writing file 'po/main/nl.po':
475 ...
476 msgstr "gazmod msgstr"
477 <BLANKLINE>
478+ DEBUG ...
479 INFO Unlock.
480 ERROR Failure: Simulated race condition.
481 INFO Processed 1 item(s); 1 failure(s).
482
483=== modified file 'lib/lp/translations/scripts/translations_to_branch.py'
484--- lib/lp/translations/scripts/translations_to_branch.py 2009-10-20 06:03:46 +0000
485+++ lib/lp/translations/scripts/translations_to_branch.py 2009-11-27 16:21:25 +0000
486@@ -119,7 +119,7 @@
487 def _commit(self, source, committer):
488 """Commit changes to branch. Check for race conditions."""
489 self._checkForObjections(source)
490- committer.commit(self.commit_message)
491+ committer.commit(self.commit_message, txn=self.txn)
492
493 def _isTranslationsCommit(self, revision):
494 """Is `revision` an automatic translations commit?"""
495@@ -159,6 +159,9 @@
496 self._checkForObjections(source)
497
498 committer = self._prepareBranchCommit(source.translations_branch)
499+ self.logger.debug("Created DirectBranchCommit.")
500+ if self.txn:
501+ self.txn.commit()
502
503 bzr_branch = committer.bzrbranch
504
505@@ -185,15 +188,17 @@
506 base_path = os.path.dirname(template.path)
507
508 for pofile in template.pofiles:
509-
510 has_changed = (
511 changed_since is None or
512 pofile.date_changed > changed_since)
513 if not has_changed:
514 continue
515
516+ language_code = pofile.getFullLanguageCode()
517+ self.logger.debug("Exporting %s." % language_code)
518+
519 pofile_path = os.path.join(
520- base_path, pofile.getFullLanguageCode() + '.po')
521+ base_path, language_code + '.po')
522 pofile_contents = pofile.export()
523
524 committer.writeFile(pofile_path, pofile_contents)
525@@ -210,6 +215,7 @@
526 template.clearPOFileCache()
527
528 if change_count > 0:
529+ self.logger.debug("Writing to branch.")
530 self._commit(source, committer)
531 finally:
532 committer.unlock()
533@@ -231,13 +237,14 @@
534 raise
535 except Exception, e:
536 items_failed += 1
537- self.logger.error("Failure: %s" % e)
538+ message = unicode(e)
539+ if message == u'':
540+ message = e.__class__.__name__
541+ self.logger.error("Failure: %s" % message)
542 if self.txn:
543 self.txn.abort()
544
545 items_done += 1
546- if self.txn:
547- self.txn.begin()
548
549 self.logger.info("Processed %d item(s); %d failure(s)." % (
550 items_done, items_failed))
551
552=== modified file 'lib/lp/translations/utilities/gettext_po_exporter.py'
553--- lib/lp/translations/utilities/gettext_po_exporter.py 2009-11-02 00:10:05 +0000
554+++ lib/lp/translations/utilities/gettext_po_exporter.py 2009-11-27 16:21:25 +0000
555@@ -14,6 +14,7 @@
556 'GettextPOExporter',
557 ]
558
559+import logging
560 import os
561
562 from zope.interface import implements
563@@ -344,8 +345,20 @@
564 raise UnicodeEncodeError(
565 '%s:\n%s' % (file_path, str(error)))
566
567- # This message cannot be represented in current encoding,
568- # change to UTF-8 and try again.
569+ # This message cannot be represented in the current
570+ # encoding.
571+ if translation_file.path:
572+ file_description = translation_file.path
573+ elif translation_file.language_code:
574+ file_description = (
575+ "%s translation" % translation_file.language_code)
576+ else:
577+ file_description = "template"
578+ logging.info(
579+ "Can't represent %s as %s; using UTF-8 instead." % (
580+ file_description,
581+ translation_file.header.charset.upper()))
582+
583 old_charset = translation_file.header.charset
584 translation_file.header.charset = 'UTF-8'
585 # We need to update the header too.
586
587=== modified file 'utilities/rocketfuel-setup'
588--- utilities/rocketfuel-setup 2009-11-12 06:57:28 +0000
589+++ utilities/rocketfuel-setup 2009-11-27 16:21:25 +0000
590@@ -7,7 +7,7 @@
591 # workstation, from scratch. The script lives in the LP codebase itself,
592 # as utilities/rocketfuel-setup
593
594-# We require Bazaar 1.16.1 or higher.
595+# We require Bazaar 1.16.1 or higher.
596 # So first, grab the output of 'bzr --version' and transform the
597 # version line, like "Bazaar (bzr) 1.16.1", into "1 16 1":
598 VER_RAW=`bzr --version | head -1 | sed -e 's/Bazaar (bzr) //g'`
599@@ -315,6 +315,8 @@
600 fi
601 fi
602
603+# Call the newly minted Launchpad branch's 'make install' target to do some
604+# more apache setup.
605 sudo make install > /dev/null
606 if [ $? -ne 0 ]; then
607 echo "ERROR: Unable to install apache config appropriately"

Subscribers

People subscribed via source and target branches

to status/vote changes: