← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~abentley/launchpad/refactor-migration into lp:launchpad

 

Aaron Bentley has proposed merging lp:~abentley/launchpad/refactor-migration into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~abentley/launchpad/refactor-migration/+merge/49086

= Summary =
Make message-sharing-migration script reusable for when new Packagings are
created.

== Proposed fix ==
Extract a TranslationMerger from the message-sharing-migration script that can
be reused in a TranslationMerge Job.

== Pre-implementation notes ==
None

== Implementation details ==
I made some style changes along the way, e.g. marking methods as classmethods
or staticmethods if they didn't use instance variables.  I also switched from
"record_statements" to StormStatementRecorder, which I find more readable.

Even though I renamed scripts/message_sharing_migration.py to
translationmerger.py, I kept the MessageSharingMerge class in the same file, to
make the actual changes more obvious, and to retain annotation history.

I also extracted a TransactionManager class, because otherwise, both the
MessageSharingMerge and the TranslationMerger would have needed to provide this
kind of functionality.

== Tests ==
bin/test -vt test_translationmerger -t message-sharing-merge-script.txt


== Demo and Q/A ==
None; refactoring


= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/translations/tests/test_translationmerger.py
  lib/lp/translations/translationmerger.py
  scripts/rosetta/message-sharing-merge.py

./scripts/rosetta/message-sharing-merge.py
      10: '_pythonpath' imported but unused
      24: E303 too many blank lines (3)
-- 
https://code.launchpad.net/~abentley/launchpad/refactor-migration/+merge/49086
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~abentley/launchpad/refactor-migration into lp:launchpad.
=== renamed file 'lib/lp/translations/scripts/tests/test_message_sharing_migration.py' => 'lib/lp/translations/tests/test_translationmerger.py'
--- lib/lp/translations/scripts/tests/test_message_sharing_migration.py	2011-01-26 19:28:48 +0000
+++ lib/lp/translations/tests/test_translationmerger.py	2011-02-09 16:43:57 +0000
@@ -15,7 +15,7 @@
 from canonical.testing.layers import LaunchpadZopelessLayer
 from lp.services.worlddata.interfaces.language import ILanguageSet
 from lp.testing import (
-    record_statements,
+    StormStatementRecorder,
     TestCaseWithFactory,
     )
 from lp.testing.sampledata import ADMIN_EMAIL
@@ -23,8 +23,10 @@
 from lp.translations.model.pomsgid import POMsgID
 from lp.translations.model.potemplate import POTemplate
 from lp.translations.model.potranslation import POTranslation
