launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #03599
[Merge] lp:~sinzui/launchpad/answers-api-1 into lp:launchpad
Curtis Hovey has proposed merging lp:~sinzui/launchpad/answers-api-1 into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #108246 in Launchpad itself: "SourcePackage shouldn't directly provide IQuestionTarget"
https://bugs.launchpad.net/launchpad/+bug/108246
Bug #780078 in Launchpad itself: "export answer contact methods to the API"
https://bugs.launchpad.net/launchpad/+bug/780078
For more details, see:
https://code.launchpad.net/~sinzui/launchpad/answers-api-1/+merge/60804
Export answer contact methods to the API.
Launchpad bug:
https://bugs.launchpad.net/bugs/780078
https://bugs.launchpad.net/bugs/108246
Pre-implementation: wgrant, jcsackett
The QuestionTarget interfaces need reorganisation and The targets must
descend from them to enable th exported methods to work for projects
and distros.
ADDENDUM
After working 2 hours to update ISourcePackage to inherit from
IQuestionTarget, I decided that this was pointless. We have known for 4
years that this should not be the case. It is easier to bug 108246;
source packages should not be question targets.
90% of the diff is mechanical changes where code is moved or deleted.
The substantial changes are the +gethelp refactoring. The existing
tests demonstrate that this refactoring is successful.
--------------------------------------------------------------------
RULES
* Make IProduct, IDistribution, ISourcePackage descend from
IQuestionTarget
* Compose IQuestionTarget from smaller interfaces that define permissions.
* Move the +gethelp page to IDistributionSourcePackage, ensure the
the existing URL do not break.
* Remove IQuestionTarget from ISourcePackage.
QA
* Run this script:
from launchpadlib.launchpad import Launchpad
lp = Launchpad.login_with(
'test', 'https://api.qastaging.launchpad.net/', version='devel')
project = lp.projects['launchpad']
user = lp.people['sinzui']
for language in lp.languages:
if language.code == 'fr':
break
print "Adding %s to %s" % (language.code, user.name)
user.addLanguage(language=language)
print project.canUserAlterAnswerContact(person=user)
# expect True
print project.addAnswerContact(person=user)
# expect True
for lang in project.getSupportedLanguages():
print lang.code
for contact in project.getAnswerContactsForLanguage(language=language):
print contact.name
# Expect sinzui
LINT
lib/lp/answers/interfaces/questiontarget.py
lib/lp/answers/templates/sourcepackage-gethelp.pt
lib/lp/answers/tests/test_doc.py
lib/lp/bugs/tests/test_bugtarget.py
lib/lp/registry/configure.zcml
lib/lp/registry/browser/configure.zcml
lib/lp/registry/browser/distributionsourcepackage.py
lib/lp/registry/browser/sourcepackage.py
lib/lp/registry/interfaces/distribution.py
lib/lp/registry/interfaces/distributionsourcepackage.py
lib/lp/registry/interfaces/product.py
lib/lp/registry/model/distribution.py
lib/lp/registry/model/distributionsourcepackage.py
lib/lp/registry/model/product.py
lib/lp/registry/model/sourcepackage.py
TEST
./bin/test -vv -t questiontarget -t question-add
IMPLEMENTATION
Split IQuestionTarget into Public and AnyPerson interfaces. Updated
IDistribution, IDistributionSourcePackage, and IProduct to inherit
IQuestionTarget.
lib/lp/answers/interfaces/questiontarget.py
lib/lp/registry/configure.zcml
lib/lp/registry/interfaces/distribution.py
lib/lp/registry/interfaces/distributionsourcepackage.py
lib/lp/registry/interfaces/product.py
lib/lp/registry/interfaces/sourcepackage.py
lib/lp/registry/model/distribution.py
lib/lp/registry/model/distributionsourcepackage.py
lib/lp/registry/model/product.py
lib/lp/registry/model/sourcepackage.py
Removed IQuestionTarget from ISourcePackage and added a redirect to ensure
stories/question-add.txt continues to work.
lib/lp/registry/browser/configure.zcml
lib/lp/registry/browser/sourcepackage.py
lib/lp/registry/interfaces/sourcepackage.py
lib/lp/registry/model/sourcepackage.py
Removed unneeded tests and test setups.
Removed the test that verified that a question created for a source package
was really created on a distribution source package
lib/lp/answers/doc/questiontarget-sourcepackage.txt
lib/lp/answers/tests/test_doc.py
lib/lp/bugs/tests/test_bugtarget.py
Moved +gethelp to IDistributionSourcePackage. stories/question-add verifies
that the user still arrives at a page and can create a question.
lib/lp/registry/browser/distributionsourcepackage.py
Removed the request to link the package to a project. The user just
came form his desktop to get help. There is near zero chance that the user has
packaging experience and Launchpad knowledge to do this.
lib/lp/answers/templates/sourcepackage-gethelp.pt
--
https://code.launchpad.net/~sinzui/launchpad/answers-api-1/+merge/60804
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~sinzui/launchpad/answers-api-1 into lp:launchpad.
=== removed file 'lib/lp/answers/doc/questiontarget-sourcepackage.txt'
--- lib/lp/answers/doc/questiontarget-sourcepackage.txt 2011-05-09 16:35:10 +0000
+++ lib/lp/answers/doc/questiontarget-sourcepackage.txt 1970-01-01 00:00:00 +0000
@@ -1,141 +0,0 @@
-IQuestionTarget for SourcePackage
-=================================
-
-The implementation of IQuestionTarget by SourcePackage and
-DistributionSourcePackage contain some small differences with the other
-ones. (See questiontarget.txt for the generic interface description.)
-
-
-ISourcePackage.target
-.....................
-
-The target attribute of questions created on SourcePackage will be that
-of the DistributionSourcePackage (and not the SourcePackage):
-
- >>> login('no-priv@xxxxxxxxxxxxx')
- >>> from lp.registry.interfaces.distribution import IDistributionSet
- >>> from lp.registry.interfaces.person import IPersonSet
- >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
- >>> firefox = ubuntu.currentseries.getSourcePackage('mozilla-firefox')
-
- >>> question = firefox.getQuestion(3)
- >>> question.target == firefox
- False
-
- >>> question.target == ubuntu.getSourcePackage('mozilla-firefox')
- True
-
-
-get()
-.....
-
-The question created on a SourcePackage or DistributionSourcePackage can
-also be retrieved via the distribution.
-
- >>> ubuntu.getQuestion(3) == question
- True
-
- # Create a new question on the evolution source package.
-
- >>> sample_person = getUtility(IPersonSet).getByName('name16')
- >>> evolution = ubuntu.getSourcePackage('evolution')
- >>> evolution_question = evolution.newQuestion(
- ... sample_person, 'Evolution crashed',
- ... 'Surprise, surprise! Evolution crashed... again...'
- ... 'while clicking on a thread expander.')
-
- >>> ubuntu.getQuestion(evolution_question.id) == evolution_question
- True
-
-
-Support Contacts
-................
-
-The support contacts of a SourcePackage contain all the support contacts
-from its containing distribution.
-
- >>> list(ubuntu.answer_contacts)
- []
-
- >>> list(evolution.answer_contacts)
- []
-
- >>> ubuntu.addAnswerContact(sample_person, sample_person)
- True
-
- >>> [person.name for person in evolution.answer_contacts]
- [u'name16']
-
-It is possible to obtain the list of IPerson registed as support
-contacts specifically for the source package through the
-direct_answer_contacts attributes.
-
- >>> [person.name for person in evolution.direct_answer_contacts]
- []
-
-A user can still subscribe as support contact for specific sourcepackage
-even if he's already a support contact for the distribution.
-
- >>> evolution.addAnswerContact(sample_person, sample_person)
- True
-
- >>> [person.name for person in evolution.direct_answer_contacts]
- [u'name16']
-
-But he's only listed once in the support contacts list.
-
- >>> [person.name for person in evolution.answer_contacts]
- [u'name16']
-
-The removeAnswerContact() method can only be used to remove the user
-from the sourcepackage support contact list, not from the ubuntu
-distribution list:
-
- >>> evolution.removeAnswerContact(sample_person, sample_person)
- True
-
- >>> [person.name for person in evolution.direct_answer_contacts]
- []
-
- >>> [person.name for person in evolution.answer_contacts]
- [u'name16']
-
- >>> evolution.removeAnswerContact(sample_person, sample_person)
- False
-
- >>> [person.name for person in evolution.answer_contacts]
- [u'name16']
-
-The same principle applies to DistributionSourcePackage:
-
- >>> [person.name for person in evolution.direct_answer_contacts]
- []
-
- >>> [person.name for person in evolution.answer_contacts]
- [u'name16']
-
- >>> evolution.addAnswerContact(sample_person, sample_person)
- True
-
- >>> [person.name for person in evolution.direct_answer_contacts]
- [u'name16']
-
- >>> [person.name for person in evolution.answer_contacts]
- [u'name16']
-
- >>> evolution.removeAnswerContact(sample_person, sample_person)
- True
-
- >>> [person.name for person in evolution.answer_contacts]
- [u'name16']
-
- >>> evolution.removeAnswerContact(sample_person, sample_person)
- False
-
- >>> [person.name for person in evolution.direct_answer_contacts]
- []
-
- >>> [person.name for person in evolution.answer_contacts]
- [u'name16']
-
-
=== modified file 'lib/lp/answers/interfaces/questiontarget.py'
--- lib/lp/answers/interfaces/questiontarget.py 2011-05-06 18:11:56 +0000
+++ lib/lp/answers/interfaces/questiontarget.py 2011-05-12 15:26:36 +0000
@@ -48,10 +48,83 @@
from lp.services.worlddata.interfaces.language import ILanguage
-class IQuestionTarget(ISearchableByQuestionOwner):
- """An object that can have a new question asked about it."""
-
- export_as_webservice_entry(as_of='devel')
+class IQuestionTargetPublic(ISearchableByQuestionOwner):
+ """Methods that anonymous in user can access."""
+
+ @operation_parameters(
+ question_id=Int(title=_('Question Number'), required=True))
+ @export_read_operation()
+ @operation_for_version('devel')
+ def getQuestion(question_id):
+ """Return the question by its id, if it is applicable to this target.
+
+ :question_id: A question id.
+
+ If there is no such question number for this target, return None
+ """
+
+ def findSimilarQuestions(title):
+ """Return questions similar to title.
+
+ Return a list of question similar to the title provided. These
+ questions should be found using a fuzzy search. The list should be
+ ordered from the most similar question to the least similar question.
+
+ :title: A phrase
+ """
+
+ @operation_parameters(
+ language=Reference(ILanguage))
+ @operation_returns_collection_of(IPerson)
+ @export_read_operation()
+ @operation_for_version('devel')
+ def getAnswerContactsForLanguage(language):
+ """Return the list of Persons that provide support for a language.
+
+ An answer contact supports questions in his preferred languages.
+ """
+
+ def getAnswerContactRecipients(language):
+ """Return an `INotificationRecipientSet` of answer contacts.
+
+ :language: an ILanguage or None. When language is none, all
+ answer contacts are returned.
+
+ Return an INotificationRecipientSet of the answer contacts and the
+ reason they are recipients of an email. The answer contacts are
+ selected by their language and the fact that they are answer contacts
+ for the QuestionTarget.
+ """
+
+ @operation_returns_collection_of(ILanguage)
+ @export_read_operation()
+ @operation_for_version('devel')
+ def getSupportedLanguages():
+ """Return a list of languages spoken by at the answer contacts.
+
+ An answer contact is considered to speak a given language if that
+ language is listed as one of his preferred languages.
+ """
+
+ answer_contacts = List(
+ title=_("Answer Contacts"),
+ description=_(
+ "Persons that are willing to provide support for this target. "
+ "They receive email notifications about each new question as "
+ "well as for changes to any questions related to this target."),
+ value_type=PublicPersonChoice(vocabulary="ValidPersonOrTeam"))
+
+ direct_answer_contacts = List(
+ title=_("Direct Answer Contacts"),
+ description=_(
+ "IPersons that registered as answer contacts explicitely on "
+ "this target. (answer_contacts may include answer contacts "
+ "inherited from other context.)"),
+ value_type=PublicPersonChoice(vocabulary="ValidPersonOrTeam"))
+
+
+class IQuestionTargetView(Interface):
+ """Methods that logged in user can access."""
def newQuestion(owner, title, description, language=None,
datecreated=None):
@@ -87,28 +160,6 @@
"""
@operation_parameters(
- question_id=Int(title=_('Question Number'), required=True))
- @export_read_operation()
- @operation_for_version('devel')
- def getQuestion(question_id):
- """Return the question by its id, if it is applicable to this target.
-
- :question_id: A question id.
-
- If there is no such question number for this target, return None
- """
-
- def findSimilarQuestions(title):
- """Return questions similar to title.
-
- Return a list of question similar to the title provided. These
- questions should be found using a fuzzy search. The list should be
- ordered from the most similar question to the least similar question.
-
- :title: A phrase
- """
-
- @operation_parameters(
person=PublicPersonChoice(
title=_('The user or an administered team'), required=True,
vocabulary='ValidPersonOrTeam'))
@@ -159,54 +210,10 @@
answer contact.
"""
- @operation_parameters(
- language=Reference(ILanguage))
- @operation_returns_collection_of(IPerson)
- @export_read_operation()
- @operation_for_version('devel')
- def getAnswerContactsForLanguage(language):
- """Return the list of Persons that provide support for a language.
-
- An answer contact supports questions in his preferred languages.
- """
-
- def getAnswerContactRecipients(language):
- """Return an `INotificationRecipientSet` of answer contacts.
-
- :language: an ILanguage or None. When language is none, all
- answer contacts are returned.
-
- Return an INotificationRecipientSet of the answer contacts and the
- reason they are recipients of an email. The answer contacts are
- selected by their language and the fact that they are answer contacts
- for the QuestionTarget.
- """
-
- @operation_returns_collection_of(ILanguage)
- @export_read_operation()
- @operation_for_version('devel')
- def getSupportedLanguages():
- """Return a list of languages spoken by at the answer contacts.
-
- An answer contact is considered to speak a given language if that
- language is listed as one of his preferred languages.
- """
-
- answer_contacts = List(
- title=_("Answer Contacts"),
- description=_(
- "Persons that are willing to provide support for this target. "
- "They receive email notifications about each new question as "
- "well as for changes to any questions related to this target."),
- value_type=PublicPersonChoice(vocabulary="ValidPersonOrTeam"))
-
- direct_answer_contacts = List(
- title=_("Direct Answer Contacts"),
- description=_(
- "IPersons that registered as answer contacts explicitely on "
- "this target. (answer_contacts may include answer contacts "
- "inherited from other context.)"),
- value_type=PublicPersonChoice(vocabulary="ValidPersonOrTeam"))
+
+class IQuestionTarget(IQuestionTargetPublic, IQuestionTargetView):
+ """An object that can have a new question asked about it."""
+ export_as_webservice_entry(as_of='devel')
# These schemas are only used by browser/questiontarget.py and should really
=== modified file 'lib/lp/answers/templates/sourcepackage-gethelp.pt'
--- lib/lp/answers/templates/sourcepackage-gethelp.pt 2009-09-13 20:51:35 +0000
+++ lib/lp/answers/templates/sourcepackage-gethelp.pt 2011-05-12 15:26:36 +0000
@@ -50,17 +50,6 @@
<a href="http://ubuntu.com/support/supportoptions/local">support
in languages other than English</a>.
</p>
-
- <tal:needupstream condition="not: context/productseries">
- <h2>Help us help you</h2>
- <p class="helpwanted message" tal:condition="not: context/productseries">
- Launchpad doesn’t know which project and series this package
- belongs to.
- If you can, please <a href="+edit-packaging">let us know</a>,
- so we can provide you and other people with relevant help sources.
- Thanks!
- </p>
- </tal:needupstream>
</div>
</div>
</body>
=== modified file 'lib/lp/answers/tests/test_doc.py'
--- lib/lp/answers/tests/test_doc.py 2010-10-04 19:50:45 +0000
+++ lib/lp/answers/tests/test_doc.py 2011-05-12 15:26:36 +0000
@@ -99,7 +99,6 @@
'questiontarget.txt',
[('product', productSetUp),
('distribution', distributionSetUp),
- ('sourcepackage', sourcepackageSetUp),
('distributionsourcepackage', distributionsourcepackageSetUp),
]),
=== modified file 'lib/lp/bugs/tests/test_bugtarget.py'
--- lib/lp/bugs/tests/test_bugtarget.py 2011-04-22 15:18:02 +0000
+++ lib/lp/bugs/tests/test_bugtarget.py 2011-05-12 15:26:36 +0000
@@ -178,16 +178,6 @@
test.globs['question_target'] = ubuntu.getSourcePackage('mozilla-firefox')
-def sourcePackageForQuestionSetUp(test):
- """Setup the `ISourcePackage` test for QuestionTarget testing."""
- setUp(test)
- ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
- warty = ubuntu.getSeries('warty')
- test.globs['bugtarget'] = warty.getSourcePackage('mozilla-firefox')
- test.globs['filebug'] = sourcepackage_filebug_for_question
- test.globs['question_target'] = ubuntu.getSourcePackage('mozilla-firefox')
-
-
class TestBugTargetSearchTasks(TestCaseWithFactory):
"""Tests of IHasBugs.searchTasks()."""
@@ -293,7 +283,6 @@
distributionSetUp,
distributionSourcePackageSetUp,
distributionSeriesSetUp,
- sourcePackageForQuestionSetUp,
]
for setUpMethod in setUpMethods:
@@ -302,7 +291,6 @@
layer=DatabaseFunctionalLayer)
suite.addTest(test)
- setUpMethods.remove(sourcePackageForQuestionSetUp)
setUpMethods.append(sourcePackageSetUp)
setUpMethods.append(projectSetUp)
=== modified file 'lib/lp/registry/browser/configure.zcml'
--- lib/lp/registry/browser/configure.zcml 2011-04-17 18:00:45 +0000
+++ lib/lp/registry/browser/configure.zcml 2011-05-12 15:26:36 +0000
@@ -508,9 +508,17 @@
name="+edit"
facet="overview"
template="../../app/templates/generic-edit.pt"/>
+ <browser:page
+ for="lp.registry.interfaces.distributionsourcepackage.IDistributionSourcePackage"
+ permission="zope.Public"
+ class="lp.registry.browser.distributionsourcepackage.DistributionSourcePackageHelpView"
+ name="+gethelp"
+ facet="answers"
+ template="../../answers/templates/sourcepackage-gethelp.pt"/>
<browser:menus
classes="
DistributionSourcePackageActionMenu
+ DistributionSourcePackageAnswersMenu
DistributionSourcePackageBugsMenu
DistributionSourcePackageFacets
DistributionSourcePackageOverviewMenu"
@@ -2088,10 +2096,6 @@
for="lp.registry.interfaces.sourcepackage.ISourcePackage"
layer="lp.bugs.publisher.BugsLayer"
name="+bugs"/>
- <browser:defaultView
- for="lp.registry.interfaces.sourcepackage.ISourcePackage"
- layer="lp.answers.publisher.AnswersLayer"
- name="+questions"/>
<browser:navigation
module="lp.registry.browser.sourcepackage"
classes="
@@ -2137,18 +2141,10 @@
facet="overview"
class="lp.registry.browser.sourcepackage.SourcePackageUpstreamConnectionsView"
template="../templates/sourcepackage-upstream-connections.pt"/>
- <browser:page
- for="lp.registry.interfaces.sourcepackage.ISourcePackage"
- permission="zope.Public"
- class="lp.registry.browser.sourcepackage.SourcePackageHelpView"
- name="+gethelp"
- facet="answers"
- template="../../answers/templates/sourcepackage-gethelp.pt"/>
<browser:menus
classes="
SourcePackageFacets
- SourcePackageOverviewMenu
- SourcePackageAnswersMenu"
+ SourcePackageOverviewMenu"
module="lp.registry.browser.sourcepackage"/>
<browser:navigation
module="lp.registry.browser.productrelease"
=== modified file 'lib/lp/registry/browser/distributionsourcepackage.py'
--- lib/lp/registry/browser/distributionsourcepackage.py 2011-04-26 15:44:26 +0000
+++ lib/lp/registry/browser/distributionsourcepackage.py 2011-05-12 15:26:36 +0000
@@ -5,10 +5,12 @@
__all__ = [
'distribution_from_distributionsourcepackage',
+ 'DistributionSourcePackageAnswersMenu',
'DistributionSourcePackageBreadcrumb',
'DistributionSourcePackageChangelogView',
'DistributionSourcePackageEditView',
'DistributionSourcePackageFacets',
+ 'DistributionSourcePackageHelpView',
'DistributionSourcePackageNavigation',
'DistributionSourcePackageOverviewMenu',
'DistributionSourcePackagePublishingHistoryView',
@@ -52,6 +54,7 @@
from canonical.launchpad.webapp.sorting import sorted_dotted_numbers
from canonical.lazr.utils import smartquote
from lp.answers.browser.questiontarget import (
+ QuestionTargetAnswersMenu,
QuestionTargetFacetMixin,
QuestionTargetTraversalMixin,
)
@@ -170,6 +173,17 @@
return links
+class DistributionSourcePackageAnswersMenu(QuestionTargetAnswersMenu):
+
+ usedfor = IDistributionSourcePackage
+ facet = 'answers'
+
+ links = QuestionTargetAnswersMenu.links + ['gethelp']
+
+ def gethelp(self):
+ return Link('+gethelp', 'Help and support options', icon='info')
+
+
class DistributionSourcePackageNavigation(Navigation,
BugTargetTraversalMixin, HasCustomLanguageCodesTraversalMixin,
QuestionTargetTraversalMixin,
@@ -600,3 +614,9 @@
return canonical_url(self.context)
cancel_url = next_url
+
+
+class DistributionSourcePackageHelpView:
+ """A View to show Answers help."""
+
+ page_title = 'Help and support options'
=== modified file 'lib/lp/registry/browser/sourcepackage.py'
--- lib/lp/registry/browser/sourcepackage.py 2011-05-12 12:41:00 +0000
+++ lib/lp/registry/browser/sourcepackage.py 2011-05-12 15:26:36 +0000
@@ -11,7 +11,6 @@
'SourcePackageBreadcrumb',
'SourcePackageChangeUpstreamView',
'SourcePackageFacets',
- 'SourcePackageHelpView',
'SourcePackageNavigation',
'SourcePackageOverviewMenu',
'SourcePackageRemoveUpstreamView',
@@ -80,10 +79,6 @@
from canonical.launchpad.webapp.menu import structured
from canonical.launchpad.webapp.publisher import LaunchpadView
from canonical.lazr.utils import smartquote
-from lp.answers.browser.questiontarget import (
- QuestionTargetAnswersMenu,
- QuestionTargetFacetMixin,
- )
from lp.app.browser.launchpadform import (
action,
custom_widget,
@@ -180,9 +175,7 @@
@stepto('+filebug')
def filebug(self):
"""Redirect to the IDistributionSourcePackage +filebug page."""
- sourcepackage = self.context
- distro_sourcepackage = sourcepackage.distribution.getSourcePackage(
- sourcepackage.name)
+ distro_sourcepackage = self.context.distribution_sourcepackage
redirection_url = canonical_url(
distro_sourcepackage, view_name='+filebug')
@@ -190,6 +183,13 @@
redirection_url += '?no-redirect'
return self.redirectSubTree(redirection_url, status=303)
+ @stepto('+gethelp')
+ def gethelp(self):
+ """Redirect to the IDistributionSourcePackage +gethelp page."""
+ dsp = self.context.distribution_sourcepackage
+ redirection_url = canonical_url(dsp, view_name='+gethelp')
+ return redirection(redirection_url)
+
@adapter(ISourcePackage)
@implementer(IServiceUsage)
@@ -207,10 +207,10 @@
return smartquote('"%s" source package') % (self.context.name)
-class SourcePackageFacets(QuestionTargetFacetMixin, StandardLaunchpadFacets):
+class SourcePackageFacets(StandardLaunchpadFacets):
usedfor = ISourcePackage
- enable_only = ['overview', 'bugs', 'branches', 'answers', 'translations']
+ enable_only = ['overview', 'bugs', 'branches', 'translations']
class SourcePackageOverviewMenu(ApplicationMenu):
@@ -260,17 +260,6 @@
return packaging.userCanDelete()
-class SourcePackageAnswersMenu(QuestionTargetAnswersMenu):
-
- usedfor = ISourcePackage
- facet = 'answers'
-
- links = QuestionTargetAnswersMenu.links + ['gethelp']
-
- def gethelp(self):
- return Link('+gethelp', 'Help and support options', icon='info')
-
-
class SourcePackageChangeUpstreamStepOne(ReturnToReferrerMixin, StepView):
"""A view to set the `IProductSeries` of a sourcepackage."""
schema = Interface
@@ -549,12 +538,6 @@
return list(self.context.getCurrentTranslationTemplates())
-class SourcePackageHelpView:
- """A View to show Answers help."""
-
- page_title = 'Help and support options'
-
-
class SourcePackageAssociationPortletView(LaunchpadFormView):
"""A view for linking to an upstream package."""
=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml 2011-05-05 18:15:23 +0000
+++ lib/lp/registry/configure.zcml 2011-05-12 15:26:36 +0000
@@ -513,25 +513,11 @@
<!-- IQuestionTarget -->
- <allow
- attributes="
- getQuestion
- searchQuestions
- findSimilarQuestions
- answer_contacts
- direct_answer_contacts
- getSupportedLanguages
- getQuestionLanguages
- getAnswerContactsForLanguage
- getAnswerContactRecipients"/>
+ <allow interface="lp.answers.interfaces.questiontarget.IQuestionTargetPublic"/>
<require
- permission="launchpad.AnyPerson"
- attributes="
- newQuestion
- createQuestionFromBug
- canUserAlterAnswerContact
- addAnswerContact
- removeAnswerContact"/>
+ permission="launchpad.AnyPerson"
+ interface="lp.answers.interfaces.questiontarget.IQuestionTargetView"/>
+
<require
permission="launchpad.BugSupervisor"
set_attributes="
@@ -1254,25 +1240,10 @@
<!-- IQuestionTarget -->
- <allow
- attributes="
- getQuestion
- searchQuestions
- findSimilarQuestions
- answer_contacts
- direct_answer_contacts
- getSupportedLanguages
- getQuestionLanguages
- getAnswerContactsForLanguage
- getAnswerContactRecipients"/>
+ <allow interface="lp.answers.interfaces.questiontarget.IQuestionTargetPublic"/>
<require
- permission="launchpad.AnyPerson"
- attributes="
- newQuestion
- createQuestionFromBug
- canUserAlterAnswerContact
- addAnswerContact
- removeAnswerContact"/>
+ permission="launchpad.AnyPerson"
+ interface="lp.answers.interfaces.questiontarget.IQuestionTargetView"/>
<!-- IFAQTarget -->
@@ -1536,26 +1507,10 @@
<!-- IQuestionTarget -->
- <allow
- attributes="
- getQuestion
- searchQuestions
- findSimilarQuestions
- answer_contacts
- direct_answer_contacts
- getSupportedLanguages
- getQuestionLanguages
- getAnswerContactsForLanguage
- getAnswerContactRecipients"/>
+ <allow interface="lp.answers.interfaces.questiontarget.IQuestionTargetPublic"/>
<require
- permission="launchpad.AnyPerson"
- attributes="
- newQuestion
- createQuestionFromBug
- canUserAlterAnswerContact
- addAnswerContact
- removeAnswerContact"/>
-
+ permission="launchpad.AnyPerson"
+ interface="lp.answers.interfaces.questiontarget.IQuestionTargetView"/>
<!-- IFAQTarget -->
@@ -1631,28 +1586,6 @@
interface="lp.bugs.interfaces.bugtarget.IHasBugHeat"/>
<allow
interface="lp.soyuz.interfaces.buildrecords.IHasBuildRecords"/>
-
- <!-- IQuestionTarget -->
-
- <allow
- attributes="
- getQuestion
- searchQuestions
- findSimilarQuestions
- answer_contacts
- direct_answer_contacts
- getQuestionLanguages
- getAnswerContactsForLanguage
- getSupportedLanguages
- getAnswerContactRecipients"/>
- <require
- permission="launchpad.AnyPerson"
- attributes="
- newQuestion
- createQuestionFromBug
- canUserAlterAnswerContact
- addAnswerContact
- removeAnswerContact"/>
</class>
<securedutility
component="lp.registry.model.sourcepackage.SourcePackage"
=== modified file 'lib/lp/registry/interfaces/distribution.py'
--- lib/lp/registry/interfaces/distribution.py 2011-04-14 20:40:03 +0000
+++ lib/lp/registry/interfaces/distribution.py 2011-05-12 15:26:36 +0000
@@ -57,6 +57,7 @@
IHasAppointedDriver,
IHasDrivers,
)
+from lp.answers.interfaces.questiontarget import IQuestionTarget
from lp.app.errors import NameLookupFailed
from lp.app.interfaces.headings import IRootContext
from lp.app.interfaces.launchpad import (
@@ -641,7 +642,7 @@
class IDistribution(
IDistributionEditRestricted, IDistributionPublic, IHasBugSupervisor,
- IRootContext, IStructuralSubscriptionTarget):
+ IQuestionTarget, IRootContext, IStructuralSubscriptionTarget):
"""An operating system distribution.
Launchpadlib example: retrieving the current version of a package in a
=== modified file 'lib/lp/registry/interfaces/distributionsourcepackage.py'
--- lib/lp/registry/interfaces/distributionsourcepackage.py 2011-01-21 08:12:29 +0000
+++ lib/lp/registry/interfaces/distributionsourcepackage.py 2011-05-12 15:26:36 +0000
@@ -31,6 +31,7 @@
)
from canonical.launchpad import _
+from lp.answers.interfaces.questiontarget import IQuestionTarget
from lp.bugs.interfaces.bugtarget import (
IBugTarget,
IHasOfficialBugTags,
@@ -48,8 +49,9 @@
class IDistributionSourcePackage(IBugTarget, IHasBranches, IHasMergeProposals,
+ IHasOfficialBugTags,
IStructuralSubscriptionTarget,
- IHasOfficialBugTags):
+ IQuestionTarget):
"""Represents a source package in a distribution.
Create IDistributionSourcePackages by invoking
=== modified file 'lib/lp/registry/interfaces/product.py'
--- lib/lp/registry/interfaces/product.py 2011-04-12 23:25:45 +0000
+++ lib/lp/registry/interfaces/product.py 2011-05-12 15:26:36 +0000
@@ -77,6 +77,7 @@
IHasLogo,
IHasMugshot,
)
+from lp.answers.interfaces.questiontarget import IQuestionTarget
from lp.app.errors import NameLookupFailed
from lp.app.interfaces.headings import IRootContext
from lp.app.interfaces.launchpad import (
@@ -815,7 +816,8 @@
class IProduct(
IHasBugSupervisor, IProductEditRestricted,
IProductModerateRestricted, IProductDriverRestricted,
- IProductPublic, IRootContext, IStructuralSubscriptionTarget):
+ IProductPublic, IQuestionTarget, IRootContext,
+ IStructuralSubscriptionTarget):
"""A Product.
The Launchpad Registry describes the open source world as ProjectGroups
=== modified file 'lib/lp/registry/model/distribution.py'
--- lib/lp/registry/model/distribution.py 2011-04-26 16:25:00 +0000
+++ lib/lp/registry/model/distribution.py 2011-05-12 15:26:36 +0000
@@ -70,7 +70,6 @@
from canonical.launchpad.webapp.url import urlparse
from lp.answers.interfaces.faqtarget import IFAQTarget
from lp.answers.enums import QUESTION_STATUS_DEFAULT_SEARCH
-from lp.answers.interfaces.questiontarget import IQuestionTarget
from lp.answers.model.faq import (
FAQ,
FAQSearch,
@@ -219,7 +218,7 @@
implements(
IDistribution, IFAQTarget, IHasBugHeat, IHasBugSupervisor,
IHasBuildRecords, IHasIcon, IHasLogo, IHasMugshot, ILaunchpadUsage,
- IQuestionTarget, IServiceUsage)
+ IServiceUsage)
_table = 'Distribution'
_defaultOrder = 'name'
=== modified file 'lib/lp/registry/model/distributionsourcepackage.py'
--- lib/lp/registry/model/distributionsourcepackage.py 2011-04-12 06:21:39 +0000
+++ lib/lp/registry/model/distributionsourcepackage.py 2011-05-12 15:26:36 +0000
@@ -38,7 +38,6 @@
from canonical.launchpad.database.emailaddress import EmailAddress
from canonical.launchpad.interfaces.lpstorm import IStore
from canonical.lazr.utils import smartquote
-from lp.answers.interfaces.questiontarget import IQuestionTarget
from lp.bugs.interfaces.bugtarget import IHasBugHeat
from lp.bugs.interfaces.bugtask import UNRESOLVED_BUGTASK_STATUSES
from lp.bugs.model.bug import (
@@ -140,8 +139,7 @@
"""
implements(
- IDistributionSourcePackage, IHasBugHeat, IHasCustomLanguageCodes,
- IQuestionTarget)
+ IDistributionSourcePackage, IHasBugHeat, IHasCustomLanguageCodes)
bug_reporting_guidelines = DistributionSourcePackageProperty(
'bug_reporting_guidelines')
=== modified file 'lib/lp/registry/model/product.py'
--- lib/lp/registry/model/product.py 2011-04-26 16:25:00 +0000
+++ lib/lp/registry/model/product.py 2011-05-12 15:26:36 +0000
@@ -81,7 +81,6 @@
from canonical.lazr.utils import safe_hasattr
from lp.answers.interfaces.faqtarget import IFAQTarget
from lp.answers.enums import QUESTION_STATUS_DEFAULT_SEARCH
-from lp.answers.interfaces.questiontarget import IQuestionTarget
from lp.answers.model.faq import (
FAQ,
FAQSearch,
@@ -309,7 +308,7 @@
implements(
IFAQTarget, IHasBugHeat, IHasBugSupervisor, IHasCustomLanguageCodes,
IHasIcon, IHasLogo, IHasMugshot, ILaunchpadUsage, IProduct,
- IQuestionTarget, IServiceUsage)
+ IServiceUsage)
_table = 'Product'
=== modified file 'lib/lp/registry/model/sourcepackage.py'
--- lib/lp/registry/model/sourcepackage.py 2011-05-09 18:57:18 +0000
+++ lib/lp/registry/model/sourcepackage.py 2011-05-12 15:26:36 +0000
@@ -33,7 +33,6 @@
from canonical.lazr.utils import smartquote
from canonical.launchpad.webapp.interfaces import ILaunchBag
from lp.answers.enums import QUESTION_STATUS_DEFAULT_SEARCH
-from lp.answers.interfaces.questiontarget import IQuestionTarget
from lp.answers.model.question import (
QuestionTargetMixin,
QuestionTargetSearch,
@@ -187,10 +186,9 @@
return sorted(answer_contacts, key=attrgetter('displayname'))
-class SourcePackage(BugTargetBase, SourcePackageQuestionTargetMixin,
+class SourcePackage(BugTargetBase, HasBugHeatMixin, HasCodeImportsMixin,
HasTranslationImportsMixin, HasTranslationTemplatesMixin,
- HasBranchesMixin, HasMergeProposalsMixin,
- HasBugHeatMixin, HasCodeImportsMixin):
+ HasBranchesMixin, HasMergeProposalsMixin):
"""A source package, e.g. apache2, in a distroseries.
This object is not a true database object, but rather attempts to
@@ -199,7 +197,7 @@
"""
implements(
- ISourcePackage, IHasBugHeat, IHasBuildRecords, IQuestionTarget)
+ ISourcePackage, IHasBugHeat, IHasBuildRecords)
classProvides(ISourcePackageFactory)