~launchpad-pqm/launchpad/devel

14642.1.8 by Curtis Hovey
Updated copyright.
1
# Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
8687.15.17 by Karl Fogel
Add the copyright header block to the rest of the files under lib/lp/.
2
# GNU Affero General Public License version 3 (see the file LICENSE).
2705 by Canonical.com Patch Queue Manager
r=spiv, mark's soyuz loving.
3
4
__metaclass__ = type
5
6
__all__ = [
13014.2.2 by Curtis Hovey
Remove IQuestionTarget from ISourcePackage.
7
    'DistributionSourcePackageAnswersMenu',
9209.4.5 by Guilherme Salgado
Update all existing breadcrumb adapters to use Breadcrumb rather than BreadcrumbBuilder. Also rename them all
8
    'DistributionSourcePackageBreadcrumb',
11664.3.2 by Edwin Grubbs
IService adapters and disable Report Bug button and bug listing in buglisting-default.pt for objects that do not use LP.
9
    'DistributionSourcePackageChangelogView',
7509.3.6 by Gavin Panella
Reorder __all__.
10
    'DistributionSourcePackageEditView',
2705 by Canonical.com Patch Queue Manager
r=spiv, mark's soyuz loving.
11
    'DistributionSourcePackageFacets',
13014.2.2 by Curtis Hovey
Remove IQuestionTarget from ISourcePackage.
12
    'DistributionSourcePackageHelpView',
2705 by Canonical.com Patch Queue Manager
r=spiv, mark's soyuz loving.
13
    'DistributionSourcePackageNavigation',
3732 by Steve Alexander
merge from mainline, resolving conflicts
14
    'DistributionSourcePackageOverviewMenu',
11664.3.2 by Edwin Grubbs
IService adapters and disable Report Bug button and bug listing in buglisting-default.pt for objects that do not use LP.
15
    'DistributionSourcePackagePublishingHistoryView',
7509.3.1 by Gavin Panella
Implement distribution source package editing via the web. Only bug reporting guidelines can be changed right now.
16
    'DistributionSourcePackageView',
2705 by Canonical.com Patch Queue Manager
r=spiv, mark's soyuz loving.
17
    ]
18
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
19
from datetime import datetime
6615.1.4 by James Henstridge
Add back support for getting package diffs in one query.
20
import itertools
21
import operator
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
22
23
from lazr.delegates import delegates
13590.2.1 by William Grant
Make DSP:+index use IJSONRequestCache rather than manipulating LP.cache directly. That doesn't work since r13548.
24
from lazr.restful.interfaces import IJSONRequestCache
13931.2.1 by Steve Kowalik
Chip away at canonical.lazr a little more.
25
from lazr.restful.utils import smartquote
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
26
import pytz
11664.3.2 by Edwin Grubbs
IService adapters and disable Report Bug button and bug listing in buglisting-default.pt for objects that do not use LP.
27
from zope.component import (
28
    adapter,
29
    getUtility,
30
    )
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
31
from zope.interface import (
32
    implements,
33
    Interface,
34
    )
9854.1.1 by Curtis Hovey
Use the sorted_dotted_numbers function to sort distroseries by version as is done for product series and releases.
35
36
from lp.answers.browser.questiontarget import (
13014.2.2 by Curtis Hovey
Remove IQuestionTarget from ISourcePackage.
37
    QuestionTargetAnswersMenu,
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
38
    QuestionTargetFacetMixin,
39
    QuestionTargetTraversalMixin,
40
    )
12915.5.1 by Curtis Hovey
Rename questionenums.py to the new standard or enums.py
41
from lp.answers.enums import QuestionStatus
14642.1.2 by Curtis Hovey
Removed action from webapp globs.
42
from lp.app.browser.launchpadform import (
43
    action,
44
    LaunchpadEditFormView,
45
    )
13269.2.13 by Jonathan Lange
lp.app.browser.stringformatter seems better than lp.app.text
46
from lp.app.browser.stringformatter import (
47
    extract_bug_numbers,
13269.2.15 by Jonathan Lange
Move extract_email_addresses.
48
    extract_email_addresses,
13269.2.13 by Jonathan Lange
lp.app.browser.stringformatter seems better than lp.app.text
49
    )
14550.1.1 by Steve Kowalik
Run format-imports over lib/lp and lib/canonical/launchpad
50
from lp.app.browser.tales import CustomizableFormatter
12617.2.6 by Curtis Hovey
Added a property to help the template construct a sentence about bug and questions.
51
from lp.app.enums import ServiceUsage
11926.7.3 by Edwin Grubbs
Formatted imports.
52
from lp.app.interfaces.launchpad import IServiceUsage
9854.1.1 by Curtis Hovey
Use the sorted_dotted_numbers function to sort distroseries by version as is done for product series and releases.
53
from lp.bugs.browser.bugtask import BugTargetTraversalMixin
7675.1025.1 by Gary Poster
structural subscriptions are moved from registry to bugs. moved tests pass.
54
from lp.bugs.browser.structuralsubscription import (
12393.32.1 by Gary Poster
add links for distribution source packages
55
    expose_structural_subscription_data_to_js,
56
    StructuralSubscriptionMenuMixin,
7675.1025.1 by Gary Poster
structural subscriptions are moved from registry to bugs. moved tests pass.
57
    StructuralSubscriptionTargetTraversalMixin,
58
    )
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
59
from lp.bugs.interfaces.bug import IBugSet
12688.1.5 by Brad Crittenden
Fixed issues from review. Created add_subscribe_link.
60
from lp.registry.browser import add_subscribe_link
10981.4.14 by Brad Crittenden
Add configure_bugtracker to involvement portlet on product bugs page. Refactored bugs menus for DRY
61
from lp.registry.browser.pillar import PillarBugsMenu
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
62
from lp.registry.interfaces.distributionsourcepackage import (
63
    IDistributionSourcePackage,
64
    )
