~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/soyuz/adapters/archivesourcepublication.py

[r=sinzui][bug=855670] Add additional checks to the private team
        launchpad.LimitedView security adaptor so more users in defined
        roles can see the team.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2009-2010 Canonical Ltd.  This software is licensed under the
 
2
# GNU Affero General Public License version 3 (see the file LICENSE).
 
3
 
 
4
"""Decorated `SourcePackagePublishingHistory` setup infrastructure.
 
5
 
 
6
`ArchiveSourcePublications` allows any callsite dealing with a set of
 
7
`SourcePackagePublishingHistory` to quickly fetch all the external
 
8
references needed to present them properly in the PPA pages.
 
9
"""
 
10
 
 
11
__metaclass__ = type
 
12
 
 
13
__all__ = [
 
14
    'ArchiveSourcePublications',
 
15
    ]
 
16
 
 
17
from collections import defaultdict
 
18
 
 
19
from lazr.delegates import delegates
 
20
from zope.component import getUtility
 
21
 
 
22
from lp.registry.model.distroseries import DistroSeries
 
23
from lp.registry.model.sourcepackagename import SourcePackageName
 
24
from lp.services.database.lpstorm import IStore
 
25
from lp.services.librarian.browser import ProxiedLibraryFileAlias
 
26
from lp.soyuz.interfaces.publishing import (
 
27
    IPublishingSet,
 
28
    ISourcePackagePublishingHistory,
 
29
    )
 
30
from lp.soyuz.interfaces.sourcepackagerelease import ISourcePackageRelease
 
31
 
 
32
 
 
33
class ArchiveSourcePackageRelease:
 
34
    """Decorated `SourcePackageRelease` with cached 'upload_changesfile'.
 
35
 
 
36
    It receives the related upload changesfile, so it doesn't need
 
37
    to be recalculated.
 
38
    """
 
39
    delegates(ISourcePackageRelease)
 
40
 
 
41
    def __init__(self, context, changesfile):
 
42
        self.context = context
 
43
        self._changesfile = changesfile
 
44
 
 
45
    @property
 
46
    def upload_changesfile(self):
 
47
        """See `ISourcePackageRelease`."""
 
48
        return self._changesfile
 
49
 
 
50
 
 
51
class ArchiveSourcePublication:
 
52
    """Delegates to `ISourcePackagePublishingHistory`.
 
53
 
 
54
    It receives the expensive external references when it is created
 
55
    and provide them as through the decorated interface transparently.
 
56
    """
 
57
    delegates(ISourcePackagePublishingHistory)
 
58
 
 
59
    def __init__(self, context, changesfile, status_summary):
 
60
        self.context = context
 
61
        self._changesfile = changesfile
 
62
        self._status_summary = status_summary
 
63
 
 
64
    @property
 
65
    def sourcepackagerelease(self):
 
66
        if self._changesfile is not None:
 
67
            changesfile = ProxiedLibraryFileAlias(
 
68
                self._changesfile, self.context.archive)
 
69
        else:
 
70
            changesfile = None
 
71
        return ArchiveSourcePackageRelease(
 
72
            self.context.sourcepackagerelease, changesfile)
 
73
 
 
74
    def getStatusSummaryForBuilds(self):
 
75
        """See `ISourcePackagePublishingHistory`."""
 
76
        return self._status_summary
 
77
 
 
78
 
 
79
class ArchiveSourcePublications:
 
80
    """`ArchiveSourcePublication` iterator."""
 
81
 
 
82
    def __init__(self, source_publications):
 
83
        """Receives the list of target `SourcePackagePublishingHistory`."""
 
84
        self._source_publications = list(source_publications)
 
85
 
 
86
    @property
 
87
    def has_sources(self):
 
88
        """Whether or not there are sources to be processed."""
 
89
        return len(self._source_publications) > 0
 
90
 
 
91
    def getChangesFileBySource(self):
 
92
        """Map changesfiles by their corresponding source publications."""
 
93
        publishing_set = getUtility(IPublishingSet)
 
94
        changesfile_set = publishing_set.getChangesFilesForSources(
 
95
            self._source_publications)
 
96
        changesfile_mapping = {}
 
97
        for entry in changesfile_set:
 
98
            source, queue_record, source_release, changesfile, content = entry
 
99
            changesfile_mapping[source] = changesfile
 
100
        return changesfile_mapping
 
101
 
 
102
    def __nonzero__(self):
 
103
        """Are there any sources to iterate?"""
 
104
        return self.has_sources
 
105
 
 
106
    def __iter__(self):
 
107
        """`ArchiveSourcePublication` iterator."""
 
108
        results = []
 
109
        if not self.has_sources:
 
110
            return iter(results)
 
111
 
 
112
        # Load the extra-information for all source publications.
 
113
        # All of this code would be better on an object representing a set of
 
114
        # publications.
 
115
        changesfiles_by_source = self.getChangesFileBySource()
 
116
        # Source package names are used by setNewerDistroSeriesVersions:
 
117
        # batch load the used source package names.
 
118
        spn_ids = set()
 
119
        for spph in self._source_publications:
 
120
            spn_ids.add(spph.sourcepackagerelease.sourcepackagenameID)
 
121
        list(IStore(SourcePackageName).find(SourcePackageName,
 
122
            SourcePackageName.id.is_in(spn_ids)))
 
123
        DistroSeries.setNewerDistroSeriesVersions(self._source_publications)
 
124
        # Load all the build status summaries at once.
 
125
        publishing_set = getUtility(IPublishingSet)
 
126
        archive_pub_ids = defaultdict(list)
 
127
        for pub in self._source_publications:
 
128
            archive_pub_ids[pub.archive].append(pub.id)
 
129
        status_summaries = {}
 
130
        for archive, pub_ids in archive_pub_ids.items():
 
131
            status_summaries.update(
 
132
                publishing_set.getBuildStatusSummariesForSourceIdsAndArchive(
 
133
                    pub_ids, archive))
 
134
 
 
135
        # Build the decorated object with the information we have.
 
136
        for pub in self._source_publications:
 
137
            changesfile = changesfiles_by_source.get(pub, None)
 
138
            status_summary = status_summaries[pub.id]
 
139
            complete_pub = ArchiveSourcePublication(
 
140
                pub, changesfile=changesfile, status_summary=status_summary)
 
141
            results.append(complete_pub)
 
142
 
 
143
        return iter(results)