← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~jcsackett/launchpad/api-wants-questionset into lp:launchpad

 

j.c.sackett has proposed merging lp:~jcsackett/launchpad/api-wants-questionset into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~jcsackett/launchpad/api-wants-questionset/+merge/57023

Summary
=======
This exposes question set on the api, so https://api.launchpad.net/devel/questions/1 works, and the API doesn't require url hacking to get at a question.

Preimp
======
Spoke with Curtis Hovey about exposing the top level elements of an application.

Implementation
==============
lib/lp/answers/browser/question.py
----------------------------------
Change the traverse method for the questionset. It previously returned a redirect to the canonical_url of the question directly, and was request unaware, so it would redirect outside of api. Since canonical_url is called on returned objects higher up the stack (and *is* request aware), we can just rely on that.

lib/lp/answers/interfaces/questioncollection.py
lib/lp/answers/interfaces/webservice.py
---------------------------------------
Exposed the needed elements of the QuestionSet interface on the API.

Tests
=====
bin/test -m lp.answers

QA
==
Since this changes traversal for questions, first make sure a the usual question links are working (e.g. /questions/$question_id and /$product/+question/$question_id).

Then, attempt to load a question via the api over https://api.launchpad.net/devel/questions/$question_id and https://api.launchpad.net/devel/$product/+question/$question_id. They should both show the same data.

Lint
====
make lint output:

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/answers/browser/question.py
  lib/lp/answers/interfaces/questioncollection.py
  lib/lp/answers/interfaces/webservice.py

./lib/lp/answers/interfaces/questioncollection.py
      94: E302 expected 2 blank lines, found 0
./lib/lp/answers/interfaces/webservice.py
      18: 'IQuestionSet' imported but unused
      17: 'IQuestion' imported but unused

The two unused imports are needed for the webservice zcml.
-- 
https://code.launchpad.net/~jcsackett/launchpad/api-wants-questionset/+merge/57023
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jcsackett/launchpad/api-wants-questionset into lp:launchpad.
=== modified file 'lib/lp/answers/browser/question.py'
--- lib/lp/answers/browser/question.py	2011-02-02 15:43:31 +0000
+++ lib/lp/answers/browser/question.py	2011-04-08 22:04:35 +0000
@@ -73,7 +73,6 @@
     Link,
     Navigation,
     NavigationMenu,
-    redirection,
     )
 from canonical.launchpad.webapp.authorization import check_permission
 from canonical.launchpad.webapp.breadcrumb import Breadcrumb
@@ -237,7 +236,7 @@
             question = None
         if question is None:
             raise NotFoundError(name)
-        return redirection(canonical_url(question), status=301)
+        return question
 
 
 class QuestionBreadcrumb(Breadcrumb):

=== modified file 'lib/lp/answers/interfaces/questioncollection.py'
--- lib/lp/answers/interfaces/questioncollection.py	2010-08-20 20:31:18 +0000
+++ lib/lp/answers/interfaces/questioncollection.py	2011-04-08 22:04:35 +0000
@@ -11,14 +11,24 @@
     'IQuestionCollection',
     'IQuestionSet',
     'ISearchableByQuestionOwner',
-    'QUESTION_STATUS_DEFAULT_SEARCH'
+    'QUESTION_STATUS_DEFAULT_SEARCH',
     ]
 
 from zope.interface import (
     Attribute,
     Interface,
     )
-
+from zope.schema import Int
+
+from lazr.restful.declarations import (
+    collection_default_content,
+    export_as_webservice_collection,
+    export_read_operation,
+    operation_for_version,
+    operation_parameters,
+    )
+
+from canonical.launchpad import _
 from lp.answers.interfaces.questionenums import QuestionStatus
 
 
@@ -47,7 +57,7 @@
         against the question's language. If None or an empty sequence,
         the language is not included as a filter criteria.
 
-        :sort:  An attribute of QuestionSort. If None, a default value is used.
+        :sort: An attribute of QuestionSort. If None, a default value is used.
         When there is a search_text value, the default is to sort by
         RELEVANCY, otherwise results are sorted NEWEST_FIRST.
         """
@@ -79,11 +89,21 @@
         """
 
 
+# Hurray circular imports!
+from lp.answers.interfaces.question import IQuestion
 class IQuestionSet(IQuestionCollection):
     """A utility that contain all the questions published in Launchpad."""
 
+    export_as_webservice_collection(IQuestion)
+
     title = Attribute('Title')
 
+    @operation_parameters(
+        question_id=Int(
+            title=_('The id of the question to get'),
+            required=True))
+    @export_read_operation()
+    @operation_for_version('devel')
     def get(question_id, default=None):
         """Return the question with the given id.
 
@@ -98,6 +118,7 @@
         comments in the last <days_before_expiration> days.
         """
 
+    @collection_default_content(limit=5)
     def getMostActiveProjects(limit=5):
         """Return the list of projects that asked the most questions in
         the last 60 days.

=== modified file 'lib/lp/answers/interfaces/webservice.py'
--- lib/lp/answers/interfaces/webservice.py	2011-03-21 21:34:04 +0000
+++ lib/lp/answers/interfaces/webservice.py	2011-04-08 22:04:35 +0000
@@ -11,6 +11,8 @@
 
 __all__ = [
     'IQuestion',
+    'IQuestionSet',
     ]
 
 from lp.answers.interfaces.question import IQuestion
+from lp.answers.interfaces.questioncollection import IQuestionSet