13760.2.4 by Steve Kowalik
Clean up pyflakes warnings.
65
from lp.registry.interfaces.person import IPersonSet
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
66
from lp.registry.interfaces.pocket import pocketsuffix
11926.7.3 by Edwin Grubbs
Formatted imports.
67
from lp.registry.interfaces.series import SeriesStatus
14612.2.1 by William Grant
format-imports on lib/. So many imports.
68
from lp.services.helpers import shortlist
11382.6.34 by Gavin Panella
Reformat imports in all files touched so far.
69
from lp.services.propertycache import cachedproperty
14612.2.1 by William Grant
format-imports on lib/. So many imports.
70
from lp.services.webapp import (
71
    canonical_url,
72
    Navigation,
73
    redirection,
74
    StandardLaunchpadFacets,
75
    )
76
from lp.services.webapp.breadcrumb import Breadcrumb
77
from lp.services.webapp.interfaces import IBreadcrumb
78
from lp.services.webapp.menu import (
79
    ApplicationMenu,
80
    enabled_with_permission,
81
    Link,
82
    NavigationMenu,
83
    )
14642.1.2 by Curtis Hovey
Removed action from webapp globs.
84
from lp.services.webapp.publisher import LaunchpadView
14612.2.1 by William Grant
format-imports on lib/. So many imports.
85
from lp.services.webapp.sorting import sorted_dotted_numbers
13760.2.4 by Steve Kowalik
Clean up pyflakes warnings.
86
from lp.soyuz.browser.sourcepackagerelease import linkify_changelog
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
87
from lp.soyuz.interfaces.archive import IArchiveSet
8447.1.2 by Jonathan Lange
Fix up lots of lint, including removing code that's been disabled forever.
88
from lp.soyuz.interfaces.distributionsourcepackagerelease import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
89
    IDistributionSourcePackageRelease,
90
    )
8294.6.1 by Julian Edwards
First stab at code-reorg. Still got a discrepancy on stuff I assigned to registry but not migrated yet.
91
from lp.soyuz.interfaces.packagediff import IPackageDiffSet
9556.2.2 by Jeroen Vermeulen
Lifted Nav class into a mixin for DistributionSourcePackage's benefit.
92
from lp.translations.browser.customlanguagecode import (
11382.6.44 by Gavin Panella
Fix and reformat imports.
93
    HasCustomLanguageCodesTraversalMixin,
94
    )
6476.1.4 by Matthew Paul Thomas
Converts distribution source package Web stuff to use smartquote().
95
4363.1.11 by Mark Shuttleworth
Add option to show complete publishing history of source package
96
11227.3.18 by Curtis Hovey
Redefine render() not __call__ to ensure redirect work. Added
97
class DistributionSourcePackageFormatterAPI(CustomizableFormatter):
98
    """Adapt IDistributionSourcePackage objects to a formatted string."""
99
11227.3.19 by Curtis Hovey
Added test for dsp link formatter and fixed view permission.
100
    _link_permission = 'zope.Public'
11227.3.18 by Curtis Hovey
Redefine render() not __call__ to ensure redirect work. Added
101
    _link_summary_template = '%(displayname)s'
102
103
    def _link_summary_values(self):
104
        displayname = self._context.displayname
105
        return {'displayname': displayname}
106
107
11664.3.2 by Edwin Grubbs
IService adapters and disable Report Bug button and bug listing in buglisting-default.pt for objects that do not use LP.
108
@adapter(IDistributionSourcePackage)
9209.4.5 by Guilherme Salgado
Update all existing breadcrumb adapters to use Breadcrumb rather than BreadcrumbBuilder. Also rename them all
109
class DistributionSourcePackageBreadcrumb(Breadcrumb):
6767.6.26 by Maris Fogels
Rework based on reviewer feedback.
110
    """Builds a breadcrumb for an `IDistributionSourcePackage`."""
11664.3.2 by Edwin Grubbs
IService adapters and disable Report Bug button and bug listing in buglisting-default.pt for objects that do not use LP.
111
    implements(IBreadcrumb)
9752.2.9 by Curtis Hovey
Merged from launchpad devel. Resolved conflicts in lp.r.b.distributionsourcepackge.
112
6767.6.7 by Maris Fogels
Migrated the DistributionSourcePackage breadcrumb to the new system interface.
113
    @property
114
    def text(self):
115
        return smartquote('"%s" package') % (
116
            self.context.sourcepackagename.name)
117
118
3691.398.19 by Francis J. Lacoste
Rename most remaining classes (views, database, authorizations, notifications, scripts.)
119
class DistributionSourcePackageFacets(QuestionTargetFacetMixin,
3691.188.5 by Francis J. Lacoste
Refactor common tickettarget support facet link and traversal into common mixins
120
                                      StandardLaunchpadFacets):
2705 by Canonical.com Patch Queue Manager
r=spiv, mark's soyuz loving.
121
122
    usedfor = IDistributionSourcePackage
8698.5.6 by Tim Penhey
Enable the Code tab for DistributionSourcePackages.
123
    enable_only = ['overview', 'bugs', 'answers', 'branches']
2705 by Canonical.com Patch Queue Manager
r=spiv, mark's soyuz loving.
124
13324.9.1 by Jonathan Riddell
add hover text for distro package pages
125
    def overview(self):
126
        text = 'Overview'
13303.11.22 by Aaron Bentley
Fix lint.
127
        summary = 'General information about {0}'.format(
128
            self.context.displayname)
13324.9.1 by Jonathan Riddell
add hover text for distro package pages
129
        return Link('', text, summary)
