Commits

Olemis Lang  committed 4e22892

BH RPC : Patch jsonrpclib.jsonclass.load to support Trac JSON-RPC datetime object deserialization ( __jsonclass__ ) in test cases

  • Participants
  • Parent commits 4a5a84f

Comments (0)

Files changed (2)

File trunk/tracrpc/tests/__init__.py

         @staticmethod
         def tester_class(baseurl):
             # FIXME: Parameterize test runs to activate JSON-RPC
-            #return DefaultJsonRpcTester(baseurl, skiplogin=True)
-            return DefaultXmlRpcTester(baseurl, skiplogin=True)
+            return DefaultJsonRpcTester(baseurl, skiplogin=True)
+            #return DefaultXmlRpcTester(baseurl, skiplogin=True)
 
         def testenv_path(self, port=None):
             if port is None:

File trunk/tracrpc/tests/_jsonrpclib.py

 (c) 2013      ::: Olemis Lang (olemis+trac@gmail.com)
 """
 
+import datetime
+import re
 import types
 import xmlrpclib
 import jsonrpclib.jsonrpc
+from jsonrpclib import jsonclass
+
+from tracrpc.api import Binary
+
+strptime = datetime.datetime.strptime
 
 #--------------------------------------------------
-#   jsonrpclib compatibility upgrade
+#   jsonrpclib - custom types
+#--------------------------------------------------
+
+config = jsonrpclib.config
+
+def datetime(rfc3339str):
+    """Factory method for JSON-RPC datetime values
+    """
+    return strptime(rfc3339str, '%Y-%m-%dT%H:%M:%S')
+
+def binary(base64str):
+    """Factory method for JSON-RPC binary values
+    """
+    return Binary(base64str.decode("base64"))
+
+config.classes.add(datetime)
+config.classes.add(binary)
+
+#--------------------------------------------------
+#   jsonrpclib - compatibility upgrade
 #--------------------------------------------------
 
 def isbatch(result):
         raise xmlrpclib.Fault(code, message)
     return result
 
+def load(obj):
+    if type(obj) in (jsonclass.string_types + jsonclass.numeric_types + 
+                     jsonclass.value_types):
+        return obj
+    if type(obj) is types.ListType:
+        return [load(entry) for entry in obj]
+    # Othewise, it's a dict type
+    if '__jsonclass__' not in obj:
+        return dict([key, load(value)] for key, value in obj.iteritems())
+    # It's a dict, and it's a __jsonclass__
+    orig_module_name = obj['__jsonclass__'][0]
+    params = obj['__jsonclass__'][1]
+    if orig_module_name == '':
+        raise TranslationError('Module name empty.')
+    json_module_clean = re.sub(jsonclass.invalid_module_chars, '', 
+                               orig_module_name)
+    if json_module_clean != orig_module_name:
+        raise TranslationError('Module name %s has invalid characters.' %
+                               orig_module_name)
+    json_module_parts = json_module_clean.split('.')
+    json_class = None
+    if len(json_module_parts) == 1:
+        # Local class name -- probably means it won't work
+        if json_module_parts[0] not in config.classes.keys():
+            raise jsonclass.TranslationError('Unknown class or module %s.' %
+                                   json_module_parts[0])
+        json_class = config.classes[json_module_parts[0]]
+    else:
+        json_class_name = json_module_parts.pop()
+        json_module_tree = '.'.join(json_module_parts)
+        try:
+            temp_module = __import__(json_module_tree)
+        except ImportError:
+            raise jsonclass.TranslationError('Could not import %s from module %s.' %
+                                   (json_class_name, json_module_tree))
+        json_class = getattr(temp_module, json_class_name)
+    # Creating the object...
+    new_obj = None
+    if type(params) is types.ListType:
+        new_obj = json_class(*params)
+    elif type(params) is types.DictType:
+        new_obj = json_class(**params)
+    else:
+        #raise jsonclass.TranslationError('Constructor args must be a dict or list.')
+        # Supply single param
+        new_obj = json_class(params)
+    for key, value in obj.iteritems():
+        if key == '__jsonclass__':
+            continue
+        setattr(new_obj, key, value)
+    return new_obj
+
 jsonrpclib.jsonrpc.check_for_errors = check_for_errors
 jsonrpclib.jsonrpc.isbatch = isbatch
+jsonrpclib.jsonclass.load = load