launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #24863
[Merge] ~cjwatson/launchpad:stormify-translationimportqueueentry into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:stormify-translationimportqueueentry into launchpad:master.
Commit message:
Convert TranslationImportQueueEntry to Storm
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/385638
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-translationimportqueueentry into launchpad:master.
diff --git a/lib/lp/services/database/stormexpr.py b/lib/lp/services/database/stormexpr.py
index 38bc533..37772f1 100644
--- a/lib/lp/services/database/stormexpr.py
+++ b/lib/lp/services/database/stormexpr.py
@@ -16,6 +16,8 @@ __all__ = [
'Greatest',
'get_where_for_reference',
'IsDistinctFrom',
+ 'IsFalse',
+ 'IsTrue',
'NullCount',
'NullsFirst',
'NullsLast',
@@ -212,6 +214,26 @@ class ArrayIntersects(CompoundOper):
oper = "&&"
+class IsTrue(SuffixExpr):
+ """True iff the input Boolean expression is `TRUE`.
+
+ Unlike `expr` or `expr == True`, this returns `FALSE` when
+ `expr IS NULL`.
+ """
+ __slots__ = ()
+ suffix = "IS TRUE"
+
+
+class IsFalse(SuffixExpr):
+ """True iff the input Boolean expression is `FALSE`.
+
+ Unlike `Not(expr)` or `expr == False`, this returns `FALSE` when
+ `expr IS NULL`.
+ """
+ __slots__ = ()
+ suffix = "IS FALSE"
+
+
class IsDistinctFrom(CompoundOper):
"""True iff the left side is distinct from the right side."""
__slots__ = ()
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index c04041d..d1cb161 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -3417,7 +3417,7 @@ class BareLaunchpadObjectFactory(ObjectFactory):
by_maintainer=False):
"""Create a `TranslationImportQueueEntry`."""
if path is None:
- path = self.getUniqueString() + '.pot'
+ path = self.getUniqueUnicode() + '.pot'
for_distro = not (distroseries is None and sourcepackagename is None)
for_project = productseries is not None
@@ -3441,7 +3441,7 @@ class BareLaunchpadObjectFactory(ObjectFactory):
uploader = self.makePerson()
if content is None:
- content = self.getUniqueString()
+ content = self.getUniqueBytes()
if format is None:
format = TranslationFileFormat.PO
@@ -3449,8 +3449,7 @@ class BareLaunchpadObjectFactory(ObjectFactory):
if status is None:
status = RosettaImportStatus.NEEDS_REVIEW
- if type(content) == unicode:
- content = content.encode('utf-8')
+ content = six.ensure_binary(content)
entry = getUtility(ITranslationImportQueue).addOrUpdateEntry(
path=path, content=content, by_maintainer=by_maintainer,
diff --git a/lib/lp/translations/browser/hastranslationimports.py b/lib/lp/translations/browser/hastranslationimports.py
index fe55038..c73bd82 100644
--- a/lib/lp/translations/browser/hastranslationimports.py
+++ b/lib/lp/translations/browser/hastranslationimports.py
@@ -3,6 +3,8 @@
"""Browser view for IHasTranslationImports."""
+from __future__ import absolute_import, print_function, unicode_literals
+
__metaclass__ = type
__all__ = [
diff --git a/lib/lp/translations/browser/tests/pofile-views.txt b/lib/lp/translations/browser/tests/pofile-views.txt
index 5d504d2..2221e92 100644
--- a/lib/lp/translations/browser/tests/pofile-views.txt
+++ b/lib/lp/translations/browser/tests/pofile-views.txt
@@ -403,7 +403,7 @@ Get it and check that some attributes are set as they should.
>>> from lp.translations.enums import RosettaImportStatus
>>> entry = translationimportqueue.getAllEntries(
- ... import_status=RosettaImportStatus.NEEDS_REVIEW)[-1]
+ ... import_status=RosettaImportStatus.NEEDS_REVIEW).last()
>>> entry.pofile == pofile_es
True
diff --git a/lib/lp/translations/browser/tests/potemplate-views.txt b/lib/lp/translations/browser/tests/potemplate-views.txt
index 5ada83e..712ca5a 100644
--- a/lib/lp/translations/browser/tests/potemplate-views.txt
+++ b/lib/lp/translations/browser/tests/potemplate-views.txt
@@ -69,7 +69,7 @@ the entry should be linked with the IPOTemplate we are using.
>>> from lp.translations.enums import RosettaImportStatus
>>> entry = translationimportqueue.getAllEntries(
- ... import_status=RosettaImportStatus.NEEDS_REVIEW)[-1]
+ ... import_status=RosettaImportStatus.NEEDS_REVIEW).last()
>>> entry.potemplate == potemplate
True
@@ -102,7 +102,7 @@ Get it and check that some attributes are set as they should. For instance,
the entry should be linked with the IPOTemplate we are using.
>>> entry = translationimportqueue.getAllEntries(
- ... import_status=RosettaImportStatus.NEEDS_REVIEW)[-1]
+ ... import_status=RosettaImportStatus.NEEDS_REVIEW).last()
>>> entry.potemplate == potemplate
True
diff --git a/lib/lp/translations/browser/tests/test_translationimportqueueentry.py b/lib/lp/translations/browser/tests/test_translationimportqueueentry.py
index ce9e44d..f054931 100644
--- a/lib/lp/translations/browser/tests/test_translationimportqueueentry.py
+++ b/lib/lp/translations/browser/tests/test_translationimportqueueentry.py
@@ -3,6 +3,8 @@
"""Unit tests for translation import queue views."""
+from __future__ import absolute_import, print_function, unicode_literals
+
from datetime import datetime
from pytz import timezone
@@ -58,8 +60,8 @@ class TestTranslationImportQueueEntryView(WithScenarios, TestCaseWithFactory):
def _makeEntry(self, productseries=None, distroseries=None,
sourcepackagename=None, filename=None, potemplate=None):
if filename is None:
- filename = self.factory.getUniqueString() + '.pot'
- contents = self.factory.getUniqueString()
+ filename = self.factory.getUniqueUnicode() + '.pot'
+ contents = self.factory.getUniqueBytes()
entry = self.queue.addOrUpdateEntry(
filename, contents, False, self.uploader,
productseries=productseries, distroseries=distroseries,
diff --git a/lib/lp/translations/doc/translationimportqueue.txt b/lib/lp/translations/doc/translationimportqueue.txt
index c62423b..1c950a6 100644
--- a/lib/lp/translations/doc/translationimportqueue.txt
+++ b/lib/lp/translations/doc/translationimportqueue.txt
@@ -878,8 +878,8 @@ We need to attach a new entry to play with:
When we just import it, this method tells us that it's "just requested"
- >>> entry.getElapsedTimeText()
- 'just requested'
+ >>> print(entry.getElapsedTimeText())
+ just requested
Now, we need to update the 'dateimported' field to check that we get a good
value when takes more time since the import. We need to force the date here
@@ -900,8 +900,8 @@ Let's change the field with a date 2 days, 13 hours and 5 minutes ago.
And this method gets the right text.
- >>> entry.getElapsedTimeText()
- '2 days 13 hours 5 minutes ago'
+ >>> print(entry.getElapsedTimeText())
+ 2 days 13 hours 5 minutes ago
TranslationImportQueue
diff --git a/lib/lp/translations/model/pofile.py b/lib/lp/translations/model/pofile.py
index 01187aa..a975b67 100644
--- a/lib/lp/translations/model/pofile.py
+++ b/lib/lp/translations/model/pofile.py
@@ -15,6 +15,7 @@ __all__ = [
import datetime
import pytz
+import six
from sqlobject import (
BoolCol,
ForeignKey,
@@ -981,7 +982,7 @@ class POFile(SQLBase, POFileMixIn):
template_mail = 'poimport-not-exported-from-rosetta.txt'
import_rejected = True
entry_to_import.setErrorOutput(
- "File was not exported from Launchpad.")
+ u"File was not exported from Launchpad.")
except (MixedNewlineMarkersError, TranslationFormatSyntaxError,
TranslationFormatInvalidInputError,
UnicodeDecodeError) as exception:
@@ -995,7 +996,7 @@ class POFile(SQLBase, POFileMixIn):
else:
template_mail = 'poimport-syntax-error.txt'
import_rejected = True
- error_text = str(exception)
+ error_text = six.text_type(exception)
entry_to_import.setErrorOutput(error_text)
needs_notification_for_imported = True
except OutdatedTranslationError as exception:
@@ -1005,15 +1006,15 @@ class POFile(SQLBase, POFileMixIn):
logger.info('Got an old version for %s' % self.title)
template_mail = 'poimport-got-old-version.txt'
import_rejected = True
- error_text = str(exception)
+ error_text = six.text_type(exception)
entry_to_import.setErrorOutput(
- "Outdated translation. " + error_text)
+ u"Outdated translation. " + error_text)
except TooManyPluralFormsError:
if logger:
logger.warning("Too many plural forms.")
template_mail = 'poimport-too-many-plural-forms.txt'
import_rejected = True
- entry_to_import.setErrorOutput("Too many plural forms.")
+ entry_to_import.setErrorOutput(u"Too many plural forms.")
else:
# The import succeeded. There may still be non-fatal errors
# or warnings for individual messages (kept as a list in
@@ -1047,7 +1048,7 @@ class POFile(SQLBase, POFileMixIn):
data = self._prepare_pomessage_error_message(errors, replacements)
subject, template_mail, errorsdetails = data
entry_to_import.setErrorOutput(
- "Imported, but with errors:\n" + errorsdetails)
+ u"Imported, but with errors:\n" + errorsdetails)
else:
# The import was successful.
template_mail = 'poimport-confirmation.txt'
diff --git a/lib/lp/translations/model/potemplate.py b/lib/lp/translations/model/potemplate.py
index 70dedd2..9a622a0 100644
--- a/lib/lp/translations/model/potemplate.py
+++ b/lib/lp/translations/model/potemplate.py
@@ -944,7 +944,7 @@ class POTemplate(SQLBase, RosettaStats):
template_mail = 'poimport-syntax-error.txt'
entry_to_import.setStatus(RosettaImportStatus.FAILED,
rosetta_experts)
- error_text = str(exception)
+ error_text = six.text_type(exception)
entry_to_import.setErrorOutput(error_text)
else:
error_text = None
diff --git a/lib/lp/translations/model/translationimportqueue.py b/lib/lp/translations/model/translationimportqueue.py
index 483a4c3..fa41afa 100644
--- a/lib/lp/translations/model/translationimportqueue.py
+++ b/lib/lp/translations/model/translationimportqueue.py
@@ -1,6 +1,8 @@
# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+from __future__ import absolute_import, print_function, unicode_literals
+
__metaclass__ = type
__all__ = [
'collect_import_info',
@@ -20,20 +22,18 @@ from textwrap import dedent
import posixpath
import pytz
import six
-from sqlobject import (
- BoolCol,
- ForeignKey,
- SQLObjectNotFound,
- StringCol,
- )
from storm.expr import (
And,
Or,
Select,
)
from storm.locals import (
+ Bool,
+ DateTime,
Int,
Reference,
+ Store,
+ Unicode,
)
from zope.component import (
getUtility,
@@ -59,20 +59,18 @@ from lp.services.database.constants import (
DEFAULT,
UTC_NOW,
)
-from lp.services.database.datetimecol import UtcDateTimeCol
-from lp.services.database.enumcol import EnumCol
+from lp.services.database.enumcol import DBEnum
from lp.services.database.interfaces import (
IMasterStore,
ISlaveStore,
IStore,
)
from lp.services.database.sqlbase import (
- cursor,
quote,
quote_like,
- SQLBase,
- sqlvalues,
)
+from lp.services.database.stormbase import StormBase
+from lp.services.database.stormexpr import IsFalse
from lp.services.librarian.interfaces.client import ILibrarianClient
from lp.services.worlddata.interfaces.language import ILanguageSet
from lp.translations.enums import RosettaImportStatus
@@ -169,18 +167,20 @@ def compose_approval_conflict_notice(domain, templates_count, sample):
@implementer(ITranslationImportQueueEntry)
-class TranslationImportQueueEntry(SQLBase):
-
- _table = 'TranslationImportQueueEntry'
-
- path = StringCol(dbName='path', notNull=True)
- content = ForeignKey(foreignKey='LibraryFileAlias', dbName='content',
- notNull=False)
- importer = ForeignKey(
- dbName='importer', foreignKey='Person',
- storm_validator=validate_person,
- notNull=True)
- dateimported = UtcDateTimeCol(dbName='dateimported', notNull=True,
+class TranslationImportQueueEntry(StormBase):
+
+ __storm_table__ = 'TranslationImportQueueEntry'
+
+ id = Int(primary=True)
+
+ path = Unicode(name='path', allow_none=False)
+ content_id = Int(name='content', allow_none=True)
+ content = Reference(content_id, 'LibraryFileAlias.id')
+ importer_id = Int(
+ name='importer', validator=validate_person, allow_none=False)
+ importer = Reference(importer_id, 'Person.id')
+ dateimported = DateTime(
+ tzinfo=pytz.UTC, name='dateimported', allow_none=False,
default=DEFAULT)
sourcepackagename_id = Int(name='sourcepackagename', allow_none=True)
sourcepackagename = Reference(
@@ -189,18 +189,35 @@ class TranslationImportQueueEntry(SQLBase):
distroseries = Reference(distroseries_id, 'DistroSeries.id')
productseries_id = Int(name='productseries', allow_none=True)
productseries = Reference(productseries_id, 'ProductSeries.id')
- by_maintainer = BoolCol(notNull=True)
- pofile = ForeignKey(foreignKey='POFile', dbName='pofile',
- notNull=False, default=None)
- potemplate = ForeignKey(foreignKey='POTemplate',
- dbName='potemplate', notNull=False, default=None)
- format = EnumCol(dbName='format', schema=TranslationFileFormat,
- default=TranslationFileFormat.PO, notNull=True)
- status = EnumCol(dbName='status', notNull=True,
- schema=RosettaImportStatus, default=RosettaImportStatus.NEEDS_REVIEW)
- date_status_changed = UtcDateTimeCol(dbName='date_status_changed',
- notNull=True, default=DEFAULT)
- error_output = StringCol(notNull=False, default=None)
+ by_maintainer = Bool(allow_none=False)
+ pofile_id = Int(name='pofile', allow_none=True, default=None)
+ pofile = Reference(pofile_id, 'POFile.id')
+ potemplate_id = Int(name='potemplate', allow_none=True, default=None)
+ potemplate = Reference(potemplate_id, 'POTemplate.id')
+ format = DBEnum(
+ name='format', enum=TranslationFileFormat,
+ default=TranslationFileFormat.PO, allow_none=False)
+ status = DBEnum(
+ name='status', allow_none=False,
+ enum=RosettaImportStatus, default=RosettaImportStatus.NEEDS_REVIEW)
+ date_status_changed = DateTime(
+ tzinfo=pytz.UTC, name='date_status_changed',
+ allow_none=False, default=DEFAULT)
+ error_output = Unicode(allow_none=True, default=None)
+
+ def __init__(self, path, content, importer, sourcepackagename,
+ distroseries, productseries, by_maintainer, potemplate,
+ pofile, format):
+ self.path = path
+ self.content = content
+ self.importer = importer
+ self.sourcepackagename = sourcepackagename
+ self.distroseries = distroseries
+ self.productseries = productseries
+ self.by_maintainer = by_maintainer
+ self.potemplate = potemplate
+ self.pofile = pofile
+ self.format = format
@property
def sourcepackage(self):
@@ -588,11 +605,12 @@ class TranslationImportQueueEntry(SQLBase):
# No way to guess anything...
return None
- existing_entry = TranslationImportQueueEntry.selectOneBy(
+ existing_entry = IStore(TranslationImportQueueEntry).find(
+ TranslationImportQueueEntry,
importer=self.importer, path=self.path, potemplate=potemplate,
distroseries=self.distroseries,
sourcepackagename=self.sourcepackagename,
- productseries=self.productseries)
+ productseries=self.productseries).one()
if existing_entry is not None:
warning = ("%s: can't approve entry %d ('%s') "
"because entry %d is in the way." % (
@@ -796,24 +814,27 @@ class TranslationImportQueueEntry(SQLBase):
importer = getUtility(ITranslationImporter)
path = os.path.dirname(self.path)
- suffix_clauses = [
- "path LIKE '%%' || %s" % quote_like(suffix)
- for suffix in importer.template_suffixes]
-
clauses = [
- "path LIKE %s || '%%'" % quote_like(path),
- "id <> %s" % quote(self.id),
- "(%s)" % " OR ".join(suffix_clauses)]
+ TranslationImportQueueEntry.path.startswith(path),
+ TranslationImportQueueEntry.id != self.id,
+ Or(*(
+ TranslationImportQueueEntry.path.endswith(suffix)
+ for suffix in importer.template_suffixes))]
if self.distroseries is not None:
- clauses.append('distroseries = %s' % quote(self.distroseries))
+ clauses.append(
+ TranslationImportQueueEntry.distroseries == self.distroseries)
if self.sourcepackagename is not None:
clauses.append(
- 'sourcepackagename = %s' % quote(self.sourcepackagename))
+ TranslationImportQueueEntry.sourcepackagename ==
+ self.sourcepackagename)
if self.productseries is not None:
- clauses.append("productseries = %s" % quote(self.productseries))
+ clauses.append(
+ TranslationImportQueueEntry.productseries ==
+ self.productseries)
- return TranslationImportQueueEntry.select(" AND ".join(clauses))
+ return IStore(TranslationImportQueueEntry).find(
+ TranslationImportQueueEntry, *clauses)
def getElapsedTimeText(self):
"""See ITranslationImportQueue."""
@@ -926,13 +947,15 @@ class TranslationImportQueue:
def countEntries(self):
"""See `ITranslationImportQueue`."""
- return TranslationImportQueueEntry.select().count()
+ return IStore(TranslationImportQueueEntry).find(
+ TranslationImportQueueEntry).count()
def _iterNeedsReview(self):
"""Iterate over all entries in the queue that need review."""
- return iter(TranslationImportQueueEntry.selectBy(
+ return iter(IStore(TranslationImportQueueEntry).find(
+ TranslationImportQueueEntry,
status=RosettaImportStatus.NEEDS_REVIEW,
- orderBy=['dateimported']))
+ ).order_by(TranslationImportQueueEntry.dateimported))
def _getMatchingEntry(self, path, importer, potemplate, pofile,
sourcepackagename, distroseries, productseries):
@@ -1077,6 +1100,7 @@ class TranslationImportQueue:
except TranslationImportQueueConflictError:
return None
+ store = IMasterStore(TranslationImportQueueEntry)
if entry is None:
# It's a new row.
entry = TranslationImportQueueEntry(path=path, content=alias,
@@ -1084,6 +1108,7 @@ class TranslationImportQueue:
distroseries=distroseries, productseries=productseries,
by_maintainer=by_maintainer, potemplate=potemplate,
pofile=pofile, format=format)
+ store.add(entry)
else:
# It's an update.
entry.setErrorOutput(None)
@@ -1113,8 +1138,8 @@ class TranslationImportQueue:
entry.date_status_changed = UTC_NOW
entry.format = format
- entry.sync()
+ store.flush()
return entry
def _iterTarballFiles(self, tarball):
@@ -1204,88 +1229,96 @@ class TranslationImportQueue:
def get(self, id):
"""See ITranslationImportQueue."""
- try:
- return TranslationImportQueueEntry.get(id)
- except SQLObjectNotFound:
- return None
+ return IStore(TranslationImportQueueEntry).get(
+ TranslationImportQueueEntry, id)
def _getQueryByFiltering(self, target=None, status=None,
file_extensions=None):
"""See `ITranslationImportQueue.`"""
- queries = ["TRUE"]
- clause_tables = []
+ # Avoid circular imports.
+ from lp.registry.model.distroseries import DistroSeries
+ from lp.registry.model.productseries import ProductSeries
+
+ queries = [True]
if target is not None:
if IPerson.providedBy(target):
- queries.append('importer = %s' % sqlvalues(target))
+ queries.append(TranslationImportQueueEntry.importer == target)
elif IProduct.providedBy(target):
- queries.append('productseries = ProductSeries.id')
- queries.append(
- 'ProductSeries.product = %s' % sqlvalues(target))
- clause_tables.append('ProductSeries')
+ queries.extend([
+ TranslationImportQueueEntry.productseries ==
+ ProductSeries.id,
+ ProductSeries.product == target,
+ ])
elif IProductSeries.providedBy(target):
- queries.append('productseries = %s' % sqlvalues(target))
- elif IDistribution.providedBy(target):
- queries.append('distroseries = DistroSeries.id')
queries.append(
- 'DistroSeries.distribution = %s' % sqlvalues(target))
- clause_tables.append('DistroSeries')
+ TranslationImportQueueEntry.productseries == target)
+ elif IDistribution.providedBy(target):
+ queries.extend([
+ TranslationImportQueueEntry.distroseries ==
+ DistroSeries.id,
+ DistroSeries.distribution == target,
+ ])
elif IDistroSeries.providedBy(target):
- queries.append('distroseries = %s' % sqlvalues(target))
- elif ISourcePackage.providedBy(target):
queries.append(
- 'distroseries = %s' % sqlvalues(target.distroseries))
- queries.append(
- 'sourcepackagename = %s' % sqlvalues(
- target.sourcepackagename))
+ TranslationImportQueueEntry.distroseries == target)
+ elif ISourcePackage.providedBy(target):
+ queries.extend([
+ TranslationImportQueueEntry.distroseries ==
+ target.distroseries,
+ TranslationImportQueueEntry.sourcepackagename ==
+ target.sourcepackagename,
+ ])
elif target == SpecialTranslationImportTargetFilter.PRODUCT:
- queries.append('productseries IS NOT NULL')
+ queries.append(
+ TranslationImportQueueEntry.productseries != None)
elif target == SpecialTranslationImportTargetFilter.DISTRIBUTION:
- queries.append('distroseries IS NOT NULL')
+ queries.append(
+ TranslationImportQueueEntry.distroseries != None)
else:
raise AssertionError(
'Target argument must be one of IPerson, IProduct,'
' IProductSeries, IDistribution, IDistroSeries or'
' ISourcePackage')
if status is not None:
- queries.append(
- 'TranslationImportQueueEntry.status = %s' % sqlvalues(status))
+ queries.append(TranslationImportQueueEntry.status == status)
if file_extensions:
- extension_clauses = [
- "path LIKE '%%' || %s" % quote_like(extension)
- for extension in file_extensions]
- queries.append("(%s)" % " OR ".join(extension_clauses))
+ queries.append(Or(*(
+ TranslationImportQueueEntry.path.endswith(extension)
+ for extension in file_extensions)))
- return queries, clause_tables
+ return queries
def getAllEntries(self, target=None, import_status=None,
file_extensions=None):
"""See ITranslationImportQueue."""
- queries, clause_tables = self._getQueryByFiltering(
+ queries = self._getQueryByFiltering(
target, import_status, file_extensions)
- return TranslationImportQueueEntry.select(
- " AND ".join(queries), clauseTables=clause_tables,
- orderBy=['status', 'dateimported', 'id'])
+ return IStore(TranslationImportQueueEntry).find(
+ TranslationImportQueueEntry, *queries).order_by(
+ 'status', 'dateimported', 'id')
def getFirstEntryToImport(self, target=None):
"""See ITranslationImportQueue."""
+ # Avoid circular import.
+ from lp.registry.model.distroseries import DistroSeries
+
# Prepare the query to get only APPROVED entries.
- queries, clause_tables = self._getQueryByFiltering(
+ queries = self._getQueryByFiltering(
target, status=RosettaImportStatus.APPROVED)
if (IDistribution.providedBy(target) or
- IDistroSeries.providedBy(target) or
- ISourcePackage.providedBy(target)):
- # If the Distribution series has actived the option to defer
+ IDistroSeries.providedBy(target) or
+ ISourcePackage.providedBy(target)):
+ # If the Distribution series has activated the option to defer
# translation imports, we ignore those entries.
- if 'DistroSeries' not in clause_tables:
- clause_tables.append('DistroSeries')
- queries.append('distroseries = DistroSeries.id')
-
- queries.append('DistroSeries.defer_translation_imports IS FALSE')
+ queries.extend([
+ TranslationImportQueueEntry.distroseries == DistroSeries.id,
+ IsFalse(DistroSeries.defer_translation_imports),
+ ])
- return TranslationImportQueueEntry.selectFirst(
- " AND ".join(queries), clauseTables=clause_tables,
- orderBy=['dateimported'])
+ return IStore(TranslationImportQueueEntry).find(
+ TranslationImportQueueEntry,
+ *queries).order_by('dateimported').first()
def getRequestTargets(self, user, status=None):
"""See `ITranslationImportQueue`."""
@@ -1487,8 +1520,7 @@ class TranslationImportQueue:
"""
# XXX JeroenVermeulen 2009-09-18 bug=271938: Stormify this once
# the Storm remove() syntax starts working properly for joins.
- cur = cursor()
- cur.execute("""
+ result = store.execute("""
DELETE FROM TranslationImportQueueEntry AS Entry
USING ProductSeries, Product
WHERE
@@ -1496,7 +1528,7 @@ class TranslationImportQueue:
Product.id = ProductSeries.product AND
Product.active IS FALSE
""")
- return cur.rowcount
+ return result.rowcount
def _cleanUpObsoleteDistroEntries(self, store):
"""Delete some queue entries for obsolete `DistroSeries`.
@@ -1506,8 +1538,7 @@ class TranslationImportQueue:
"""
# XXX JeroenVermeulen 2009-09-18 bug=271938,432484: Stormify
# this once Storm's remove() supports joins and slices.
- cur = cursor()
- cur.execute("""
+ result = store.execute("""
DELETE FROM TranslationImportQueueEntry
WHERE id IN (
SELECT Entry.id
@@ -1519,7 +1550,7 @@ class TranslationImportQueue:
WHERE DistroSeries.releasestatus = %s
LIMIT 100)
""" % quote(SeriesStatus.OBSOLETE))
- return cur.rowcount
+ return result.rowcount
def cleanUpQueue(self):
"""See `ITranslationImportQueue`."""
@@ -1532,4 +1563,4 @@ class TranslationImportQueue:
def remove(self, entry):
"""See ITranslationImportQueue."""
- TranslationImportQueueEntry.delete(entry.id)
+ IMasterStore(TranslationImportQueueEntry).remove(entry)
diff --git a/lib/lp/translations/scripts/tests/test_translations_approval.py b/lib/lp/translations/scripts/tests/test_translations_approval.py
index fd4bd41..9a53f96 100644
--- a/lib/lp/translations/scripts/tests/test_translations_approval.py
+++ b/lib/lp/translations/scripts/tests/test_translations_approval.py
@@ -1,6 +1,8 @@
# Copyright 2011 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+from __future__ import absolute_import, print_function, unicode_literals
+
import logging
import transaction
diff --git a/lib/lp/translations/scripts/tests/test_translations_import.py b/lib/lp/translations/scripts/tests/test_translations_import.py
index bbb94cc..2fe67ae 100644
--- a/lib/lp/translations/scripts/tests/test_translations_import.py
+++ b/lib/lp/translations/scripts/tests/test_translations_import.py
@@ -1,6 +1,8 @@
# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+from __future__ import absolute_import, print_function, unicode_literals
+
import logging
import re
@@ -47,7 +49,7 @@ class TestTranslationsImport(TestCaseWithFactory):
"""Produce a queue entry."""
uploader = kwargs.pop('uploader', self.owner)
return self.queue.addOrUpdateEntry(
- path, '# Nothing here', False, uploader, **kwargs)
+ path, b'# Nothing here', False, uploader, **kwargs)
def _makeApprovedEntry(self, uploader):
"""Produce an approved queue entry."""
diff --git a/lib/lp/translations/tests/test_autoapproval.py b/lib/lp/translations/tests/test_autoapproval.py
index 03c60b3..e1005e0 100644
--- a/lib/lp/translations/tests/test_autoapproval.py
+++ b/lib/lp/translations/tests/test_autoapproval.py
@@ -8,6 +8,8 @@ Documentation-style tests go in there, ones that go systematically
through the possibilities should go here.
"""
+from __future__ import absolute_import, print_function, unicode_literals
+
from contextlib import contextmanager
from datetime import (
datetime,
@@ -16,6 +18,7 @@ from datetime import (
from fixtures import FakeLogger
from pytz import UTC
+from storm.locals import Store
from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy
@@ -189,7 +192,7 @@ class TestGuessPOFileCustomLanguageCode(TestCaseWithFactory,
def _makeQueueEntry(self, language_code):
"""Create translation import queue entry."""
return self.queue.addOrUpdateEntry(
- "%s.po" % language_code, 'contents', True, self.product.owner,
+ "%s.po" % language_code, b'contents', True, self.product.owner,
productseries=self.series)
def _setCustomLanguageCode(self, language_code, target_language_code):
@@ -606,13 +609,13 @@ class TestTemplateGuess(TestCaseWithFactory, GardenerDbUserMixin):
template.path = 'program/program.pot'
self.producttemplate2.path = 'errors/errors.pot'
entry1 = queue.addOrUpdateEntry(
- 'program/nl.po', 'contents', False, template.owner,
+ 'program/nl.po', b'contents', False, template.owner,
productseries=template.productseries)
# The clashing entry goes through approval unsuccessfully, but
# without causing breakage.
queue.addOrUpdateEntry(
- 'program/nl.po', 'other contents', False, template.owner,
+ 'program/nl.po', b'other contents', False, template.owner,
productseries=template.productseries, potemplate=template)
self.becomeTheGardener()
@@ -626,7 +629,7 @@ class TestTemplateGuess(TestCaseWithFactory, GardenerDbUserMixin):
template.iscurrent = False
queue = getUtility(ITranslationImportQueue)
entry = queue.addOrUpdateEntry(
- pofile.path, 'contents', False, self.factory.makePerson(),
+ pofile.path, b'contents', False, self.factory.makePerson(),
productseries=template.productseries)
self.assertEqual(None, entry.getGuessedPOFile())
@@ -645,7 +648,7 @@ class TestTemplateGuess(TestCaseWithFactory, GardenerDbUserMixin):
queue = getUtility(ITranslationImportQueue)
entry = queue.addOrUpdateEntry(
- current_pofile.path, 'contents', False, self.factory.makePerson(),
+ current_pofile.path, b'contents', False, self.factory.makePerson(),
productseries=series)
self.assertEqual(current_pofile, entry.getGuessedPOFile())
@@ -662,7 +665,7 @@ class TestTemplateGuess(TestCaseWithFactory, GardenerDbUserMixin):
queue = TranslationImportQueue()
entry = queue.addOrUpdateEntry(
- 'test.pot', 'contents', False, template.owner,
+ 'test.pot', b'contents', False, template.owner,
productseries=template.productseries)
self.assertEqual(template, entry.guessed_potemplate)
@@ -675,7 +678,7 @@ class TestTemplateGuess(TestCaseWithFactory, GardenerDbUserMixin):
queue = TranslationImportQueue()
entry = queue.addOrUpdateEntry(
- 'other.pot', 'contents', False, template.owner,
+ 'other.pot', b'contents', False, template.owner,
productseries=template.productseries)
self.assertEqual(None, entry.guessed_potemplate)
@@ -691,7 +694,7 @@ class TestTemplateGuess(TestCaseWithFactory, GardenerDbUserMixin):
queue = TranslationImportQueue()
entry = queue.addOrUpdateEntry(
- 'test.pot', 'contents', False, template.owner,
+ 'test.pot', b'contents', False, template.owner,
productseries=template.productseries)
self.assertEqual(None, entry.guessed_potemplate)
@@ -709,7 +712,7 @@ class TestTemplateGuess(TestCaseWithFactory, GardenerDbUserMixin):
queue = TranslationImportQueue()
entry = queue.addOrUpdateEntry(
- 'test.pot', 'contents', False, template.owner,
+ 'test.pot', b'contents', False, template.owner,
productseries=template.productseries)
self.assertEqual(template, entry.guessed_potemplate)
@@ -724,10 +727,10 @@ class TestTemplateGuess(TestCaseWithFactory, GardenerDbUserMixin):
queue = TranslationImportQueue()
template = self.factory.makePOTemplate()
old_entry = queue.addOrUpdateEntry(
- template.path, '# Content here', False, template.owner,
+ template.path, b'# Content here', False, template.owner,
productseries=template.productseries)
new_entry = queue.addOrUpdateEntry(
- template.path, '# Content here', False, template.owner,
+ template.path, b'# Content here', False, template.owner,
productseries=template.productseries, potemplate=template)
# Before approval, the two entries differ in that the new one
@@ -785,7 +788,7 @@ class TestKdePOFileGuess(TestCaseWithFactory, GardenerDbUserMixin):
translation_domain='kde4')
self.pofile_nl = nl_template.newPOFile('nl')
- self.pocontents = """
+ self.pocontents = b"""
msgid "foo"
msgstr ""
"""
@@ -836,7 +839,7 @@ class TestGetPOFileFromLanguage(TestCaseWithFactory, GardenerDbUserMixin):
template.iscurrent = True
entry = self.queue.addOrUpdateEntry(
- 'nl.po', '# ...', False, template.owner, productseries=trunk)
+ 'nl.po', b'# ...', False, template.owner, productseries=trunk)
self.becomeTheGardener()
pofile = entry._get_pofile_from_language('nl', 'domain')
@@ -854,7 +857,7 @@ class TestGetPOFileFromLanguage(TestCaseWithFactory, GardenerDbUserMixin):
template.iscurrent = False
entry = self.queue.addOrUpdateEntry(
- 'nl.po', '# ...', False, template.owner, productseries=trunk)
+ 'nl.po', b'# ...', False, template.owner, productseries=trunk)
self.becomeTheGardener()
pofile = entry._get_pofile_from_language('nl', 'domain')
@@ -873,7 +876,7 @@ class TestGetPOFileFromLanguage(TestCaseWithFactory, GardenerDbUserMixin):
self.factory.makePOTMsgSet(template, "translator-credits")
entry = self.queue.addOrUpdateEntry(
- 'nl.po', '# ...', False, template.owner, productseries=trunk)
+ 'nl.po', b'# ...', False, template.owner, productseries=trunk)
self.becomeTheGardener()
pofile = entry._get_pofile_from_language('nl', 'domain')
@@ -896,7 +899,7 @@ class TestCleanup(TestCaseWithFactory, GardenerDbUserMixin):
translations_usage=ServiceUsage.LAUNCHPAD)
trunk = product.getSeries('trunk')
entry = self.queue.addOrUpdateEntry(
- path, '# contents', False, product.owner, productseries=trunk)
+ path, b'# contents', False, product.owner, productseries=trunk)
if status is not None:
entry.status = status
return entry
@@ -906,7 +909,7 @@ class TestCleanup(TestCaseWithFactory, GardenerDbUserMixin):
package = self.factory.makeSourcePackage()
owner = package.distroseries.owner
entry = self.queue.addOrUpdateEntry(
- path, '# contents', False, owner,
+ path, b'# contents', False, owner,
sourcepackagename=package.sourcepackagename,
distroseries=package.distroseries)
if status is not None:
@@ -917,7 +920,7 @@ class TestCleanup(TestCaseWithFactory, GardenerDbUserMixin):
"""Make an entry's timestamps older by a given interval."""
entry.dateimported -= interval
entry.date_status_changed -= interval
- entry.syncUpdate()
+ Store.of(entry).flush()
def _exists(self, entry_id):
"""Is the entry with the given id still on the queue?"""
@@ -932,7 +935,7 @@ class TestCleanup(TestCaseWithFactory, GardenerDbUserMixin):
getUtility(ILaunchpadCelebrities).rosetta_experts)
if when is not None:
entry.date_status_changed = when
- entry.syncUpdate()
+ Store.of(entry).flush()
def test_cleanUpObsoleteEntries_unaffected_statuses(self):
# _cleanUpObsoleteEntries leaves entries in states without
@@ -1106,7 +1109,7 @@ class TestAutoApprovalNewPOFile(TestCaseWithFactory, GardenerDbUserMixin):
def _makeQueueEntry(self, series):
"""Create translation import queue entry."""
return self.queue.addOrUpdateEntry(
- "%s.po" % self.language.code, 'contents', True,
+ "%s.po" % self.language.code, b'contents', True,
self.product.owner, productseries=series)
def test_getGuessedPOFile_creates_POFile(self):
diff --git a/lib/lp/translations/tests/test_translationbranchapprover.py b/lib/lp/translations/tests/test_translationbranchapprover.py
index 43e4b36..fb77425 100644
--- a/lib/lp/translations/tests/test_translationbranchapprover.py
+++ b/lib/lp/translations/tests/test_translationbranchapprover.py
@@ -3,6 +3,8 @@
"""Translation File Auto Approver tests."""
+from __future__ import absolute_import, print_function, unicode_literals
+
__metaclass__ = type
from zope.component import getUtility
@@ -36,7 +38,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
def _upload_file(self, upload_path):
# Put a template or translation file in the import queue.
return self.queue.addOrUpdateEntry(upload_path,
- self.factory.getUniqueString(), True, self.series.owner,
+ self.factory.getUniqueBytes(), True, self.series.owner,
productseries=self.series)
def _createTemplate(self, path, domain, productseries=None):
@@ -58,7 +60,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
def test_new_template_approved(self):
# The approver puts new entries in the Approved state.
- template_path = self.factory.getUniqueString() + u'.pot'
+ template_path = self.factory.getUniqueUnicode() + u'.pot'
entry = self._upload_file(template_path)
self.assertEqual(RosettaImportStatus.NEEDS_REVIEW, entry.status)
self._createApprover(template_path).approve(entry)
@@ -88,7 +90,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
'sourcepackagename': package.sourcepackagename,
}
entry = self.queue.addOrUpdateEntry(
- 'messages.pot', self.factory.getUniqueString(), True,
+ 'messages.pot', self.factory.getUniqueBytes(), True,
self.factory.makePerson(), **package_kwargs)
TranslationBranchApprover(entry.path, **package_kwargs).approve(entry)
@@ -104,7 +106,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
def test_new_template_domain(self):
# The approver gets the translation domain for the entry from the
# file path if possible.
- translation_domain = self.factory.getUniqueString()
+ translation_domain = self.factory.getUniqueUnicode()
template_path = translation_domain + u'.pot'
entry = self._upload_file(template_path)
self._createApprover(template_path).approve(entry)
@@ -123,7 +125,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
def test_replace_existing_approved(self):
# Template files that replace existing entries are approved.
- translation_domain = self.factory.getUniqueString()
+ translation_domain = self.factory.getUniqueUnicode()
template_path = translation_domain + u'.pot'
self._createTemplate(template_path, translation_domain)
entry = self._upload_file(template_path)
@@ -133,7 +135,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
def test_replace_existing_potemplate(self):
# When replacing an existing template, the queue entry is linked
# to that existing entry.
- translation_domain = self.factory.getUniqueString()
+ translation_domain = self.factory.getUniqueUnicode()
template_path = translation_domain + u'.pot'
potemplate = self._createTemplate(template_path, translation_domain)
entry = self._upload_file(template_path)
@@ -143,7 +145,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
def test_ignore_existing_inactive_potemplate(self):
# When replacing an existing inactive template, the entry is not
# approved and no template is created for it.
- translation_domain = self.factory.getUniqueString()
+ translation_domain = self.factory.getUniqueUnicode()
template_path = translation_domain + u'.pot'
potemplate = self._createTemplate(template_path, translation_domain)
potemplate.setActive(False)
@@ -155,10 +157,10 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
def test_replace_existing_any_path(self):
# If just one template file is found in the tree and just one
# POTemplate is in the database, the upload is always approved.
- existing_domain = self.factory.getUniqueString()
+ existing_domain = self.factory.getUniqueUnicode()
existing_path = existing_domain + u'.pot'
potemplate = self._createTemplate(existing_path, existing_domain)
- template_path = self.factory.getUniqueString() + u'.pot'
+ template_path = self.factory.getUniqueUnicode() + u'.pot'
entry = self._upload_file(template_path)
self._createApprover(template_path).approve(entry)
self.assertEqual(RosettaImportStatus.APPROVED, entry.status)
@@ -168,7 +170,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
# If an upload file has a generic path that does not yield a
# translation domain, it is still approved if an entry with the
# same file name exists.
- translation_domain = self.factory.getUniqueString()
+ translation_domain = self.factory.getUniqueUnicode()
generic_path = u'po/messages.pot'
self._createTemplate(generic_path, translation_domain)
entry = self._upload_file(generic_path)
@@ -191,7 +193,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
template = self.factory.makePOTemplate(**package_kwargs)
original_domain = template.translation_domain
entry = self.queue.addOrUpdateEntry(
- generic_path, self.factory.getUniqueString(), True,
+ generic_path, self.factory.getUniqueBytes(), True,
template.owner, potemplate=template, **package_kwargs)
approver = TranslationBranchApprover(generic_path, **package_kwargs)
@@ -201,10 +203,10 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
def test_add_template(self):
# When adding a template to an existing one it is approved if the
# approver is told about both template files in the tree.
- existing_domain = self.factory.getUniqueString()
+ existing_domain = self.factory.getUniqueUnicode()
existing_path = u"%s/%s.pot" % (existing_domain, existing_domain)
self._createTemplate(existing_path, existing_domain)
- new_domain = self.factory.getUniqueString()
+ new_domain = self.factory.getUniqueUnicode()
new_path = u"%s/%s.pot" % (new_domain, new_domain)
entry = self._upload_file(new_path)
self._createApprover((existing_path, new_path)).approve(entry)
@@ -214,8 +216,8 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
def test_upload_multiple_new_templates(self):
# Multiple new templates can be added using the same
# TranslationBranchApprover instance.
- pot_path1 = self.factory.getUniqueString() + ".pot"
- pot_path2 = self.factory.getUniqueString() + ".pot"
+ pot_path1 = self.factory.getUniqueUnicode() + ".pot"
+ pot_path2 = self.factory.getUniqueUnicode() + ".pot"
entry1 = self._upload_file(pot_path1)
entry2 = self._upload_file(pot_path2)
approver = self._createApprover((pot_path1, pot_path2))
@@ -239,7 +241,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
def test_approve_only_if_needs_review(self):
# If an entry is not in NEEDS_REVIEW state, it must not be approved.
- pot_path = self.factory.getUniqueString() + ".pot"
+ pot_path = self.factory.getUniqueUnicode() + ".pot"
entry = self._upload_file(pot_path)
entry.potemplate = self.factory.makePOTemplate()
not_approve_status = (
@@ -258,7 +260,7 @@ class TestTranslationBranchApprover(TestCaseWithFactory):
# When the approver creates a new template, the new template
# gets copies of any existing POFiles for templates that it will
# share translations with.
- domain = self.factory.getUniqueString()
+ domain = self.factory.getUniqueUnicode()
pot_path = domain + ".pot"
trunk = self.series.product.getSeries('trunk')
trunk_template = self._createTemplate(
@@ -340,7 +342,7 @@ class TestBranchApproverPrivileges(TestCaseWithFactory):
self.factory.makePackagingLink(
productseries=productseries, **package_kwargs)
- template_name = self.factory.getUniqueString()
+ template_name = self.factory.getUniqueUnicode()
template_path = "%s.pot" % template_name
self.factory.makePOFile(
diff --git a/lib/lp/translations/tests/test_translationbuildapprover.py b/lib/lp/translations/tests/test_translationbuildapprover.py
index c2a1d83..e38b2c2 100644
--- a/lib/lp/translations/tests/test_translationbuildapprover.py
+++ b/lib/lp/translations/tests/test_translationbuildapprover.py
@@ -3,6 +3,8 @@
"""Tests for the `TranslationBuildApprover`."""
+from __future__ import absolute_import, print_function, unicode_literals
+
__metaclass__ = type
from zope.component import getUtility
@@ -31,7 +33,7 @@ class TestTranslationBuildApprover(TestCaseWithFactory):
"""Create a list of queue entries and approve them."""
return [
approver.approve(self.queue.addOrUpdateEntry(
- path, "#Dummy content.", False, self.uploader,
+ path, b"#Dummy content.", False, self.uploader,
productseries=series))
for path in filenames]
diff --git a/lib/lp/translations/tests/test_translationimportqueue.py b/lib/lp/translations/tests/test_translationimportqueue.py
index c4ed52e..67a05e1 100644
--- a/lib/lp/translations/tests/test_translationimportqueue.py
+++ b/lib/lp/translations/tests/test_translationimportqueue.py
@@ -1,11 +1,14 @@
# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+from __future__ import absolute_import, print_function, unicode_literals
+
__metaclass__ = type
from operator import attrgetter
import os.path
+import six
import transaction
from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy
@@ -166,7 +169,7 @@ class TestCanSetStatusBase:
# that are targeted to Ubuntu.
self._setUpUbuntu()
ubuntu_entry = self.queue.addOrUpdateEntry(
- 'demo.pot', '#demo', False, self.uploaderperson,
+ 'demo.pot', b'#demo', False, self.uploaderperson,
distroseries=self.factory.makeDistroSeries(self.ubuntu),
sourcepackagename=self.factory.makeSourcePackageName(),
potemplate=self.potemplate)
@@ -193,7 +196,7 @@ class TestCanSetStatusPOTemplate(TestCanSetStatusBase, TestCaseWithFactory):
self.potemplate = self.factory.makePOTemplate(
productseries=self.productseries)
self.entry = self.queue.addOrUpdateEntry(
- 'demo.pot', '#demo', False, self.uploaderperson,
+ 'demo.pot', b'#demo', False, self.uploaderperson,
productseries=self.productseries, potemplate=self.potemplate)
@@ -209,7 +212,7 @@ class TestCanSetStatusPOFile(TestCanSetStatusBase, TestCaseWithFactory):
self.pofile = self.factory.makePOFile(
'eo', potemplate=self.potemplate)
self.entry = self.queue.addOrUpdateEntry(
- 'demo.po', '#demo', False, self.uploaderperson,
+ 'demo.po', b'#demo', False, self.uploaderperson,
productseries=self.productseries, pofile=self.pofile)
@@ -279,8 +282,8 @@ class TestGetGuessedPOFile(TestCaseWithFactory):
package, pot = self.createSourcePackageAndPOTemplate(
source_name, template_name)
queue_entry = self.queue.addOrUpdateEntry(
- '%s.po' % template_path, template_name, True, self.uploaderperson,
- distroseries=package.distroseries,
+ '%s.po' % template_path, six.ensure_binary(template_name), True,
+ self.uploaderperson, distroseries=package.distroseries,
sourcepackagename=package.sourcepackagename)
pofile = queue_entry.getGuessedPOFile()
return (pot, pofile)
@@ -353,7 +356,7 @@ class TestProductOwnerEntryImporter(TestCaseWithFactory):
# Changing the Product owner also updates the importer of the entry.
with person_logged_in(self.old_owner):
entry = self.import_queue.addOrUpdateEntry(
- u'po/sr.po', 'foo', True, self.old_owner,
+ u'po/sr.po', b'foo', True, self.old_owner,
productseries=self.product.series[0])
self.product.owner = self.new_owner
self.assertEqual(self.new_owner, entry.importer)
@@ -364,11 +367,11 @@ class TestProductOwnerEntryImporter(TestCaseWithFactory):
# cause an non-unique key for the entry.
with person_logged_in(self.new_owner):
self.import_queue.addOrUpdateEntry(
- u'po/sr.po', 'foo', True, self.new_owner,
+ u'po/sr.po', b'foo', True, self.new_owner,
productseries=self.product.series[0])
with person_logged_in(self.old_owner):
old_entry = self.import_queue.addOrUpdateEntry(
- u'po/sr.po', 'foo', True, self.old_owner,
+ u'po/sr.po', b'foo', True, self.old_owner,
productseries=self.product.series[0])
self.product.owner = self.new_owner
self.assertEqual(self.old_owner, old_entry.importer)
@@ -390,12 +393,12 @@ class TestTranslationImportQueue(TestCaseWithFactory):
Returns a tuple (name, content).
"""
- filename = self.factory.getUniqueString()
+ filename = self.factory.getUniqueUnicode()
if extension is not None:
filename = "%s.%s" % (filename, extension)
if directory is not None:
filename = os.path.join(directory, filename)
- content = self.factory.getUniqueString()
+ content = self.factory.getUniqueBytes()
return (filename, content)
def _getQueuePaths(self):
@@ -469,7 +472,7 @@ class TestTranslationImportQueue(TestCaseWithFactory):
# Repeated occurrence of the same approval conflict will not
# result in repeated setting of error_output.
series = self.factory.makeProductSeries()
- domain = self.factory.getUniqueString()
+ domain = self.factory.getUniqueUnicode()
templates = [
self.factory.makePOTemplate(
productseries=series, translation_domain=domain)
@@ -509,7 +512,7 @@ class TestHelpers(TestCaseWithFactory):
# The output from compose_approval_conflict_notice summarizes
# the conflict: what translation domain is affected and how many
# clashing templates are there?
- domain = self.factory.getUniqueString()
+ domain = self.factory.getUniqueUnicode()
num_templates = self.factory.getUniqueInteger()
notice = compose_approval_conflict_notice(domain, num_templates, [])
@@ -526,9 +529,9 @@ class TestHelpers(TestCaseWithFactory):
def __init__(self, displayname):
self.displayname = displayname
- domain = self.factory.getUniqueString()
+ domain = self.factory.getUniqueUnicode()
samples = [
- FakePOTemplate(self.factory.getUniqueString())
+ FakePOTemplate(self.factory.getUniqueUnicode())
for counter in range(3)]
sorted_samples = sorted(samples, key=attrgetter('displayname'))
@@ -547,9 +550,9 @@ class TestHelpers(TestCaseWithFactory):
def __init__(self, displayname):
self.displayname = displayname
- domain = self.factory.getUniqueString()
+ domain = self.factory.getUniqueUnicode()
samples = [
- FakePOTemplate(self.factory.getUniqueString())
+ FakePOTemplate(self.factory.getUniqueUnicode())
for counter in range(3)]
samples.sort(key=attrgetter('displayname'))
diff --git a/lib/lp/translations/utilities/gettext_po_importer.py b/lib/lp/translations/utilities/gettext_po_importer.py
index 8b04120..79f99de 100644
--- a/lib/lp/translations/utilities/gettext_po_importer.py
+++ b/lib/lp/translations/utilities/gettext_po_importer.py
@@ -1,6 +1,8 @@
# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+from __future__ import absolute_import, print_function, unicode_literals
+
__metaclass__ = type
__all__ = [
diff --git a/lib/lp/translations/utilities/tests/test_gettext_po_importer.py b/lib/lp/translations/utilities/tests/test_gettext_po_importer.py
index 0c57242..65ba8f6 100644
--- a/lib/lp/translations/utilities/tests/test_gettext_po_importer.py
+++ b/lib/lp/translations/utilities/tests/test_gettext_po_importer.py
@@ -3,6 +3,8 @@
"""Gettext PO importer tests."""
+from __future__ import absolute_import, print_function, unicode_literals
+
__metaclass__ = type
from io import BytesIO
@@ -27,7 +29,7 @@ from lp.translations.interfaces.translationimportqueue import (
from lp.translations.utilities.gettext_po_importer import GettextPOImporter
-test_template = r'''
+test_template = br'''
msgid ""
msgstr ""
"PO-Revision-Date: 2005-05-03 20:41+0100\n"
@@ -38,7 +40,7 @@ msgid "foo"
msgstr ""
'''
-test_translation_file = r'''
+test_translation_file = br'''
msgid ""
msgstr ""
"PO-Revision-Date: 2005-05-03 20:41+0100\n"
diff --git a/lib/lp/translations/utilities/tests/test_kde_po_importer.py b/lib/lp/translations/utilities/tests/test_kde_po_importer.py
index 4aeb5eb..71407be 100644
--- a/lib/lp/translations/utilities/tests/test_kde_po_importer.py
+++ b/lib/lp/translations/utilities/tests/test_kde_po_importer.py
@@ -3,6 +3,8 @@
"""KDE PO importer tests."""
+from __future__ import absolute_import, print_function, unicode_literals
+
__metaclass__ = type
from io import BytesIO
@@ -31,7 +33,7 @@ from lp.translations.utilities.tests.test_gettext_po_importer import (
)
-test_kde_template = r'''
+test_kde_template = br'''
msgid ""
msgstr ""
"PO-Revision-Date: 2005-05-03 20:41+0100\n"
@@ -46,7 +48,7 @@ msgid "_: Context\nMessage"
msgstr ""
'''
-test_kde_translation_file = r'''
+test_kde_translation_file = br'''
msgid ""
msgstr ""
"PO-Revision-Date: 2005-05-03 20:41+0100\n"
diff --git a/lib/lp/translations/utilities/tests/test_translation_importer.py b/lib/lp/translations/utilities/tests/test_translation_importer.py
index 2d47d01..106ca2d 100644
--- a/lib/lp/translations/utilities/tests/test_translation_importer.py
+++ b/lib/lp/translations/utilities/tests/test_translation_importer.py
@@ -3,6 +3,8 @@
"""Translation Importer tests."""
+from __future__ import absolute_import, print_function, unicode_literals
+
__metaclass__ = type
from io import BytesIO
@@ -233,7 +235,7 @@ class TranslationImporterTestCase(TestCaseWithFactory):
existing_translation = self.factory.makeCurrentTranslationMessage(
pofile=pofile, potmsgset=potmsgset1)
- text = """
+ text = b"""
msgid ""
msgstr ""
"MIME-Version: 1.0\\n"
diff --git a/lib/lp/translations/utilities/tests/test_xpi_po_exporter.py b/lib/lp/translations/utilities/tests/test_xpi_po_exporter.py
index 982fb97..78ab7cc 100644
--- a/lib/lp/translations/utilities/tests/test_xpi_po_exporter.py
+++ b/lib/lp/translations/utilities/tests/test_xpi_po_exporter.py
@@ -5,6 +5,8 @@
# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+from __future__ import absolute_import, print_function, unicode_literals
+
__metaclass__ = type
from textwrap import dedent