launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #16201
[Merge] lp:~wgrant/launchpad/ttb-not-ttbj into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/ttb-not-ttbj into lp:launchpad with lp:~wgrant/launchpad/no-bfjo-pls as a prerequisite.
Commit message:
Flip TranslationTemplatesBuild(Job) creation on its head; everything is now build-driven like the other BuildFarmJobs.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/ttb-not-ttbj/+merge/195195
Flip TTB(J) creation on its head. Rather than having TranslationTemplatesBuildJobSource.create() implicitly create a TTB and then a TTBJ and BQ to wrap it, we instead call TranslationTemplatesBuildSource.create().queueBuild() to match the BPB and SPRB API. This lets most code ignore TTBJs, which is handy because they'll soon cease to exist.
--
https://code.launchpad.net/~wgrant/launchpad/ttb-not-ttbj/+merge/195195
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/ttb-not-ttbj into lp:launchpad.
=== modified file 'lib/lp/buildmaster/interfaces/buildfarmjob.py'
--- lib/lp/buildmaster/interfaces/buildfarmjob.py 2013-11-12 00:12:53 +0000
+++ lib/lp/buildmaster/interfaces/buildfarmjob.py 2013-11-14 10:19:29 +0000
@@ -228,6 +228,16 @@
def calculateScore():
"""Calculate the build queue priority for this job."""
+ def estimateDuration():
+ """Estimate the build duration."""
+
+ def queueBuild(suspended=False):
+ """Create a BuildQueue entry for this build.
+
+ :param suspended: Whether the associated `Job` instance should be
+ created in a suspended state.
+ """
+
title = exported(TextLine(title=_("Title"), required=False),
as_of="beta")
=== modified file 'lib/lp/buildmaster/interfaces/packagebuild.py'
--- lib/lp/buildmaster/interfaces/packagebuild.py 2013-02-04 06:58:14 +0000
+++ lib/lp/buildmaster/interfaces/packagebuild.py 2013-11-14 10:19:29 +0000
@@ -69,9 +69,6 @@
title=_("Distribution series"), required=True,
description=_("Shortcut for its distribution series.")))
- def estimateDuration():
- """Estimate the build duration."""
-
def verifySuccessfulUpload():
"""Verify that the upload of this build completed succesfully."""
@@ -91,13 +88,6 @@
upload log.
"""
- def queueBuild(suspended=False):
- """Create a BuildQueue entry for this build.
-
- :param suspended: Whether the associated `Job` instance should be
- created in a suspended state.
- """
-
def getUploader(changes):
"""Return the person responsible for the upload.
=== modified file 'lib/lp/buildmaster/model/buildfarmjob.py'
--- lib/lp/buildmaster/model/buildfarmjob.py 2013-11-12 00:12:53 +0000
+++ lib/lp/buildmaster/model/buildfarmjob.py 2013-11-14 10:19:29 +0000
@@ -39,6 +39,7 @@
IBuildFarmJobSet,
IBuildFarmJobSource,
)
+from lp.buildmaster.model.buildqueue import BuildQueue
from lp.services.database.enumcol import DBEnum
from lp.services.database.interfaces import (
IMasterStore,
@@ -223,6 +224,28 @@
"""See `IBuildFarmJob`."""
raise NotImplementedError
+ def estimateDuration(self):
+ """See `IBuildFarmJob`."""
+ raise NotImplementedError
+
+ def queueBuild(self, suspended=False):
+ """See `IBuildFarmJob`."""
+ specific_job = self.makeJob()
+
+ # This build queue job is to be created in a suspended state.
+ if suspended:
+ specific_job.job.suspend()
+
+ duration_estimate = self.estimateDuration()
+ job = specific_job.job
+ queue_entry = BuildQueue(
+ estimated_duration=duration_estimate,
+ job_type=self.job_type,
+ job=job, processor=self.processor,
+ virtualized=self.virtualized)
+ Store.of(self).add(queue_entry)
+ return queue_entry
+
class SpecificBuildFarmJobSourceMixin:
=== modified file 'lib/lp/buildmaster/model/packagebuild.py'
--- lib/lp/buildmaster/model/packagebuild.py 2013-11-11 07:17:29 +0000
+++ lib/lp/buildmaster/model/packagebuild.py 2013-11-14 10:19:29 +0000
@@ -9,12 +9,10 @@
from cStringIO import StringIO
-from storm.locals import Store
from zope.component import getUtility
from lp.buildmaster.enums import BuildStatus
from lp.buildmaster.model.buildfarmjob import BuildFarmJobMixin
-from lp.buildmaster.model.buildqueue import BuildQueue
from lp.services.helpers import filenameToContentType
from lp.services.librarian.browser import ProxiedLibraryFileAlias
from lp.services.librarian.interfaces import ILibraryFileAliasSet
@@ -50,10 +48,6 @@
"""See `IBuildFarmJob`"""
return self.archive.private
- def estimateDuration(self):
- """See `IPackageBuild`."""
- raise NotImplementedError
-
def updateStatus(self, status, builder=None, slave_status=None,
date_started=None, date_finished=None):
super(PackageBuildMixin, self).updateStatus(
@@ -109,21 +103,3 @@
def getUploader(self, changes):
"""See `IPackageBuild`."""
raise NotImplementedError
-
- def queueBuild(self, suspended=False):
- """See `IPackageBuild`."""
- specific_job = self.makeJob()
-
- # This build queue job is to be created in a suspended state.
- if suspended:
- specific_job.job.suspend()
-
- duration_estimate = self.estimateDuration()
- job = specific_job.job
- queue_entry = BuildQueue(
- estimated_duration=duration_estimate,
- job_type=self.job_type,
- job=job, processor=self.processor,
- virtualized=self.virtualized)
- Store.of(self).add(queue_entry)
- return queue_entry
=== modified file 'lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py'
--- lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py 2013-11-12 09:07:01 +0000
+++ lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py 2013-11-14 10:19:29 +0000
@@ -69,7 +69,7 @@
distroarchseries=distroarchseries, pocket=pocket, archive=archive)
def test_getBuildCookie(self):
- build = self.factory.makeTranslationTemplatesBuildJob().build
+ build = self.factory.makeTranslationTemplatesBuild()
behavior = self._makeBehavior(build)
self.assertEqual(
'%s-%s' % (build.job_type.name, build.id),
=== modified file 'lib/lp/codehosting/scanner/bzrsync.py'
--- lib/lp/codehosting/scanner/bzrsync.py 2012-06-26 10:23:26 +0000
+++ lib/lp/codehosting/scanner/bzrsync.py 2013-11-14 10:19:29 +0000
@@ -35,8 +35,8 @@
from lp.codehosting.scanner import events
from lp.services.config import config
from lp.services.utils import iter_list_chunks
-from lp.translations.interfaces.translationtemplatesbuildjob import (
- ITranslationTemplatesBuildJobSource,
+from lp.translations.interfaces.translationtemplatesbuild import (
+ ITranslationTemplatesBuildSource,
)
@@ -313,7 +313,7 @@
def schedule_translation_templates_build(tip_changed):
- utility = getUtility(ITranslationTemplatesBuildJobSource)
+ utility = getUtility(ITranslationTemplatesBuildSource)
utility.scheduleTranslationTemplatesBuild(tip_changed.db_branch)
=== modified file 'lib/lp/soyuz/browser/tests/test_builder.py'
--- lib/lp/soyuz/browser/tests/test_builder.py 2013-11-14 07:36:26 +0000
+++ lib/lp/soyuz/browser/tests/test_builder.py 2013-11-14 10:19:29 +0000
@@ -9,8 +9,6 @@
from zope.component import getUtility
from lp.buildmaster.interfaces.builder import IBuilderSet
-from lp.buildmaster.model.buildqueue import BuildQueue
-from lp.services.database.interfaces import IStore
from lp.services.job.model.job import Job
from lp.soyuz.browser.tests.test_builder_views import BuildCreationMixin
from lp.testing import (
@@ -20,9 +18,6 @@
from lp.testing.layers import LaunchpadFunctionalLayer
from lp.testing.matchers import HasQueryCount
from lp.testing.views import create_initialized_view
-from lp.translations.interfaces.translationtemplatesbuildjob import (
- ITranslationTemplatesBuildJobSource,
- )
def builders_homepage_render():
@@ -43,7 +38,7 @@
# even further, detecting more preloading issues.
self.factory.makeBinaryPackageBuild().queueBuild()
self.factory.makeSourcePackageRecipeBuild().queueBuild()
- self.factory.makeTranslationTemplatesBuildJob()
+ self.factory.makeTranslationTemplatesBuild().queueBuild()
def test_builders_binary_package_build_query_count(self):
def create_build():
@@ -69,11 +64,7 @@
def test_builders_translation_template_build_query_count(self):
def create_build():
- jobset = getUtility(ITranslationTemplatesBuildJobSource)
- branch = self.factory.makeBranch()
- specific_job = jobset.create(branch)
- queue = IStore(BuildQueue).find(
- BuildQueue, job=specific_job.job).one()
+ queue = self.factory.makeTranslationTemplatesBuild().queueBuild()
queue.markAsBuilding(self.factory.makeBuilder())
nb_objects = 2
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2013-11-14 07:36:26 +0000
+++ lib/lp/testing/factory.py 2013-11-14 10:19:29 +0000
@@ -96,10 +96,7 @@
ICveSet,
)
from lp.bugs.model.bug import FileBugData
-from lp.buildmaster.enums import (
- BuildFarmJobType,
- BuildStatus,
- )
+from lp.buildmaster.enums import BuildStatus
from lp.buildmaster.interfaces.builder import IBuilderSet
from lp.code.enums import (
BranchMergeProposalStatus,
@@ -333,8 +330,8 @@
RosettaTranslationOrigin,
)
from lp.translations.interfaces.translationsperson import ITranslationsPerson
-from lp.translations.interfaces.translationtemplatesbuildjob import (
- ITranslationTemplatesBuildJobSource,
+from lp.translations.interfaces.translationtemplatesbuild import (
+ ITranslationTemplatesBuildSource,
)
from lp.translations.interfaces.translator import ITranslatorSet
from lp.translations.model.translationtemplateitem import (
@@ -2866,16 +2863,16 @@
IStore(spr_build).flush()
return spr_build
- def makeTranslationTemplatesBuildJob(self, branch=None):
- """Make a new `TranslationTemplatesBuildJob`.
+ def makeTranslationTemplatesBuild(self, branch=None):
+ """Make a new `TranslationTemplatesBuild`.
- :param branch: The branch that the job should be for. If none
+ :param branch: The branch that the build should be for. If none
is given, one will be created.
"""
if branch is None:
branch = self.makeBranch()
- jobset = getUtility(ITranslationTemplatesBuildJobSource)
+ jobset = getUtility(ITranslationTemplatesBuildSource)
return jobset.create(branch)
def makePOTemplate(self, productseries=None, distroseries=None,
=== modified file 'lib/lp/translations/interfaces/translationtemplatesbuild.py'
--- lib/lp/translations/interfaces/translationtemplatesbuild.py 2013-01-31 10:38:23 +0000
+++ lib/lp/translations/interfaces/translationtemplatesbuild.py 2013-11-14 10:19:29 +0000
@@ -35,3 +35,13 @@
def findByBranch(branch, store=None):
"""Find `ITranslationTemplatesBuild`s for `branch`."""
+
+ def generatesTemplates(branch):
+ """Can this branch usefully generate translation templates?
+
+ If yes, then use `create` to schedule a build-farm job to
+ generate the templates based on the source code in the branch.
+ """
+
+ def scheduleTranslationTemplatesBuild(branch):
+ """Schedule a translation templates build job, if appropriate."""
=== modified file 'lib/lp/translations/interfaces/translationtemplatesbuildjob.py'
--- lib/lp/translations/interfaces/translationtemplatesbuildjob.py 2013-01-07 02:40:55 +0000
+++ lib/lp/translations/interfaces/translationtemplatesbuildjob.py 2013-11-14 10:19:29 +0000
@@ -13,25 +13,5 @@
class ITranslationTemplatesBuildJobSource(Interface):
"""Container for `TranslationTemplatesBuildJob`s."""
- def generatesTemplates(branch):
- """Can this branch usefully generate translation templates?
-
- If yes, then use `create` to schedule a build-farm job to
- generate the templates based on the source code in the branch.
- """
-
- def create(branch):
- """Create new `TranslationTemplatesBuildJob`.
-
- Also creates the matching `IBuildQueue` and `IJob`.
-
- :param branch: A `Branch` that this job will check out and
- generate templates for.
- :return: A new `TranslationTemplatesBuildJob`.
- """
-
- def scheduleTranslationTemplatesBuild(branch):
- """Schedule a translation templates build job, if appropriate."""
-
def getByBranch(branch):
"""Find `TranslationTemplatesBuildJob` for given `Branch`."""
=== modified file 'lib/lp/translations/model/translationtemplatesbuild.py'
--- lib/lp/translations/model/translationtemplatesbuild.py 2013-11-12 00:12:53 +0000
+++ lib/lp/translations/model/translationtemplatesbuild.py 2013-11-14 10:19:29 +0000
@@ -9,12 +9,16 @@
'TranslationTemplatesBuild',
]
+from datetime import timedelta
+import logging
+
import pytz
from storm.locals import (
Bool,
DateTime,
Int,
Reference,
+ Store,
Storm,
)
from zope.component import getUtility
@@ -22,6 +26,7 @@
classProvides,
implements,
)
+from zope.security.proxy import removeSecurityProxy
from lp.app.interfaces.launchpad import ILaunchpadCelebrities
from lp.buildmaster.enums import (
@@ -33,6 +38,7 @@
BuildFarmJobMixin,
SpecificBuildFarmJobSourceMixin,
)
+from lp.code.interfaces.branchjob import IRosettaUploadJobSource
from lp.code.model.branch import Branch
from lp.code.model.branchcollection import GenericBranchCollection
from lp.code.model.branchjob import (
@@ -40,6 +46,7 @@
BranchJobType,
)
from lp.registry.model.product import Product
+from lp.services.config import config
from lp.services.database.bulk import load_related
from lp.services.database.decoratedresultset import DecoratedResultSet
from lp.services.database.enumcol import DBEnum
@@ -51,6 +58,7 @@
from lp.translations.model.translationtemplatesbuildjob import (
TranslationTemplatesBuildJob,
)
+from lp.translations.pottery.detect_intltool import is_intltool_structure
HARDCODED_TRANSLATIONTEMPLATESBUILD_SCORE = 2510
@@ -105,11 +113,14 @@
self.branch = branch
self.status = BuildStatus.NEEDSBUILD
self.processor = processor
+ self.virtualized = True
+
+ def estimateDuration(self):
+ """See `IBuildFarmJob`."""
+ return timedelta(seconds=10)
def makeJob(self):
- """See `IBuildFarmJobOld`."""
- store = IStore(BranchJob)
-
+ """See `IBuildFarmJob`."""
# Pass public HTTP URL for the branch.
metadata = {
'branch_url': self.branch.composePublicURL(),
@@ -117,7 +128,7 @@
}
branch_job = BranchJob(
self.branch, BranchJobType.TRANSLATION_TEMPLATES_BUILD, metadata)
- store.add(branch_job)
+ Store.of(self).add(branch_job)
return TranslationTemplatesBuildJob(branch_job)
@classmethod
@@ -138,6 +149,42 @@
return ubuntu.currentseries.nominatedarchindep.processor
@classmethod
+ def _hasPotteryCompatibleSetup(cls, branch):
+ """Does `branch` look as if pottery can generate templates for it?
+
+ :param branch: A `Branch` object.
+ """
+ bzr_branch = removeSecurityProxy(branch).getBzrBranch()
+ return is_intltool_structure(bzr_branch.basis_tree())
+
+ @classmethod
+ def generatesTemplates(cls, branch):
+ """See `ITranslationTemplatesBuildJobSource`."""
+ logger = logging.getLogger('translation-templates-build')
+ if branch.private:
+ # We don't support generating template from private branches
+ # at the moment.
+ logger.debug("Branch %s is private.", branch.unique_name)
+ return False
+
+ utility = getUtility(IRosettaUploadJobSource)
+ if not utility.providesTranslationFiles(branch):
+ # Nobody asked for templates generated from this branch.
+ logger.debug(
+ "No templates requested for branch %s.",
+ branch.unique_name)
+ return False
+
+ if not cls._hasPotteryCompatibleSetup(branch):
+ # Nothing we could do with this branch if we wanted to.
+ logger.debug(
+ "Branch %s is not pottery-compatible.", branch.unique_name)
+ return False
+
+ # Yay! We made it.
+ return True
+
+ @classmethod
def create(cls, branch):
"""See `ITranslationTemplatesBuildSource`."""
processor = cls._getBuildArch()
@@ -150,6 +197,26 @@
return build
@classmethod
+ def scheduleTranslationTemplatesBuild(cls, branch):
+ """See `ITranslationTemplatesBuildJobSource`."""
+ logger = logging.getLogger('translation-templates-build')
+ if not config.rosetta.generate_templates:
+ # This feature is disabled by default.
+ logging.debug("Templates generation is disabled.")
+ return
+
+ try:
+ if cls.generatesTemplates(branch):
+ # This branch is used for generating templates.
+ logger.info(
+ "Requesting templates build for branch %s.",
+ branch.unique_name)
+ cls.create(branch).queueBuild()
+ except Exception as e:
+ logger.error(e)
+ raise
+
+ @classmethod
def getByID(cls, build_id, store=None):
"""See `ITranslationTemplatesBuildSource`."""
store = cls._getStore(store)
=== modified file 'lib/lp/translations/model/translationtemplatesbuildjob.py'
--- lib/lp/translations/model/translationtemplatesbuildjob.py 2013-11-12 00:12:53 +0000
+++ lib/lp/translations/model/translationtemplatesbuildjob.py 2013-11-14 10:19:29 +0000
@@ -6,40 +6,28 @@
'TranslationTemplatesBuildJob',
]
-from datetime import timedelta
-import logging
-
from storm.store import Store
from zope.component import getUtility
from zope.interface import (
classProvides,
implements,
)
-from zope.security.proxy import removeSecurityProxy
-from lp.buildmaster.enums import BuildFarmJobType
from lp.buildmaster.interfaces.buildfarmbranchjob import IBuildFarmBranchJob
from lp.buildmaster.model.buildfarmjob import BuildFarmJobOld
-from lp.buildmaster.model.buildqueue import BuildQueue
-from lp.code.interfaces.branchjob import IRosettaUploadJobSource
from lp.code.model.branchjob import (
BranchJob,
BranchJobDerived,
BranchJobType,
)
-from lp.services.config import config
from lp.services.database.bulk import load_related
-from lp.services.database.interfaces import (
- IMasterStore,
- IStore,
- )
+from lp.services.database.interfaces import IStore
from lp.translations.interfaces.translationtemplatesbuild import (
ITranslationTemplatesBuildSource,
)
from lp.translations.interfaces.translationtemplatesbuildjob import (
ITranslationTemplatesBuildJobSource,
)
-from lp.translations.pottery.detect_intltool import is_intltool_structure
class TranslationTemplatesBuildJob(BuildFarmJobOld, BranchJobDerived):
@@ -52,8 +40,6 @@
classProvides(ITranslationTemplatesBuildJobSource)
- duration_estimate = timedelta(seconds=10)
-
def cleanUp(self):
"""See `IBuildFarmJob`."""
# This class is not itself database-backed. But it delegates to
@@ -73,88 +59,6 @@
int(build_id))
@classmethod
- def _hasPotteryCompatibleSetup(cls, branch):
- """Does `branch` look as if pottery can generate templates for it?
-
- :param branch: A `Branch` object.
- """
- bzr_branch = removeSecurityProxy(branch).getBzrBranch()
- return is_intltool_structure(bzr_branch.basis_tree())
-
- @classmethod
- def generatesTemplates(cls, branch):
- """See `ITranslationTemplatesBuildJobSource`."""
- logger = logging.getLogger('translation-templates-build')
- if branch.private:
- # We don't support generating template from private branches
- # at the moment.
- logger.debug("Branch %s is private.", branch.unique_name)
- return False
-
- utility = getUtility(IRosettaUploadJobSource)
- if not utility.providesTranslationFiles(branch):
- # Nobody asked for templates generated from this branch.
- logger.debug(
- "No templates requested for branch %s.",
- branch.unique_name)
- return False
-
- if not cls._hasPotteryCompatibleSetup(branch):
- # Nothing we could do with this branch if we wanted to.
- logger.debug(
- "Branch %s is not pottery-compatible.", branch.unique_name)
- return False
-
- # Yay! We made it.
- return True
-
- @classmethod
- def create(cls, branch, testing=False):
- """See `ITranslationTemplatesBuildJobSource`."""
- logger = logging.getLogger('translation-templates-build')
-
- build = getUtility(ITranslationTemplatesBuildSource).create(
- branch)
- logger.debug("Made TranslationTemplatesBuild %s.", build.id)
-
- specific_job = build.makeJob()
- if testing:
- removeSecurityProxy(specific_job)._constructed_build = build
- logger.debug("Made %s.", specific_job)
-
- duration_estimate = cls.duration_estimate
-
- build_queue_entry = BuildQueue(
- estimated_duration=duration_estimate,
- job_type=BuildFarmJobType.TRANSLATIONTEMPLATESBUILD,
- job=specific_job.job, processor=build.processor)
- IMasterStore(BuildQueue).add(build_queue_entry)
-
- logger.debug("Made BuildQueue %s.", build_queue_entry.id)
-
- return specific_job
-
- @classmethod
- def scheduleTranslationTemplatesBuild(cls, branch):
- """See `ITranslationTemplatesBuildJobSource`."""
- logger = logging.getLogger('translation-templates-build')
- if not config.rosetta.generate_templates:
- # This feature is disabled by default.
- logging.debug("Templates generation is disabled.")
- return
-
- try:
- if cls.generatesTemplates(branch):
- # This branch is used for generating templates.
- logger.info(
- "Requesting templates build for branch %s.",
- branch.unique_name)
- cls.create(branch)
- except Exception as e:
- logger.error(e)
- raise
-
- @classmethod
def getByJob(cls, job):
"""See `IBuildFarmJob`.
=== modified file 'lib/lp/translations/stories/buildfarm/xx-build-summary.txt'
--- lib/lp/translations/stories/buildfarm/xx-build-summary.txt 2013-09-02 08:11:21 +0000
+++ lib/lp/translations/stories/buildfarm/xx-build-summary.txt 2013-11-14 10:19:29 +0000
@@ -12,10 +12,8 @@
>>> from testtools.monkey import patch
>>> from zope.component import getUtility
>>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
- >>> from lp.buildmaster.model.buildqueue import BuildQueue
>>> from lp.app.enums import ServiceUsage
>>> from lp.buildmaster.interactor import BuilderSlave
- >>> from lp.services.database.interfaces import IStore
>>> from lp.services.librarian.interfaces import (
... ILibraryFileAliasSet)
>>> from lp.testing.factory import (
@@ -45,9 +43,8 @@
>>> naked_productseries.branch = factory.makeBranch()
>>> naked_productseries.translations_autoimport_mode = (
... TranslationsBranchImportMode.IMPORT_TEMPLATES)
- >>> specific_job = factory.makeTranslationTemplatesBuildJob(branch=branch)
- >>> buildqueue = IStore(BuildQueue).find(
- ... BuildQueue, job=specific_job.job).one()
+ >>> build = factory.makeTranslationTemplatesBuild(branch=branch)
+ >>> buildqueue = build.queueBuild()
>>> fake_chroot = getUtility(ILibraryFileAliasSet)[1]
>>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
=== modified file 'lib/lp/translations/tests/test_translationtemplatesbuild.py'
--- lib/lp/translations/tests/test_translationtemplatesbuild.py 2013-11-12 07:39:51 +0000
+++ lib/lp/translations/tests/test_translationtemplatesbuild.py 2013-11-14 10:19:29 +0000
@@ -7,12 +7,23 @@
from storm.store import Store
from zope.component import getUtility
+from zope.event import notify
from zope.interface.verify import verifyObject
+from zope.security.proxy import removeSecurityProxy
+from lp.app.enums import InformationType
+from lp.app.interfaces.launchpad import ILaunchpadCelebrities
from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJob
+from lp.code.model.branchjob import BranchJob
+from lp.code.model.directbranchcommit import DirectBranchCommit
+from lp.codehosting.scanner import events
+from lp.services.database.interfaces import IStore
from lp.testing import TestCaseWithFactory
from lp.testing.dbuser import switch_dbuser
from lp.testing.layers import LaunchpadZopelessLayer
+from lp.translations.interfaces.translations import (
+ TranslationsBranchImportMode,
+ )
from lp.translations.interfaces.translationtemplatesbuild import (
ITranslationTemplatesBuild,
ITranslationTemplatesBuildSource,
@@ -20,12 +31,76 @@
from lp.translations.model.translationtemplatesbuild import (
TranslationTemplatesBuild,
)
+from lp.translations.model.translationtemplatesbuildjob import (
+ TranslationTemplatesBuildJob,
+ )
+
+
+class FakeTranslationTemplatesSource(TranslationTemplatesBuild):
+ """Fake utility class.
+
+ Allows overriding of _hasPotteryCompatibleSetup.
+
+ How do you fake a utility that is implemented as a class, not a
+ factory? By inheriting from `TranslationTemplatesBuild`, this class
+ "copies" the utility. But you can make it fake the utility's
+ behavior by setting an attribute of the class (not an object!) at
+ the beginning of every test.
+ """
+ # Fake _hasPotteryCompatibleSetup, and if so, make it give what
+ # answer?
+ fake_pottery_compatibility = None
+
+ @classmethod
+ def _hasPotteryCompatibleSetup(cls, branch):
+ if cls.fake_pottery_compatibility is None:
+ # No fake compatibility setting call the real method.
+ return TranslationTemplatesBuild._hasPotteryCompatibleSetup(
+ branch)
+ else:
+ # Fake pottery compatibility.
+ return cls.fake_pottery_compatibility
class TestTranslationTemplatesBuild(TestCaseWithFactory):
layer = LaunchpadZopelessLayer
+ def setUp(self):
+ super(TestTranslationTemplatesBuild, self).setUp()
+ self.jobsource = FakeTranslationTemplatesSource
+ self.jobsource.fake_pottery_compabitility = None
+
+ def tearDown(self):
+ self._fakePotteryCompatibleSetup(compatible=None)
+ super(TestTranslationTemplatesBuild, self).tearDown()
+
+ def _makeTranslationBranch(self, fake_pottery_compatible=None):
+ """Create a branch that provides translations for a productseries."""
+ if fake_pottery_compatible is None:
+ self.useBzrBranches(direct_database=True)
+ branch, tree = self.create_branch_and_tree()
+ else:
+ branch = self.factory.makeAnyBranch()
+ product = removeSecurityProxy(branch.product)
+ trunk = product.getSeries('trunk')
+ trunk.branch = branch
+ trunk.translations_autoimport_mode = (
+ TranslationsBranchImportMode.IMPORT_TEMPLATES)
+
+ self._fakePotteryCompatibleSetup(fake_pottery_compatible)
+
+ return branch
+
+ def _fakePotteryCompatibleSetup(self, compatible=True):
+ """Mock up branch compatibility check.
+
+ :param compatible: Whether the mock check should say that
+ branches have a pottery-compatible setup, or that they
+ don't.
+ """
+ self.jobsource.fake_pottery_compatibility = compatible
+
def test_baseline(self):
branch = self.factory.makeBranch()
build = getUtility(ITranslationTemplatesBuildSource).create(branch)
@@ -45,23 +120,95 @@
# restrictions.
Store.of(build).flush()
- def test_created_by_buildjobsource(self):
- # ITranslationTemplatesBuildJobSource.create also creates a
- # TranslationTemplatesBuild. This utility will become obsolete
- # later.
- source = getUtility(ITranslationTemplatesBuildSource)
- branch = self.factory.makeBranch()
- source.create(branch)
+ def test_queueBuild(self):
+ build = self.factory.makeTranslationTemplatesBuild()
+ bq = build.queueBuild()
+ self.assertEqual(build, bq.specific_job.build)
+ self.assertEqual(build, bq.specific_build)
+ ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
+ self.assertEquals(
+ ubuntu.currentseries.nominatedarchindep.processor, bq.processor)
- builds = list(source.findByBranch(branch))
- self.assertEqual(1, len(builds))
- self.assertIsInstance(builds[0], TranslationTemplatesBuild)
+ # A job is created with the branch URL in its metadata.
+ metadata = bq.specific_job.metadata
+ self.assertIn('branch_url', metadata)
+ url = metadata['branch_url']
+ head = 'http://'
+ self.assertEqual(head, url[:len(head)])
+ tail = build.branch.name
+ self.assertEqual(tail, url[-len(tail):])
def test_score(self):
# For now, these jobs always score themselves at 2510. In the
# future however the scoring system is to be revisited.
- job = self.factory.makeTranslationTemplatesBuildJob()
- self.assertEqual(2510, job.build.calculateScore())
+ build = self.factory.makeTranslationTemplatesBuild()
+ self.assertEqual(2510, build.calculateScore())
+
+ def test_generatesTemplates(self):
+ # A branch "generates templates" if it is a translation branch
+ # for a productseries that imports templates from it; is not
+ # private; and has a pottery compatible setup.
+ # For convenience we fake the pottery compatibility here.
+ branch = self._makeTranslationBranch(fake_pottery_compatible=True)
+ self.assertTrue(self.jobsource.generatesTemplates(branch))
+
+ def test_not_pottery_compatible(self):
+ # If pottery does not see any files it can work with in the
+ # branch, generatesTemplates returns False.
+ branch = self._makeTranslationBranch()
+ self.assertFalse(self.jobsource.generatesTemplates(branch))
+
+ def test_branch_not_used(self):
+ # We don't generate templates branches not attached to series.
+ branch = self._makeTranslationBranch(fake_pottery_compatible=True)
+
+ trunk = branch.product.getSeries('trunk')
+ removeSecurityProxy(trunk).branch = None
+
+ self.assertFalse(self.jobsource.generatesTemplates(branch))
+
+ def test_not_importing_templates(self):
+ # We don't generate templates when imports are disabled.
+ branch = self._makeTranslationBranch(fake_pottery_compatible=True)
+
+ trunk = branch.product.getSeries('trunk')
+ removeSecurityProxy(trunk).translations_autoimport_mode = (
+ TranslationsBranchImportMode.NO_IMPORT)
+
+ self.assertFalse(self.jobsource.generatesTemplates(branch))
+
+ def test_private_branch(self):
+ # We don't generate templates for private branches.
+ branch = self._makeTranslationBranch(fake_pottery_compatible=True)
+ removeSecurityProxy(branch).information_type = (
+ InformationType.USERDATA)
+ self.assertFalse(self.jobsource.generatesTemplates(branch))
+
+ def test_scheduleTranslationTemplatesBuild_subscribed(self):
+ # If the feature is enabled, a TipChanged event for a branch that
+ # generates templates will schedule a templates build.
+ branch = self._makeTranslationBranch()
+ removeSecurityProxy(branch).last_scanned_id = 'null:'
+ commit = DirectBranchCommit(branch)
+ commit.writeFile('POTFILES.in', 'foo')
+ commit.commit('message')
+ notify(events.TipChanged(branch, None, False))
+ branchjobs = list(TranslationTemplatesBuildJob.iterReady())
+ self.assertEqual(1, len(branchjobs))
+ self.assertEqual(branch, branchjobs[0].branch)
+
+ def test_scheduleTranslationTemplatesBuild(self):
+ # If the feature is enabled, scheduleTranslationTemplatesBuild
+ # will schedule a templates build whenever a change is pushed to
+ # a branch that generates templates.
+ branch = self._makeTranslationBranch(fake_pottery_compatible=True)
+
+ self.jobsource.scheduleTranslationTemplatesBuild(branch)
+
+ store = IStore(BranchJob)
+ branchjobs = list(store.find(BranchJob, BranchJob.branch == branch))
+ self.assertEqual(1, len(branchjobs))
+ self.assertEqual(branch, branchjobs[0].branch)
def test_findByBranch(self):
source = getUtility(ITranslationTemplatesBuildSource)
=== modified file 'lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py'
--- lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py 2013-11-12 06:03:14 +0000
+++ lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py 2013-11-14 10:19:29 +0000
@@ -63,9 +63,8 @@
Anything that might communicate with build slaves and such
(which we can't really do here) is mocked up.
"""
- specific_job = self.factory.makeTranslationTemplatesBuildJob(
- branch=branch)
- behavior = IBuildFarmJobBehavior(specific_job.build)
+ build = self.factory.makeTranslationTemplatesBuild(branch=branch)
+ behavior = IBuildFarmJobBehavior(build)
slave = WaitingSlave(**kwargs)
behavior.setBuilder(self.factory.makeBuilder(), slave)
if use_fake_chroot:
@@ -73,7 +72,8 @@
self.layer.txn.commit()
behavior._getChroot = lambda: lf
if want_bfjo:
- return behavior, specific_job
+ bq = build.queueBuild()
+ return behavior, bq.specific_job
else:
return behavior
=== modified file 'lib/lp/translations/tests/test_translationtemplatesbuildjob.py'
--- lib/lp/translations/tests/test_translationtemplatesbuildjob.py 2013-11-12 07:39:51 +0000
+++ lib/lp/translations/tests/test_translationtemplatesbuildjob.py 2013-11-14 10:19:29 +0000
@@ -5,19 +5,12 @@
from storm.store import Store
from zope.component import getUtility
-from zope.event import notify
from zope.security.proxy import removeSecurityProxy
-from lp.app.enums import InformationType
-from lp.app.interfaces.launchpad import ILaunchpadCelebrities
from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJobOld
-from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet
from lp.buildmaster.model.buildqueue import BuildQueue
from lp.code.interfaces.branch import IBranchSet
from lp.code.interfaces.branchjob import IBranchJob
-from lp.code.model.branchjob import BranchJob
-from lp.code.model.directbranchcommit import DirectBranchCommit
-from lp.codehosting.scanner import events
from lp.services.database.interfaces import IStore
from lp.services.job.model.job import Job
from lp.testing import (
@@ -28,9 +21,6 @@
LaunchpadZopelessLayer,
ZopelessDatabaseLayer,
)
-from lp.translations.interfaces.translations import (
- TranslationsBranchImportMode,
- )
from lp.translations.interfaces.translationtemplatesbuildjob import (
ITranslationTemplatesBuildJobSource,
)
@@ -52,8 +42,9 @@
def setUp(self):
super(TestTranslationTemplatesBuildJob, self).setUp()
self.jobset = getUtility(ITranslationTemplatesBuildJobSource)
- self.branch = self.factory.makeBranch()
- self.specific_job = self.jobset.create(self.branch)
+ self.build = self.factory.makeTranslationTemplatesBuild()
+ self.build.queueBuild()
+ self.specific_job = self.jobset.getByBranch(self.build.branch)
def test_new_TranslationTemplatesBuildJob(self):
# TranslationTemplateBuildJob implements IBuildFarmJobOld,
@@ -62,7 +53,7 @@
verifyObject(IBuildFarmJobOld, self.specific_job)
# Each of these jobs knows the branch it will operate on.
- self.assertEqual(self.branch, self.specific_job.branch)
+ self.assertEqual(self.build.branch, self.specific_job.branch)
def test_has_Job(self):
# Associated with each TranslationTemplateBuildJob is a Job.
@@ -75,26 +66,6 @@
TranslationTemplatesBuildJob.getByJob(base_job))
self.assertEqual(self.specific_job, specific_job_for_base_job)
- def test_has_BuildQueue(self):
- # There's also a BuildQueue item associated with the job.
- queueset = getUtility(IBuildQueueSet)
- job_id = get_job_id(self.specific_job.job)
- buildqueue = queueset.get(job_id)
-
- self.assertIsInstance(buildqueue, BuildQueue)
- self.assertEqual(job_id, get_job_id(buildqueue.job))
-
- def test_BuildQueue_for_arch(self):
- # BuildQueue entry is for i386 (default Ubuntu) architecture.
- queueset = getUtility(IBuildQueueSet)
- job_id = get_job_id(self.specific_job.job)
- buildqueue = queueset.get(job_id)
-
- ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
- self.assertEquals(
- ubuntu.currentseries.nominatedarchindep.processor,
- buildqueue.processor)
-
def test_cleanUp(self):
# TranslationTemplatesBuildJob has its own customized cleanup
# behaviour, since it's actually a BranchJob.
@@ -103,7 +74,7 @@
job_id = job.id
store = Store.of(job)
- branch_name = self.branch.unique_name
+ branch_name = self.build.branch.unique_name
buildqueue.destroySelf()
@@ -116,33 +87,8 @@
self.assertIs(None, TranslationTemplatesBuildJob.getByJob(job_id))
# Branch is still here.
branch_set = getUtility(IBranchSet)
- self.assertEqual(self.branch, branch_set.getByUniqueName(branch_name))
-
-
-class FakeTranslationTemplatesJobSource(TranslationTemplatesBuildJob):
- """Fake utility class.
-
- Allows overriding of _hasPotteryCompatibleSetup.
-
- How do you fake a utility that is implemented as a class, not a
- factory? By inheriting from `TranslationTemplatesJob`, this class
- "copies" the utility. But you can make it fake the utility's
- behavior by setting an attribute of the class (not an object!) at
- the beginning of every test.
- """
- # Fake _hasPotteryCompatibleSetup, and if so, make it give what
- # answer?
- fake_pottery_compatibility = None
-
- @classmethod
- def _hasPotteryCompatibleSetup(cls, branch):
- if cls.fake_pottery_compatibility is None:
- # No fake compatibility setting call the real method.
- return TranslationTemplatesBuildJob._hasPotteryCompatibleSetup(
- branch)
- else:
- # Fake pottery compatibility.
- return cls.fake_pottery_compatibility
+ self.assertEqual(
+ self.build.branch, branch_set.getByUniqueName(branch_name))
class TestTranslationTemplatesBuildJobSource(TestCaseWithFactory):
@@ -150,127 +96,7 @@
layer = LaunchpadZopelessLayer
- def setUp(self):
- super(TestTranslationTemplatesBuildJobSource, self).setUp()
- self.jobsource = FakeTranslationTemplatesJobSource
- self.jobsource.fake_pottery_compabitility = None
-
- def tearDown(self):
- self._fakePotteryCompatibleSetup(compatible=None)
- super(TestTranslationTemplatesBuildJobSource, self).tearDown()
-
- def _makeTranslationBranch(self, fake_pottery_compatible=None):
- """Create a branch that provides translations for a productseries."""
- if fake_pottery_compatible is None:
- self.useBzrBranches(direct_database=True)
- branch, tree = self.create_branch_and_tree()
- else:
- branch = self.factory.makeAnyBranch()
- product = removeSecurityProxy(branch.product)
- trunk = product.getSeries('trunk')
- trunk.branch = branch
- trunk.translations_autoimport_mode = (
- TranslationsBranchImportMode.IMPORT_TEMPLATES)
-
- self._fakePotteryCompatibleSetup(fake_pottery_compatible)
-
- return branch
-
- def _fakePotteryCompatibleSetup(self, compatible=True):
- """Mock up branch compatibility check.
-
- :param compatible: Whether the mock check should say that
- branches have a pottery-compatible setup, or that they
- don't.
- """
- self.jobsource.fake_pottery_compatibility = compatible
-
def test_baseline(self):
utility = getUtility(ITranslationTemplatesBuildJobSource)
verifyObject(ITranslationTemplatesBuildJobSource, utility)
- def test_generatesTemplates(self):
- # A branch "generates templates" if it is a translation branch
- # for a productseries that imports templates from it; is not
- # private; and has a pottery compatible setup.
- # For convenience we fake the pottery compatibility here.
- branch = self._makeTranslationBranch(fake_pottery_compatible=True)
- self.assertTrue(self.jobsource.generatesTemplates(branch))
-
- def test_not_pottery_compatible(self):
- # If pottery does not see any files it can work with in the
- # branch, generatesTemplates returns False.
- branch = self._makeTranslationBranch()
- self.assertFalse(self.jobsource.generatesTemplates(branch))
-
- def test_branch_not_used(self):
- # We don't generate templates branches not attached to series.
- branch = self._makeTranslationBranch(fake_pottery_compatible=True)
-
- trunk = branch.product.getSeries('trunk')
- removeSecurityProxy(trunk).branch = None
-
- self.assertFalse(self.jobsource.generatesTemplates(branch))
-
- def test_not_importing_templates(self):
- # We don't generate templates when imports are disabled.
- branch = self._makeTranslationBranch(fake_pottery_compatible=True)
-
- trunk = branch.product.getSeries('trunk')
- removeSecurityProxy(trunk).translations_autoimport_mode = (
- TranslationsBranchImportMode.NO_IMPORT)
-
- self.assertFalse(self.jobsource.generatesTemplates(branch))
-
- def test_private_branch(self):
- # We don't generate templates for private branches.
- branch = self._makeTranslationBranch(fake_pottery_compatible=True)
- removeSecurityProxy(branch).information_type = (
- InformationType.USERDATA)
- self.assertFalse(self.jobsource.generatesTemplates(branch))
-
- def test_scheduleTranslationTemplatesBuild_subscribed(self):
- # If the feature is enabled, a TipChanged event for a branch that
- # generates templates will schedule a templates build.
- branch = self._makeTranslationBranch()
- removeSecurityProxy(branch).last_scanned_id = 'null:'
- commit = DirectBranchCommit(branch)
- commit.writeFile('POTFILES.in', 'foo')
- commit.commit('message')
- notify(events.TipChanged(branch, None, False))
- branchjobs = list(TranslationTemplatesBuildJob.iterReady())
- self.assertEqual(1, len(branchjobs))
- self.assertEqual(branch, branchjobs[0].branch)
-
- def test_scheduleTranslationTemplatesBuild(self):
- # If the feature is enabled, scheduleTranslationTemplatesBuild
- # will schedule a templates build whenever a change is pushed to
- # a branch that generates templates.
- branch = self._makeTranslationBranch(fake_pottery_compatible=True)
-
- self.jobsource.scheduleTranslationTemplatesBuild(branch)
-
- store = IStore(BranchJob)
- branchjobs = list(store.find(BranchJob, BranchJob.branch == branch))
- self.assertEqual(1, len(branchjobs))
- self.assertEqual(branch, branchjobs[0].branch)
-
- def test_create(self):
- branch = self._makeTranslationBranch(fake_pottery_compatible=True)
-
- specific_job = self.jobsource.create(branch)
-
- # A job is created with the branch URL in its metadata.
- metadata = specific_job.metadata
- self.assertIn('branch_url', metadata)
- url = metadata['branch_url']
- head = 'http://'
- self.assertEqual(head, url[:len(head)])
- tail = branch.name
- self.assertEqual(tail, url[-len(tail):])
-
- def test_create_with_build(self):
- branch = self._makeTranslationBranch(fake_pottery_compatible=True)
- specific_job = self.jobsource.create(branch, testing=True)
- naked_job = removeSecurityProxy(specific_job)
- self.assertEquals(naked_job._constructed_build, specific_job.build)
Follow ups