def query_pofiletranslator(self, pofile, person):
        """Query `POFileTranslator` for a specific record.

        :return: Storm result set.
        """
        store = IStore(pofile)
        return store.find(POFileTranslator, pofile=pofile, person=person)
예제 #2
0
    def test_retrieveDatabaseAncestry(self):
        # retrieveDatabaseAncestry should set db_ancestry and db_history to
        # Launchpad's current understanding of the branch state.
        # db_branch_revision_map should map Bazaar revision_ids to
        # BranchRevision.ids.

        # Use the sampledata for this test, so we do not have to rely on
        # BzrSync to fill the database. That would cause a circular
        # dependency, as the test setup would depend on
        # retrieveDatabaseAncestry.
        branch = getUtility(IBranchLookup).getByUniqueName("~name12/+junk/junk.contrib")
        branch_revisions = IStore(BranchRevision).find(BranchRevision, BranchRevision.branch == branch)
        sampledata = list(branch_revisions.order_by(BranchRevision.sequence))
        expected_ancestry = set(branch_revision.revision.revision_id for branch_revision in sampledata)
        expected_history = [
            branch_revision.revision.revision_id
            for branch_revision in sampledata
            if branch_revision.sequence is not None
        ]

        self.create_branch_and_tree(db_branch=branch)

        bzrsync = self.makeBzrSync(branch)
        db_ancestry, db_history = bzrsync.retrieveDatabaseAncestry()
        self.assertEqual(expected_ancestry, set(db_ancestry))
        self.assertEqual(expected_history, list(db_history))
def get_potmsgset_ids(potemplate_id):
    """Get the ids for each current `POTMsgSet` in a `POTemplate`."""
    store = IStore(POTemplate)
    return store.find(
        TranslationTemplateItem.potmsgsetID,
        TranslationTemplateItem.potemplateID == potemplate_id,
        TranslationTemplateItem.sequence > 0)
예제 #4
0
def get_files_to_parse(file_paths):
    """Return an iterator of file and position where reading should start.

    The lines read from that position onwards will be the ones that have not
    been parsed yet.

    :param file_paths: The paths to the files.
    """
    store = IStore(ParsedApacheLog)
    for file_path in file_paths:
        fd, file_size = get_fd_and_file_size(file_path)
        first_line = unicode(fd.readline())
        parsed_file = store.find(ParsedApacheLog, first_line=first_line).one()
        position = 0
        if parsed_file is not None:
            # This file has been parsed already; we'll now check if there's
            # anything in it that hasn't been parsed yet.
            if parsed_file.bytes_read >= file_size:
                # There's nothing new in it for us to parse, so just skip it.
                fd.close()
                continue
            else:
                # This one has stuff we haven't parsed yet, so we'll just
                # parse what's new.
                position = parsed_file.bytes_read

        yield fd, position
예제 #5
0
    def setsIncludingSource(self, sourcepackagename, distroseries=None,
                            direct_inclusion=False):
        """See `IPackagesetSet`."""
        sourcepackagename = self._nameToSourcePackageName(sourcepackagename)

        if direct_inclusion:
            query = '''
                SELECT pss.packageset FROM packagesetsources pss
                WHERE pss.sourcepackagename = ?
            '''
        else:
            query = '''
                SELECT fpsi.parent
                FROM packagesetsources pss, flatpackagesetinclusion fpsi
                WHERE pss.sourcepackagename = ?
                AND pss.packageset = fpsi.child
            '''
        store = IStore(Packageset)
        psets = SQL(query, (sourcepackagename.id,))
        clauses = [Packageset.id.is_in(psets)]
        if distroseries:
            clauses.append(Packageset.distroseries == distroseries)

        result_set = store.find(Packageset, *clauses)
        return _order_result_set(result_set)
예제 #6
0
    def calculateSourceOverrides(self, archive, distroseries, pocket, spns,
                                 source_component=None, include_deleted=False):
        def eager_load(rows):
            bulk.load(Component, (row[1] for row in rows))
            bulk.load(Section, (row[2] for row in rows))

        store = IStore(SourcePackagePublishingHistory)
        already_published = DecoratedResultSet(
            store.find(
                (SourcePackagePublishingHistory.sourcepackagenameID,
                 SourcePackagePublishingHistory.componentID,
                 SourcePackagePublishingHistory.sectionID),
                SourcePackagePublishingHistory.archiveID == archive.id,
                SourcePackagePublishingHistory.distroseriesID ==
                    distroseries.id,
                SourcePackagePublishingHistory.status.is_in(
                    self.getExistingPublishingStatuses(include_deleted)),
                SourcePackagePublishingHistory.sourcepackagenameID.is_in(
                    spn.id for spn in spns)).order_by(
                        SourcePackagePublishingHistory.sourcepackagenameID,
                        Desc(SourcePackagePublishingHistory.datecreated),
                        Desc(SourcePackagePublishingHistory.id),
                ).config(
                    distinct=(
                        SourcePackagePublishingHistory.sourcepackagenameID,)),
            id_resolver((SourcePackageName, Component, Section)),
            pre_iter_hook=eager_load)
        return [
            SourceOverride(name, component, section)
            for (name, component, section) in already_published]
예제 #7
0
 def sourcesNotSharedBy(self, other_package_set, direct_inclusion=False):
     """See `IPackageset`."""
     if direct_inclusion == False:
         query = '''
             SELECT pss_this.sourcepackagename
             FROM packagesetsources pss_this,
                 flatpackagesetinclusion fpsi_this
             WHERE pss_this.packageset = fpsi_this.child
                 AND fpsi_this.parent = ?
             EXCEPT
             SELECT pss_other.sourcepackagename
             FROM packagesetsources pss_other,
                 flatpackagesetinclusion fpsi_other
             WHERE pss_other.packageset = fpsi_other.child
                 AND fpsi_other.parent = ?
         '''
     else:
         query = '''
             SELECT pss_this.sourcepackagename
             FROM packagesetsources pss_this WHERE pss_this.packageset = ?
             EXCEPT
             SELECT pss_other.sourcepackagename
             FROM packagesetsources pss_other
             WHERE pss_other.packageset = ?
         '''
     store = IStore(Packageset)
     source_names = SQL(query, (self.id, other_package_set.id))
     result_set = store.find(
         SourcePackageName, SourcePackageName.id.is_in(source_names))
     return _order_result_set(result_set)
예제 #8
0
    def getBuildsForArchive(self, archive, status=None):
        """See `IBuildFarmJobSet`."""

        extra_exprs = []

        if status is not None:
            extra_exprs.append(BuildFarmJob.status == status)

        result_set = IStore(BuildFarmJob).find(
            BuildFarmJob, BuildFarmJob.archive == archive, *extra_exprs)

        # When we have a set of builds that may include pending or
        # superseded builds, we order by -date_created (as we won't
        # always have a date_finished). Otherwise we can order by
        # -date_finished.
        unfinished_states = [
            BuildStatus.NEEDSBUILD,
            BuildStatus.BUILDING,
            BuildStatus.UPLOADING,
            BuildStatus.SUPERSEDED,
            ]
        if status is None or status in unfinished_states:
            result_set.order_by(
                Desc(BuildFarmJob.date_created), BuildFarmJob.id)
        else:
            result_set.order_by(
                Desc(BuildFarmJob.date_finished), BuildFarmJob.id)

        return result_set