130
131
    def bugs(self):
132
        text = 'Bugs'
133
        summary = 'Bugs reported about {0}'.format(self.context.displayname)
134
        return Link('', text, summary)
135
136
    def branches(self):
137
        text = 'Code'
138
        summary = 'Branches for {0}'.format(self.context.displayname)
139
        return Link('', text, summary)
140
2705 by Canonical.com Patch Queue Manager
r=spiv, mark's soyuz loving.
141
9660.4.4 by Tom Berger
do not use a mixin inside a mixin. zope cant handle that
142
class DistributionSourcePackageLinksMixin:
9752.2.9 by Curtis Hovey
Merged from launchpad devel. Resolved conflicts in lp.r.b.distributionsourcepackge.
143
4363.1.11 by Mark Shuttleworth
Add option to show complete publishing history of source package
144
    def publishinghistory(self):
145
        return Link('+publishinghistory', 'Show publishing history')
2821.2.25 by Brad Bollenbach
checkpoint
146
11702.2.4 by Brian Murray
convert some additional launchpad.Edits to launchpad.BugSupervisor
147
    @enabled_with_permission('launchpad.BugSupervisor')
7509.3.4 by Gavin Panella
Move the link to the actions menu and rename it.
148
    def edit(self):
149
        """Edit the details of this source package."""
150
        # This is titled "Edit bug reporting guidelines" because that
151
        # is the only editable property of a source package right now.
7675.993.1 by Abel Deuring
The forms to configure the bugtracker for products and for DSPs now contains a field enable_bugfiling_duplicate_search; bug filing pages show immediately the complete form if enable_bugfiling_duplicate_search is turned off.
152
        return Link('+edit', 'Configure bug tracker', icon='edit')
7509.3.4 by Gavin Panella
Move the link to the actions menu and rename it.
153
8971.28.21 by Julian Edwards
Lots of changes
154
    def new_bugs(self):
155
        base_path = "+bugs"
156
        get_data = "?field.status:list=NEW"
157
        return Link(base_path + get_data, "New bugs", site="bugs")
158
159
    def open_questions(self):
160
        base_path = "+questions"
161
        get_data = "?field.status=OPEN"
162
        return Link(base_path + get_data, "Open Questions", site="answers")
163
2821.2.25 by Brad Bollenbach
checkpoint
164
9150.6.21 by Julian Edwards
Fix some tests
165
class DistributionSourcePackageOverviewMenu(
166
    ApplicationMenu, DistributionSourcePackageLinksMixin):
167
168
    usedfor = IDistributionSourcePackage
169
    facet = 'overview'
12393.32.1 by Gary Poster
add links for distribution source packages
170
    links = ['new_bugs', 'open_questions']
9150.6.21 by Julian Edwards
Fix some tests
171
172
5220.8.2 by David Allouche
Experimental browser code to delete packaging entries from the distributionsourcepackage page.
173
class DistributionSourcePackageBugsMenu(
12393.32.1 by Gary Poster
add links for distribution source packages
174
    PillarBugsMenu,
175
    StructuralSubscriptionMenuMixin,
176
    DistributionSourcePackageLinksMixin):
2821.2.25 by Brad Bollenbach
checkpoint
177
178
    usedfor = IDistributionSourcePackage
179
    facet = 'bugs'
12393.32.1 by Gary Poster
add links for distribution source packages
180
181
    @cachedproperty
182
    def links(self):
183
        links = ['filebug']
12688.1.5 by Brad Crittenden
Fixed issues from review. Created add_subscribe_link.
184
        add_subscribe_link(links)
12393.32.1 by Gary Poster
add links for distribution source packages
185
        return links
8399.3.1 by Michael Nelson
Diff from old branch..
186
2821.2.25 by Brad Bollenbach
checkpoint
187
13014.2.2 by Curtis Hovey
Remove IQuestionTarget from ISourcePackage.
188
class DistributionSourcePackageAnswersMenu(QuestionTargetAnswersMenu):
189
190
    usedfor = IDistributionSourcePackage
191
    facet = 'answers'
192
193
    links = QuestionTargetAnswersMenu.links + ['gethelp']
194
195
    def gethelp(self):
196
        return Link('+gethelp', 'Help and support options', icon='info')
197
198
8903.3.3 by Jonathan Lange
Fix traversal from distrosourcepackages.
199
class DistributionSourcePackageNavigation(Navigation,
9556.2.2 by Jeroen Vermeulen
Lifted Nav class into a mixin for DistributionSourcePackage's benefit.
200
    BugTargetTraversalMixin, HasCustomLanguageCodesTraversalMixin,
201
    QuestionTargetTraversalMixin,
9206.2.1 by William Grant
Add a URL and traversal mixin for IStructuralSubscription. Mix it into all targets.
202
    StructuralSubscriptionTargetTraversalMixin):
2821.2.25 by Brad Bollenbach
checkpoint
203
204
    usedfor = IDistributionSourcePackage
205
3112.1.3 by Brad Bollenbach
fix https://launchpad.net/products/malone/+bug/29182 (Can't change the Initial Bug Contact on a source package) by adding a URL-hacker-friendly redirect
206
    redirection("+editbugcontact", "+subscribe")
207
8903.3.3 by Jonathan Lange
Fix traversal from distrosourcepackages.
208
    def traverse(self, name):
209
        return self.context.getVersion(name)
210
2705 by Canonical.com Patch Queue Manager
r=spiv, mark's soyuz loving.
211
6615.1.3 by James Henstridge
Undo DistributionSourcePackageRelease changes, and create a
212
class DecoratedDistributionSourcePackageRelease:
213
    """A decorated DistributionSourcePackageRelease.
214
215
    The publishing history and package diffs for the release are
216
    pre-cached.
217
    """