-from lp.translations.scripts.message_sharing_migration import (
+from lp.translations.translationmerger import (
     MessageSharingMerge,
+    TransactionManager,
+    TranslationMerger,
     )
 
 
@@ -53,6 +55,8 @@
 
         self.script = MessageSharingMerge('tms-merging-test', test_args=[])
         self.script.logger.setLevel(ERROR)
+        tm = TransactionManager(self.script.txn, self.script.options.dry_run)
+        self.merger = TranslationMerger(self.templates, tm)
 
 
 class TestPOTMsgSetMerging(TestCaseWithFactory, TranslatableProductMixin):
@@ -76,7 +80,7 @@
         stable_potmsgset = self.factory.makePOTMsgSet(
             self.stable_template, singular='foo', sequence=1)
 
-        self.script._mergePOTMsgSets(self.templates)
+        self.merger.mergePOTMsgSets()
 
         trunk_messages = list(self.trunk_template.getPOTMsgSets(False))
         stable_messages = list(self.stable_template.getPOTMsgSets(False))
@@ -92,8 +96,8 @@
         stable_potmsgset = self.factory.makePOTMsgSet(
             self.stable_template, singular='foo', sequence=1)
 
-        self.script._mergePOTMsgSets(self.templates)
-        self.script._mergePOTMsgSets(self.templates)
+        self.merger.mergePOTMsgSets()
+        self.merger.mergePOTMsgSets()
 
         trunk_messages = list(self.trunk_template.getPOTMsgSets(False))
         stable_messages = list(self.stable_template.getPOTMsgSets(False))
@@ -108,7 +112,7 @@
         stable_potmsgset = self.factory.makePOTMsgSet(
             self.stable_template, singular='foo', context='bar', sequence=1)
 
-        self.script._mergePOTMsgSets(self.templates)
+        self.merger.mergePOTMsgSets()
 
         trunk_messages = list(self.trunk_template.getPOTMsgSets(False))
         stable_messages = list(self.stable_template.getPOTMsgSets(False))
@@ -125,7 +129,7 @@
         self.factory.makePOTMsgSet(
             self.stable_template, singular='foo', sequence=9)
 
-        self.script._mergePOTMsgSets(self.templates)
+        self.merger.mergePOTMsgSets()
 
         trunk_potmsgset = self.trunk_template.getPOTMsgSetByMsgIDText('foo')
         stable_potmsgset = self.stable_template.getPOTMsgSetByMsgIDText('foo')
@@ -251,7 +255,7 @@
          * Two templates for the "trunk" and "stable" release series.
          * Matching POTMsgSets for the string "foo" in each.
 
-        The matching POTMsgSets will be merged by the _mergePOTMsgSets
+        The matching POTMsgSets will be merged by the mergePOTMsgSets
         call.
         """
         super(TestPOTMsgSetMergingAndTranslations, self).setUp(
@@ -267,7 +271,7 @@
         trunk_message.is_current_upstream = True
         stable_message.is_current_upstream = True
 
-        self.script._mergePOTMsgSets(self.templates)
+        self.merger.mergePOTMsgSets()
 
         self.assertEqual(self._getTranslations(), ('bar', 'splat'))
         self.assertEqual(self._getMessages(), (trunk_message, stable_message))
@@ -281,7 +285,7 @@
         trunk_message.is_current_upstream = True
         stable_message.is_current_upstream = True
 
-        self.script._mergePOTMsgSets(self.templates)
+        self.merger.mergePOTMsgSets()
 
         self.assertEqual(self._getTranslations(), ('bar', 'bar'))
 
@@ -294,7 +298,7 @@
         trunk_message.is_current_upstream = True
         stable_message.is_current_upstream = True
 
-        self.script._mergePOTMsgSets(self.templates)
+        self.merger.mergePOTMsgSets()
 
         # The POTMsgSets are now merged.
         potmsgset = self.trunk_template.getPOTMsgSetByMsgIDText('foo')
@@ -317,7 +321,7 @@
         trunk_message.is_current_upstream = False
         stable_message.is_current_upstream = False
 
-        self.script._mergePOTMsgSets(self.templates)
+        self.merger.mergePOTMsgSets()
 
         # Having these suggestions does not mean that there are current
         # translations.
@@ -331,7 +335,7 @@
         trunk_message.is_current_upstream = True
         stable_message.is_current_upstream = True
 
-        self.script._mergePOTMsgSets(self.templates)
+        self.merger.mergePOTMsgSets()
 
         trunk_message, stable_message = self._getMessages()
         self.assertEqual(trunk_message.potemplate, None)
@@ -356,7 +360,7 @@
 
         self.assertEqual(self._getTranslations(), ('bzo', 'smurf'))
 
-        self.script._mergePOTMsgSets(self.templates)
+        self.merger.mergePOTMsgSets()
 
         # The current translations stay as they are.
         self.assertEqual(self._getTranslations(), ('bzo', 'smurf'))
@@ -386,7 +390,7 @@
         # be.
         self._makeTranslationMessages('x', 'x')
 
-        self.script._mergeTranslationMessages(self.templates)
+        self.merger.mergeTranslationMessages()
 
         trunk_message, stable_message = self._getMessages()
         self.assertNotEqual(trunk_message, stable_message)
@@ -414,8 +418,8 @@
         self._makeTranslationMessages(
             'a', 'b', trunk_diverged=True, stable_diverged=True)
 
-        self.script._mergePOTMsgSets(self.templates)
-        self.script._mergeTranslationMessages(self.templates)
+        self.merger.mergePOTMsgSets()
+        self.merger.mergeTranslationMessages()
 
         # Translations for the existing templates stay as they are.
         self.assertEqual(self._getTranslations(), ('a', 'b'))
@@ -430,8 +434,8 @@
         self._makeTranslationMessages(
             'x', 'x', trunk_diverged=True, stable_diverged=True)
 
-        self.script._mergePOTMsgSets(self.templates)
-        self.script._mergeTranslationMessages(self.templates)
+        self.merger.mergePOTMsgSets()
+        self.merger.mergeTranslationMessages()
 
         trunk_message, stable_message = self._getMessages()
         self.assertEqual(trunk_message, stable_message)
@@ -453,8 +457,8 @@
         trunk_message.is_current_upstream = False
         stable_message.is_current_upstream = False
 
-        self.script._mergePOTMsgSets(self.templates)
-        self.script._mergeTranslationMessages(self.templates)
+        self.merger.mergePOTMsgSets()
+        self.merger.mergeTranslationMessages()
 
         # Translations for the existing templates stay as they are.
         self.assertEqual(self._getTranslations(), (None, None))
@@ -470,8 +474,8 @@
         self._makeTranslationMessages(
             'ips', 'unq', trunk_diverged=True, stable_diverged=False)
 
-        self.script._mergePOTMsgSets(self.templates)
-        self.script._mergeTranslationMessages(self.templates)
+        self.merger.mergePOTMsgSets()
+        self.merger.mergeTranslationMessages()
 
         # Translations for the existing templates stay as they are.
         self.assertEqual(self._getTranslations(), ('ips', 'unq'))
@@ -491,8 +495,8 @@
 
         self.assertEqual(self._getTranslations(), ('n', None))
 
-        self.script._mergePOTMsgSets(self.templates)
-        self.script._mergeTranslationMessages(self.templates)
+        self.merger.mergePOTMsgSets()
+        self.merger.mergeTranslationMessages()
 
         # The less-representative POTMsgSet gains a translation, because
         # it now uses the shared translation.
@@ -553,8 +557,8 @@
         # Now the migration script runs.  This also carries the
         # POFileTranslator record for stable_message into trunk_pofile.
         # The one for contented_message disappears in the process.
-        self.script._mergePOTMsgSets(self.templates)
-        self.script._mergeTranslationMessages(self.templates)
+        self.merger.mergePOTMsgSets()
+        self.merger.mergeTranslationMessages()
 
         poft = poftset.getForPersonPOFile(translator, self.trunk_pofile)
         self.assertEqual(poft.latest_message, stable_message)
@@ -591,7 +595,7 @@
         tms = set(potmsgset.getAllTranslationMessages())
         self.assertEqual(tms, set([trunk_message, stable_message]))
 
-        self.script._removeDuplicateMessages(self.templates)
+        self.merger._removeDuplicateMessages()
 
         # The duplicates have been cleaned up.
         self.assertEqual(potmsgset.getAllTranslationMessages().count(), 1)
@@ -611,7 +615,7 @@
             pofile=self.trunk_pofile, potmsgset=self.trunk_potmsgset,
             text='gbzidh', diverged=False)
 
-        self.script._scrubPOTMsgSetTranslations(self.trunk_potmsgset)
+        self.merger._scrubPOTMsgSetTranslations(self.trunk_potmsgset)
 
         message1, message2 = self._getMessages()
         self.assertIsNot(None, message1)
@@ -634,7 +638,7 @@
         message2.potemplate = self.trunk_template
         ids = (message1.id, message2.id)
 
-        self.script._scrubPOTMsgSetTranslations(self.trunk_potmsgset)
+        self.merger._scrubPOTMsgSetTranslations(self.trunk_potmsgset)
 
         message, no_message = self._getMessages()
 
@@ -654,7 +658,7 @@
         # potmsgset.
         trunk_message, stable_message = self._makeTranslationMessages(
             'ex', 'why', trunk_diverged=False, stable_diverged=False)
-        ubuntu_clash, upstream_clash, twin = self.script._findClashes(
+        ubuntu_clash, upstream_clash, twin = self.merger._findClashes(
             stable_message, self.trunk_potmsgset, None)
 
         # Moving stable_message fully into trunk would clash with
@@ -677,7 +681,7 @@
             message.is_current_upstream = False
             message.is_current_ubuntu = True
 
-        ubuntu_clash, upstream_clash, twin = self.script._findClashes(
+        ubuntu_clash, upstream_clash, twin = self.merger._findClashes(
             stable_message, self.trunk_potmsgset, None)
 
         self.assertEqual(upstream_clash, None)
@@ -691,7 +695,7 @@
             'klob', 'klob', trunk_diverged=False, stable_diverged=False)
         trunk_message.is_current_upstream = False
 
-        ubuntu_clash, upstream_clash, twin = self.script._findClashes(
+        ubuntu_clash, upstream_clash, twin = self.merger._findClashes(
             stable_message, self.trunk_potmsgset, None)
 
         self.assertEqual(upstream_clash, None)
@@ -704,7 +708,7 @@
         trunk_message, stable_message = self._makeTranslationMessages(
             'sniw', 'sniw', trunk_diverged=False, stable_diverged=False)
 
-        ubuntu_clash, upstream_clash, twin = self.script._findClashes(
+        ubuntu_clash, upstream_clash, twin = self.merger._findClashes(
             stable_message, self.trunk_potmsgset, None)
 
         self.assertEqual(upstream_clash, None)
@@ -720,7 +724,7 @@
         current_message = self._makeTranslationMessage(
             self.trunk_pofile, self.trunk_potmsgset, 'gah', False)
 
-        ubuntu_clash, upstream_clash, twin = self.script._findClashes(
+        ubuntu_clash, upstream_clash, twin = self.merger._findClashes(
             stable_message, self.trunk_potmsgset, None)
 
         self.assertEqual(upstream_clash, current_message)
@@ -788,17 +792,19 @@
         self._resetReferences()
         self.assertNotEqual([], self.templates)
 
-        _ignored, statements = record_statements(
-            self.script._mergePOTMsgSets, self.templates)
-        self.assertNoStatementsInvolvingTable(POMsgID._table, statements)
-        self.assertNoStatementsInvolvingTable(
-            POTranslation._table, statements)
+        with StormStatementRecorder() as recorder:
+            self.merger.mergePOTMsgSets()
+        self.assertNoStatementsInvolvingTable(
+            POMsgID._table, recorder.statements)
+        self.assertNoStatementsInvolvingTable(
+            POTranslation._table, recorder.statements)
 
-        _ignored, statements = record_statements(
-            self.script._mergeTranslationMessages, self.templates)
-        self.assertNoStatementsInvolvingTable(POMsgID._table, statements)
-        self.assertNoStatementsInvolvingTable(
-            POTranslation._table, statements)
+        with StormStatementRecorder() as recorder:
+            self.merger.mergeTranslationMessages()
+        self.assertNoStatementsInvolvingTable(
+            POMsgID._table, recorder.statements)
+        self.assertNoStatementsInvolvingTable(
+            POTranslation._table, recorder.statements)
 
 
 def test_suite():

=== renamed file 'lib/lp/translations/scripts/message_sharing_migration.py' => 'lib/lp/translations/translationmerger.py'
--- lib/lp/translations/scripts/message_sharing_migration.py	2011-01-26 19:28:48 +0000
+++ lib/lp/translations/translationmerger.py	2011-02-09 16:43:57 +0000
@@ -1,9 +1,11 @@
-# Copyright 2009-2010 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 __metaclass__ = type
 __all__ = [
     'MessageSharingMerge',
+    'TransactionManager',
+    'TranslationMerger',
     ]
 
 
@@ -266,32 +268,54 @@
         class_count = len(equivalence_classes)
         log.info("Merging %d template equivalence classes." % class_count)
 
+        tm = TransactionManager(self.txn, self.options.dry_run)
         for number, name in enumerate(sorted(equivalence_classes.iterkeys())):
             templates = equivalence_classes[name]
             log.info(
                 "Merging equivalence class '%s': %d template(s) (%d / %d)" % (
                     name, len(templates), number + 1, class_count))
             log.debug("Templates: %s" % str(templates))
-
+            merger = TranslationMerger(templates, tm)
             if self.options.remove_duplicates:
                 log.info("Removing duplicate messages.")
-                self._removeDuplicateMessages(templates)
-                self._endTransaction(intermediate=True)
+                merger.removeDuplicateMessages()
+                tm.endTransaction(intermediate=True)
 
             if self.options.merge_potmsgsets:
                 log.info("Merging POTMsgSets.")
-                self._mergePOTMsgSets(templates)
-                self._endTransaction(intermediate=True)
+                merger.mergePOTMsgSets()
+                tm.endTransaction(intermediate=True)
 
             if self.options.merge_translationmessages:
                 log.info("Merging TranslationMessages.")
-                self._mergeTranslationMessages(templates)
+                merger.mergeTranslationMessages()
 
-            self._endTransaction()
+            tm.endTransaction()
 
         log.info("Done.")
 
-    def _endTransaction(self, intermediate=False):
+
+class TransactionManager:
+    """Manage transactions for script runs.
+
+    For normal operation, every tenth intermediate transaction is actually
+    committed.  At the end, the final transaction is committed.
+
+    For dry runs, no transactions are committed and the final transaction is
+    aborted.
+    """
+
+    def __init__(self, txn, dry_run):
+        """Constructor.
+
+        :param txn: The transaction to commit or abort.
+        :param dry_run: If true, this is a dry run.
+        """
+        self.txn = txn
+        self.dry_run = dry_run
+        self.commit_count = 0
+
+    def endTransaction(self, intermediate=False):
         """End this transaction and start a new one.
 
         :param intermediate: Whether this is an intermediate commit.
@@ -308,38 +332,49 @@
         if intermediate and self.commit_count % 10 != 0:
             return
 
-        if self.options.dry_run:
+        if self.dry_run:
             if not intermediate:
                 self.txn.abort()
         else:
             self.txn.commit()
 
-    def _removeDuplicateMessages(self, potemplates):
+
+class TranslationMerger:
+    """Merge translations across a set of potemplates."""
+
+    def __init__(self, potemplates, tm):
+        """Constructor.
+
+        :param potemplates: The templates to merge across.
+        """
+        self.template_set = getUtility(IPOTemplateSet)
+        self.compare_template_precedence = (
+            self.template_set.compareSharingPrecedence)
+        self.potemplates = potemplates
+        self.tm = tm
+
+    def _removeDuplicateMessages(self):
         """Get rid of duplicate `TranslationMessages` where needed."""
-        self._setUpUtilities()
-
         representatives = {}
         order_check = OrderingCheck(cmp=self.compare_template_precedence)
 
-        for template in potemplates:
+        for template in self.potemplates:
             order_check.check(template)
             for potmsgset in template.getPOTMsgSets(False, prefetch=False):
                 key = get_potmsgset_key(potmsgset)
                 if key not in representatives:
                     representatives[key] = potmsgset.id
 
-        self._endTransaction(intermediate=True)
+        self.tm.endTransaction(intermediate=True)
 
         for representative_id in representatives.itervalues():
             representative = POTMsgSet.get(representative_id)
             self._scrubPOTMsgSetTranslations(representative)
-            self._endTransaction(intermediate=True)
+            self.tm.endTransaction(intermediate=True)
 
-    def _mapRepresentatives(self, potemplates):
+    def _mapRepresentatives(self):
         """Map out POTMsgSets' subordinates and templates.
 
-        :param potemplates: An equivalence class of `POTemplate`s to
-            sort out.
         :return: A tuple of dicts.  The first maps each `POTMsgSet`'s
             key (as returned by `get_potmsgset_key`) to a list of its
             subordinate `POTMsgSet`s.  The second maps each
@@ -364,7 +399,7 @@
         # key we find, the first POTMsgSet is the representative one.
         order_check = OrderingCheck(cmp=self.compare_template_precedence)
 
-        for template in potemplates:
+        for template in self.potemplates:
             order_check.check(template)
             for potmsgset in template.getPOTMsgSets(False, prefetch=False):
                 key = get_potmsgset_key(potmsgset)
@@ -379,12 +414,9 @@
 
         return subordinates, representative_templates
 
-    def _mergePOTMsgSets(self, potemplates):
+    def mergePOTMsgSets(self):
         """Merge POTMsgSets for given sequence of sharing templates."""
-        self._setUpUtilities()
-
-        subordinates, representative_templates = self._mapRepresentatives(
-            potemplates)
+        subordinates, representative_templates = self._mapRepresentatives()
 
         num_representatives = len(subordinates)
         representative_num = 0
@@ -446,7 +478,7 @@
                 removeSecurityProxy(subordinate).destroySelf()
                 potmsgset_deletions += 1
 
-                self._endTransaction(intermediate=True)
+                self.tm.endTransaction(intermediate=True)
 
             report = "Deleted POTMsgSets: %d.  TranslationMessages: %d." % (
                 potmsgset_deletions, tm_deletions)
@@ -455,19 +487,19 @@
             else:
                 log.log(DEBUG2, report)
 
-    def _getPOTMsgSetIds(self, template):
+    @staticmethod
+    def _getPOTMsgSetIds(template):
         """Get list of ids for `template`'s `POTMsgSet`s."""
         return [
             potmsgset.id
             for potmsgset in template.getPOTMsgSets(False, prefetch=False)]
 
-    def _mergeTranslationMessages(self, potemplates):
+    def mergeTranslationMessages(self):
         """Share `TranslationMessage`s between templates where possible."""
-        self._setUpUtilities()
         order_check = OrderingCheck(cmp=self.compare_template_precedence)
-        for template_number, template in enumerate(potemplates):
+        for template_number, template in enumerate(self.potemplates):
             log.info("Merging template %d/%d." % (
-                template_number + 1, len(potemplates)))
+                template_number + 1, len(self.potemplates)))
             deletions = 0
             order_check.check(template)
             potmsgset_ids = self._getPOTMsgSetIds(template)