예제 #9
0
 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.markAsBuilding(self.factory.makeBuilder())
예제 #10
0
def load_referencing(object_type, owning_objects, reference_keys,
                     extra_conditions=[]):
    """Load objects of object_type that reference owning_objects.

    Note that complex types like Person are best loaded through dedicated
    helpers that can eager load other related things (e.g. validity for
    Person).

    :param object_type: The object type to load - e.g. BranchSubscription.
    :param owning_objects: The objects which are referenced. E.g. [Branch()]
        At this point, all the objects should be of the same type, but that
        constraint could be lifted in future.
    :param reference_keys: A list of attributes that should be used to select
        object_type keys. e.g. ['branchID']
    :param extra_conditions: A list of Storm clauses that will be used in the
        final query.
    :return: A list of object_type where any of reference_keys refered to the
        primary key of any of owning_objects.
    """
    store = IStore(object_type)
    if type(owning_objects) not in (list, tuple):
        owning_objects = tuple(owning_objects)
    if not owning_objects:
        return []
    exemplar = owning_objects[0]
    primary_key = _primary_key(get_type(exemplar))
    attribute = primary_key.name
    ids = set(map(attrgetter(attribute), owning_objects))
    conditions = []
    # Note to future self doing perf tuning: may want to make ids a WITH
    # clause.
    for column in map(partial(getattr, object_type), reference_keys):
        conditions.append(column.is_in(ids))
    return list(store.find(object_type, Or(conditions), *extra_conditions))
 def test_get_string(self):
     # Test NameBlacklistSet.get() with string id.
     name_blacklist = self.name_blacklist_set.create(u'foo', u'bar')
     store = IStore(name_blacklist)
     store.flush()
     retrieved = self.name_blacklist_set.get(str(name_blacklist.id))
     self.assertEqual(name_blacklist, retrieved)
    def getForDistroSeries(distroseries, since=None,
                           source_package_name=None):
        """See `IDistroSeriesDifferenceCommentSource`."""
        # Avoid circular imports.
        from lp.registry.model.distroseriesdifference import (
            DistroSeriesDifference,
            )
        store = IStore(DistroSeriesDifferenceComment)
        DSD = DistroSeriesDifference
        DSDComment = DistroSeriesDifferenceComment
        conditions = [
            DSDComment.distro_series_difference_id == DSD.id,
            DSD.derived_series_id == distroseries.id,
            ]

        if source_package_name is not None:
            conditions += [
                SourcePackageName.id == DSD.source_package_name_id,
                SourcePackageName.name == source_package_name,
                ]

        if since is not None:
            older_messages = store.find(
                Message.id, Message.datecreated < since).order_by(
                    Desc(Message.datecreated))
            preceding_message = older_messages.first()
            if preceding_message is not None:
                conditions.append(DSDComment.message_id > preceding_message)

        return store.find(DSDComment, *conditions).order_by(
            DSDComment.message_id)
예제 #13
0
    def get(ujob_id):
        """Return the named job database class.

        :param ujob_id: A tuple of Job.id, module name, class name for the
            class to retrieve.
        Return derived job class.
        """
        job_id, module_name, class_name = ujob_id
        bc_module = __import__(module_name, fromlist=[class_name])
        db_class = getattr(bc_module, class_name)
        factory = getattr(db_class, "makeInstance", None)
        if factory is not None:
            return factory(job_id)
        # This method can be called with two distinct types of Jobs:
        # - Jobs that are backed by a DB table with a foreign key onto Job.
        # - Jobs that have no backing, and are only represented by a row in
        #   the Job table, but the class name we are given is the abstract
        #   job class.
        # If there is no __storm_table__, it is the second type, and we have
        # to look it up via the Job table.
        if getattr(db_class, "__storm_table__", None) is None:
            db_job = IStore(Job).find(Job, Job.id == job_id).one()
            # Job.makeDerived() would be a mess of circular imports, so it is
            # cleaner to just return the bare Job wrapped in the class.
            return db_class(db_job)
        # Otherwise, we have the concrete DB class, so use its FK.
        db_job = IStore(db_class).find(db_class, db_class.job == job_id).one()
        if db_job is None:
            return None
        return db_job.makeDerived()
    def test_jobs_with_retry_exceptions_are_queued_again(self):
        # A job that raises a retry error is automatically queued
        # and executed again.
        self.useFixture(FeatureFixture({
            'jobs.celery.enabled_classes': 'TestJobWithRetryError'
        }))
        with block_on_job(self):
            job = TestJobWithRetryError()
            job.celeryRunOnCommit()
            job_id = job.job_id
            transaction.commit()
            store = IStore(Job)

            # block_on_job() is not aware of the Celery request
            # issued when the retry exception occurs, but we can
            # check the status of the job in the database.
            def job_finished():
                transaction.abort()
                dbjob = store.find(Job, id=job_id)[0]
                return (
                    dbjob.status == JobStatus.COMPLETED and
                    dbjob.attempt_count == 2)
            count = 0
            while count < 300 and not job_finished():
                # We have a maximum wait of one minute.  We should not get
                # anywhere close to that on developer machines (10 seconds was
                # working fine), but when the test suite is run in parallel we
                # can need a lot more time (see bug 1007576).
                sleep(0.2)
                count += 1

        dbjob = store.find(Job, id=job_id)[0]
        self.assertEqual(2, dbjob.attempt_count)
        self.assertEqual(JobStatus.COMPLETED, dbjob.status)
예제 #15
0
    def getDiffsToReleases(self, sprs, preload_for_display=False):
        """See `IPackageDiffSet`."""
        from lp.registry.model.distribution import Distribution
        from lp.soyuz.model.archive import Archive
        from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
        if len(sprs) == 0:
            return EmptyResultSet()
        spr_ids = [spr.id for spr in sprs]
        result = IStore(PackageDiff).find(
            PackageDiff, PackageDiff.to_sourceID.is_in(spr_ids))
        result.order_by(PackageDiff.to_sourceID,
                        Desc(PackageDiff.date_requested))

        def preload_hook(rows):
            lfas = load(LibraryFileAlias, (pd.diff_contentID for pd in rows))
            load(LibraryFileContent, (lfa.contentID for lfa in lfas))
            sprs = load(
                SourcePackageRelease,
                itertools.chain.from_iterable(
                    (pd.from_sourceID, pd.to_sourceID) for pd in rows))
            archives = load(Archive, (spr.upload_archiveID for spr in sprs))
            load(Distribution, (a.distributionID for a in archives))

        if preload_for_display:
            return DecoratedResultSet(result, pre_iter_hook=preload_hook)
        else:
            return result