7465.5.1 by Gary Poster
integrate lazr.config and lazr.delegates
218
    delegates(IDistributionSourcePackageRelease, 'context')
6615.1.3 by James Henstridge
Undo DistributionSourcePackageRelease changes, and create a
219
9719.5.12 by Muharem Hrnjadovic
Large-scale refactoring to allow the linkification using decorated IDistributionSourcePackageRelease instances.
220
    def __init__(
221
        self, distributionsourcepackagerelease, publishing_history,
222
        package_diffs, person_data, user):
6615.1.3 by James Henstridge
Undo DistributionSourcePackageRelease changes, and create a
223
        self.context = distributionsourcepackagerelease
224
        self._publishing_history = publishing_history
225
        self._package_diffs = package_diffs
9719.5.12 by Muharem Hrnjadovic
Large-scale refactoring to allow the linkification using decorated IDistributionSourcePackageRelease instances.
226
        self._person_data = person_data
227
        self._user = user
6615.1.3 by James Henstridge
Undo DistributionSourcePackageRelease changes, and create a
228
229
    @property
230
    def publishing_history(self):
231
        """ See `IDistributionSourcePackageRelease`."""
232
        return self._publishing_history
233
234
    @property
235
    def package_diffs(self):
236
        """ See `ISourcePackageRelease`."""
237
        return self._package_diffs
238
9719.5.12 by Muharem Hrnjadovic
Large-scale refactoring to allow the linkification using decorated IDistributionSourcePackageRelease instances.
239
    @property
240
    def change_summary(self):
241
        """ See `ISourcePackageRelease`."""
9719.5.22 by Muharem Hrnjadovic
Removed test code.
242
        return linkify_changelog(
9719.5.20 by Muharem Hrnjadovic
Bug fix, used the wrong spr.
243
            self._user, self.context.change_summary, self._person_data)
9719.5.12 by Muharem Hrnjadovic
Large-scale refactoring to allow the linkification using decorated IDistributionSourcePackageRelease instances.
244
6615.1.3 by James Henstridge
Undo DistributionSourcePackageRelease changes, and create a
245
8971.28.8 by Julian Edwards
dsp mockup enhancements
246
class IDistributionSourcePackageActionMenu(Interface):
247
    """Marker interface for the action menu."""
248
249
9150.6.21 by Julian Edwards
Fix some tests
250
class DistributionSourcePackageActionMenu(
12393.32.1 by Gary Poster
add links for distribution source packages
251
    NavigationMenu,
252
    StructuralSubscriptionMenuMixin,
253
    DistributionSourcePackageLinksMixin):
8971.28.8 by Julian Edwards
dsp mockup enhancements
254
    """Action menu for distro source packages."""
255
    usedfor = IDistributionSourcePackageActionMenu
256
    facet = 'overview'
257
    title = 'Actions'
12393.32.1 by Gary Poster
add links for distribution source packages
258
259
    @cachedproperty
260
    def links(self):
261
        links = ['publishing_history', 'change_log']
12688.1.5 by Brad Crittenden
Fixed issues from review. Created add_subscribe_link.
262
        add_subscribe_link(links)
12393.32.1 by Gary Poster
add links for distribution source packages
263
        links.append('edit')
264
        return links
9772.10.1 by Edwin Grubbs
Moved full publishing history link.
265
266
    def publishing_history(self):
267
        text = 'View full publishing history'
268
        return Link('+publishinghistory', text, icon="info")
8971.28.8 by Julian Edwards
dsp mockup enhancements
269
270
    def change_log(self):
271
        text = 'View full change log'
8971.28.13 by Julian Edwards
add icon to changelog link
272
        return Link('+changelog', text, icon="info")
8971.28.8 by Julian Edwards
dsp mockup enhancements
273
274
13303.11.10 by Aaron Bentley
Fix pages broken by assuming LaunchpadView.
275
class DistributionSourcePackageBaseView(LaunchpadView):
9558.4.1 by Celso Providelo
Fixing heading and titles for DistributionSourcePackage:+{changelog, publishinghistory} and DistroSeriesSourcePackage:+publishinghistory pages.
276
    """Common features to all `DistributionSourcePackage` views."""
277
278
    def releases(self):
9752.2.9 by Curtis Hovey
Merged from launchpad devel. Resolved conflicts in lp.r.b.distributionsourcepackge.
279
        """All releases for this `IDistributionSourcePackage`."""
280
9719.5.13 by Muharem Hrnjadovic
Made code more robust.
281
        def not_empty(text):
282
            return (
283
                text is not None and isinstance(text, basestring)
284
                and len(text.strip()) > 0)
285
9558.4.1 by Celso Providelo
Fixing heading and titles for DistributionSourcePackage:+{changelog, publishinghistory} and DistroSeriesSourcePackage:+publishinghistory pages.
286
        dspr_pubs = self.context.getReleasesAndPublishingHistory()
287
288
        # Return as early as possible to avoid unnecessary processing.
289
        if len(dspr_pubs) == 0:
290
            return []
291
9719.5.9 by Muharem Hrnjadovic
Slightly enhanced code.
292
        sprs = [dspr.sourcepackagerelease for (dspr, spphs) in dspr_pubs]
9719.5.16 by Muharem Hrnjadovic
Enhanced comments.
293
        # Pre-load the bugs and persons referenced by the +changelog page from
294
        # the database.
295
        # This will improve the performance of the ensuing changelog
296
        # linkification.
9719.5.13 by Muharem Hrnjadovic
Made code more robust.
297
        the_changelog = '\n'.join(
298
            [spr.changelog_entry for spr in sprs
299
             if not_empty(spr.changelog_entry)])
