Merge lp:~sinzui/launchpad/poimport-typeerror into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merged at revision: 16261
Proposed branch: lp:~sinzui/launchpad/poimport-typeerror
Merge into: lp:launchpad
Diff against target: 141 lines (+82/-22)
2 files modified
lib/lp/translations/model/pofile.py (+24/-21)
lib/lp/translations/tests/test_pofile.py (+58/-1)
To merge this branch: bzr merge lp:~sinzui/launchpad/poimport-typeerror
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Review via email: mp+133713@code.launchpad.net

Commit message

Ensure the error data is sane enough to send an error email.

Description of the change

The TypeError happens when the script is trying to log an error. All the
data is sanitised except for the call to
potmsgset.getSequence(self.potemplate) to get the sequence. This can be
None if the TTI is incomplete. We just want to ensure the data is sane
enough so that we can log the error.

--------------------------------------------------------------------

RULES

    Pre-implementation: stevenk, jcsackett
    * Extract the logic that makes the error email to a separate testable
      method.
    * Add a test for the current behaviour.
    * Update the method to fallback to -1 if the sequence is None
    * Revise the loop to avoid needless string concatenation of errordetails

QA

    * Untestable, the case happens when the object is in an invalid state.

LINT

    lib/lp/translations/model/pofile.py
    lib/lp/translations/tests/test_pofile.py

LoC

    I have a credit of 4000 lines.

TEST

    ./bin/test -vvc -t prepare_pomessage lp.translations.tests.test_pofile

IMPLEMENTATION

Extracted the logic to a method and added a test. Added a rule to use -1
of the sequence is None.
    lib/lp/translations/model/pofile.py
    lib/lp/translations/tests/test_pofile.py

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :

Hi Curtis,

Typo: enail

When there is no sequence will the users understand '-1'? Would another string like "Invalid sequence" be better?

Overall it looks good.

review: Approve (code)
Revision history for this message
Curtis Hovey (sinzui) wrote :