예제 #16
0
    def packagesetsForSource(
        self, archive, sourcepackagename, direct_permissions=True):
        """See `IArchivePermissionSet`."""
        sourcepackagename = self._nameToSourcePackageName(sourcepackagename)
        store = IStore(ArchivePermission)

        if direct_permissions:
            origin = SQL('ArchivePermission, PackagesetSources')
            rset = store.using(origin).find(ArchivePermission, SQL('''
                ArchivePermission.packageset = PackagesetSources.packageset
                AND PackagesetSources.sourcepackagename = ?
                AND ArchivePermission.archive = ?
                ''', (sourcepackagename.id, archive.id)))
        else:
            origin = SQL(
                'ArchivePermission, PackagesetSources, '
                'FlatPackagesetInclusion')
            rset = store.using(origin).find(ArchivePermission, SQL('''
                ArchivePermission.packageset = FlatPackagesetInclusion.parent
                AND PackagesetSources.packageset =
                    FlatPackagesetInclusion.child
                AND PackagesetSources.sourcepackagename = ?
                AND ArchivePermission.archive = ?
                ''', (sourcepackagename.id, archive.id)))
        return rset
 def getComments(self):
     """See `IDistroSeriesDifference`."""
     DSDComment = DistroSeriesDifferenceComment
     comments = IStore(DSDComment).find(
         DistroSeriesDifferenceComment,
         DSDComment.distro_series_difference == self)
     return comments.order_by(Desc(DSDComment.id))
예제 #18
0
 def all_package_names(self):
     """See `IHWDriverSet`."""
     # XXX Abel Deuring 2009-06-19 The clause package_name != None
     # can be removed once bug #306265 is fixed.
     result = IStore(HWDriverPackageName).find(HWDriverPackageName, HWDriverPackageName.package_name != None)
     result.order_by(HWDriverPackageName.package_name)
     return result
def most_recent_comments(dsds):
    """The most recent comments for the given `DistroSeriesDifference`s.

    Returns an `IResultSet` that yields a single column of
        `DistroSeriesDifferenceComment`.

    :param dsds: An iterable of `DistroSeriesDifference` instances.
    """
    columns = (
        DistroSeriesDifferenceComment,
        Message,
        )
    conditions = And(
        DistroSeriesDifferenceComment
            .distro_series_difference_id.is_in(dsd.id for dsd in dsds),
        Message.id == DistroSeriesDifferenceComment.message_id)
    order_by = (
        DistroSeriesDifferenceComment.distro_series_difference_id,
        Desc(DistroSeriesDifferenceComment.id),
        )
    distinct_on = (
        DistroSeriesDifferenceComment.distro_series_difference_id,
        )
    store = IStore(DistroSeriesDifferenceComment)
    comments = store.find(
        columns, conditions).order_by(*order_by).config(distinct=distinct_on)
    return DecoratedResultSet(comments, itemgetter(0))
def get_contributions(pofile, potmsgset_ids):
    """Map all users' most recent contributions to a `POFile`.

    Returns a dict mapping `Person` id to the creation time of their most
    recent `TranslationMessage` in `POFile`.

    This leaves some small room for error: a contribution that is masked by
    a diverged entry in this POFile will nevertheless produce a
    POFileTranslator record.  Fixing that would complicate the work more than
    it is probably worth.

    :param pofile: The `POFile` to find contributions for.
    :param potmsgset_ids: The ids of the `POTMsgSet`s to look for, as returned
        by `get_potmsgset_ids`.
    """
    store = IStore(pofile)
    language_id = pofile.language.id
    template_id = pofile.potemplate.id
    contribs = store.find(
        (TranslationMessage.submitterID, TranslationMessage.date_created),
        TranslationMessage.potmsgsetID.is_in(potmsgset_ids),
        TranslationMessage.languageID == language_id,
        TranslationMessage.msgstr0 != None,
        Coalesce(TranslationMessage.potemplateID, template_id) ==
            template_id)
    contribs = contribs.config(distinct=(TranslationMessage.submitterID,))
    contribs = contribs.order_by(
        TranslationMessage.submitterID, Desc(TranslationMessage.date_created))
    return dict(contribs)
예제 #21
0
    def getByName(self, name, distroseries=None):
        """See `IPackagesetSet`."""
        store = IStore(Packageset)
        if not isinstance(name, unicode):
            name = unicode(name, 'utf-8')

        ubuntu = getUtility(IDistributionSet).getByName(u'ubuntu')
        extra_args = []
        if distroseries is not None:
            # If the user just passed a distro series name, look it up.
            if isinstance(distroseries, basestring):
                try:
                    distroseries = ubuntu[distroseries]
                except NotFoundError:
                    raise NoSuchPackageSet(distroseries)
            extra_args.append(Packageset.distroseries == distroseries)
        else:
            extra_args.append(Packageset.distroseries == ubuntu.currentseries)

        package_set = store.find(
            Packageset, Packageset.name == name, *extra_args).one()

        if package_set is None:
            raise NoSuchPackageSet(name)

        return package_set
예제 #22
0
 def getBugWatchesForRemoteBug(self, remote_bug, bug_watch_ids=None):
     """See `IBugWatchSet`."""
     query = IStore(BugWatch).find(
         BugWatch, BugWatch.remotebug == remote_bug)
     if bug_watch_ids is not None:
         query = query.find(BugWatch.id.is_in(bug_watch_ids))
     return query
    def requestBuild(self, archive, requester, distroseries,
                     pocket=PackagePublishingPocket.RELEASE,
                     manual=False):
        """See `ISourcePackageRecipe`."""
        if not archive.is_ppa:
            raise NonPPABuildRequest

        buildable_distros = BuildableDistroSeries.findSeries(archive.owner)
        if distroseries not in buildable_distros:
            raise BuildNotAllowedForDistro(self, distroseries)

        reject_reason = archive.checkUpload(
            requester, distroseries, None, archive.default_component,
            pocket)
        if reject_reason is not None:
            raise reject_reason
        if self.isOverQuota(requester, distroseries):
            raise TooManyBuilds(self, distroseries)
        pending = IStore(self).find(SourcePackageRecipeBuild,
            SourcePackageRecipeBuild.recipe_id == self.id,
            SourcePackageRecipeBuild.distroseries_id == distroseries.id,
            SourcePackageRecipeBuild.archive_id == archive.id,
            SourcePackageRecipeBuild.status == BuildStatus.NEEDSBUILD)
        if pending.any() is not None:
            raise BuildAlreadyPending(self, distroseries)

        build = getUtility(ISourcePackageRecipeBuildSource).new(distroseries,
            self, requester, archive)
        build.queueBuild()
        queue_record = build.buildqueue_record
        if manual:
            queue_record.manualScore(queue_record.lastscore + 100)
        return build