9719.5.12 by Muharem Hrnjadovic
Large-scale refactoring to allow the linkification using decorated IDistributionSourcePackageRelease instances.
300
        unique_bugs = extract_bug_numbers(the_changelog)
301
        self._bug_data = list(
7675.166.314 by Stuart Bishop
DB Unicode fixes
302
            getUtility(IBugSet).getByNumbers(
303
                [int(key) for key in unique_bugs.keys()]))
9719.5.19 by Muharem Hrnjadovic
Preload email/person data only if user is logged on.
304
        # Preload email/person data only if user is logged on. In the opposite
305
        # case the emails in the changelog will be obfuscated anyway and thus
306
        # cause no database lookups.
307
        if self.user:
308
            self._person_data = dict(
13760.2.1 by Steve Kowalik
Purge DistributionSourcePackage.getPersonsByEmail(), refactoring it into IPersonSet.getByEmails(), and rewriting IPersonSet.getByEmail() to be a wrapper around it.
309
                [(email.email, person) for (email, person) in
310
                    getUtility(IPersonSet).getByEmails(
311
                        extract_email_addresses(the_changelog),
13760.2.3 by Steve Kowalik
Use include_hidden, add a short circuit and correct the docstring.
312
                        include_hidden=False)])
9719.5.19 by Muharem Hrnjadovic
Preload email/person data only if user is logged on.
313
        else:
314
            self._person_data = None
9558.4.1 by Celso Providelo
Fixing heading and titles for DistributionSourcePackage:+{changelog, publishinghistory} and DistroSeriesSourcePackage:+publishinghistory pages.
315
        # Collate diffs for relevant SourcePackageReleases
12599.4.2 by Leonard Richardson
Merge from trunk.
316
        pkg_diffs = getUtility(IPackageDiffSet).getDiffsToReleases(
317
            sprs, preload_for_display=True)
9558.4.1 by Celso Providelo
Fixing heading and titles for DistributionSourcePackage:+{changelog, publishinghistory} and DistroSeriesSourcePackage:+publishinghistory pages.
318
        spr_diffs = {}
319
        for spr, diffs in itertools.groupby(pkg_diffs,
320
                                            operator.attrgetter('to_source')):
321
            spr_diffs[spr] = list(diffs)
322
323
        return [
324
            DecoratedDistributionSourcePackageRelease(
9719.5.12 by Muharem Hrnjadovic
Large-scale refactoring to allow the linkification using decorated IDistributionSourcePackageRelease instances.
325
                dspr, spphs, spr_diffs.get(dspr.sourcepackagerelease, []),
326
                self._person_data, self.user)
9558.4.1 by Celso Providelo
Fixing heading and titles for DistributionSourcePackage:+{changelog, publishinghistory} and DistroSeriesSourcePackage:+publishinghistory pages.
327
            for (dspr, spphs) in dspr_pubs]
328
329
330
class DistributionSourcePackageView(DistributionSourcePackageBaseView,
10374.2.11 by Edwin Grubbs
Fixed tests.
331
                                    LaunchpadView):
9150.6.36 by Julian Edwards
Review changes from barry
332
    """View class for DistributionSourcePackage."""
8971.28.8 by Julian Edwards
dsp mockup enhancements
333
    implements(IDistributionSourcePackageActionMenu)
5220.8.2 by David Allouche
Experimental browser code to delete packaging entries from the distributionsourcepackage page.
334
12393.32.1 by Gary Poster
add links for distribution source packages
335
    def initialize(self):
336
        super(DistributionSourcePackageView, self).initialize()
337
        expose_structural_subscription_data_to_js(
338
            self.context, self.request, self.user)
13598.1.1 by William Grant
Only set archive_context_url if latest_overall_publication exists.
339
340
        pub = self.context.latest_overall_publication
341
        if pub:
342
            IJSONRequestCache(self.request).objects['archive_context_url'] = (
343
                canonical_url(pub.archive, path_only_if_possible=True))
12393.32.1 by Gary Poster
add links for distribution source packages
344
9234.1.1 by Julian Edwards
Add DSP:+changelog traversal
345
    @property
7675.298.204 by Edwin Grubbs
Fixed page titles and labels.
346
    def label(self):
9234.1.1 by Julian Edwards
Add DSP:+changelog traversal
347
        return self.context.title
348
13980.3.21 by Curtis Hovey
Moved dsp index page_title into view.
349
    page_title = label
350
9752.2.3 by Curtis Hovey
Extracted PackagingDeleteView from DistributionSourcePackageView So that other
351
    @property
352
    def next_url(self):
5220.8.2 by David Allouche
Experimental browser code to delete packaging entries from the distributionsourcepackage page.
353
        """See `LaunchpadFormView`."""
9752.2.3 by Curtis Hovey
Extracted PackagingDeleteView from DistributionSourcePackageView So that other
354
        return canonical_url(self.context)
5220.8.2 by David Allouche
Experimental browser code to delete packaging entries from the distributionsourcepackage page.
355
9752.2.5 by Curtis Hovey
Converted get_packaging into a property: all_packaging.
356
    @property
5543.1.3 by Julian Edwards
Remove the properties added to ISourcePackagePublishingHistory and
357
    def all_published_in_active_distroseries(self):
358
        """Return a list of publishings in each active distroseries.
359
360
        The list contains dictionaries each with a key of "suite" and
361
        "description" where suite is "distroseries-pocket" and
362
        description is "(version): component/section".
363
        """
364
        results = []
365
        for pub in self.context.current_publishing_records:
366
            if pub.distroseries.active:
