← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~stevenk/launchpad/remove-suggested-translations into lp:launchpad

 

Steve Kowalik has proposed merging lp:~stevenk/launchpad/remove-suggested-translations into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1013013 in Launchpad itself: "Timeout viewing my own translations"
  https://bugs.launchpad.net/launchpad/+bug/1013013

For more details, see:
https://code.launchpad.net/~stevenk/launchpad/remove-suggested-translations/+merge/131820

Remove ITranslationsPerson.suggestReviewableTranslationFiles() and the parts of Person:+translations that call it.

The slightly longer story is that in r16208, the query that is at the heart of ITranslationsPerson.getReviewableTranslationFiles() was rewritten to make use of 4 CTEs rather than 10 joins. This dropped it from taking over 1.5 seconds to about 11ms. The new query was written with one assumption at its core -- we have *lots* of pofiles, but translators themselves don't tend to touch many of them, so if we limit there first, we get a small result, and therefore a fast query.

The query in suggestReviewableTranslationFiles() on the other hand, can not abide that assumption at all. The very first thing is does is a anti-join because it wants a list of pofiles that the translator has never touched. This query is incredibly expensive, and I personally don't think it's worth the value of showing maybe 1 suggestion on Person:+translations if the query is going to take over 2 seconds to run -- or worse, cause a timeout.
-- 
https://code.launchpad.net/~stevenk/launchpad/remove-suggested-translations/+merge/131820
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/remove-suggested-translations into lp:launchpad.
=== modified file 'lib/lp/translations/browser/person.py'
--- lib/lp/translations/browser/person.py	2012-10-10 18:10:52 +0000
+++ lib/lp/translations/browser/person.py	2012-10-29 06:37:22 +0000
@@ -313,21 +313,6 @@
 
         return ReviewLinksAggregator().aggregate(pofiles)
 
-    def _suggestTargetsForReview(self, max_fetch):
-        """Find random translation targets for review.
-
-        :param max_fetch: Maximum number of `POFile`s to fetch while
-            looking for these.
-        :return: a list of at most `max_fetch` translation targets.
-            Multiple `POFile`s may be aggregated together into a single
-            target.
-        """
-        person = ITranslationsPerson(self.context)
-        pofiles = person.suggestReviewableTranslationFiles(
-            no_older_than=self.history_horizon)[:max_fetch]
-
-        return ReviewLinksAggregator().aggregate(pofiles)
-
     def _getTargetsForTranslation(self, max_fetch=None):
         """Get translation targets for this person to translate.
 
@@ -405,18 +390,9 @@
         # Start out with the translations that the person has recently
         # worked on.
         recent = self._review_targets
-        overall = self._addToTargetsList(
+        return self._addToTargetsList(
             [], recent, max_known_targets, list_length)
 
-        # Fill out the list with other, randomly suggested translations
-        # that the person could also be reviewing.
-        fetch = 5 * (list_length - len(overall))
-        suggestions = self._suggestTargetsForReview(fetch)
-        overall = self._addToTargetsList(
-            overall, suggestions, list_length, list_length)
-
-        return overall
-
     @cachedproperty
     def num_projects_and_packages_to_review(self):
         """How many translations do we suggest for reviewing?"""

=== modified file 'lib/lp/translations/browser/tests/test_persontranslationview.py'
--- lib/lp/translations/browser/tests/test_persontranslationview.py	2012-10-10 19:10:07 +0000
+++ lib/lp/translations/browser/tests/test_persontranslationview.py	2012-10-29 06:37:22 +0000
@@ -167,20 +167,13 @@
 
     def test_top_projects_and_packages_to_review(self):
         # top_projects_and_packages_to_review tries to name at least one
-        # translation target that the person has worked on, and at least
-        # one random suggestion that the person hasn't worked on.
+        # translation target that the person has worked on.
         self._makeReviewer()
         pofile_worked_on = self._makePOFiles(1, previously_worked_on=True)[0]
-        pofile_not_worked_on = self._makePOFiles(
-            1, previously_worked_on=False)[0]
-
         targets = self.view.top_projects_and_packages_to_review
 
         pofile_suffix = '/+translate?show=new_suggestions'
-        expected_links = [
-            canonical_url(pofile_worked_on) + pofile_suffix,
-            canonical_url(pofile_not_worked_on) + pofile_suffix,
-            ]
+        expected_links = [canonical_url(pofile_worked_on) + pofile_suffix]
         self.assertEqual(
             set(expected_links), set(item['link'] for item in targets))
 
@@ -221,29 +214,16 @@
         self.assertEqual(9, len(targets))
         self.assertEqual(9, len(set(item['link'] for item in targets)))
 
-    def test_top_p_n_p_to_review_caps_suggestions(self):
-        # top_projects_and_packages will suggest at most 10 POFiles that
-        # the person has not worked on.
-        self._makeReviewer()
-        self._makePOFiles(11, previously_worked_on=False)
-
-        targets = self.view.top_projects_and_packages_to_review
-
-        self.assertEqual(10, len(targets))
-        self.assertEqual(10, len(set(item['link'] for item in targets)))
-
     def test_top_p_n_p_to_review_caps_total(self):
-        # top_projects_and_packages will show at most 10 POFiles
-        # overall.  The last one will be a suggestion.
+        # top_projects_and_packages will show at most 9 POFiles
+        # overall.
         self._makeReviewer()
         pofiles_worked_on = self._makePOFiles(11, previously_worked_on=True)
-        pofiles_not_worked_on = self._makePOFiles(
-            11, previously_worked_on=False)
 
         targets = self.view.top_projects_and_packages_to_review
 
-        self.assertEqual(10, len(targets))
-        self.assertEqual(10, len(set(item['link'] for item in targets)))
+        self.assertEqual(9, len(targets))
+        self.assertEqual(9, len(set(item['link'] for item in targets)))
 
     def test_person_is_translator_false(self):
         # By default, a user is not a translator.

=== modified file 'lib/lp/translations/interfaces/translationsperson.py'
--- lib/lp/translations/interfaces/translationsperson.py	2011-12-24 16:54:44 +0000
+++ lib/lp/translations/interfaces/translationsperson.py	2012-10-29 06:37:22 +0000
@@ -1,8 +1,6 @@
 # Copyright 2009 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
-# pylint: disable-msg=E0213
-
 __metaclass__ = type
 __all__ = [
     'ITranslationsPerson',
@@ -61,16 +59,6 @@
             unreviewed `TranslationMessage` (oldest first).
         """
 