예제 #24
0
 def getRevisionsNeedingKarmaAllocated(limit=None):
     """See `IRevisionSet`."""
     store = IStore(Revision)
     results = store.find(
         Revision,
         Revision.karma_allocated == False)[:limit]
     return results
def create_multiple_jobs(derived_series, parent_series):
    """Create `DistroSeriesDifferenceJob`s between parent and derived series.

    :param derived_series: A `DistroSeries` that is assumed to be derived
        from another one.
    :param parent_series: A `DistroSeries` that is a parent of
        `derived_series`.
    :return: A list of newly-created `DistributionJob` ids.
    """
    store = IStore(SourcePackagePublishingHistory)
    spn_ids = store.find(
        SourcePackagePublishingHistory.sourcepackagenameID,
        SourcePackagePublishingHistory.distroseries == derived_series.id,
        SourcePackagePublishingHistory.status.is_in(active_publishing_status))
    spn_ids = list(spn_ids)

    if len(spn_ids) == 0:
        return []

    job_ids = Job.createMultiple(store, len(spn_ids))
    return bulk.create(
            (DistributionJob.distribution, DistributionJob.distroseries,
             DistributionJob.job_type, DistributionJob.job_id,
             DistributionJob.metadata),
            [(derived_series.distribution, derived_series,
              DistributionJobType.DISTROSERIESDIFFERENCE, job_id,
              make_metadata(spn_id, parent_series.id))
             for job_id, spn_id in zip(job_ids, spn_ids)],
            get_primary_keys=True)
 def getByDerivedAndParentSeries(self, derived_series, parent_series):
     """See `IDistroSeriesParentSet`."""
     store = IStore(DistroSeriesParent)
     return store.find(
         DistroSeriesParent,
         DistroSeriesParent.parent_series_id == parent_series.id,
         DistroSeriesParent.derived_series_id == derived_series.id).one()
예제 #27
0
    def preloadVisibleStackedOnBranches(branches, user=None):
        """Preload the chains of stacked on branches related to the given list
        of branches. Only the branches visible for the given user are
        preloaded/returned.

        """
        if len(branches) == 0:
            return
        store = IStore(Branch)
        result = store.execute("""
            WITH RECURSIVE stacked_on_branches_ids AS (
                SELECT column1 as id FROM (VALUES %s) AS temp
                UNION
                SELECT DISTINCT branch.stacked_on
                FROM stacked_on_branches_ids, Branch AS branch
                WHERE
                    branch.id = stacked_on_branches_ids.id AND
                    branch.stacked_on IS NOT NULL
            )
            SELECT id from stacked_on_branches_ids
            """ % ', '.join(
                ["(%s)" % quote(id)
                 for id in map(attrgetter('id'), branches)]))
        branch_ids = [res[0] for res in result.get_all()]
        # Not really sure this is useful: if a given branch is visible by a
        # user, then I think it means that the whole chain of branches on
        # which is is stacked on is visible by this user
        expressions = [Branch.id.is_in(branch_ids)]
        if user is None:
            collection = AnonymousBranchCollection(
                branch_filter_expressions=expressions)
        else:
            collection = VisibleBranchCollection(
                user=user, branch_filter_expressions=expressions)
        return list(collection.getBranches())
 def getFlattenedOverlayTree(self, derived_series):
     """See `IDistroSeriesParentSet`."""
     self.getByDerivedSeries(derived_series)
     rec_overlay_query = '''
         RECURSIVE t_parents(parent_series) AS (
             SELECT parent_series
             FROM DistroSeriesParent
             WHERE derived_series=? AND
                 is_overlay = True
         UNION ALL
             SELECT dsp.parent_series
             FROM DistroSeriesParent dsp, t_parents p
             WHERE dsp.derived_series = p.parent_series AND
                 dsp.is_overlay = True
     ) '''
     store = IStore(DistroSeriesParent)
     # XXX: rvb 2011-05-20 bug=785733: Order by DSD.id for now.
     # Once the ordering is specified in the database, it should
     # be used to sort the results.
     return store.with_(
         SQL(rec_overlay_query, (derived_series.id, ))).find(
             DistroSeriesParent,
             SQL('DistroSeriesParent.parent_series IN '
                 '(SELECT parent_series FROM t_parents)')
             ).order_by(DistroSeriesParent.id)
    def _getInvalidTokens(self):
        """Return all invalid tokens.

        A token is invalid if it is active and the token owner is *not* a
        subscriber to the archive that the token is for. The subscription can
        be either direct or through a team.
        """
        # First we grab all the active tokens for which there is a
        # matching current archive subscription for a team of which the
        # token owner is a member.
        store = IStore(ArchiveSubscriber)
        valid_tokens = store.find(
            ArchiveAuthToken,
            ArchiveAuthToken.date_deactivated == None,
            ArchiveAuthToken.archive_id == ArchiveSubscriber.archive_id,
            ArchiveSubscriber.status == ArchiveSubscriberStatus.CURRENT,
            ArchiveSubscriber.subscriber_id == TeamParticipation.teamID,
            TeamParticipation.personID == ArchiveAuthToken.person_id)

        # We can then evaluate the invalid tokens by the difference of
        # all active tokens and valid tokens.
        all_active_tokens = store.find(
            ArchiveAuthToken,
            ArchiveAuthToken.date_deactivated == None)

        return all_active_tokens.difference(valid_tokens)
예제 #30
0
def find_team_participations(people, teams=None):
    """Find the teams the given people participate in.

    :param people: The people for which to query team participation.
    :param teams: Optionally, limit the participation check to these teams.

    This method performs its work with at most a single database query.
    It first does similar checks to those performed by IPerson.in_team() and
    it may turn out that no database query is required at all.
    """

    teams_to_query = []
    people_teams = {}

    def add_team_to_result(person, team):
        teams = people_teams.get(person)
        if teams is None:
            teams = set()
            people_teams[person] = teams
        teams.add(team)

    # Check for the simple cases - self membership etc.
    if teams:
        for team in teams:
            if team is None:
                continue
            for person in people:
                if team.id == person.id:
                    add_team_to_result(person, team)
                    continue
            if not team.is_team:
                continue
            teams_to_query.append(team)

    # Avoid circular imports
    from lp.registry.model.person import Person

    # We are either checking for membership of any team or didn't eliminate
    # all the specific team participation checks above.
    if teams_to_query or not teams:
        Team = ClassAlias(Person, 'Team')
        person_ids = [person.id for person in people]
        conditions = [
            TeamParticipation.personID == Person.id,
            TeamParticipation.teamID == Team.id,
            Person.id.is_in(person_ids)
        ]
        team_ids = [team.id for team in teams_to_query]
        if team_ids:
            conditions.append(Team.id.is_in(team_ids))

        store = IStore(Person)
        rs = store.find(
            (Person, Team),
            *conditions)

        for (person, team) in rs:
            add_team_to_result(person, team)
    return people_teams