@@ -483,7 +515,7 @@
                         message = TranslationMessage.get(id)
                         removeSecurityProxy(message).shareIfPossible()
 
-                self._endTransaction(intermediate=True)
+                self.tm.endTransaction(intermediate=True)
 
                 after = potmsgset.getAllTranslationMessages().count()
                 deletions += max(0, before - after)
@@ -494,7 +526,8 @@
             else:
                 log.log(DEBUG2, report)
 
-    def _getPOTMsgSetTranslationMessageKey(self, tm):
+    @staticmethod
+    def _getPOTMsgSetTranslationMessageKey(tm):
         """Return tuple that identifies a TranslationMessage in a POTMsgSet.
 
         A TranslationMessage is identified by (potemplate, potmsgset,
@@ -509,7 +542,8 @@
 
         return (tm.potemplateID, tm.languageID) + msgstr_ids
 
-    def _partitionTranslationMessageIds(self, potmsgset):
+    @staticmethod
+    def _partitionTranslationMessageIds(potmsgset):
         """Partition `TranslationMessage`s by language.
 
         Only the ids are stored, not the `TranslationMessage` objects
@@ -545,7 +579,7 @@
         # migration phase can be scrapped.
         ids_per_language = self._partitionTranslationMessageIds(potmsgset)
 