367
                entry = {
9752.2.9 by Curtis Hovey
Merged from launchpad devel. Resolved conflicts in lp.r.b.distributionsourcepackge.
368
                    "suite": (pub.distroseries.name.capitalize() +
5543.1.3 by Julian Edwards
Remove the properties added to ISourcePackagePublishingHistory and
369
                               pocketsuffix[pub.pocket]),
9752.2.9 by Curtis Hovey
Merged from launchpad devel. Resolved conflicts in lp.r.b.distributionsourcepackge.
370
                    "description": "(%s): %s/%s" % (
5543.1.3 by Julian Edwards
Remove the properties added to ISourcePackagePublishingHistory and
371
                        pub.sourcepackagerelease.version,
9752.2.9 by Curtis Hovey
Merged from launchpad devel. Resolved conflicts in lp.r.b.distributionsourcepackge.
372
                        pub.component.name, pub.section.name),
5543.1.3 by Julian Edwards
Remove the properties added to ISourcePackagePublishingHistory and
373
                    }
374
                results.append(entry)
375
        return results
376
8697.14.6 by Michael Nelson
Added view test with basic coverage...
377
    @property
8831.1.1 by Michael Nelson
Renamed variables to reflect ordering of related PPAs
378
    def related_ppa_versions(self):
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
379
        """Return a list of the latest 3 ppas with related publishings.
8697.14.7 by Michael Nelson
Updated distributionsourcepackage view with latest_published_ppa_versions, but has dupes.
380
381
        The list contains dictionaries each with a key of 'archive' and
382
        'publications'.
383
        """
384
        # Grab the related archive publications and limit the result to
385
        # the first 3.
8697.14.14 by Michael Nelson
Improving comments.
386
        # XXX Michael Nelson 2009-06-24 bug=387020
387
        # Currently we need to find distinct archives here manually because,
388
        # without a concept of IArchive.rank or similar, the best ordering
389
        # that orderDistributionSourcePackage.findRelatedArchives() method
390
        # can provide is on a join (SourcePackageRelease.dateuploaded), but
391
        # this prohibits a distinct clause.
392
        # To ensure that we find distinct archives here with only one query,
393
        # we grab the first 20 results and iterate through to find three
394
        # distinct archives (20 is a magic number being greater than
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
395
        # 3 * number of distroseries).
8831.1.2 by Michael Nelson
Updated the DSP.findRelatedArchives to order by creators total karma.
396
        related_archives = self.context.findRelatedArchives()
8831.1.1 by Michael Nelson
Renamed variables to reflect ordering of related PPAs
397
        related_archives.config(limit=20)
398
        top_three_archives = []
399
        for archive in related_archives:
400
            if archive in top_three_archives:
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
401
                continue
402
            else:
8831.1.1 by Michael Nelson
Renamed variables to reflect ordering of related PPAs
403
                top_three_archives.append(archive)
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
404
8831.1.1 by Michael Nelson
Renamed variables to reflect ordering of related PPAs
405
            if len(top_three_archives) == 3:
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
406
                break
407
8831.1.1 by Michael Nelson
Renamed variables to reflect ordering of related PPAs
408
        # Now we'll find the relevant publications for the top
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
409
        # three archives.
410
        archive_set = getUtility(IArchiveSet)
411
        publications = archive_set.getPublicationsInArchives(
8831.1.1 by Michael Nelson
Renamed variables to reflect ordering of related PPAs
412
                self.context.sourcepackagename, top_three_archives,
8697.16.3 by Michael Nelson
Updated DistributionSourcePackageView to ensure that new distribution arg is included when calling IArchiveSet.getPublicationsInArchives().
413
                self.context.distribution)
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
414
415
        # Collect the publishings for each archive
8697.14.11 by Michael Nelson
Finished UI and view work to display related PPAs for DSPs.
416
        archive_publishings = {}
417
        for pub in publications:
418
            archive_publishings.setdefault(pub.archive, []).append(pub)
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
419
420
        # Then construct a list of dicts with the results for easy use in
421
        # the template, preserving the order of the archives:
8697.14.11 by Michael Nelson
Finished UI and view work to display related PPAs for DSPs.
422
        archive_versions = []
8831.1.1 by Michael Nelson
Renamed variables to reflect ordering of related PPAs
423
        for archive in top_three_archives:
8697.14.11 by Michael Nelson
Finished UI and view work to display related PPAs for DSPs.
424
            versions = []
8697.14.14 by Michael Nelson
Improving comments.
425
426
            # For each publication, append something like:
427
            # 'Jaunty (1.0.1b)' to the versions list.
8697.14.11 by Michael Nelson
Finished UI and view work to display related PPAs for DSPs.
428
            for pub in archive_publishings[archive]:
429
                versions.append(
430
                    "%s (%s)" % (
431
                        pub.distroseries.displayname,
9752.2.9 by Curtis Hovey
Merged from launchpad devel. Resolved conflicts in lp.r.b.distributionsourcepackge.
432
                        pub.source_package_version,
8697.14.11 by Michael Nelson
Finished UI and view work to display related PPAs for DSPs.
433
                        )
434
                    )
435
            archive_versions.append({
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
436
                'archive': archive,
9752.2.9 by Curtis Hovey
Merged from launchpad devel. Resolved conflicts in lp.r.b.distributionsourcepackge.
437
                'versions': ", ".join(versions),
8697.14.9 by Michael Nelson
Updated to ensure that the DistributionSourcePackageView.latest_published_ppa_versions does not present duplicate archives.
438
                })
439
8697.14.11 by Michael Nelson
Finished UI and view work to display related PPAs for DSPs.
440
        return archive_versions
441
442
    @property
443
    def further_ppa_versions_url(self):
444
        """Return the url used to find further PPA versions of this package.
445
        """
446
        return "%s/+ppas?name_filter=%s" % (
447
            canonical_url(self.context.distribution),
448
            self.context.name,
449
            )