예제 #31
0
    def get(cls, job_id):
        """Get a job by id.

        :return: The `SnapJob` with the specified id, as the current
            `SnapJobDerived` subclass.
        :raises: `NotFoundError` if there is no job with the specified id,
            or its `job_type` does not match the desired subclass.
        """
        snap_job = IStore(SnapJob).get(SnapJob, job_id)
        if snap_job.job_type != cls.class_job_type:
            raise NotFoundError("No object found with id %d and type %s" %
                                (job_id, cls.class_job_type.title))
        return cls(snap_job)
예제 #32
0
    def expireSubscriptions(self):
        """Expire subscriptions as necessary.

        If an `ArchiveSubscriber`'s date_expires has passed, then
        set its status to EXPIRED.
        """
        now = datetime.now(pytz.UTC)

        store = IStore(ArchiveSubscriber)
        newly_expired_subscriptions = store.find(
            ArchiveSubscriber,
            ArchiveSubscriber.status == ArchiveSubscriberStatus.CURRENT,
            ArchiveSubscriber.date_expires != None,
            ArchiveSubscriber.date_expires <= now)

        subscription_names = [
            subs.displayname for subs in newly_expired_subscriptions]
        if subscription_names:
            newly_expired_subscriptions.set(
                status=ArchiveSubscriberStatus.EXPIRED)
            self.logger.info(
                "Expired subscriptions: %s" % ", ".join(subscription_names))
예제 #33
0
 def search(self, bus, vendor_id, product_id=None):
     """See `IHWDeviceSet`."""
     bus_vendor = HWVendorIDSet().getByBusAndVendorID(bus, vendor_id)
     args = []
     if product_id is not None:
         if not isValidProductID(bus, product_id):
             raise ParameterError(
                 '%s is not a valid product ID for %s'
                 % (repr(product_id), bus.title))
         args.append(HWDevice.bus_product_id == product_id)
     return IStore(HWDevice).find(
         HWDevice, HWDevice.bus_vendor == bus_vendor, *args).order_by(
             HWDevice.id)
예제 #34
0
    def test_update_of_existing_entries(self):
        # When given a first_line that already exists in the ParsedApacheLog
        # table, create_or_update_parsedlog_entry() will update that entry
        # with the given number of bytes read.
        first_line = u'First line'
        create_or_update_parsedlog_entry(first_line, parsed_bytes=2)
        store = IStore(ParsedApacheLog)
        entry = store.find(ParsedApacheLog, first_line=first_line).one()

        # Here we see that the new entry was created.
        self.assertIsNot(None, entry)
        self.assertEqual(entry.bytes_read, 2)

        create_or_update_parsedlog_entry(first_line,
                                         parsed_bytes=len(first_line))

        # And here we see that same entry was updated by the second call to
        # create_or_update_parsedlog_entry().
        entry2 = store.find(ParsedApacheLog, first_line=first_line).one()
        self.assertIs(entry, entry2)
        self.assertIsNot(None, entry2)
        self.assertEqual(entry2.bytes_read, len(first_line))
예제 #35
0
    def test_cleanUp(self):
        # TranslationTemplatesBuildJob has its own customized cleanup
        # behaviour, since it's actually a BranchJob.
        job = removeSecurityProxy(self.specific_job.job)
        buildqueue = IStore(BuildQueue).find(BuildQueue, job=job).one()

        job_id = job.id
        store = Store.of(job)
        branch_name = self.branch.unique_name

        buildqueue.destroySelf()

        # BuildQueue is gone.
        self.assertIs(None,
                      store.find(BuildQueue, BuildQueue.job == job_id).one())
        # Job is gone.
        self.assertIs(None, store.find(Job, Job.id == job_id).one())
        # TranslationTemplatesBuildJob is gone.
        self.assertIs(None, TranslationTemplatesBuildJob.getByJob(job_id))
        # Branch is still here.
        branch_set = getUtility(IBranchSet)
        self.assertEqual(self.branch, branch_set.getByUniqueName(branch_name))
예제 #36
0
    def getTopContributors(self, category=None, limit=None):
        """See IKarmaContext."""
        from lp.registry.model.person import Person
        store = IStore(Person)
        if IProduct.providedBy(self):
            condition = KarmaCache.productID == self.id
        elif IDistribution.providedBy(self):
            condition = KarmaCache.distributionID == self.id
        elif IProjectGroup.providedBy(self):
            condition = KarmaCache.projectgroupID == self.id
        else:
            raise AssertionError(
                "Not a product, project group or distribution: %r" % self)

        if category is not None:
            category = category.id
        contributors = store.find(
            (Person, KarmaCache.karmavalue),
            KarmaCache.personID == Person.id,
            KarmaCache.categoryID == category, condition).order_by(
                Desc(KarmaCache.karmavalue)).config(limit=limit)
        return list(contributors)
    def __getitem__(self, version):
        """See IDistroArchSeriesBinaryPackage."""
        bpph = IStore(BinaryPackagePublishingHistory).find(
            BinaryPackagePublishingHistory,
            BinaryPackageRelease.version == version,
            *self._getPublicationJoins()).order_by(
                Desc(BinaryPackagePublishingHistory.datecreated)).first()

        if bpph is None:
            return None
        return DistroArchSeriesBinaryPackageRelease(
            distroarchseries=self.distroarchseries,
            binarypackagerelease=bpph.binarypackagerelease)
예제 #38
0
    def test_with_snapbuild_metadata_as_none_set_status(self):
        db_build = self.factory.makeSnapBuild()
        unsecure_db_build = removeSecurityProxy(db_build)
        unsecure_db_build.store_upload_metadata = None
        store = IStore(SnapBuild)
        store.flush()
        loaded_build = store.find(SnapBuild, id=unsecure_db_build.id).one()

        job = SnapStoreUploadJob.create(loaded_build)
        job.status_url = 'http://example.org'
        store.flush()

        loaded_build = store.find(SnapBuild, id=unsecure_db_build.id).one()
        self.assertEqual('http://example.org',
                         loaded_build.store_upload_metadata['status_url'])
예제 #39
0
    def test_query_count(self):
        # The function issues a constant number of queries regardless of
        # team count.
        login_person(self.user)
        context = self.factory.makeProduct(owner=self.user)
        self._setup_teams(self.user)

        IStore(Person).flush()
        IStore(Person).invalidate()
        clear_cache()
        with StormStatementRecorder() as recorder:
            expose_user_administered_teams_to_js(self.request,
                                                 self.user,
                                                 context,
                                                 absoluteURL=fake_absoluteURL)
        self.assertThat(recorder, HasQueryCount(Equals(4)))

        # Create some new public teams owned by the user, and a private
        # team administered by the user.
        for i in range(3):
            self.factory.makeTeam(owner=self.user)
        pt = self.factory.makeTeam(visibility=PersonVisibility.PRIVATE,
                                   members=[self.user])
        with person_logged_in(pt.teamowner):
            pt.addMember(self.user,
                         pt.teamowner,
                         status=TeamMembershipStatus.ADMIN)

        IStore(Person).flush()
        IStore(Person).invalidate()
        clear_cache()
        del IJSONRequestCache(self.request).objects['administratedTeams']
        with StormStatementRecorder() as recorder:
            expose_user_administered_teams_to_js(self.request,
                                                 self.user,
                                                 context,
                                                 absoluteURL=fake_absoluteURL)
        self.assertThat(recorder, HasQueryCount(Equals(4)))
