~launchpad-pqm/launchpad/devel

8687.15.11 by Karl Fogel
Add the copyright header block to files under lib/lp/answers/.
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
4983.1.1 by Curtis Hovey
Added lint exceptions to __init__.py and interface/*.py.
4
# pylint: disable-msg=E0211,E0213
2396 by Canonical.com Patch Queue Manager
[r=spiv] launchpad support tracker
5
3691.398.18 by Francis J. Lacoste
Rename interfaces.
6
"""Interfaces for things which have Questions."""
2396 by Canonical.com Patch Queue Manager
[r=spiv] launchpad support tracker
7
8
__metaclass__ = type
9
10
__all__ = [
3844.1.5 by Francis J. Lacoste
Fix Answers front page to allow searching only "One project".
11
    'IAnswersFrontPageSearchForm',
3691.398.18 by Francis J. Lacoste
Rename interfaces.
12
    'IQuestionTarget',
13
    'ISearchQuestionsForm',
2396 by Canonical.com Patch Queue Manager
[r=spiv] launchpad support tracker
14
    ]
15
4755.1.28 by Curtis Hovey
pylint fixes.
16
from zope.interface import Interface
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
17
from zope.schema import (
18
    Choice,
12959.4.6 by Curtis Hovey
Exported getQuestion().
19
    Int,
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
20
    List,
21
    Set,
22
    TextLine,
23
    )
3691.110.22 by Francis J. Lacoste
Style
24
12959.4.4 by Curtis Hovey
STFU wadl generator.
25
from lazr.restful.declarations import (
26
    call_with,
27
    export_as_webservice_entry,
28
    export_read_operation,
29
    export_write_operation,
30
    operation_for_version,
31
    operation_parameters,
12959.4.15 by Curtis Hovey
exported getAnswerContactsForLanguage and getSupportedLanguages
32
    operation_returns_collection_of,
12959.4.4 by Curtis Hovey
STFU wadl generator.
33
    REQUEST_USER,
34
    )
12959.4.15 by Curtis Hovey
exported getAnswerContactsForLanguage and getSupportedLanguages
35
from lazr.restful.fields import Reference
12959.4.4 by Curtis Hovey
STFU wadl generator.
36
3691.110.22 by Francis J. Lacoste
Style
37
from canonical.launchpad import _
7944.3.18 by Francis J. Lacoste
Rename lp.apps.answers to lp.answers.
38
from lp.answers.interfaces.questioncollection import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
39
    ISearchableByQuestionOwner,
40
    )
12915.5.1 by Curtis Hovey
Rename questionenums.py to the new standard or enums.py
41
from lp.answers.enums import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
42
    QuestionSort,
43
    QuestionStatus,
12915.5.3 by Curtis Hovey
Import QUESTION_STATUS_DEFAULT_SEARCH from enums.
44
    QUESTION_STATUS_DEFAULT_SEARCH,
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
45
    )
12959.4.15 by Curtis Hovey
exported getAnswerContactsForLanguage and getSupportedLanguages
46
from lp.registry.interfaces.person import IPerson
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
47
from lp.services.fields import PublicPersonChoice
12959.4.15 by Curtis Hovey
exported getAnswerContactsForLanguage and getSupportedLanguages
48
from lp.services.worlddata.interfaces.language import ILanguage
2705 by Canonical.com Patch Queue Manager
r=spiv, mark's soyuz loving.
49
3691.110.22 by Francis J. Lacoste
Style
50
13014.2.1 by Curtis Hovey
Extracted Public and AnyPerson interfaces from IQuestionTarget.
51
class IQuestionTargetPublic(ISearchableByQuestionOwner):
52
    """Methods that anonymous in user can access."""
53
54
    @operation_parameters(
55
        question_id=Int(title=_('Question Number'), required=True))
56
    @export_read_operation()
57
    @operation_for_version('devel')
58
    def getQuestion(question_id):
59
        """Return the question by its id, if it is applicable to this target.
60
61
        :question_id: A question id.
62
63
        If there is no such question number for this target, return None
64
        """
65
13041.2.1 by Curtis Hovey
Exposed findSimilarQuestions() and searchQuestions().
66
    @operation_parameters(
67
        phrase=TextLine(title=_('A phrase'), required=True))
68
    @operation_returns_collection_of(Interface)
69
    @export_read_operation()
70
    @operation_for_version('devel')
71
    def findSimilarQuestions(phrase):
72
        """Return questions similar to phrase.
13014.2.1 by Curtis Hovey
Extracted Public and AnyPerson interfaces from IQuestionTarget.
73
13041.2.1 by Curtis Hovey
Exposed findSimilarQuestions() and searchQuestions().
74
        Return a list of question similar to the provided phrase. These
75
        questions will be found using a fuzzy search. The list is
13014.2.1 by Curtis Hovey
Extracted Public and AnyPerson interfaces from IQuestionTarget.
76
        ordered from the most similar question to the least similar question.
77
13041.2.1 by Curtis Hovey
Exposed findSimilarQuestions() and searchQuestions().
78
        :param phrase: A phrase such as the summary of a question.
13014.2.1 by Curtis Hovey
Extracted Public and AnyPerson interfaces from IQuestionTarget.
79
        """
80
81
    @operation_parameters(
82
        language=Reference(ILanguage))
83
    @operation_returns_collection_of(IPerson)
84
    @export_read_operation()
85
    @operation_for_version('devel')
86
    def getAnswerContactsForLanguage(language):
87
        """Return the list of Persons that provide support for a language.
88
89
        An answer contact supports questions in his preferred languages.
90
        """
91
92
    def getAnswerContactRecipients(language):
93
        """Return an `INotificationRecipientSet` of answer contacts.
94
95
        :language: an ILanguage or None. When language is none, all
96
                   answer contacts are returned.
97
98
        Return an INotificationRecipientSet of the answer contacts and the
99
        reason they are recipients of an email. The answer contacts are
100
        selected by their language and the fact that they are answer contacts
101
        for the QuestionTarget.
102
        """
103
104
    @operation_returns_collection_of(ILanguage)
105
    @export_read_operation()
106
    @operation_for_version('devel')
107
    def getSupportedLanguages():
108
        """Return a list of languages spoken by at the answer contacts.
109
110
        An answer contact is considered to speak a given language if that
111
        language is listed as one of his preferred languages.
112
        """
113
114
    answer_contacts = List(
115
        title=_("Answer Contacts"),
116
        description=_(
117
            "Persons that are willing to provide support for this target. "
118
            "They receive email notifications about each new question as "
119
            "well as for changes to any questions related to this target."),
120
        value_type=PublicPersonChoice(vocabulary="ValidPersonOrTeam"))
121
122
    direct_answer_contacts = List(
123
        title=_("Direct Answer Contacts"),
124
        description=_(
125
            "IPersons that registered as answer contacts explicitely on "
126
            "this target. (answer_contacts may include answer contacts "
127
            "inherited from other context.)"),
128
        value_type=PublicPersonChoice(vocabulary="ValidPersonOrTeam"))
129
130
131
class IQuestionTargetView(Interface):
132
    """Methods that logged in user can access."""
12959.4.4 by Curtis Hovey
STFU wadl generator.
133
3691.398.20 by Francis J. Lacoste
Rename all methods.
134
    def newQuestion(owner, title, description, language=None,
4755.1.43 by Curtis Hovey
Revisions pre review.
135
                    datecreated=None):
3691.398.18 by Francis J. Lacoste
Rename interfaces.
136
        """Create a new question.
137
138
         A new question is created with status OPEN.
139
140
        The owner and all of the target answer contacts will be subscribed
141
        to the question.
3691.110.17 by Francis J. Lacoste
Specify default sort order and status searches as part of the interface. Improve the doc strings of ITicketTarget.
142
143
        :owner: An IPerson.
144
        :title: A string.
145
        :description: A string.
3691.398.18 by Francis J. Lacoste
Rename interfaces.
146
        :language: An ILanguage. If that parameter is omitted, the question
147
                 is assumed to be created in English.
3691.110.18 by Francis J. Lacoste
Rename ticket_num to ticket_id. Rename when to datecreated. Change TicketSet.new to a staticmethod.
148
        :datecreated:  A datetime object that will be used for the datecreated
149
                attribute. Defaults to canonical.database.constants.UTC_NOW.
2396 by Canonical.com Patch Queue Manager
[r=spiv] launchpad support tracker
150
        """
151
4755.1.2 by Curtis Hovey
Added core functionality to create a questions from a bug. More tests are needed, particularly for IQuestionTarget ftests. The UI work and pagetests are not done; some direction is needed.
152
    def createQuestionFromBug(bug):
4755.1.3 by Curtis Hovey
Revised and expanded interface/doctests. UI is next.
153
        """Create and return a Question from a Bug.
4755.1.51 by Curtis Hovey
Updated _createUbuntuBugTaskLinkedToQuestion to clear the notifcations before the
154
4755.1.2 by Curtis Hovey
Added core functionality to create a questions from a bug. More tests are needed, particularly for IQuestionTarget ftests. The UI work and pagetests are not done; some direction is needed.
155
        The bug's title and description are used as the question title and
4755.1.3 by Curtis Hovey
Revised and expanded interface/doctests. UI is next.
156
        description. The bug owner is the question owner. The question
4755.1.2 by Curtis Hovey
Added core functionality to create a questions from a bug. More tests are needed, particularly for IQuestionTarget ftests. The UI work and pagetests are not done; some direction is needed.
157
        is automatically linked to the bug.
4755.1.51 by Curtis Hovey
Updated _createUbuntuBugTaskLinkedToQuestion to clear the notifcations before the
158
4755.1.48 by Curtis Hovey
Changes per review. Anonther massive restructuring.
159
        Note that bug messages are copied to the question, but attachments
160
        are not. The question is the same age as the bug, though its
4755.1.49 by Curtis Hovey
Changes per review.
161
        datelastresponse attribute is current to signify the question is
4755.1.48 by Curtis Hovey
Changes per review. Anonther massive restructuring.
162
        active.
4755.1.51 by Curtis Hovey
Updated _createUbuntuBugTaskLinkedToQuestion to clear the notifcations before the
163
4755.1.2 by Curtis Hovey
Added core functionality to create a questions from a bug. More tests are needed, particularly for IQuestionTarget ftests. The UI work and pagetests are not done; some direction is needed.
164
        :bug: An IBug.
165
        """
166
12959.4.6 by Curtis Hovey
Exported getQuestion().
167
    @operation_parameters(
12959.4.12 by Curtis Hovey
Exported addAnswerContact snd removeAnswerContact.
168
        person=PublicPersonChoice(
169
            title=_('The user or an administered team'), required=True,
170
            vocabulary='ValidPersonOrTeam'))
171
    @call_with(subscribed_by=REQUEST_USER)
172
    @export_read_operation()
173
    @operation_for_version('devel')
174
    def canUserAlterAnswerContact(person, subscribed_by):
12959.4.8 by Curtis Hovey
Added canUserAlterAnswerContact() to move permission rules to the model.
175
        """Can the user add or remove the answer contact.
176
177
        Users can add or remove themselves or one of the teams they
178
        administered.
179
12959.4.12 by Curtis Hovey
Exported addAnswerContact snd removeAnswerContact.
180
        :param person: The `IPerson` that is or will be an answer contact.
12959.4.11 by Curtis Hovey
Revised the canUserAlterAnswerContact() args.
181
        :param subscribed_by: The `IPerson` making the change.
12959.4.8 by Curtis Hovey
Added canUserAlterAnswerContact() to move permission rules to the model.
182
        """
183
12959.4.12 by Curtis Hovey
Exported addAnswerContact snd removeAnswerContact.
184
    @operation_parameters(
185
        person=PublicPersonChoice(
186
            title=_('The user of an administered team'), required=True,
187
            vocabulary='ValidPersonOrTeam'))
188
    @call_with(subscribed_by=REQUEST_USER)
189
    @export_write_operation()
190
    @operation_for_version('devel')
12959.4.13 by Curtis Hovey
Updated callsite and interface to require and pass the subscribed_by arg.
191
    def addAnswerContact(person, subscribed_by):
3691.398.18 by Francis J. Lacoste
Rename interfaces.
192
        """Add a new answer contact.
3258.7.9 by Bjorn Tillenius
fix test failures.
193
12959.4.8 by Curtis Hovey
Added canUserAlterAnswerContact() to move permission rules to the model.
194
        :param person: An `IPerson`.
12959.4.12 by Curtis Hovey
Exported addAnswerContact snd removeAnswerContact.
195
        :param subscribed_by: The user making the change.
12959.4.11 by Curtis Hovey
Revised the canUserAlterAnswerContact() args.
196
        :return: True if the person was added, False if the person already is
197
            an answer contact.
13099.1.7 by Curtis Hovey
Moved InvalidQuestionStateError to the errors module.
198
        :raises AddAnswerContactError: When the person or team does no have a
199
            preferred language.
3258.7.9 by Bjorn Tillenius
fix test failures.
200
        """
3258.7.1 by Bjorn Tillenius
add support contacts for products, distributions, and source packages. no UI yet, though
201
12959.4.12 by Curtis Hovey
Exported addAnswerContact snd removeAnswerContact.
202
    @operation_parameters(
203
        person=PublicPersonChoice(
204
            title=_('The user of an administered team'), required=True,
205
            vocabulary='ValidPersonOrTeam'))
206
    @call_with(subscribed_by=REQUEST_USER)
207
    @export_write_operation()
208
    @operation_for_version('devel')
12959.4.13 by Curtis Hovey
Updated callsite and interface to require and pass the subscribed_by arg.
209
    def removeAnswerContact(person, subscribed_by):
3691.398.18 by Francis J. Lacoste
Rename interfaces.
210
        """Remove an answer contact.
3258.7.9 by Bjorn Tillenius
fix test failures.
211
12959.4.12 by Curtis Hovey
Exported addAnswerContact snd removeAnswerContact.
212
        :param person: An `IPerson`.
213
        :param subscribed_by: The user making the change.
214
        :return: True if the person was removed, False if the person wasn't an
215
            answer contact.
3258.7.9 by Bjorn Tillenius
fix test failures.
216
        """
4215.2.23 by Curtis Hovey
Removed trailing whitespace.
217
13014.2.1 by Curtis Hovey
Extracted Public and AnyPerson interfaces from IQuestionTarget.
218
219
class IQuestionTarget(IQuestionTargetPublic, IQuestionTargetView):
220
    """An object that can have a new question asked about it."""
221
    export_as_webservice_entry(as_of='devel')
3691.243.4 by Francis J. Lacoste
Add registered_support_contacts attribute.
222
4611.5.1 by Curtis Hovey
Moved questions enumerations from lp.dbschema to
223
3691.398.18 by Francis J. Lacoste
Rename interfaces.
224
# These schemas are only used by browser/questiontarget.py and should really
3691.98.11 by Francis J. Lacoste
Move browser interfaces back to their main content modules.
225
# live there. See Bug #66950.
3691.398.18 by Francis J. Lacoste
Rename interfaces.
226
class ISearchQuestionsForm(Interface):
227
    """Schema for the search question form."""
3691.98.11 by Francis J. Lacoste
Move browser interfaces back to their main content modules.
228
3691.98.34 by Francis J. Lacoste
Remove colons in labels.
229
    search_text = TextLine(title=_('Search text'), required=False)
3691.98.11 by Francis J. Lacoste
Move browser interfaces back to their main content modules.
230
3691.98.34 by Francis J. Lacoste
Remove colons in labels.
231
    sort = Choice(title=_('Sort order'), required=True,
4611.5.6 by Curtis Hovey
Removed the question vocabularies.
232
                  vocabulary=QuestionSort,
3691.398.17 by Francis J. Lacoste
Rename dbschemas.
233
                  default=QuestionSort.RELEVANCY)
4004.4.19 by Curtis Hovey
Removed unused imports.
234
3691.98.34 by Francis J. Lacoste
Remove colons in labels.
235
    status = Set(title=_('Status'), required=False,
4611.5.6 by Curtis Hovey
Removed the question vocabularies.
236
                 value_type=Choice(vocabulary=QuestionStatus),
8697.27.31 by Gary Poster
resolve some dependency deprecation warnings
237
                 default=set(QUESTION_STATUS_DEFAULT_SEARCH))
3844.1.5 by Francis J. Lacoste
Fix Answers front page to allow searching only "One project".
238
239
240
class IAnswersFrontPageSearchForm(ISearchQuestionsForm):
241
    """Schema for the Answers front page search form."""
242
243
    scope = Choice(title=_('Search scope'), required=False,
10724.1.6 by Henning Eggers
Vocabulary names.
244
                   vocabulary='DistributionOrProductOrProjectGroup')