← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/translation-import-queue-entry-dsp-vocab into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/translation-import-queue-entry-dsp-vocab into lp:launchpad with lp:~cjwatson/launchpad/potemplate-dsp-vocab as a prerequisite.

Commit message:
Convert TranslationImportQueueEntry:+index to use the DistributionSourcePackage picker if the appropriate feature flag is set.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #42298 in Launchpad itself: "package picker lists unpublished (invalid) packages"
  https://bugs.launchpad.net/launchpad/+bug/42298

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/translation-import-queue-entry-dsp-vocab/+merge/305509

Convert TranslationImportQueueEntry:+index to use the DistributionSourcePackage picker if the appropriate feature flag is set.

I believe this is the last of the view conversions.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/translation-import-queue-entry-dsp-vocab into lp:launchpad.
=== modified file 'lib/lp/translations/browser/tests/test_translationimportqueueentry.py'
--- lib/lp/translations/browser/tests/test_translationimportqueueentry.py	2014-02-19 04:01:46 +0000
+++ lib/lp/translations/browser/tests/test_translationimportqueueentry.py	2016-09-12 17:58:08 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010 Canonical Ltd.  This software is licensed under the
+# Copyright 2010-2016 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Unit tests for translation import queue views."""
@@ -6,12 +6,18 @@
 from datetime import datetime
 
 from pytz import timezone
+from testscenarios import (
+    load_tests_apply_scenarios,
+    WithScenarios,
+    )
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
 
 from lp.app.enums import ServiceUsage
+from lp.services.features.testing import FeatureFixture
 from lp.services.webapp import canonical_url
 from lp.testing import (
+    celebrity_logged_in,
     TestCase,
     TestCaseWithFactory,
     )
@@ -23,14 +29,23 @@
     )
 
 
-class TestTranslationImportQueueEntryView(TestCaseWithFactory):
+class TestTranslationImportQueueEntryView(WithScenarios, TestCaseWithFactory):
     """Tests for the queue entry review form."""
 
     layer = LaunchpadFunctionalLayer
 
+    scenarios = [
+        ("spn_picker", {"features": {}}),
+        ("dsp_picker", {
+            "features": {u"disclosure.dsp_picker.enabled": u"on"},
+            }),
+        ]
+
     def setUp(self):
         super(TestTranslationImportQueueEntryView, self).setUp(
             'foo.bar@xxxxxxxxxxxxx')
+        if self.features:
+            self.useFixture(FeatureFixture(self.features))
         self.queue = getUtility(ITranslationImportQueue)
         self.uploader = self.factory.makePerson()
 
@@ -201,6 +216,32 @@
 
         self.assertEqual(name, view.initial_values['name'])
 
+    def test_change_sourcepackage(self):
+        # Changing the source package is honoured.
+        series = self.factory.makeDistroSeries()
+        packagename = self.factory.makeSourcePackageName()
+        potemplate = self.factory.makePOTemplate(
+            distroseries=series, sourcepackagename=packagename)
+        entry = self._makeEntry(
+            distroseries=series, sourcepackagename=packagename,
+            potemplate=potemplate)
+        dsp = self.factory.makeDSPCache(distroseries=series)
+        form = {
+            'field.file_type': 'POT',
+            'field.path': entry.path,
+            'field.sourcepackagename': dsp.sourcepackagename.name,
+            'field.name': potemplate.name,
+            'field.translation_domain': potemplate.translation_domain,
+            'field.languagepack': '',
+            'field.actions.approve': 'Approve',
+            }
+        with celebrity_logged_in('rosetta_experts'):
+            view = create_initialized_view(entry, '+index', form=form)
+        self.assertEqual([], view.errors)
+        self.assertEqual(
+            dsp.sourcepackagename.name,
+            entry.potemplate.sourcepackagename.name)
+
 
 class TestEscapeJSString(TestCase):
     """Test `escape_js_string`."""
