~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/translations/model/translationimportqueue.py

  • Committer: Jelmer Vernooij
  • Date: 2011-09-21 14:28:02 UTC
  • mfrom: (14006 devel)
  • mto: This revision was merged to the branch mainline in revision 14010.
  • Revision ID: jelmer@canonical.com-20110921142802-7ggkc204igsy532w
MergeĀ lp:launchpad

Show diffs side-by-side

added added

removed removed

Lines of Context:
136
136
    return info
137
137
 
138
138
 
 
139
def compose_approval_conflict_notice(domain, templates_count, sample):
 
140
    """Create a note to warn about an approval conflict.
 
141
 
 
142
    The note warns about the situation where one productseries, or source
 
143
    package, or in some cases distroseries has multiple actice templates
 
144
    with the same translation domain.
 
145
 
 
146
    :param domain: The domain that's causing trouble.
 
147
    :param templates_count: The number of clashing templates.
 
148
    :param sample: Iterable of matching templates.  Does not need to be
 
149
        complete, just enough to report the problem usefully.
 
150
    :return: A string describing the problematic clash.
 
151
    """
 
152
    sample_names = sorted([
 
153
        '"%s"' % template.displayname for template in sample])
 
154
    if templates_count > len(sample_names):
 
155
        sample_names.append("and more (not shown here)")
 
156
    return dedent("""\
 
157
        Can't auto-approve upload: it is not clear what template it belongs
 
158
        to.
 
159
 
 
160
        There are %d competing templates with translation domain '%s':
 
161
        %s.
 
162
 
 
163
        This may mean that Launchpad's auto-approver is looking for the wrong
 
164
        domain, or that these templates' domains should be changed, or that
 
165
        some of these templates are obsolete and need to be disabled.
 
166
        """
 
167
        ) % (templates_count, domain, ';\n'.join(sample_names))
 
168
 
 
169
 
139
170
class TranslationImportQueueEntry(SQLBase):
140
171
    implements(ITranslationImportQueueEntry)
141
172
 
407
438
            # We don't know where this entry should be imported.
408
439
            return None
409
440
 
 
441
    def reportApprovalConflict(self, domain, templates_count, sample):
 
442
        """Report an approval conflict."""
 
443
        # Not sending out email for now; just tack a notice onto the
 
444
        # queue entry where the user can find it through the queue UI.
 
445
        notice = compose_approval_conflict_notice(
 
446
            domain, templates_count, sample)
 
447
        if notice != self.error_output:
 
448
            self.setErrorOutput(notice)
 
449
 
 
450
    def matchPOTemplateByDomain(self, domain, sourcepackagename=None):
 
451
        """Attempt to find the one matching template, by domain.
 
452
 
 
453
        Looks within the context of the queue entry.  If multiple templates
 
454
        match, reports an approval conflict.
 
455
 
 
456
        :param domain: Translation domain to look for.
 
457
        :param sourcepackagename: Optional `SourcePackageName` to look for.
 
458
            If not given, source package name is not considered in the
 
459
            search.
 
460
        :return: A single `POTemplate`, or None.
 
461
        """
 
462
        potemplateset = getUtility(IPOTemplateSet)
 
463
        subset = potemplateset.getSubset(
 
464
            productseries=self.productseries, distroseries=self.distroseries,
 
465
            sourcepackagename=sourcepackagename, iscurrent=True)
 
466
        templates_query = subset.getPOTemplatesByTranslationDomain(domain)
 
467
 
 
468
        # Get a limited sample of the templates.  All we need from the
 
469
        # sample is (1) to detect the presence or more than one match,
 
470
        # and (2) to report a helpful sampling of the problem.
 
471
        samples = list(templates_query[:5])
 
472
 
 
473
        if len(samples) == 0:
 
474
            # No matches found, sorry.
 
475
            return None
 
476
        elif len(samples) == 1:
 
477
            # Found the one template we're looking for.
 
478
            return samples[0]
 
479
        else:
 
480
            # There's a conflict.  Report the real number of competing
 
481
            # templates, plus a sampling of template names.
 
482
            self.reportApprovalConflict(
 
483
                domain, templates_query.count(), samples)
 
484
            return None
 
485
 
410
486
    def _get_pofile_from_language(self, lang_code, translation_domain,
411
487
        sourcepackagename=None):
412
488
        """Return an IPOFile for the given language and domain.
431
507
            # of just 'es' or 'fr'.
432
508
            return None
433
509
 
434
 
        potemplateset = getUtility(IPOTemplateSet)
435
 
 
436
 
        # Let's try first the sourcepackagename or productseries where the
437
 
        # translation comes from.
438
 
        potemplate_subset = potemplateset.getSubset(
439
 
            distroseries=self.distroseries,
440
 
            sourcepackagename=self.sourcepackagename,
441
 
            productseries=self.productseries,
442
 
            iscurrent=True)
443
 
        potemplate = potemplate_subset.getPOTemplateByTranslationDomain(
444
 
            translation_domain)
 
510
        # Normally we find the translation's template in the
 
511
        # source package or productseries where the translation was
 
512
        # uploaded.  Exactly one template should have the domain we're
 
513
        # looking for.
 
514
        potemplate = self.matchPOTemplateByDomain(
 
515
            translation_domain, sourcepackagename=self.sourcepackagename)
445
516
 
446
517
        is_for_distro = self.distroseries is not None
447
518
        know_package = (
450
521
            self.sourcepackagename.name == sourcepackagename.name)
451
522
 
452
523
        if potemplate is None and is_for_distro and not know_package:
453
 
            # The source package from where this translation doesn't have the
454
 
            # template that this translation needs it, and thus, we look for
455
 
            # it in a different source package as a second try. To do it, we
456
 
            # need to get a subset of all packages in current distro series.
457
 
            potemplate_subset = potemplateset.getSubset(
458
 
                distroseries=self.distroseries, iscurrent=True)
459
 
            potemplate = potemplate_subset.getPOTemplateByTranslationDomain(
460
 
                translation_domain)
 
524
            # This translation was uploaded to a source package, but the
 
525
            # package does not have the matching template.  Try finding
 
526
            # it elsewhere in the distribution.
 
527
            potemplate = self.matchPOTemplateByDomain(translation_domain)
461
528
 
462
529
        if potemplate is None:
463
530
            # The potemplate is not yet imported; we cannot attach this
1236
1303
 
1237
1304
        # Yay!  We have a POTemplate or POFile to import this entry
1238
1305
        # into.  Approve.
1239
 
        entry.setStatus(RosettaImportStatus.APPROVED,
1240
 
                        getUtility(ILaunchpadCelebrities).rosetta_experts)
 
1306
        entry.setStatus(
 
1307
            RosettaImportStatus.APPROVED,
 
1308
            getUtility(ILaunchpadCelebrities).rosetta_experts)
 
1309
        entry.setErrorOutput(None)
1241
1310
 
1242
1311
        return True
1243
1312