예제 #40
0
    def new(self, source, target, requester, copy_binaries=False, reason=None):
        """See `IPackageCopyRequestSet`."""
        pcr = PackageCopyRequest()
        for location_data in ((source, 'source'), (target, 'target')):
            _set_location_data(pcr, *location_data)
        pcr.requester = requester
        if copy_binaries == True:
            pcr.copy_binaries = True
        if reason is not None:
            pcr.reason = reason

        pcr.status = PackageCopyStatus.NEW
        IStore(PackageCopyRequest).add(pcr)
        return pcr
예제 #41
0
 def setUp(self):
     super(TestTranslatorsCounts, self).setUp()
     self.translated_lang = self.factory.makeLanguage(pluralforms=None)
     self.untranslated_lang = self.factory.makeLanguage(pluralforms=None)
     for i in range(3):
         translator = self.factory.makePerson()
         translator.addLanguage(self.translated_lang)
         with dbuser('karma'):
             translations_category = IStore(KarmaCategory).find(
                 KarmaCategory, name='translations').one()
             getUtility(IKarmaCacheManager).new(
                 person_id=translator.id,
                 category_id=translations_category.id,
                 value=100)
예제 #42
0
    def _find(cls, distroseries, archive=None):
        """All of the cached binary package records for this distroseries.

        If 'archive' is not given it will return all caches stored for the
        distroseries main archives (PRIMARY and PARTNER).
        """
        if archive is not None:
            archives = [archive.id]
        else:
            archives = distroseries.distribution.all_distro_archive_ids

        return IStore(cls).find(cls, cls.distroseries == distroseries,
                                cls.archiveID.is_in(archives)).order_by(
                                    cls.name)
예제 #43
0
def get_builder_data():
    """How many working builders are there, how are they configured?"""
    # XXX: This is broken with multi-Processor buildds, as it only
    # considers competition from the same processor.
    per_arch_totals = list(
        IStore(Builder).find(
            (BuilderProcessor.processor_id, Builder.virtualized,
             Count(Builder.id)), BuilderProcessor.builder_id == Builder.id,
            Builder._builderok == True,
            Builder.manual == False).group_by(BuilderProcessor.processor_id,
                                              Builder.virtualized))
    per_virt_totals = list(
        IStore(Builder).find(
            (Builder.virtualized, Count(Builder.id)),
            Builder._builderok == True,
            Builder.manual == False).group_by(Builder.virtualized))

    builder_stats = defaultdict(int)
    for virtualized, count in per_virt_totals:
        builder_stats[(None, virtualized)] = count
    for processor, virtualized, count in per_arch_totals:
        builder_stats[(processor, virtualized)] = count
    return builder_stats
 def test_delete(self):
     # bugtask_flatten() returns true if the BugTaskFlat exists but
     # the task doesn't, and optionally deletes it.
     self.assertTrue(self.checkFlattened(200))
     with dbuser('testadmin'):
         IStore(Bug).execute(
             "INSERT INTO bugtaskflat "
             "(bug, bugtask, bug_owner, information_type, "
             " date_last_updated, heat, status, importance, owner, "
             " active) "
             "VALUES "
             "(1, 200, 1, 1, "
             " current_timestamp at time zone 'UTC', 999, 1, 1, 1, true);")
     self.assertFlattens(200)
예제 #45
0
 def makeCustomBuildQueue(self, score=9876, virtualized=True,
                          estimated_duration=64, sourcename=None,
                          recipe_build=None):
     """Create a `SourcePackageRecipeBuild` and a `BuildQueue` for
     testing."""
     if recipe_build is None:
         recipe_build = self.factory.makeSourcePackageRecipeBuild(
             sourcename=sourcename)
     bq = BuildQueue(
         build_farm_job=recipe_build.build_farm_job, lastscore=score,
         estimated_duration=timedelta(seconds=estimated_duration),
         virtualized=virtualized)
     IStore(BuildQueue).add(bq)
     return bq
예제 #46
0
 def checkPillarArtifactAccess(self, pillar, user):
     """See `ISharingService`."""
     tables = [
         AccessPolicyGrantFlat,
         Join(
             TeamParticipation,
             TeamParticipation.teamID == AccessPolicyGrantFlat.grantee_id),
         Join(
             AccessPolicy,
             AccessPolicy.id == AccessPolicyGrantFlat.policy_id)]
     return not IStore(AccessPolicyGrantFlat).using(*tables).find(
         AccessPolicyGrantFlat,
         AccessPolicy.product_id == pillar.id,
         TeamParticipation.personID == user.id).is_empty()
예제 #47
0
 def find(cls, person=None):
     """See `IPersonMergeJobSource`."""
     conditions = [
         PersonTransferJob.job_type == cls.class_job_type,
         PersonTransferJob.job_id == Job.id,
         Job._status.is_in(Job.PENDING_STATUSES)
     ]
     arg_conditions = []
     if person:
         arg_conditions.append(PersonTransferJob.major_person == person)
     conditions.extend(arg_conditions)
     return DecoratedResultSet(
         IStore(PersonTransferJob).find(PersonTransferJob, *conditions),
         cls)
예제 #48
0
    def setUp(self):
        """Set up a native x86 build for the test archive."""
        super(TestPlatformData, self).setUp()

        self.publisher = SoyuzTestPublisher()
        self.publisher.prepareBreezyAutotest()

        # First mark all builds in the sample data as already built.
        sample_data = IStore(BinaryPackageBuild).find(BinaryPackageBuild)
        for build in sample_data:
            build.buildstate = BuildStatus.FULLYBUILT
        IStore(BinaryPackageBuild).flush()

        # We test builds that target a primary archive.
        self.non_ppa = self.factory.makeArchive(
            name="primary", purpose=ArchivePurpose.PRIMARY)
        self.non_ppa.require_virtualized = False

        self.builds = []
        self.builds.extend(
            self.publisher.getPubSource(
                sourcename="gedit", status=PackagePublishingStatus.PUBLISHED,
                archive=self.non_ppa).createMissingBuilds())
예제 #49
0
    def delete(self, xrefs):
        # Delete both directions.
        pairs = []
        for from_, tos in xrefs.items():
            for to in tos:
                pairs.extend([(from_, to), (to, from_)])

        IStore(XRef).find(
            XRef,
            Or(*[
                And(XRef.from_type == pair[0][0], XRef.from_id == pair[0][1],
                    XRef.to_type == pair[1][0], XRef.to_id == pair[1][1])
                for pair in pairs
            ])).remove()