@@ -222,3 +263,6 @@
 
     def test_escape_js_string_ampersand(self):
         self.assertEqual('&', escape_js_string('&'))
+
+
+load_tests = load_tests_apply_scenarios

=== modified file 'lib/lp/translations/browser/translationimportqueue.py'
--- lib/lp/translations/browser/translationimportqueue.py	2015-07-08 16:05:11 +0000
+++ lib/lp/translations/browser/translationimportqueue.py	2016-09-12 17:58:08 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2010 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2016 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Browser views for `ITranslationImportQueue`."""
@@ -15,6 +15,7 @@
 
 import os
 
+from lazr.restful.interface import copy_field
 from zope.component import getUtility
 from zope.formlib.interfaces import ConversionError
 from zope.interface import implementer
@@ -26,6 +27,7 @@
 
 from lp.app.browser.launchpadform import (
     action,
+    custom_widget,
     LaunchpadFormView,
     )
 from lp.app.browser.tales import DateTimeFormatterAPI
@@ -34,9 +36,13 @@
     UnexpectedFormData,
     )
 from lp.app.validators.name import valid_name
+from lp.registry.interfaces.distributionsourcepackage import (
+    IDistributionSourcePackage,
+    )
 from lp.registry.interfaces.distroseries import IDistroSeries
 from lp.registry.interfaces.sourcepackage import ISourcePackageFactory
 from lp.services.database.constants import UTC_NOW
+from lp.services.features import getFeatureFlag
 from lp.services.webapp import (
     canonical_url,
     GetitemNavigation,
@@ -45,6 +51,9 @@
 from lp.translations.browser.hastranslationimports import (
     HasTranslationImportsView,
     )
+from lp.translations.browser.widgets.translationimportqueue import (
+    TranslationImportQueueEntrySourcePackageNameWidget,
+    )
 from lp.translations.enums import RosettaImportStatus
 from lp.translations.interfaces.pofile import IPOFileSet
 from lp.translations.interfaces.potemplate import IPOTemplateSet
@@ -85,10 +94,28 @@
     usedfor = ITranslationImportQueueEntry
 
 
+class IEditTranslationImportQueueEntryDSP(IEditTranslationImportQueueEntry):
+
+    sourcepackagename = copy_field(
+        IEditTranslationImportQueueEntry['sourcepackagename'],
+        vocabularyName='DistributionSourcePackage')
+
+
 class TranslationImportQueueEntryView(LaunchpadFormView):
     """The view part of admin interface for the translation import queue."""
     label = "Review import queue entry"
-    schema = IEditTranslationImportQueueEntry
+
+    @property
+    def schema(self):
+        """See `LaunchpadFormView`."""
+        if bool(getFeatureFlag('disclosure.dsp_picker.enabled')):
+            return IEditTranslationImportQueueEntryDSP
+        else:
+            return IEditTranslationImportQueueEntry
+
+    custom_widget(
+        'sourcepackagename',
+        TranslationImportQueueEntrySourcePackageNameWidget)
 
     max_series_to_display = 3
 
@@ -101,7 +128,7 @@
         if self.request.method == 'POST':
             # We got a form post, we don't need to do any initialization.
             return field_values
-        # Fill the know values.
+        # Fill in the known values.
         field_values['path'] = self.context.path
 
         importer = getUtility(ITranslationImporter)
@@ -418,6 +445,10 @@
             self.setFieldError('file_type', 'Please specify the file type')
             return
 
+        sourcepackagename = data.get('sourcepackagename')
+        if IDistributionSourcePackage.providedBy(sourcepackagename):
+            data['sourcepackagename'] = sourcepackagename.sourcepackagename
+
         self.path_changed = self._validatePath(file_type, data.get('path'))
 
         self.man_potemplate = None

=== added file 'lib/lp/translations/browser/widgets/tests/test_translationimportqueue.py'
--- lib/lp/translations/browser/widgets/tests/test_translationimportqueue.py	1970-01-01 00:00:00 +0000
+++ lib/lp/translations/browser/widgets/tests/test_translationimportqueue.py	2016-09-12 17:58:08 +0000
@@ -0,0 +1,78 @@
+# Copyright 2016 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Test the TranslationImportQueueEntry widget."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+
+from testscenarios import (
+    load_tests_apply_scenarios,
+    WithScenarios,
+    )
+
+from lp.services.features.testing import FeatureFixture
+from lp.services.webapp.servers import LaunchpadTestRequest
+from lp.testing import TestCaseWithFactory
+from lp.testing.layers import LaunchpadFunctionalLayer
+from lp.translations.browser.translationimportqueue import (
+    IEditTranslationImportQueueEntryDSP,
+    )
+from lp.translations.browser.widgets.translationimportqueue import (
+    TranslationImportQueueEntrySourcePackageNameWidget,
+    )
+from lp.translations.interfaces.translationimportqueue import (
+    IEditTranslationImportQueueEntry,
+    )
+
+
+class TestTranslationImportQueueEntrySourcePackageNameWidget(
+    WithScenarios, TestCaseWithFactory):
+
+    layer = LaunchpadFunctionalLayer
+
+    scenarios = [
+        ("spn_picker", {
+            "features": {},
+            "interface": IEditTranslationImportQueueEntry,
+            }),
+        ("dsp_picker", {
+            "features": {u"disclosure.dsp_picker.enabled": u"on"},
+            "interface": IEditTranslationImportQueueEntryDSP,
+            }),
+        ]
+
+    def setUp(self):
+        super(
+            TestTranslationImportQueueEntrySourcePackageNameWidget,
+            self).setUp()
+        if self.features:
+            self.useFixture(FeatureFixture(self.features))
+
+    def makeWidget(self, entry, form=None):
+        field = self.interface["sourcepackagename"]
+        bound_field = field.bind(entry)
+        request = LaunchpadTestRequest(form=form)
+        return TranslationImportQueueEntrySourcePackageNameWidget(
+            bound_field, bound_field.vocabulary, request)
+
+    def test_productseries(self):
+        productseries = self.factory.makeProductSeries()
+        entry = self.factory.makeTranslationImportQueueEntry(
+            productseries=productseries)
+        widget = self.makeWidget(entry)
+        self.assertIsNone(widget.getDistribution())
+        self.assertEqual("", widget.distribution_name)
+
+    def test_distroseries(self):
+        distroseries = self.factory.makeDistroSeries()
+        entry = self.factory.makeTranslationImportQueueEntry(
+            distroseries=distroseries)
+        widget = self.makeWidget(entry)
+        self.assertEqual(distroseries.distribution, widget.getDistribution())
+        self.assertEqual(
+            distroseries.distribution.name, widget.distribution_name)
+
+
+load_tests = load_tests_apply_scenarios

=== added file 'lib/lp/translations/browser/widgets/translationimportqueue.py'
--- lib/lp/translations/browser/widgets/translationimportqueue.py	1970-01-01 00:00:00 +0000
+++ lib/lp/translations/browser/widgets/translationimportqueue.py	2016-09-12 17:58:08 +0000
@@ -0,0 +1,34 @@
+# Copyright 2016 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Widgets related to `TranslationImportQueueEntry`."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+    "TranslationImportQueueEntrySourcePackageNameWidget",
+    ]
+
+from lp.app.widgets.popup import SourcePackageNameWidgetBase
+
+
+class TranslationImportQueueEntrySourcePackageNameWidget(
+    SourcePackageNameWidgetBase):
+    """A widget for associating a TranslationImportQueueEntry with an SPN."""
+
+    @property
+    def distribution_name(self):
+        distribution = self.getDistribution()
+        if distribution is not None:
+            return distribution.name
+        else:
+            return ''
+
+    def getDistribution(self):
+        """See `SourcePackageNameWidgetBase`."""
+        distroseries = self.context.context.distroseries
+        if distroseries is not None:
+            return distroseries.distribution
+        else:
+            return None


Follow ups