-    def suggestReviewableTranslationFiles(maximum):
-        """Suggest `POFile`s this person could review.
-
-        Unlike `getReviewableTranslationFiles`, this method looks for
-        arbitrary translations that the person has not worked on in the
-        recent past.
-
-        :param maximum: Maximum number of `POFile`s to return.
-        """
-
     def getTranslatableFiles(no_older_than=None, urgent_first=True):
         """List `POFile`s this person should be able to help translate.
 

=== modified file 'lib/lp/translations/model/translationsperson.py'
--- lib/lp/translations/model/translationsperson.py	2012-10-25 06:08:35 +0000
+++ lib/lp/translations/model/translationsperson.py	2012-10-29 06:37:22 +0000
@@ -160,22 +160,6 @@
                     '(SELECT * FROM translatable_distroseries)'))).config(
             distinct=True).order_by(POFile.date_changed)
 
-    def suggestReviewableTranslationFiles(self, no_older_than=None):
-        """See `ITranslationsPerson`."""
-        tables = self._composePOFileReviewerJoins()
-
-        # Pick files that this person has no recent POFileTranslator entry
-        # for.
-        translator_join, translator_condition = (
-            self._composePOFileTranslatorJoin(False, no_older_than))
-        tables.append(translator_join)
-
-        conditions = And(POFile.unreviewed_count > 0, translator_condition)
-
-        source = Store.of(self.person).using(*tables)
-        query = source.find(POFile, conditions)
-        return query.config(distinct=True).order_by(POFile.id)
-
     def _queryTranslatableFiles(self, worked_on, no_older_than=None,
                                 languages=None):
         """Get `POFile`s this person could help translate.

=== modified file 'lib/lp/translations/tests/test_translations_to_review.py'
--- lib/lp/translations/tests/test_translations_to_review.py	2012-01-01 02:58:52 +0000
+++ lib/lp/translations/tests/test_translations_to_review.py	2012-10-29 06:37:22 +0000
@@ -10,7 +10,7 @@
     timedelta,
     )
 