8697.14.6 by Michael Nelson
Added view test with basic coverage...
450
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
451
    @cachedproperty
452
    def active_distroseries_packages(self):
453
        """Cached proxy call to context/get_distroseries_packages."""
454
        return self.context.get_distroseries_packages()
455
456
    @property
457
    def packages_by_active_distroseries(self):
458
        """Dict of packages keyed by distroseries."""
459
        packages_dict = {}
460
        for package in self.active_distroseries_packages:
461
            packages_dict[package.distroseries] = package
462
        return packages_dict
463
11926.7.1 by Edwin Grubbs
Display form for setting upstream link on DSP page.
464
    @cachedproperty
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
465
    def active_series(self):
466
        """Return active distroseries where this package is published.
467
468
        Used in the template code that shows the table of versions.
9150.6.17 by Julian Edwards
Sort list of distroseries in the table so most-recent is first.
469
        The returned series are sorted in reverse order of creation.
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
470
        """
471
        series = set()
472
        for package in self.active_distroseries_packages:
473
            series.add(package.distroseries)
9854.1.1 by Curtis Hovey
Use the sorted_dotted_numbers function to sort distroseries by version as is done for product series and releases.
474
        result = sorted_dotted_numbers(
475
            series, key=operator.attrgetter('version'))
476
        result.reverse()
9150.6.17 by Julian Edwards
Sort list of distroseries in the table so most-recent is first.
477
        return result
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
478
479
    def published_by_version(self, sourcepackage):
480
        """Return a dict of publications keyed by version.
481
482
        :param sourcepackage: ISourcePackage
483
        """
11436.1.2 by Michael Nelson
Renamed getPublishedReleases to getPublishedSources.
484
        publications = sourcepackage.distroseries.getPublishedSources(
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
485
            sourcepackage.sourcepackagename)
486
        pocket_dict = {}
11436.1.1 by Michael Nelson
Removed shortlist from model method and put it in the browser code instead.
487
        for pub in shortlist(publications):
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
488
            version = pub.source_package_version
9150.6.36 by Julian Edwards
Review changes from barry
489
            pocket_dict.setdefault(version, []).append(pub)
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
490
        return pocket_dict
491
492
    @property
11926.7.1 by Edwin Grubbs
Display form for setting upstream link on DSP page.
493
    def latest_sourcepackage(self):
494
        if len(self.active_series) == 0:
495
            return None
496
        return self.active_series[0].getSourcePackage(
497
            self.context.sourcepackagename)
498
499
    @property
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
500
    def version_table(self):
501
        """Rows of data for the template to render in the packaging table."""
502
        rows = []
503
        packages_by_series = self.packages_by_active_distroseries
504
        for distroseries in self.active_series:
505
            # The first row for each series is the "title" row.
506
            packaging = packages_by_series[distroseries].direct_packaging
9150.6.10 by Julian Edwards
fix packaging links
507
            package = packages_by_series[distroseries]
11926.7.2 by Edwin Grubbs
Hide the set-upstream-link for older sourcepackages and added tests.
508
            # Don't show the "Set upstream link" action for older series
509
            # without packaging info, so the user won't feel required to
510
            # fill it in.
511
            show_set_upstream_link = (
512
                packaging is None
513
                and distroseries.status in (
514
                    SeriesStatus.CURRENT,
515
                    SeriesStatus.DEVELOPMENT,
516
                    )
517
                )
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
518
            title_row = {
9150.6.18 by Julian Edwards
Add spacing between series in the table and use icons with the productseries and distroseries links
519
                'blank_row': False,
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
520
                'title_row': True,
9150.6.18 by Julian Edwards
Add spacing between series in the table and use icons with the productseries and distroseries links
521
                'data_row': False,
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
522
                'distroseries': distroseries,
9150.6.10 by Julian Edwards
fix packaging links
523
                'series_package': package,
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
524
                'packaging': packaging,
11926.7.2 by Edwin Grubbs
Hide the set-upstream-link for older sourcepackages and added tests.
525
                'show_set_upstream_link': show_set_upstream_link,
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
526
                }
527
            rows.append(title_row)
528
529
            # After the title row, we list each package version that's
530
            # currently published, and which pockets it's published in.
531
            pocket_dict = self.published_by_version(package)
9150.6.36 by Julian Edwards
Review changes from barry
532
            for version in pocket_dict:
9150.6.11 by Julian Edwards
Set up the info in the template so that the XHR macro can pull the async data. Needs a fix in the JS so it works in a different context.
533
                most_recent_publication = pocket_dict[version][0]
9150.6.36 by Julian Edwards
Review changes from barry
534
                date_published = most_recent_publication.datepublished
535
                if date_published is None:
9150.6.22 by Julian Edwards
Add a load of tests and fix broken stuff that they exposed.
536
                    published_since = None
537
                else:
9150.6.36 by Julian Edwards
Review changes from barry
538
                    now = datetime.now(tz=pytz.UTC)
539
                    published_since = now - date_published
540
                pockets = ", ".join(
541
                    [pub.pocket.name for pub in pocket_dict[version]])
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
542
                row = {
9150.6.18 by Julian Edwards
Add spacing between series in the table and use icons with the productseries and distroseries links
543
                    'blank_row': False,
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
544
                    'title_row': False,
9150.6.18 by Julian Edwards
Add spacing between series in the table and use icons with the productseries and distroseries links
545
                    'data_row': True,
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
546
                    'version': version,
9150.6.11 by Julian Edwards
Set up the info in the template so that the XHR macro can pull the async data. Needs a fix in the JS so it works in a different context.
547
                    'publication': most_recent_publication,
9150.6.36 by Julian Edwards
Review changes from barry
548
                    'pockets': pockets,
9150.6.11 by Julian Edwards
Set up the info in the template so that the XHR macro can pull the async data. Needs a fix in the JS so it works in a different context.
549
                    'component': most_recent_publication.component_name,
9150.6.22 by Julian Edwards
Add a load of tests and fix broken stuff that they exposed.
550
                    'published_since': published_since,
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
551
                    }
