trac-rpc-mq / t0000 / t0000-kwargs-r7971.diff

Introducing keyword args in instances of Method class

diff -r fa00f1619d65 trunk/setup.py
--- a/trunk/setup.py	Fri May 21 12:35:35 2010 +0200
+++ b/trunk/setup.py	Fri Sep 17 19:43:15 2010 -0400
@@ -19,7 +19,7 @@
 
 setup(
     name='TracXMLRPC',
-    version='1.1.0',
+    version='1.1.1',
     license='BSD',
     author='Alec Thomas',
     author_email='alec@swapoff.org',
diff -r fa00f1619d65 trunk/tracrpc/api.py
--- a/trunk/tracrpc/api.py	Fri May 21 12:35:35 2010 +0200
+++ b/trunk/tracrpc/api.py	Fri Sep 17 19:43:15 2010 -0400
@@ -98,6 +98,7 @@
 
         method  (MANDATORY): target method name (e.g. 'ticket.get')
         params  (OPTIONAL) : a tuple containing input positional arguments
+        kwparams (OPTIONAL): a dictionary containing input keyword arguments
         headers (OPTIONAL) : if the protocol supports custom headers set 
                               by the client, then this value SHOULD be a 
                               dictionary binding `header name` to `value`. 
@@ -191,10 +192,11 @@
         self.namespace = provider.xmlrpc_namespace()
         self.namespace_description = inspect.getdoc(provider)
 
-    def __call__(self, req, args):
+    def __call__(self, req, args, kwargs=None):
         if self.permission:
             req.perm.assert_permission(self.permission)
-        result = self.callable(req, *args)
+        kwargs = kwargs or {}
+        result = self.callable(req, *args, **kwargs)
         # If result is null, return a zero
         if result is None:
             result = 0
diff -r fa00f1619d65 trunk/tracrpc/tests/api.py
--- a/trunk/tracrpc/tests/api.py	Fri May 21 12:35:35 2010 +0200
+++ b/trunk/tracrpc/tests/api.py	Fri Sep 17 19:43:15 2010 -0400
@@ -5,8 +5,9 @@
 (c) 2009      ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no)
 """
 
-import os
+import os.path
 import unittest
+import urllib
 import urllib2
 
 from tracrpc.tests import rpc_testenv, TracRpcTestCase
@@ -14,14 +15,21 @@
 from tracrpc.api import IRPCProtocol
 
 from trac.core import *
-from trac.test import Mock
 
 class ProtocolProviderTestCase(TracRpcTestCase):
 
     def setUp(self):
         TracRpcTestCase.setUp(self)
+        # Make a new plugin 
+        self.pluginfile = os.path.join(rpc_testenv.tracdir, 'plugins', 'DummyProvider.py')
 
     def tearDown(self):
+        if os.path.exists(self.pluginfile):
+            # Clean up so that provider don't affect further tests
+            os.unlink(self.pluginfile)
+            rpc_testenv.restart()
+        # Release some memory ???
+        self.pluginfile = None 
         TracRpcTestCase.tearDown(self)
 
     def test_invalid_content_type(self):
@@ -47,9 +55,7 @@
             self.fail("Expected urllib2.HTTPError")
         except urllib2.HTTPError, e:
             self.assertEquals(e.code, 415)
-        # Make a new plugin 
-        provider = os.path.join(rpc_testenv.tracdir, 'plugins', 'DummyProvider.py')
-        open(provider, 'w').write(
+        open(self.pluginfile, 'w').write(
             "from trac.core import *\n"
             "from tracrpc.api import *\n"
             "class DummyProvider(Component):\n"
@@ -70,23 +76,75 @@
             "        response = 'Got a result!'\n"
             "        req.send(response, rpcreq['mimetype'], 200)\n")
         rpc_testenv.restart()
+        req = urllib2.Request(rpc_testenv.url_anon,
+                    headers={'Content-Type': 'application/x-tracrpc-test'})
+        resp = urllib2.urlopen(req)
+        self.assertEquals(200, resp.code)
+        self.assertEquals("Got a result!", resp.read())
+        self.assertEquals(resp.headers['Content-Type'],
+                              'application/x-tracrpc-test;charset=utf-8')
+
+    def test_valid_kwargs(self):
+        # Confirm the request won't work before adding plugin
+        req = urllib2.Request(rpc_testenv.url_anon,
+                        headers={'Content-Type': 'application/x-tracrpc-test'},
+                        data="Fail! No RPC for application/x-tracrpc-test")
         try:
-            req = urllib2.Request(rpc_testenv.url_anon,
-                        headers={'Content-Type': 'application/x-tracrpc-test'})
             resp = urllib2.urlopen(req)
-            self.assertEquals(200, resp.code)
-            self.assertEquals("Got a result!", resp.read())
-            self.assertEquals(resp.headers['Content-Type'],
-                                  'application/x-tracrpc-test;charset=utf-8')
-        finally:
-            # Clean up so that provider don't affect further tests
-            os.unlink(provider)
-            rpc_testenv.restart()
+            self.fail("Expected urllib2.HTTPError")
+        except urllib2.HTTPError, e:
+            self.assertEquals(e.code, 415)
+        open(self.pluginfile, 'w').write(
+            "from trac.core import *\n"
+            "from trac.web.api import IRequestFilter\n"
+            "from tracrpc.api import *\n"
+            "from tracrpc.web_ui import *\n"
+            "class DummyProvider(Component):\n"
+            "    implements(IRPCProtocol, IRequestFilter)\n"
+            "    def pre_process_request(self, req, handler):\n"
+            "        if handler is RPCWeb(self.env) :\n"
+            "            # Avoid XSRF check \n"
+            "            self.log.debug('Tweaking XSRF protection')\n"
+            "            req.args['__FORM_TOKEN'] = req.form_token\n"
+            "            req.incookie['trac_form_token'] = "
+            "                             req.outcookie['trac_form_token']\n"
+            "        return handler\n"
+            "    def post_process_request(self, req, template, "
+            "                             data, content_type):\n"
+            "        return template, data, content_type\n"
+            "    def rpc_info(self):\n"
+            "        return ('TEST-RPC', 'No Docs!')\n"
+            "    def rpc_match(self):\n"
+            "        yield ('rpc', 'application/x-www-form-urlencoded')\n"
+            "        yield ('rpc', 'application/x-tracrpc-test')\n"
+            "    def parse_rpc_request(self, req, content_type):\n"
+            "        return dict(method=req.args.pop('_function', None),"
+            "                    kwparams=dict([k, v] "
+            "                                   for k,v in req.args.items()"
+            "                                   if k[0] != '_'))\n"
+            "    def send_rpc_error(self, req, e):\n"
+            "        rpcreq = req.rpc\n"
+            "        req.send_error(None, template='', content_type=rpcreq['mimetype'],\n"
+            "                       status=500, env=None, data='Test failure ')\n"
+            "    def send_rpc_result(self, req, result):\n"
+            "        rpcreq = req.rpc\n"
+            "        response = 'Got a result!'\n"
+            "        req.send(response, 'text/plain', 200)\n")
+        rpc_testenv.restart()
+        req = urllib2.Request(rpc_testenv.url_anon,
+                    headers={'Content-Type': 'application/x-www-form-urlencoded'},
+                    data=urllib.urlencode(
+                            {'_function' : 'system.methodHelp',
+                            'method' : 'system.methodHelp',})
+                    )
+        resp = urllib2.urlopen(req)
+        self.assertEquals(200, resp.code)
+        self.assertEquals("Got a result!", resp.read())
+        self.assertEquals(resp.headers['Content-Type'],
+                              'text/plain;charset=utf-8')
 
     def test_general_provider_error(self):
-        # Make a new plugin and restart server
-        provider = os.path.join(rpc_testenv.tracdir, 'plugins', 'DummyProvider.py')
-        open(provider, 'w').write(
+        open(self.pluginfile, 'w').write(
             "from trac.core import *\n"
             "from tracrpc.api import *\n"
             "class DummyProvider(Component):\n"
@@ -118,10 +176,6 @@
             self.assertEquals(500, e.code)
             self.assertEquals("No good.", e.fp.read())
             self.assertTrue(e.hdrs['Content-Type'].startswith('text/plain'))
-        finally:
-            # Clean up so that provider don't affect further tests
-            os.unlink(provider)
-            rpc_testenv.restart()
 
 def test_suite():
     return unittest.makeSuite(ProtocolProviderTestCase)
diff -r fa00f1619d65 trunk/tracrpc/web_ui.py
--- a/trunk/tracrpc/web_ui.py	Fri May 21 12:35:35 2010 +0200
+++ b/trunk/tracrpc/web_ui.py	Fri Sep 17 19:43:15 2010 -0400
@@ -54,13 +54,16 @@
                 if req.path_info in ['/%s' % p_path, '/login/%s' % p_path]:
                     must_handle_request = True
                     if content_type.startswith(p_type):
-                        req.args['protocol'] = protocol
+                        req.rpc = {'protocol' : protocol}
                         return True
         # No protocol call, need to handle for docs or error if handled path
         return must_handle_request
 
     def process_request(self, req):
-        protocol = req.args.get('protocol', None)
+        try :
+            protocol = req.rpc['protocol']
+        except AttributeError :
+            protocol = None
         content_type = req.get_header('Content-Type') or 'text/html'
         if protocol:
             # Perform the method call
@@ -151,10 +154,11 @@
             if method_name is None :
                 raise ProtocolException('Missing method name')
             args = rpcreq.get('params') or []
+            kwargs = rpcreq.get('kwparams') or {}
             self.log.debug("RPC(%s) call by '%s' %s", proto_id, \
                                               req.authname, method_name)
             try :
-                result = (XMLRPCSystem(self.env).get_method(method_name)(req, args))[0]
+                result = (XMLRPCSystem(self.env).get_method(method_name)(req, args, kwargs))[0]
                 if isinstance(result, GeneratorType):
                     result = list(result)
             except (RPCError, PermissionError, ResourceNotFound), e:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.