The emails are often parsed by scripts and we want to keep using the number. This is case though where there is nothing wrong with the sequence in the pofile...Lp is bad, not the pofile.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/translations/model/pofile.py'
2--- lib/lp/translations/model/pofile.py 2012-09-28 06:25:44 +0000
3+++ lib/lp/translations/model/pofile.py 2012-11-13 13:43:23 +0000
4@@ -1098,29 +1098,10 @@
5 subject = 'Import problem - %s - %s' % (
6 self.language.displayname, self.potemplate.displayname)
7 elif len(errors) > 0:
8- # There were some errors with translations.
9- errorsdetails = ''
10- for error in errors:
11- potmsgset = error['potmsgset']
12- pomessage = error['pomessage']
13- error_message = error['error-message']
14- errorsdetails = '%s%d. "%s":\n\n%s\n\n' % (
15- errorsdetails,
16- potmsgset.getSequence(self.potemplate),
17- error_message,
18- pomessage)
19-
20+ data = self._prepare_pomessage_error_message(errors, replacements)
21+ subject, template_mail, errorsdetails = data
22 entry_to_import.setErrorOutput(
23 "Imported, but with errors:\n" + errorsdetails)
24-
25- replacements['numberoferrors'] = len(errors)
26- replacements['errorsdetails'] = errorsdetails
27- replacements['numberofcorrectmessages'] = (
28- msgsets_imported - len(errors))
29-
30- template_mail = 'poimport-with-errors.txt'
31- subject = 'Translation problems - %s - %s' % (
32- self.language.displayname, self.potemplate.displayname)
33 else:
34 # The import was successful.
35 template_mail = 'poimport-confirmation.txt'
36@@ -1165,6 +1146,28 @@
37 message = template % replacements
38 return (subject, message)
39
40+ def _prepare_pomessage_error_message(self, errors, replacements):
41+ # Return subject, template_mail, and errorsdetails to make
42+ # an error email message.
43+ error_count = len(errors)
44+ error_text = []
45+ for error in errors:
46+ potmsgset = error['potmsgset']
47+ pomessage = error['pomessage']
48+ sequence = potmsgset.getSequence(self.potemplate) or -1
49+ error_message = error['error-message']
50+ error_text.append('%d. "%s":\n\n%s\n\n' % (
51+ sequence, error_message, pomessage))
52+ errorsdetails = ''.join(error_text)
53+ replacements['numberoferrors'] = error_count
54+ replacements['errorsdetails'] = errorsdetails
55+ replacements['numberofcorrectmessages'] = (
56+ replacements['numberofmessages'] - error_count)
57+ template_mail = 'poimport-with-errors.txt'
58+ subject = 'Translation problems - %s - %s' % (
59+ self.language.displayname, self.potemplate.displayname)
60+ return subject, template_mail, errorsdetails
61+
62 def export(self, ignore_obsolete=False, force_utf8=False):
63 """See `IPOFile`."""
64 translation_exporter = getUtility(ITranslationExporter)
65
66=== modified file 'lib/lp/translations/tests/test_pofile.py'
67--- lib/lp/translations/tests/test_pofile.py 2012-02-15 21:14:05 +0000
68+++ lib/lp/translations/tests/test_pofile.py 2012-11-13 13:43:23 +0000
69@@ -20,7 +20,10 @@
70 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
71 from lp.services.database.constants import UTC_NOW
72 from lp.services.webapp.publisher import canonical_url
73-from lp.testing import TestCaseWithFactory
74+from lp.testing import (
75+ monkey_patch,
76+ TestCaseWithFactory,
77+ )
78 from lp.testing.fakemethod import FakeMethod
79 from lp.testing.layers import ZopelessDatabaseLayer
80 from lp.translations.interfaces.pofile import IPOFileSet
81@@ -2149,6 +2152,60 @@
82 language.code, with_plural=True)
83 self.assertTrue(pofile.hasPluralFormInformation())
84
85+ def test_prepare_pomessage_error_message(self):
86+ # The method returns subject, template_mail, and errorsdetails
87+ # to make an email message about errors.
88+ errors = []
89+ errors.append({
90+ 'potmsgset': self.factory.makePOTMsgSet(
91+ potemplate=self.pofile.potemplate, sequence=1),
92+ 'pomessage': 'purrs',
93+ 'error-message': 'claws error',
94+ })
95+ errors.append({
96+ 'potmsgset': self.factory.makePOTMsgSet(
97+ potemplate=self.pofile.potemplate, sequence=2),
98+ 'pomessage': 'plays',
99+ 'error-message': 'string error',
100+ })
101+ replacements = {'numberofmessages': 5}
102+ pofile = removeSecurityProxy(self.pofile)
103+ data = pofile._prepare_pomessage_error_message(
104+ errors, replacements)
105+ subject, template_mail, errorsdetails = data
106+ pot_displayname = self.pofile.potemplate.displayname
107+ self.assertEqual(
108+ 'Translation problems - Esperanto (eo) - %s' % pot_displayname,
109+ subject)
110+ self.assertEqual('poimport-with-errors.txt', template_mail)
111+ self.assertEqual(2, replacements['numberoferrors'])
112+ self.assertEqual(3, replacements['numberofcorrectmessages'])
113+ self.assertEqual(errorsdetails, replacements['errorsdetails'])
114+ self.assertEqual(
115+ '1. "claws error":\n\npurrs\n\n2. "string error":\n\nplays\n\n',
116+ errorsdetails)
117+
118+ def test_prepare_pomessage_error_message_sequence_is_invalid(self):
119+ # The errordetails can be contructed when the sequnce is invalid.
120+ errors = [{
121+ 'potmsgset': self.factory.makePOTMsgSet(
122+ potemplate=self.pofile.potemplate, sequence=None),
123+ 'pomessage': 'purrs',
124+ 'error-message': 'claws error',
125+ }]
126+ replacements = {'numberofmessages': 5}
127+ pofile = removeSecurityProxy(self.pofile)
128+ potmsgset = removeSecurityProxy(errors[0]['potmsgset'])
129+
130+ def get_sequence(pot):
131+ return None
132+
133+ with monkey_patch(potmsgset, getSequence=get_sequence):
134+ data = pofile._prepare_pomessage_error_message(
135+ errors, replacements)
136+ subject, template_mail, errorsdetails = data
137+ self.assertEqual('-1. "claws error":\n\npurrs\n\n', errorsdetails)
138+
139
140 class TestPOFileUbuntuUpstreamSharingMixin:
141 """Test sharing between Ubuntu und upstream POFiles."""