552
                rows.append(row)
9150.6.18 by Julian Edwards
Add spacing between series in the table and use icons with the productseries and distroseries links
553
            # We need a blank row after each section, so the series
554
            # header row doesn't appear too close to the previous
555
            # section.
556
            rows.append({
557
                'blank_row': True,
558
                'title_row': False,
559
                'data_row': False,
560
                })
9150.6.3 by Julian Edwards
Convert the mockup table into one that pulls real data
561
562
        return rows
6615.1.3 by James Henstridge
Undo DistributionSourcePackageRelease changes, and create a
563
8971.28.21 by Julian Edwards
Lots of changes
564
    @cachedproperty
565
    def open_questions(self):
566
        """Return result set containing open questions for this package."""
567
        return self.context.searchQuestions(status=QuestionStatus.OPEN)
568
12617.2.6 by Curtis Hovey
Added a property to help the template construct a sentence about bug and questions.
569
    @cachedproperty
570
    def bugs_answers_usage(self):
571
        """Return a  dict of uses_bugs, uses_answers, uses_both, uses_either.
572
        """
573
        service_usage = IServiceUsage(self.context)
574
        uses_bugs = (
575
            service_usage.bug_tracking_usage == ServiceUsage.LAUNCHPAD)
576
        uses_answers = service_usage.answers_usage == ServiceUsage.LAUNCHPAD
577
        uses_both = uses_bugs and uses_answers
578
        uses_either = uses_bugs or uses_answers
579
        return dict(
580
            uses_bugs=uses_bugs, uses_answers=uses_answers,
581
            uses_both=uses_both, uses_either=uses_either)
582
7509.3.1 by Gavin Panella
Implement distribution source package editing via the web. Only bug reporting guidelines can be changed right now.
583
9558.4.1 by Celso Providelo
Fixing heading and titles for DistributionSourcePackage:+{changelog, publishinghistory} and DistroSeriesSourcePackage:+publishinghistory pages.
584
class DistributionSourcePackageChangelogView(
585
    DistributionSourcePackageBaseView, LaunchpadView):
9558.4.3 by Celso Providelo
'Change log' it is.
586
    """View for presenting change logs for a `DistributionSourcePackage`."""
9558.4.1 by Celso Providelo
Fixing heading and titles for DistributionSourcePackage:+{changelog, publishinghistory} and DistroSeriesSourcePackage:+publishinghistory pages.
587
9558.4.3 by Celso Providelo
'Change log' it is.
588
    page_title = 'Change log'
9558.4.1 by Celso Providelo
Fixing heading and titles for DistributionSourcePackage:+{changelog, publishinghistory} and DistroSeriesSourcePackage:+publishinghistory pages.
589
590
    @property
591
    def label(self):
9558.4.3 by Celso Providelo
'Change log' it is.
592
        return 'Change log for %s' % self.context.title
9558.4.1 by Celso Providelo
Fixing heading and titles for DistributionSourcePackage:+{changelog, publishinghistory} and DistroSeriesSourcePackage:+publishinghistory pages.
593
594
595
class DistributionSourcePackagePublishingHistoryView(LaunchpadView):
596
    """View for presenting `DistributionSourcePackage` publishing history."""
597
598
    page_title = 'Publishing history'
599
600
    @property
601
    def label(self):
602
        return 'Publishing history of %s' % self.context.title
603
604
7509.3.1 by Gavin Panella
Implement distribution source package editing via the web. Only bug reporting guidelines can be changed right now.
605
class DistributionSourcePackageEditView(LaunchpadEditFormView):
606
    """Edit a distribution source package."""
607
608
    schema = IDistributionSourcePackage
609
    field_names = [
610
        'bug_reporting_guidelines',
10977.7.2 by Abel Deuring
the relevant edit forms for ProjectGroup, Product, Distribution, DistributionSourcePackage now have fields to edit the bug report acknowledgement message
611
        'bug_reported_acknowledgement',
7675.993.1 by Abel Deuring
The forms to configure the bugtracker for products and for DSPs now contains a field enable_bugfiling_duplicate_search; bug filing pages show immediately the complete form if enable_bugfiling_duplicate_search is turned off.
612
        'enable_bugfiling_duplicate_search',
7509.3.1 by Gavin Panella
Implement distribution source package editing via the web. Only bug reporting guidelines can be changed right now.
613
        ]
614
9116.3.1 by Curtis Hovey
Updated dsp +edit to UI 3.0.
615
    @property
616
    def label(self):
617
        """The form label."""
618
        return 'Edit %s' % self.context.title
619
620
    @property
621
    def page_title(self):
622
        """The page title."""
623
        return self.label
624
7509.3.1 by Gavin Panella
Implement distribution source package editing via the web. Only bug reporting guidelines can be changed right now.
625
    @action("Change", name='change')
626
    def change_action(self, action, data):
627
        self.updateContextFromData(data)
628
629
    @property
630
    def next_url(self):
631
        return canonical_url(self.context)
632
633
    cancel_url = next_url
13014.2.2 by Curtis Hovey
Remove IQuestionTarget from ISourcePackage.
634
635
13303.11.10 by Aaron Bentley
Fix pages broken by assuming LaunchpadView.
636
class DistributionSourcePackageHelpView(LaunchpadView):
13014.2.2 by Curtis Hovey
Remove IQuestionTarget from ISourcePackage.
637
    """A View to show Answers help."""
638
639
    page_title = 'Help and support options'