-from pytz import timezone
+from pytz import UTC
 import transaction
 from zope.security.proxy import removeSecurityProxy
 
@@ -23,9 +23,6 @@
 from lp.translations.model.translator import TranslatorSet
 
 
-UTC = timezone('UTC')
-
-
 class ReviewTestMixin:
     """Base for testing which translations a reviewer can review."""
 
@@ -99,12 +96,6 @@
         return list(person.getReviewableTranslationFiles(
             *args, **kwargs))
 
-    def _suggestReviewables(self, *args, **kwargs):
-        """Shorthand for `self.person.suggestReviewableTranslationFiles`."""
-        person = ITranslationsPerson(self.person)
-        return list(person.suggestReviewableTranslationFiles(
-            *args, **kwargs))
-
 
 class ReviewableTranslationFilesTest:
     """Test getReviewableTranslationFiles for a given setup.
@@ -190,69 +181,3 @@
     def setUp(self):
         super(TestReviewableDistroTranslationFiles, self).setUp()
         ReviewTestMixin.setUpMixin(self, for_product=False)
-
-
-class TestSuggestReviewableTranslationFiles(TestCaseWithFactory,
-                                            ReviewTestMixin):
-    """Test `Person.suggestReviewableTranslationFiles`."""
-    layer = DatabaseFunctionalLayer
-
-    def setUp(self):
-        super(TestSuggestReviewableTranslationFiles, self).setUp()
-        ReviewTestMixin.setUpMixin(self)
-
-    def _makeOtherPOFile(self, language_code='nl', same_group=True,
-                         with_unreviewed=True):
-        """Set up a `POFile` for an unrelated `POTemplate`."""
-        other_pofile = self.factory.makePOFile(language_code=language_code)
-        other_pofile = removeSecurityProxy(other_pofile)
-
-        product = other_pofile.potemplate.productseries.product
-        product.translations_usage = ServiceUsage.LAUNCHPAD
-
-        if with_unreviewed:
-            other_pofile.unreviewed_count = 1
-
-        if same_group:
-            product.translationgroup = self.translationgroup
-
-        return other_pofile
-
-    def test_suggestReviewableTranslationFiles_suggests_files(self):
-        # suggestReviewableTranslationFiles suggests translations to
-        # review.
-        other_pofile = self._makeOtherPOFile()
-        self.assertEqual([other_pofile], self._suggestReviewables())
-
-    def test_suggestReviewableTranslationFiles_is_complementary(self):
-        # suggestReviewableTranslationFiles does not suggest files that
-        # the person is already working on.
-        self.assertFalse(self.pofile in self._suggestReviewables())
-
-    def test_suggestReviewableTranslationFiles_ignores_old_involvement(self):
-        # After a person's involvement with a translation grows old
-        # enough, it becomes eligible for suggestion again.
-        poftset = POFileTranslatorSet()
-        involvement = poftset.getForPersonPOFile(self.person, self.pofile)
-        removeSecurityProxy(involvement).date_last_touched -= timedelta(366)
-        suggestions = self._suggestReviewables(
-            no_older_than=involvement.date_last_touched + timedelta(1))
-
-        self.assertEqual([self.pofile], suggestions)
-
-    def test_suggestReviewableTranslationFiles_no_translation_group(self):
-        # Only translations that fall under the same translation group
-        # are suggested.
-        other_pofile = self._makeOtherPOFile(same_group=False)
-        self.assertFalse(other_pofile in self._suggestReviewables())
-
-    def test_suggestReviewableTranslationFiles_ignores_other_languages(self):
-        # suggestReviewableTranslationFiles does not suggest files in
-        # languages that the person is not active in.
-        other_pofile = self._makeOtherPOFile(language_code='ban')
-        self.assertFalse(other_pofile in self._suggestReviewables())
-
-    def test_suggestReviewableTranslationFiles_checks_unreviewed(self):
-        # Translations without unreviewed suggestions are ignored.
-        other_pofile = self._makeOtherPOFile(with_unreviewed=False)
-        self.assertFalse(other_pofile in self._suggestReviewables())


Follow ups