Commits

Olemis Lang committed f649f02

Minor optimizations. Protocol provider docs (WikiFormatting) shown in RPC docs page.

Comments (0)

Files changed (1)

t5437/t5437-protocol_api-r6141.diff

 new file mode 100644
 --- /dev/null
 +++ b/trunk/tracrpc/json_rpc.py
-@@ -0,0 +1,176 @@
+@@ -0,0 +1,193 @@
 +# -*- coding: utf-8 -*-
 +"""
 +License: BSD
 +
 +
 +class JsonRpcProtocol(Component):
++    r"""
++    ==== JSON-RPC example ====
++    
++    {{{
++    user: ~ > cat body.json
++    {"params": ["WikiStart"], "method": "wiki.getPage", "id": 123}
++    user: ~ > curl -H "Content-Type: application/json" --data @body.json ${req.abs_href.jsonrpc()}
++    {"id": 123, "error": null, "result": "= Welcome to....
++    }}}
++    
++    - JSON-RPC has no formalized type system, so a class-hint system is used
++      for input and output of non-standard types:
++      - `{"__jsonclass__": ["datetime", "YYYY-MM-DDTHH:MM:SS"]}` = DateTime (UTC)
++      - `{"__jsonclass__": ["binary", "<base64-encoded>"]} = Binary
++    - `"id"` is optional, and any marker value received with a
++      request is returned with the response.
++    """
 +
 +    implements(IRPCProtocol)
 +
 +    # IRPCProtocol methods
 +
 +    def rpc_info(self):
-+        return ('JSON-RPC', True, "Docs for JSON-RPC rendered here...")
++        return ('JSON-RPC', True, self.__doc__)
 +
 +    def rpc_match(self):
 +        yield ('jsonrpc', 'application/json')
 diff --git a/trunk/tracrpc/templates/xmlrpclist.html b/trunk/tracrpc/templates/xmlrpclist.html
 --- a/trunk/tracrpc/templates/xmlrpclist.html
 +++ b/trunk/tracrpc/templates/xmlrpclist.html
-@@ -15,9 +15,9 @@
+@@ -15,11 +15,24 @@
        <h1>Remote Procedure Call (RPC) Interface</h1>
        <dl>
          <dt>API Status:</dt>
 -            ${xmlrpc.json and 'available' or 'not available'}</strong></dd>
 +          <dd py:for="protocol in xmlrpc.protocols">
 +            ${protocol[0]} is <strong>
-+              ${protocol[1] and 'available' or 'not available'}</strong></dd>
++              ${protocol[1] and 'available' or 'not available'}</strong>
++          </dd>
        </dl>
  
++      <h2>Calling Methods</h2>
++      <p>Libraries for remote procedure calls and parsing exists
++        for most major languages and platforms - use a tested, standard library
++        for consistent results.</p>
++      <p>The following are examples for illustration only, and shows raw
++        access to RPC using <tt>curl</tt> (with Content-Type and Body for POST request):</p>
++      <div class="help">
++        <div py:for="protocol in xmlrpc.protocols">
++            ${protocol[2]}
++        </div>
++      </div>
++
        <h2>RPC exported functions</h2>
+ 
+       <div id="searchable">
+@@ -50,60 +63,6 @@
+         </dl>
+       </div>
+       
+-      <h2>Calling Methods</h2>
+-      <p>XML and JSON libraries for remote procedure calls and parsing exists
+-        for all major languages and platforms - use a tested, standard library
+-        for consistent results.</p>
+-      <p>The following are examples for illustration only, and shows raw
+-        access to RPC using <tt>curl</tt> (with Content-Type and Body for POST request):</p>
+-      <div class="help">
+-        <h4>XML-RPC example</h4>
+-        <pre>
+-user: ~ &gt; cat body.xml
+-&lt;?xml version="1.0"?&gt;
+-&lt;methodCall&gt;
+-&lt;methodName&gt;wiki.getPage&lt;/methodName&gt;
+-&lt;params&gt;
+-&lt;param&gt;&lt;string&gt;WikiStart&lt;/string&gt;&lt;/param&gt;
+-&lt;/params&gt;
+-&lt;/methodCall&gt;
+-user: ~ &gt; curl -H "Content-Type: application/xml" --data @body.xml ${req.abs_href.xmlrpc()}
+-&lt;?xml version='1.0'?&gt;
+-&lt;methodResponse&gt;
+-&lt;params&gt;
+-&lt;param&gt;
+-&lt;value&gt;&lt;string&gt;= Welcome to....
+-      </pre>
+-      <ul>
+-        <li>Use <tt>${req.abs_href.login('xmlrpc')}</tt> with basic
+-            authentication for user context.</li>
+-      </ul>
+-      </div>
+-      <div>
+-        <h4>JSON-RPC example</h4>
+-        <pre>
+-user: ~ &gt; cat body.json
+-{"params": ["WikiStart"], "method": "wiki.getPage", "id": 123}
+-user: ~ &gt; curl -H "Content-Type: application/json" --data @body.json ${req.abs_href.jsonrpc()}
+-{"id": 123, "error": null, "result": "= Welcome to....
+-        </pre>
+-        <ul>
+-          <li>JSON-RPC has no formalized type system, so a class-hint system is used
+-              for input and output of non-standard types:
+-            <ul>
+-              <li><tt>{"__jsonclass__": ["datetime", "YYYY-MM-DDTHH:MM:SS"]}</tt>
+-                  = DateTime (UTC)</li>
+-              <li><tt>{"__jsonclass__": ["binary", "&lt;base64-encoded&gt;"]}</tt>
+-                  = Binary</li>
+-            </ul>
+-          </li>
+-          <li><tt>"id"</tt> is optional, and any marker value received with a
+-            request is returned with the response.</li>
+-          <li>Use <tt>${req.abs_href.login('jsonrpc')}</tt> with basic
+-            authentication for user context.</li>
+-        </ul>
+-      </div>
+-      
+       <script type="text/javascript">
+         addHeadingLinks(document.getElementById("searchable"));
+       </script>
 diff --git a/trunk/tracrpc/tests/__init__.py b/trunk/tracrpc/tests/__init__.py
 --- a/trunk/tracrpc/tests/__init__.py
 +++ b/trunk/tracrpc/tests/__init__.py
 diff --git a/trunk/tracrpc/tests/xml.py b/trunk/tracrpc/tests/xml_rpc.py
 rename from trunk/tracrpc/tests/xml.py
 rename to trunk/tracrpc/tests/xml_rpc.py
+diff --git a/trunk/tracrpc/ticket.py b/trunk/tracrpc/ticket.py
+--- a/trunk/tracrpc/ticket.py
++++ b/trunk/tracrpc/ticket.py
+@@ -21,7 +21,7 @@
+ 
+ import inspect
+ import xmlrpclib
+-from StringIO import StringIO
++from util import StringIO
+ 
+ from tracrpc.api import IXMLRPCHandler, expose_rpc
+ 
 diff --git a/trunk/tracrpc/util.py b/trunk/tracrpc/util.py
 --- a/trunk/tracrpc/util.py
 +++ b/trunk/tracrpc/util.py
-@@ -6,24 +6,6 @@
+@@ -6,24 +6,10 @@
  (c) 2009      ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no)
  """
  
 -    return apply(datetime.datetime, t, {'tzinfo': utc})
 -
 -### INTERNAL / COMPAT
++try:
++  from cStringIO import StringIO
++except ImportError:
++  from StringIO import StringIO
  
  try:
      # Method only available in Trac 0.11.3 or higher
 -            else:
 -                new_result.append(res)
 -        return new_result
-+                from StringIO import StringIO
++                from util import StringIO
 +                import traceback
 +                out = StringIO()
 +                traceback.print_exc(file=out)
  
      # ITemplateProvider
      def get_htdocs_dirs(self):
+diff --git a/trunk/tracrpc/wiki.py b/trunk/tracrpc/wiki.py
+--- a/trunk/tracrpc/wiki.py
++++ b/trunk/tracrpc/wiki.py
+@@ -6,10 +6,7 @@
+ (c) 2009      ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no)
+ """
+ 
+-try:
+-    from cStringIO import StringIO
+-except ImportError:
+-    from StringIO import StringIO
++from util import StringIO
+ import xmlrpclib
+ import os
+ 
 diff --git a/trunk/tracrpc/xml_rpc.py b/trunk/tracrpc/xml_rpc.py
 new file mode 100644
 --- /dev/null
 +++ b/trunk/tracrpc/xml_rpc.py
-@@ -0,0 +1,126 @@
+@@ -0,0 +1,155 @@
 +# -*- coding: utf-8 -*-
 +"""
 +License: BSD
 +    return apply(datetime.datetime, t, {'tzinfo': utc})
 +
 +class XmlRpcProtocol(Component):
-+
++    r"""
++    ==== Calling Methods ====
++    
++    XML libraries for remote procedure calls and parsing 
++    exists for all major languages and platforms - use a tested, 
++    standard library for consistent results.
++    
++    The following is an example for illustration only, and shows 
++    raw access to RPC using curl (with Content-Type and Body for 
++    POST request):
++    
++    ==== XML-RPC example ====
++    {{{
++    user: ~ > cat body.xml
++    <?xml version="1.0"?>
++    <methodCall>
++    <methodName>wiki.getPage</methodName>
++    <params>
++    <param><string>WikiStart</string></param>
++    </params>
++    </methodCall>
++    
++    user: ~ > curl -H "Content-Type: application/xml" --data @body.xml ${req.abs_href.xmlrpc()}
++    <?xml version='1.0'?>
++    <methodResponse>
++    <params>
++    <param>
++    <value><string>= Welcome to....
++    }}}
++    """
 +    implements(IRPCProtocol)
 +
 +    # IRPCProtocol methods
 +
 +    def rpc_info(self):
-+        return ('XML-RPC', True, "Docs for XML-RPC rendered here...")
++        return ('XML-RPC', True, self.__doc__)
 +
 +    def rpc_match(self):
 +        yield ('xmlrpc', 'application/xml')
 +        except Exception, e:
 +            self.log.error(e)
 +            import traceback
-+            from StringIO import StringIO
++            from util import StringIO
 +            out = StringIO()
 +            traceback.print_exc(file = out)
 +            self.log.error(out.getvalue())
 +            elif isinstance(arg, basestring):
 +                new_args.append(arg.replace("\n", "\r\n"))
 +            elif isinstance(arg, dict):
-+                for key in arg.keys():
-+                    arg[key] = self._normalize_xml_input([arg[key]])[0]
++                for key, val in arg.items():
++                    arg[key], = self._normalize_xml_input([val])
 +                new_args.append(arg)
-+            elif isinstance(arg, list) or isinstance(arg, tuple):
++            elif isinstance(arg, (list, tuple)):
 +                new_args.append(self._normalize_xml_input(arg))
 +            else:
 +                new_args.append(arg)
 +                new_result.append(to_xmlrpc_datetime(res))
 +            elif res == None:
 +                new_result.append('')
-+            elif isinstance(res, genshi.builder.Fragment) \
-+                        or isinstance(res, genshi.core.Markup):
++            elif isinstance(res, (genshi.builder.Fragment, \
++                                  genshi.core.Markup)):
 +                new_result.append(to_unicode(res))
 +            elif isinstance(res, dict):
-+                for key in res.keys():
-+                    res[key] = self._normalize_xml_output([res[key]])[0]
++                for key, val in res.items():
++                    res[key], = self._normalize_xml_output([val])
 +                new_result.append(res)
 +            elif isinstance(res, list) or isinstance(res, tuple):
 +                new_result.append(self._normalize_xml_output(res))