changeset 5695:3e1b66c4e1e2

Update docs. Correct errors reported by setup.py build_docs. Add rest interface and link to rest doc to features page. Add link to xmlrpc doc to features page. Add rest doc to index. Update rest doc, hopefully clarify confusing use of parameters in patch action section. Fix code examples in "Adding new rest endpoints" section. Fix example adding import of exception.
author John Rouillard <rouilj@ieee.org>
date Sun, 07 Apr 2019 20:17:52 -0400
parents c3ffa1ef6b7f
children b67636bc87d0
files doc/features.txt doc/index.txt doc/rest.txt
diffstat 3 files changed, 44 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/doc/features.txt	Sat Apr 06 10:20:19 2019 -0400
+++ b/doc/features.txt	Sun Apr 07 20:17:52 2019 -0400
@@ -104,10 +104,17 @@
 
 *xmlrpc interface*
  - simple remote tracker interface with basic HTTP authentication
+   available at the /xmlrpc endpoint.
  - provides same access to tracker as roundup-admin, but based on
    XMLRPC calls
+ - see the `xmlrpc guide`_ for more details simple clients etc.
+
+*restful interface*
+ - accessible using basic HTTP authentication at /rest starting point
+ - see the `rest guide`_ for details.
 
 .. _sqlite: http://www.hwaci.com/sw/sqlite/
 .. _mysql: https://pypi.org/project/MySQL-python/
 .. _postgresql: http://initd.org/software/initd/psycopg
-
+.. _`xmlrpc guide`: xmlrpc.html
+.. _`rest guide`: rest.html
--- a/doc/index.txt	Sat Apr 06 10:20:19 2019 -0400
+++ b/doc/index.txt	Sun Apr 07 20:17:52 2019 -0400
@@ -19,6 +19,7 @@
    admin_guide
    debugging
    xmlrpc
+   rest
    overview
    Design (original) <design>
    developers
--- a/doc/rest.txt	Sat Apr 06 10:20:19 2019 -0400
+++ b/doc/rest.txt	Sun Apr 07 20:17:52 2019 -0400
@@ -36,7 +36,7 @@
 Summary
 =======
 
-A Summary page can be reached via ``/data/summary`` via the ``GET`` method.
+A Summary page can be reached via ``/summary`` via the ``GET`` method.
 This is currently hard-coded for the standard tracker schema shipped
 with roundup and will display a summary of open issues.
 
@@ -136,13 +136,13 @@
 
 Finally the ``PATCH`` method can be applied to individual items, e.g.,
 ``/data/issue/42`` and to properties, e.g., ``/data/issue/42/title``.
-This method gets an operator ``@op=<method>`` where ``<method`` is one
+This method gets an operator ``@op=<method>`` where ``<method>`` is one
 of ``add``, ``replace``, ``remove``, only for an item (not for a
 property) an additional operator ``action`` is supported. If no operator
 is specified, the default is ``replace``. The first three operators are
 self explanatory. For an ``action`` operator an ``@action_name`` and
 optional ``@action_argsXXX`` parameters have to be supplied. Currently
-there are only two actions without parameters, namely ``retire`` and
+there are only two actions, neither has args, namely ``retire`` and
 ``restore``. The ``retire`` action on an item is the same as a
 ``DELETE`` method, it retires the item. The ``restore`` action is the
 inverse of ``retire``, the item is again visible.
@@ -198,9 +198,10 @@
 Add or edit the file interfaces.py at the root of the tracker
 directory.
 
-In that file add (remove indentation):
+In that file add::
 
     from roundup.rest import Routing, RestfulInstance, _data_decorator
+    from roundup.exceptions import Unauthorised
 
     class RestfulInstance:
 
@@ -210,7 +211,7 @@
 	    result = { "hello": "world" }
 	    return 200, result
 
-will make a new endpoint .../rest/summary2 that you can test with:
+will make a new endpoint .../rest/summary2 that you can test with::
 
     $ curl -X GET .../rest/summary2
     {
@@ -219,25 +220,29 @@
         }
     }
 
-Similarly appending this to interfaces.py after summary2:
+Similarly appending this to interfaces.py after summary2::
 
-    @Routing.route("/data/<:class_name>/@schema", 'GET')
-    def get_element_schema(self, class_name, input):
-        result = { "schema": {} }
-        uid = self.db.getuid ()
-        if not self.db.security.hasPermission('View', uid, class_name) :
-            raise Unauthorised('Permission to view %s denied' % class_name)
+    # handle more endpoints
+        @Routing.route("/data/<:class_name>/@schema", 'GET')
+        def get_element_schema(self, class_name, input):
+	    result = { "schema": {} }
+	    uid = self.db.getuid ()
+	    if not self.db.security.hasPermission('View', uid, class_name) :
+		raise Unauthorised('Permission to view %s denied' % class_name)
 
-        class_obj = self.db.getclass(class_name)
-        props = class_obj.getprops(protected=False)
-        schema = result['schema']
+	    class_obj = self.db.getclass(class_name)
+	    props = class_obj.getprops(protected=False)
+	    schema = result['schema']
+
+	    for prop in props:
+		schema[prop] = { "type": repr(class_obj.properties[prop]) }
 
-        for prop in props:
-            schema[prop] = { "type": repr(class_obj.properties[prop]) }
+	    return result
 
-        return result
+..
+  the # comment in the example is needed to preserve indention under Class.
 
-returns some data about the class
+returns some data about the class::
 
     $ curl -X GET .../rest/data/issue/@schema
     {   
@@ -258,6 +263,9 @@
     }
 
 
+Adding other endpoints (e.g. to allow an OPTIONS query against
+``/data/issue/@schema``) is left as an exercise for the reader.
+
 Searches and selection
 ======================
 
@@ -271,9 +279,9 @@
 to get a list of items for the user to select from.
 
 Consider a multi-select box for the superseder property.  Using
-selectize.js (and jquery) code similar to:
+selectize.js (and jquery) code similar to::
 
- $('#superseder').selectize({
+    $('#superseder').selectize({
 	valueField: 'id',
 	labelField: 'title',
 	searchField: 'title', ...
@@ -289,9 +297,9 @@
 
 Sets up a box that a user can type the word "request" into. Then
 selectize.js will use that word to generate an ajax request with the
-url: .../rest/data/issue?@verbose=2&title=request
+url: ``.../rest/data/issue?@verbose=2&title=request``
 
-This will return data like:
+This will return data like::
 
   {
     "data": {
@@ -307,6 +315,7 @@
 	  "id": "27",
 	  "title": "Request for foo"
       },
+  ...
 
 selectize.js will look at these objects (as passed to
 callback(res.data.collection)) and create a select list from the each
@@ -316,7 +325,7 @@
 issues. Only 440 had the word "request" somewhere in the title greatly
 reducing the amount of data that needed to be transferred.
 
-Similar things can be set up to search a large list of keywords using
+Similar code can be set up to search a large list of keywords using::
 
   .../rest/data/keyword?@verbose=2&name=some
 
@@ -326,7 +335,7 @@
 Hopefully future enhancements will allow get on a collection to
 include other fields. Why do we want this?  Selectize.js can set up
 option groups (optgroups) in the select pulldown. So by including
-status in the returned data:
+status in the returned data::
 
       {
 	  "link": ".../rest/data/issue/27",
@@ -335,7 +344,7 @@
 	  'status": "open"
       },
 
-a select widget like:
+a select widget like::
 
   === New ===
   A request

Roundup Issue Tracker: http://roundup-tracker.org/