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
=== modified file 'lib/lp/translations/model/pofile.py'
--- lib/lp/translations/model/pofile.py 2012-09-28 06:25:44 +0000
+++ lib/lp/translations/model/pofile.py 2012-11-13 13:43:23 +0000
@@ -1098,29 +1098,10 @@
1098 subject = 'Import problem - %s - %s' % (1098 subject = 'Import problem - %s - %s' % (
1099 self.language.displayname, self.potemplate.displayname)1099 self.language.displayname, self.potemplate.displayname)
1100 elif len(errors) > 0:1100 elif len(errors) > 0:
1101 # There were some errors with translations.1101 data = self._prepare_pomessage_error_message(errors, replacements)
1102 errorsdetails = ''1102 subject, template_mail, errorsdetails = data
1103 for error in errors:
1104 potmsgset = error['potmsgset']
1105 pomessage = error['pomessage']
1106 error_message = error['error-message']
1107 errorsdetails = '%s%d. "%s":\n\n%s\n\n' % (
1108 errorsdetails,
1109 potmsgset.getSequence(self.potemplate),
1110 error_message,
1111 pomessage)
1112
1113 entry_to_import.setErrorOutput(1103 entry_to_import.setErrorOutput(
1114 "Imported, but with errors:\n" + errorsdetails)1104 "Imported, but with errors:\n" + errorsdetails)
1115
1116 replacements['numberoferrors'] = len(errors)
1117 replacements['errorsdetails'] = errorsdetails
1118 replacements['numberofcorrectmessages'] = (
1119 msgsets_imported - len(errors))
1120
1121 template_mail = 'poimport-with-errors.txt'
1122 subject = 'Translation problems - %s - %s' % (
1123 self.language.displayname, self.potemplate.displayname)
1124 else:1105 else:
1125 # The import was successful.1106 # The import was successful.
1126 template_mail = 'poimport-confirmation.txt'1107 template_mail = 'poimport-confirmation.txt'
@@ -1165,6 +1146,28 @@
1165 message = template % replacements1146 message = template % replacements
1166 return (subject, message)1147 return (subject, message)
11671148
1149 def _prepare_pomessage_error_message(self, errors, replacements):
1150 # Return subject, template_mail, and errorsdetails to make
1151 # an error email message.
1152 error_count = len(errors)
1153 error_text = []
1154 for error in errors:
1155 potmsgset = error['potmsgset']
1156 pomessage = error['pomessage']
1157 sequence = potmsgset.getSequence(self.potemplate) or -1
1158 error_message = error['error-message']
1159 error_text.append('%d. "%s":\n\n%s\n\n' % (
1160 sequence, error_message, pomessage))
1161 errorsdetails = ''.join(error_text)
1162 replacements['numberoferrors'] = error_count
1163 replacements['errorsdetails'] = errorsdetails
1164 replacements['numberofcorrectmessages'] = (
1165 replacements['numberofmessages'] - error_count)
1166 template_mail = 'poimport-with-errors.txt'
1167 subject = 'Translation problems - %s - %s' % (
1168 self.language.displayname, self.potemplate.displayname)
1169 return subject, template_mail, errorsdetails
1170
1168 def export(self, ignore_obsolete=False, force_utf8=False):1171 def export(self, ignore_obsolete=False, force_utf8=False):
1169 """See `IPOFile`."""1172 """See `IPOFile`."""
1170 translation_exporter = getUtility(ITranslationExporter)1173 translation_exporter = getUtility(ITranslationExporter)
11711174
=== modified file 'lib/lp/translations/tests/test_pofile.py'
--- lib/lp/translations/tests/test_pofile.py 2012-02-15 21:14:05 +0000
+++ lib/lp/translations/tests/test_pofile.py 2012-11-13 13:43:23 +0000
@@ -20,7 +20,10 @@
20from lp.app.interfaces.launchpad import ILaunchpadCelebrities20from lp.app.interfaces.launchpad import ILaunchpadCelebrities
21from lp.services.database.constants import UTC_NOW21from lp.services.database.constants import UTC_NOW
22from lp.services.webapp.publisher import canonical_url22from lp.services.webapp.publisher import canonical_url
23from lp.testing import TestCaseWithFactory23from lp.testing import (
24 monkey_patch,
25 TestCaseWithFactory,
26 )
24from lp.testing.fakemethod import FakeMethod27from lp.testing.fakemethod import FakeMethod
25from lp.testing.layers import ZopelessDatabaseLayer28from lp.testing.layers import ZopelessDatabaseLayer
26from lp.translations.interfaces.pofile import IPOFileSet29from lp.translations.interfaces.pofile import IPOFileSet
@@ -2149,6 +2152,60 @@
2149 language.code, with_plural=True)2152 language.code, with_plural=True)
2150 self.assertTrue(pofile.hasPluralFormInformation())2153 self.assertTrue(pofile.hasPluralFormInformation())
21512154
2155 def test_prepare_pomessage_error_message(self):
2156 # The method returns subject, template_mail, and errorsdetails
2157 # to make an email message about errors.
2158 errors = []
2159 errors.append({
2160 'potmsgset': self.factory.makePOTMsgSet(
2161 potemplate=self.pofile.potemplate, sequence=1),
2162 'pomessage': 'purrs',
2163 'error-message': 'claws error',
2164 })
2165 errors.append({
2166 'potmsgset': self.factory.makePOTMsgSet(
2167 potemplate=self.pofile.potemplate, sequence=2),
2168 'pomessage': 'plays',
2169 'error-message': 'string error',
2170 })
2171 replacements = {'numberofmessages': 5}
2172 pofile = removeSecurityProxy(self.pofile)
2173 data = pofile._prepare_pomessage_error_message(
2174 errors, replacements)
2175 subject, template_mail, errorsdetails = data
2176 pot_displayname = self.pofile.potemplate.displayname
2177 self.assertEqual(
2178 'Translation problems - Esperanto (eo) - %s' % pot_displayname,
2179 subject)
2180 self.assertEqual('poimport-with-errors.txt', template_mail)
2181 self.assertEqual(2, replacements['numberoferrors'])
2182 self.assertEqual(3, replacements['numberofcorrectmessages'])
2183 self.assertEqual(errorsdetails, replacements['errorsdetails'])
2184 self.assertEqual(
2185 '1. "claws error":\n\npurrs\n\n2. "string error":\n\nplays\n\n',
2186 errorsdetails)
2187
2188 def test_prepare_pomessage_error_message_sequence_is_invalid(self):
2189 # The errordetails can be contructed when the sequnce is invalid.
2190 errors = [{
2191 'potmsgset': self.factory.makePOTMsgSet(
2192 potemplate=self.pofile.potemplate, sequence=None),
2193 'pomessage': 'purrs',
2194 'error-message': 'claws error',
2195 }]
2196 replacements = {'numberofmessages': 5}
2197 pofile = removeSecurityProxy(self.pofile)
2198 potmsgset = removeSecurityProxy(errors[0]['potmsgset'])
2199
2200 def get_sequence(pot):
2201 return None
2202
2203 with monkey_patch(potmsgset, getSequence=get_sequence):
2204 data = pofile._prepare_pomessage_error_message(
2205 errors, replacements)
2206 subject, template_mail, errorsdetails = data
2207 self.assertEqual('-1. "claws error":\n\npurrs\n\n', errorsdetails)
2208
21522209
2153class TestPOFileUbuntuUpstreamSharingMixin:2210class TestPOFileUbuntuUpstreamSharingMixin:
2154 """Test sharing between Ubuntu und upstream POFiles."""2211 """Test sharing between Ubuntu und upstream POFiles."""