예제 #50
0
    def getPeopleWithoutAccess(self, concrete_artifact, people):
        """See `ISharingService`."""
        # Public artifacts allow everyone to have access.
        access_artifacts = list(
            getUtility(IAccessArtifactSource).find([concrete_artifact]))
        if not access_artifacts:
            return []

        access_artifact = access_artifacts[0]
        # Determine the grantees who have access via an access policy grant.
        policy_grantees = (Select(
            (AccessPolicyGrant.grantee_id, ),
            where=And(
                AccessPolicyArtifact.abstract_artifact == access_artifact,
                AccessPolicyGrant.policy_id == AccessPolicyArtifact.policy_id))
                           )

        # Determine the grantees who have access via an access artifact grant.
        artifact_grantees = (Select(
            (AccessArtifactGrant.grantee_id, ),
            where=And(AccessArtifactGrant.abstract_artifact_id ==
                      access_artifact.id)))

        # Find the people who can see the artifacts.
        person_ids = [person.id for person in people]
        store = IStore(AccessArtifactGrant)
        tables = [
            Person,
            Join(TeamParticipation, TeamParticipation.personID == Person.id)
        ]
        result_set = store.using(*tables).find(
            Person,
            Or(In(TeamParticipation.teamID, policy_grantees),
               In(TeamParticipation.teamID, artifact_grantees)),
            In(Person.id, person_ids))

        return set(people).difference(set(result_set))
예제 #51
0
    def getMirrorsToProbe(self,
                          content_type,
                          ignore_last_probe=False,
                          limit=None):
        """See IDistributionMirrorSet"""
        query = """
            SELECT distributionmirror.id, MAX(mirrorproberecord.date_created)
            FROM distributionmirror
            LEFT OUTER JOIN mirrorproberecord
                ON mirrorproberecord.distribution_mirror =
                    distributionmirror.id
            WHERE distributionmirror.content = %s
                AND distributionmirror.official_candidate IS TRUE
                AND distributionmirror.status = %s
            GROUP BY distributionmirror.id
            """ % sqlvalues(content_type, MirrorStatus.OFFICIAL)

        if not ignore_last_probe:
            query += """
                HAVING MAX(mirrorproberecord.date_created) IS NULL
                    OR MAX(mirrorproberecord.date_created)
                        < %s - '%s hours'::interval
                """ % sqlvalues(UTC_NOW, PROBE_INTERVAL)

        query += """
            ORDER BY MAX(COALESCE(
                mirrorproberecord.date_created, '1970-01-01')) ASC, id"""

        if limit is not None:
            query += " LIMIT %d" % limit

        store = IStore(MirrorDistroArchSeries)
        ids = ", ".join(str(id) for (id, date_created) in store.execute(query))
        query = '1 = 2'
        if ids:
            query = 'id IN (%s)' % ids
        return DistributionMirror.select(query)
예제 #52
0
 def test_run(self):
     # The job requests builds and records the result.
     distroseries, processors = self.makeSeriesAndProcessors(
         ["avr2001", "sparc64", "x32"])
     [git_ref] = self.factory.makeGitRefs()
     snap = self.factory.makeSnap(
         git_ref=git_ref, distroseries=distroseries, processors=processors)
     expected_date_created = get_transaction_timestamp(IStore(snap))
     job = SnapRequestBuildsJob.create(
         snap, snap.registrant, distroseries.main_archive,
         PackagePublishingPocket.RELEASE, {"core": "stable"})
     snapcraft_yaml = dedent("""\
         architectures:
           - build-on: avr2001
           - build-on: x32
         """)
     self.useFixture(GitHostingFixture(blob=snapcraft_yaml))
     with dbuser(config.ISnapRequestBuildsJobSource.dbuser):
         JobRunner([job]).runAll()
     now = get_transaction_timestamp(IStore(snap))
     self.assertEmailQueueLength(0)
     self.assertThat(job, MatchesStructure(
         job=MatchesStructure.byEquality(status=JobStatus.COMPLETED),
         date_created=Equals(expected_date_created),
         date_finished=MatchesAll(
             GreaterThan(expected_date_created), LessThan(now)),
         error_message=Is(None),
         builds=AfterPreprocessing(set, MatchesSetwise(*[
             MatchesStructure(
                 build_request=MatchesStructure.byEquality(id=job.job.id),
                 requester=Equals(snap.registrant),
                 snap=Equals(snap),
                 archive=Equals(distroseries.main_archive),
                 distro_arch_series=Equals(distroseries[arch]),
                 pocket=Equals(PackagePublishingPocket.RELEASE),
                 channels=Equals({"core": "stable"}))
             for arch in ("avr2001", "x32")]))))
예제 #53
0
    def searchBinaryPackages(self, text):
        """See `IDistroArchSeries`."""
        from lp.soyuz.model.publishing import BinaryPackagePublishingHistory

        origin = [
            BinaryPackageRelease,
            Join(
                BinaryPackagePublishingHistory,
                BinaryPackagePublishingHistory.binarypackagerelease ==
                    BinaryPackageRelease.id),
            Join(
                BinaryPackageName,
                BinaryPackageRelease.binarypackagename ==
                    BinaryPackageName.id)]

        find_spec = [BinaryPackageRelease, BinaryPackageName]
        archives = self.distroseries.distribution.getArchiveIDList()

        clauses = [
            BinaryPackagePublishingHistory.distroarchseries == self,
            BinaryPackagePublishingHistory.archiveID.is_in(archives),
            BinaryPackagePublishingHistory.status.is_in(
                active_publishing_status)]
        order_by = [BinaryPackageName.name]
        if text:
            ranking = rank_by_fti(BinaryPackageRelease, text)
            find_spec.append(ranking)
            clauses.append(
                Or(
                    fti_search(BinaryPackageRelease, text),
                    BinaryPackageName.name.contains_string(text.lower())))
            order_by.insert(0, ranking)
        result = IStore(BinaryPackageName).using(*origin).find(
            tuple(find_spec), *clauses).config(distinct=True).order_by(
                *order_by)

        # import here to avoid circular import problems
        from lp.soyuz.model.distroarchseriesbinarypackagerelease import (
            DistroArchSeriesBinaryPackageRelease)

        # Create a function that will decorate the results, converting
        # them from the find_spec above into DASBPRs.
        def result_to_dasbpr(row):
            return DistroArchSeriesBinaryPackageRelease(
                distroarchseries=self, binarypackagerelease=row[0])

        # Return the decorated result set so the consumer of these
        # results will only see DSPs.
        return DecoratedResultSet(result, result_to_dasbpr)
 def getFlattenedOverlayTree(self, derived_series):
     """See `IDistroSeriesParentSet`."""
     self.getByDerivedSeries(derived_series)
     rec_overlay_query = '''
         RECURSIVE t_parents(parent_series) AS (
             SELECT parent_series
             FROM DistroSeriesParent
             WHERE derived_series=? AND
                 is_overlay = True
         UNION ALL
             SELECT dsp.parent_series
             FROM DistroSeriesParent dsp, t_parents p
             WHERE dsp.derived_series = p.parent_series AND
                 dsp.is_overlay = True
     ) '''
     store = IStore(DistroSeriesParent)
     # XXX: rvb 2011-05-20 bug=785733: Order by DSD.id for now.
     # Once the ordering is specified in the database, it should
     # be used to sort the results.
     return store.with_(SQL(rec_overlay_query, (derived_series.id, ))).find(
         DistroSeriesParent,
         SQL('DistroSeriesParent.parent_series IN '
             '(SELECT parent_series FROM t_parents)')).order_by(
                 DistroSeriesParent.id)