-        self._endTransaction(intermediate=True)
+        self.tm.endTransaction(intermediate=True)
 
         deletions = 0
 
@@ -577,7 +611,7 @@
                 else:
                     translations[key] = tm
 
-            self._endTransaction(intermediate=True)
+            self.tm.endTransaction(intermediate=True)
 
         report = "Deleted TranslationMessages: %d" % deletions
         if deletions > 0:
@@ -585,7 +619,8 @@
         else:
             log.log(DEBUG2, report)
 
-    def _findClashes(self, message, target_potmsgset, target_potemplate):
+    @staticmethod
+    def _findClashes(message, target_potmsgset, target_potemplate):
         """What would clash if we moved `message` to the target environment?
 
         A clash can be either `message` being current when the target
@@ -646,7 +681,8 @@
         # have to go.
         return False
 
-    def _divergeTo(self, message, target_potmsgset, target_potemplate):
+    @classmethod
+    def _divergeTo(cls, message, target_potmsgset, target_potemplate):
         """Attempt to save `message` by diverging to `target_potemplate`.
 
         :param message: a TranslationMessage to save by diverging.
@@ -658,7 +694,7 @@
             True, you're done with `message`.  If False, you'll have to
             find another place for it.
         """
-        clashing_current, clashing_imported, twin = self._findClashes(
+        clashing_current, clashing_imported, twin = cls._findClashes(
             message, target_potmsgset, target_potemplate)
 
         if clashing_current is not None or clashing_imported is not None:

=== modified file 'scripts/rosetta/message-sharing-merge.py'
--- scripts/rosetta/message-sharing-merge.py	2010-04-27 19:48:39 +0000
+++ scripts/rosetta/message-sharing-merge.py	2011-02-09 16:43:57 +0000
@@ -9,7 +9,7 @@
 
 import _pythonpath
 
-from lp.translations.scripts.message_sharing_migration import (
+from lp.translations.translationmerger import (
     MessageSharingMerge)
 
 # This script merges POTMsgSets for sharing POTemplates.  This involves