def test_config_custom(self): """ Tests configured custom serializer """ # Get the current time object now = datetime.datetime.now() # Check if it is correctly serialized std_serialized = dump(now) self.assertEqual(std_serialized['__jsonclass__'][0], 'datetime.datetime') # Configure a custom serializer def datetime_serializer(obj, serialize_method, ignore_attribute, ignore, config): """ Custom datetime serializer (returns an ISO date string) """ self.assertIs(type(obj), datetime.datetime) return obj.isoformat() handlers = {datetime.datetime: datetime_serializer} config = jsonrpclib.config.Config(serialize_handlers=handlers) # Dump with out configuration custom_serialized = dump(now, config=config) # This should be a raw string self.assertEqual(custom_serialized, now.isoformat())
def test_config_custom(self): """ Tests configured custom serializer """ # Get the current time object now = datetime.datetime.now() # Check if it is correctly serialized std_serialized = dump(now) self.assertEqual( std_serialized["__jsonclass__"][0], "datetime.datetime" ) # Configure a custom serializer def datetime_serializer( obj, serialize_method, ignore_attribute, ignore, config ): """ Custom datetime serializer (returns an ISO date string) """ self.assertIs(type(obj), datetime.datetime) return obj.isoformat() handlers = {datetime.datetime: datetime_serializer} config = jsonrpclib.config.Config(serialize_handlers=handlers) # Dump with out configuration custom_serialized = dump(now, config=config) # This should be a raw string self.assertEqual(custom_serialized, now.isoformat())
def test_iterable(self): """ Tests dump & load of iterable types """ tuple_values = (42, 42.12, "string", True, False, None) list_values = list(tuple_values) set_values = set(tuple_values) frozen_values = frozenset(tuple_values) for iterable in (tuple_values, list_values, set_values, frozen_values): # Dump... serialized = dump(iterable) # Reload... deserialized = load(serialized) self.assertIs( type(serialized), list, "Dumped iterable should be a list" ) self.assertIs( type(deserialized), list, "Loaded iterable should be a list" ) # Check content self.assertCountEqual( deserialized, tuple_values, "Values order changed" )
def test_primitive(self): """ Tests dump & load of primitive types """ for value in (42, 42.12, "string", True, False, None): # Dump.. serialized = dump(value) # Reload... deserialized = load(serialized) self.assertIs( type(serialized), type(value), "Type changed during serialization", ) self.assertIs( type(deserialized), type(value), "Type changed during deserialization", ) self.assertEqual( serialized, value, "Value changed during serialization" ) self.assertEqual( deserialized, value, "Value changed during deserialization" )
def dump(params=[], methodname=None, rpcid=None, version=None, is_response=None, is_notify=None, config=jsonrpclib.config.DEFAULT): """ Prepares a JSON-RPC dictionary (request, notification, response or error) :param params: Method parameters (if a method name is given) or a Fault :param methodname: Method name :param rpcid: Request ID :param version: JSON-RPC version :param is_response: If True, this is a response dictionary :param is_notify: If True, this is a notification request :param config: A JSONRPClib Config instance :return: A JSON-RPC dictionary """ # Default version if not version: version = config.version # Validate method name and parameters valid_params = (utils.TupleType, utils.ListType, utils.DictType, Fault) if methodname in utils.StringTypes and \ not isinstance(params, valid_params): """ If a method, and params are not in a listish or a Fault, error out. """ raise TypeError('Params must be a dict, list, tuple or Fault instance.') # Prepares the JSON-RPC content payload = Payload(rpcid=rpcid, version=version) if type(params) is Fault: # Prepare an error dictionary return payload.error(params.faultCode, params.faultString) if type(methodname) not in utils.StringTypes and not is_response: # Neither a request nor a response raise ValueError('Method name must be a string, or is_response ' \ 'must be set to True.') if config.use_jsonclass: # Use jsonclass to convert the parameters params = jsonclass.dump(params) if is_response: # Prepare a response dictionary if rpcid is None: # A response must have a request ID raise ValueError('A method response must have an rpcid.') return payload.response(params) if is_notify: # Prepare a notification dictionary return payload.notify(methodname, params) else: # Prepare a method call dictionary return payload.request(methodname, params)
def test_object(self): """ Tests dump & load of a custom type """ types = { Bean: ("public", "_protected", "_Bean__private"), InheritanceBean: ("public", "_protected", "first", "_second"), SlotBean: ("public", "_protected"), InheritanceSlotBean: ("public", "_protected", "first", "_second"), SecondInheritanceSlotBean: ( "public", "_protected", "first", "_second", "third", "_fourth", ), } for clazz, fields in types.items(): # Prepare the bean data = clazz() # Dump it... serialized = dump(data) # Check serialized content self.assertIn("__jsonclass__", serialized) for field in fields: self.assertIn(field, serialized) # Check class name self.assertEqual( serialized["__jsonclass__"][0], "{0}.{1}".format(clazz.__module__, clazz.__name__), ) # Reload it deserialized = load(serialized) # Dictionary is left as-is self.assertIn( "__jsonclass__", serialized, "Serialized dictionary has been modified", ) self.assertFalse( hasattr(deserialized, "__jsonclass__"), "The deserialized bean shouldn't have a " "__jsonclass__ attribute", ) # Check deserialized value self.assertIs(type(deserialized), type(data)) self.assertEqual( deserialized, data, "Source and deserialized bean are not equal" )
def test_enum(self): """ Tests the serialization of enumerations """ if enum is None: self.skipTest("enum package not available.") for data in (Color.BLUE, Color.RED): # Serialization enum_serialized = dump(data) self.assertIn(Color.__name__, enum_serialized["__jsonclass__"][0]) self.assertEqual(data.value, enum_serialized["__jsonclass__"][1][0]) # Loading result = load(enum_serialized) self.assertEqual(data, result) # Embedded data = [Color.BLUE, Color.RED] serialized = dump(data) result = load(serialized) self.assertListEqual(data, result)
def dumps(params=[], methodname=None, methodresponse=None, encoding=None, rpcid=None, version=None, notify=None): """ This differs from the Python implementation in that it implements the rpcid argument since the 2.0 spec requires it for responses. """ if not version: version = config.version valid_params = (types.TupleType, types.ListType, types.DictType) if methodname in types.StringTypes and \ type(params) not in valid_params and \ not isinstance(params, Fault): """ If a method, and params are not in a listish or a Fault, error out. """ raise TypeError('Params must be a dict, list, tuple or Fault ' + 'instance.') # Begin parsing object payload = Payload(rpcid=rpcid, version=version) if not encoding: encoding = 'utf-8' if type(params) is Fault: response = payload.error(params.faultCode, params.faultString) return jdumps(response, encoding=encoding) if type(methodname) not in types.StringTypes and \ methodresponse is not True: raise ValueError( 'Method name must be a string, or methodresponse must ' 'be set to True.') if config.use_jsonclass is True: from jsonrpclib import jsonclass params = jsonclass.dump(params) if methodresponse is True: if rpcid is None: raise ValueError('A method response must have an rpcid.') response = payload.response(params) return jdumps(response, encoding=encoding) request = None if notify is True: request = payload.notify(methodname, params) else: request = payload.request(methodname, params) return jdumps(request, encoding=encoding)
def test_enum(self): """ Tests the serialization of enumerations """ if enum is None: self.skipTest("enum package not available.") for data in (Color.BLUE, Color.RED): # Serialization enum_serialized = dump(data) self.assertIn( Color.__name__, enum_serialized['__jsonclass__'][0]) self.assertEqual( data.value, enum_serialized['__jsonclass__'][1][0]) # Loading result = load(enum_serialized) self.assertEqual(data, result) # Embedded data = [Color.BLUE, Color.RED] serialized = dump(data) result = load(serialized) self.assertListEqual(data, result)
def dumps( params=[], methodname=None, methodresponse=None, encoding=None, rpcid=None, version=None, notify=None): """ This differs from the Python implementation in that it implements the rpcid argument since the 2.0 spec requires it for responses. """ if not version: version = config.version valid_params = (tuple, list, dict) if methodname in types.StringTypes and \ type(params) not in valid_params and \ not isinstance(params, Fault): """ If a method, and params are not in a listish or a Fault, error out. """ raise TypeError('Params must be a dict, list, tuple or Fault ' + 'instance.') # Begin parsing object payload = Payload(rpcid=rpcid, version=version) if not encoding: encoding = 'utf-8' if type(params) is Fault: response = payload.error(params.faultCode, params.faultString) return jdumps(response, encoding=encoding) if type(methodname) not in types.StringTypes and \ methodresponse is not True: raise ValueError( 'Method name must be a string, or methodresponse must ' 'be set to True.') if config.use_jsonclass is True: from jsonrpclib import jsonclass params = jsonclass.dump(params) if methodresponse is True: if rpcid is None: raise ValueError('A method response must have an rpcid.') response = payload.response(params) return jdumps(response, encoding=encoding) request = None if notify: request = payload.notify(methodname, params) else: request = payload.request(methodname, params) return jdumps(request, encoding=encoding)
def test_dictionary(self): """ Tests dump & load of dictionaries """ dictionary = {'int': 42, 'float': 42.2, None: "string", True: False, 42.1: None, 'dict': {"sub": 1}, "list": [1, 2, 3]} # Dump it serialized = dump(dictionary) # Reload it deserialized = load(serialized) self.assertDictEqual(deserialized, dictionary)
def test_object(self): """ Tests dump & load of a custom type """ types = {Bean: ('public', '_protected', '_Bean__private'), InheritanceBean: ('public', '_protected', 'first', '_second'), SlotBean: ('public', '_protected'), InheritanceSlotBean: ('public', '_protected', 'first', '_second'), SecondInheritanceSlotBean: ('public', '_protected', 'first', '_second', 'third', '_fourth'), } for clazz, fields in types.items(): # Prepare the bean data = clazz() # Dump it... serialized = dump(data) # Check serialized content self.assertIn('__jsonclass__', serialized) for field in fields: self.assertIn(field, serialized) # Check class name self.assertEqual(serialized['__jsonclass__'][0], '{0}.{1}'.format(clazz.__module__, clazz.__name__)) # Reload it deserialized = load(serialized) # Dictionary is left as-is self.assertIn('__jsonclass__', serialized, "Serialized dictionary has been modified") self.assertFalse(hasattr(deserialized, '__jsonclass__'), "The deserialized bean shouldn't have a " "__jsonclass__ attribute") # Check deserialized value self.assertIs(type(deserialized), type(data)) self.assertEqual(deserialized, data, "Source and deserialized bean are not equal")
def test_primitive(self): """ Tests dump & load of primitive types """ for value in (42, 42.12, "string", True, False, None): # Dump.. serialized = dump(value) # Reload... deserialized = load(serialized) self.assertIs(type(serialized), type(value), "Type changed during serialization") self.assertIs(type(deserialized), type(value), "Type changed during deserialization") self.assertEqual(serialized, value, "Value changed during serialization") self.assertEqual(deserialized, value, "Value changed during deserialization")
def test_dictionary(self): """ Tests dump & load of dictionaries """ dictionary = { "int": 42, "float": 42.2, None: "string", True: False, 42.1: None, "dict": {"sub": 1}, "list": [1, 2, 3], } # Dump it serialized = dump(dictionary) # Reload it deserialized = load(serialized) self.assertDictEqual(deserialized, dictionary)
def test_iterable(self): """ Tests dump & load of iterable types """ tuple_values = (42, 42.12, "string", True, False, None) list_values = list(tuple_values) set_values = set(tuple_values) frozen_values = frozenset(tuple_values) for iterable in (tuple_values, list_values, set_values, frozen_values): # Dump... serialized = dump(iterable) # Reload... deserialized = load(serialized) self.assertIs(type(serialized), list, "Dumped iterable should be a list") self.assertIs(type(deserialized), list, "Loaded iterable should be a list") # Check content self.assertCountEqual(deserialized, tuple_values, "Values order changed")
def dump(params=None, methodname=None, rpcid=None, version=None, is_response=None, is_notify=None, config=jsonrpclib.config.DEFAULT): """ Prepares a JSON-RPC dictionary (request, notification, response or error) :param params: Method parameters (if a method name is given) or a Fault :param methodname: Method name :param rpcid: Request ID :param version: JSON-RPC version :param is_response: If True, this is a response dictionary :param is_notify: If True, this is a notification request :param config: A JSONRPClib Config instance :return: A JSON-RPC dictionary """ # Default version if not version: version = config.version if not is_response and params is None: params = [] # Validate method name and parameters valid_params = [utils.TupleType, utils.ListType, utils.DictType, Fault] if is_response: valid_params.append(type(None)) if isinstance(methodname, utils.STRING_TYPES) and \ not isinstance(params, tuple(valid_params)): """ If a method, and params are not in a listish or a Fault, error out. """ raise TypeError("Params must be a dict, list, tuple " "or Fault instance.") # Prepares the JSON-RPC content payload = Payload(rpcid=rpcid, version=version) if isinstance(params, Fault): # Prepare an error dictionary # pylint: disable=E1103 return payload.error(params.faultCode, params.faultString, params.data) if not isinstance(methodname, utils.STRING_TYPES) and not is_response: # Neither a request nor a response raise ValueError('Method name must be a string, or is_response ' 'must be set to True.') if config.use_jsonclass: # Use jsonclass to convert the parameters params = jsonclass.dump(params, config=config) if is_response: # Prepare a response dictionary if rpcid is None: # A response must have a request ID raise ValueError('A method response must have an rpcid.') return payload.response(params) if is_notify: # Prepare a notification dictionary return payload.notify(methodname, params) else: # Prepare a method call dictionary return payload.request(methodname, params)