def get_packagesets(dsds, in_parent):
    """Return the packagesets for the given dsds inside the parent or
    the derived `DistroSeries`.

    Returns a dict with the corresponding packageset list for each dsd id.

    :param dsds: An iterable of `DistroSeriesDifference` instances.
    :param in_parent: A boolean indicating if we should look in the parent
        series' archive instead of the derived series' archive.
    """
    if len(dsds) == 0:
        return {}

    FlatPackagesetInclusion = Table("FlatPackagesetInclusion")

    tables = IStore(Packageset).using(DistroSeriesDifference, Packageset,
                                      PackagesetSources,
                                      FlatPackagesetInclusion)
    results = tables.find(
        (DistroSeriesDifference.id, Packageset),
        PackagesetSources.packageset_id == Column("child",
                                                  FlatPackagesetInclusion),
        Packageset.distroseries_id == (
            DistroSeriesDifference.parent_series_id
            if in_parent else DistroSeriesDifference.derived_series_id),
        Column("parent", FlatPackagesetInclusion) == Packageset.id,
        PackagesetSources.sourcepackagename_id == (
            DistroSeriesDifference.source_package_name_id),
        DistroSeriesDifference.id.is_in(dsd.id for dsd in dsds))
    results = results.order_by(PackagesetSources.sourcepackagename_id,
                               Packageset.name)

    grouped = defaultdict(list)
    for dsd_id, packageset in results:
        grouped[dsd_id].append(packageset)
    return grouped
예제 #56
0
    def getBranchesWithVisibleBugs(self, branches, user):
        """See `IBugBranchSet`."""
        # Avoid circular imports.
        from lp.bugs.model.bugtaskflat import BugTaskFlat
        from lp.bugs.model.bugtasksearch import get_bug_privacy_filter

        branch_ids = [branch.id for branch in branches]
        if not branch_ids:
            return []

        visible = get_bug_privacy_filter(user)
        return IStore(BugBranch).find(BugBranch.branchID,
                                      BugBranch.branch_id.is_in(branch_ids),
                                      BugTaskFlat.bug_id == BugBranch.bugID,
                                      visible).config(distinct=True)
예제 #57
0
def load_referencing(object_type,
                     owning_objects,
                     reference_keys,
                     extra_conditions=[]):
    """Load objects of object_type that reference owning_objects.

    Note that complex types like Person are best loaded through dedicated
    helpers that can eager load other related things (e.g. validity for
    Person).

    :param object_type: The object type to load - e.g. BranchSubscription.
    :param owning_objects: The objects which are referenced. E.g. [Branch()]
        At this point, all the objects should be of the same type, but that
        constraint could be lifted in future.
    :param reference_keys: A list of attributes that should be used to select
        object_type keys. e.g. ['branchID']
    :param extra_conditions: A list of Storm clauses that will be used in the
        final query.
    :return: A list of object_type where any of reference_keys refered to the
        primary key of any of owning_objects.
    """
    store = IStore(object_type)
    if type(owning_objects) not in (list, tuple):
        owning_objects = tuple(owning_objects)
    if not owning_objects:
        return []
    exemplar = owning_objects[0]
    primary_key = _primary_key(get_type(exemplar))
    attribute = primary_key.name
    ids = set(map(attrgetter(attribute), owning_objects))
    conditions = []
    # Note to future self doing perf tuning: may want to make ids a WITH
    # clause.
    for column in map(partial(getattr, object_type), reference_keys):
        conditions.append(column.is_in(ids))
    return list(store.find(object_type, Or(conditions), *extra_conditions))
 def getProductSeriesForBranches(branch_ids):
     """See `IBranchListingQueryOptimiser`."""
     # Since the branch listing renders the linked product series as
     # hyperlinks to the product series itself, and the canonical_url of
     # the product series traverses to the product, we can save ourselves
     # extra queries here by loading both the product and product series
     # objects.  These objects are then in the object cache, and not
     # queried again, but we only return the product series objects.
     return [
         series for product, series in IStore(Product).find((
             Product,
             ProductSeries), ProductSeries.branchID.is_in(
                 branch_ids), ProductSeries.product == Product.id).order_by(
                     ProductSeries.name)
     ]
예제 #59
0
 def find(cls, product, date_since=None, job_type=None):
     """See `IPersonMergeJobSource`."""
     conditions = [
         ProductJob.job_id == Job.id,
         ProductJob.product == product.id,
         ]
     if date_since is not None:
         conditions.append(
             Job.date_created >= date_since)
     if job_type is not None:
         conditions.append(
             ProductJob.job_type == job_type)
     return DecoratedResultSet(
         IStore(ProductJob).find(
             ProductJob, *conditions), cls)
    def requestBuild(self,
                     archive,
                     requester,
                     distroseries,
                     pocket=PackagePublishingPocket.RELEASE,
                     manual=False):
        """See `ISourcePackageRecipe`."""
        if not archive.is_ppa:
            raise NonPPABuildRequest

        buildable_distros = BuildableDistroSeries.findSeries(archive.owner)
        if distroseries not in buildable_distros:
            raise BuildNotAllowedForDistro(self, distroseries)

        reject_reason = archive.checkUpload(requester, distroseries, None,
                                            archive.default_component, pocket)
        if reject_reason is not None:
            raise reject_reason
        if self.isOverQuota(requester, distroseries):
            raise TooManyBuilds(self, distroseries)
        pending = IStore(self).find(
            SourcePackageRecipeBuild,
            SourcePackageRecipeBuild.recipe_id == self.id,
            SourcePackageRecipeBuild.distroseries_id == distroseries.id,
            SourcePackageRecipeBuild.archive_id == archive.id,
            SourcePackageRecipeBuild.status == BuildStatus.NEEDSBUILD)
        if pending.any() is not None:
            raise BuildAlreadyPending(self, distroseries)

        build = getUtility(ISourcePackageRecipeBuildSource).new(
            distroseries, self, requester, archive)
        build.queueBuild()
        queue_record = build.buildqueue_record
        if manual:
            queue_record.manualScore(queue_record.lastscore + 100)
        return build