def bytes_in_uni_out(self, in_string): """ This test is desigened to take input that consists of characters contained in the latin-1 (iso-8859-1) character set. The incomming bytes are mirrored back to the client. Inside the method we test that the incomming encoding is endeed correct. @param in_string: The input string that will be mirrored back to the client. """ # check type if type(in_string) != PORTABLE_BYTES: if sys.version_info[0] >= 3: return 'wrong_type' else: return PORTABLE_STRING('wrong_type', 'utf-8') # Test that the incomming bytes are correct encoded try: in_str = in_string.decode('latin-1') except: if sys.version_info[0] >= 3: return 'wrong_encoding' else: return PORTABLE_STRING('wrong_encoding', 'utf-8') if sys.version_info[0] >= 3: in_str += 'æøåÆØÅß' else: in_str += PORTABLE_STRING('æøåÆØÅß', 'utf-8') return in_str
def parse_constant(x): if x == 'false': return PORTABLE_STRING("False") elif x == 'true': return PORTABLE_STRING("True") elif x == 'null': return PORTABLE_STRING("None") return PORTABLE_STRING(x)
def to_unicode_string(self, val, expected_typ, prefilters=None, postfilters=None, attr_name=None): """Convert a primitive type to unicode. The method uses TypeConverter options in the decition making, and encoding. """ # Run outgoing filters aka. outgoing prefilters if prefilters: for func in prefilters: val = func(val) typ = type(val) # Expecting unicode or raw string if expected_typ in [PORTABLE_BYTES, PORTABLE_STRING]: # No unsafe conversion can enter here as long as the user's service method obeys # the internal encoding it advertises for raw strings (aka bytes in python 3) if typ == PORTABLE_STRING: pass elif typ == PORTABLE_BYTES: val = PORTABLE_STRING(val, self.encoding) else: val = PORTABLE_STRING(val) # Run outgoing_raw filters aka. outgoing postfilters if postfilters: for func in postfilters: val = func(val) return val if not self.allow_unsafe_conversion: # Check if the conversion is unsafe if expected_typ not in safe_conversions[typ]: raise UnsafeConversionDisabled(typ, expected_typ, attr_name=attr_name) try: val = expected_typ(val) except Exception as e: raise UnsafeConversionError(typ, expected_typ, str(e), attr_name=attr_name) if self.only_strings_to_unicode: pass else: if expected_typ == bool: val = PORTABLE_STRING(val).lower() val = PORTABLE_STRING(val) # Run outgoing_raw filters aka. outgoing postfilters if postfilters: for func in postfilters: val = func(val) return val
def from_unicode_string(self, val, typ, prefilters=None, postfilters=None, attr_name=None): """Convert a unicode string to certain types. """ # Run incoming_raw filters aka. incoming prefilters if prefilters: for func in prefilters: val = func(val) vtyp = type(val) # The following fix (accepting booleans) has been added because # keyword parameter parse_constant of json.loads has changed to # not react on true/false (http://bugs.python.org/issue14692) if vtyp == bool and typ == bool: val = PORTABLE_STRING(val) vtyp = PORTABLE_STRING # Check the value type if not vtyp == PORTABLE_STRING: raise NonUnicodeError(type(val), attr_name=attr_name) # unicode to unicode or raw string if typ in [PORTABLE_BYTES, PORTABLE_STRING]: if typ == PORTABLE_BYTES: val = val.encode(self.encoding) # Run incoming filters aka. incoming postfilters if postfilters: for func in postfilters: val = func(val) return val # other primitive types try: if typ == bool and (val[0].upper() == PORTABLE_STRING('F') or val.strip() == '0'): val = False else: val = typ(val) # Run incoming filters aka. incoming postfilters if postfilters: for func in postfilters: val = func(val) return val except Exception as e: raise FromUnicodeConversionError(typ, str(e), attr_name=attr_name)
def parse_response(self, response): headers = dict((k.upper(), v) for k, v in response.getheaders()) jsonwsp_response = JSONWSPResponse(response.status, response.reason, headers) jsonwsp_charset = probe_charset(jsonwsp_response.headers) content_type = response.getheader('content-type') content_type = content_type.replace('\n', '') multipart_match = rx_detect_multipart.findall(content_type) if len(multipart_match): multipart = multipart_match[0] boundary_match = rx_detect_boundary.findall(content_type) if len(boundary_match): boundary = boundary_match[0] mpr = MultiPartReader(20000, boundary.encode(jsonwsp_charset), response) mpr.read_chunk() while not mpr.eos: mpr.read_chunk() for cid, cinfo in mpr.attachments_by_id.items(): jsonwsp_response.attachments[PORTABLE_STRING( cid, jsonwsp_charset)] = attachment( open(cinfo['path'], 'rb'), cinfo['size'], cinfo['headers'], jsonwsp_charset) resdata = mpr.interface_request jsonwsp_response.response_body = resdata else: resdata = response.read() jsonwsp_response.response_body = resdata return jsonwsp_response
def call_method(self, method_name, **kw): attachment_map = {'cid_seq': 1, 'files': {}} extra_headers = None if 'extra_headers' in kw: extra_headers = kw['extra_headers'] walk_args_dict(kw, attachment_map) if self.description_loaded: minfo = self.method_info(method_name) mandatory_params = list(minfo['mandatory_params']) optional_params = list(minfo['optional_params']) for arg in kw.keys(): if arg in mandatory_params: mandatory_params.remove(arg) if len(mandatory_params): return -1 data = {'methodname': method_name} if 'mirror' in kw: data['mirror'] = kw.pop('mirror') data['args'] = kw if len(attachment_map['files']): jsonwsp_response = self.post_mp_request( json.dumps(data), attachment_map['files'], extra_headers=extra_headers) else: jsonwsp_response = self.post_request(json.dumps(data), extra_headers=extra_headers) if jsonwsp_response.status == 200: response_charset = probe_charset(jsonwsp_response.headers) jsonwsp_response.response_dict = json.loads( PORTABLE_STRING(jsonwsp_response.response_body, response_charset)) jsonwsp_response.walk_result_dict() return jsonwsp_response
def from_unicode_string(self, val, typ, prefilters=None, postfilters=None): """Convert a unicode string to certain types. """ # Run incoming_raw filters aka. incoming prefilters if prefilters: for func in prefilters: val = func(val) # Check the value type if not type(val) == PORTABLE_STRING: raise NonUnicodeError(type(val)) # unicode to unicode or raw string if typ in [PORTABLE_BYTES, PORTABLE_STRING]: if typ == PORTABLE_BYTES: val = val.encode(self.encoding) # Run incoming filters aka. incoming postfilters if postfilters: for func in postfilters: val = func(val) return val # other primitive types try: if typ == bool and (val[0].upper() == PORTABLE_STRING('F') or val.strip() == '0'): val = False else: val = typ(val) # Run incoming filters aka. incoming postfilters if postfilters: for func in postfilters: val = func(val) return val except Exception as e: raise FromUnicodeConversionError(typ, str(e))
def blameClientFault(self,search_frase=PORTABLE_STRING('')): # In this method I raise a client fault from within a method invokation. # This meens that the client sent a request that has the correct signature # in regards to methodname and argument types. Instead it could be that the # combination of arguments does not make any logical sense. In this type of # situation it is sometimes preferred to send a client fault raise ClientFault('Arguments parsed to method makes no sense')
def str_to_portable_string(in_str): """ Assumes that we always use UTF-8 encoding in script files """ if sys.version_info[0] >= 3: return in_str else: return PORTABLE_STRING(in_str, 'utf-8')
def from_unicode_string(self,val,typ,prefilters=None,postfilters=None): """Convert a unicode string to certain types. """ # Run incoming_raw filters aka. incoming prefilters if prefilters: for func in prefilters: val = func(val) vtyp = type(val) # The following fix (accepting booleans) has been added because # keyword parameter parse_constant of json.loads has changed to # not react on true/false (http://bugs.python.org/issue14692) if vtyp==bool and typ==bool: val = PORTABLE_STRING(val) vtyp = PORTABLE_STRING # Check the value type if not vtyp==PORTABLE_STRING: raise NonUnicodeError(type(val)) # unicode to unicode or raw string if typ in [PORTABLE_BYTES,PORTABLE_STRING]: if typ==PORTABLE_BYTES: val = val.encode(self.encoding) # Run incoming filters aka. incoming postfilters if postfilters: for func in postfilters: val = func(val) return val # other primitive types try: if typ==bool and (val[0].upper()==PORTABLE_STRING('F') or val.strip()=='0'): val = False else: val = typ(val) # Run incoming filters aka. incoming postfilters if postfilters: for func in postfilters: val = func(val) return val except Exception as e: raise FromUnicodeConversionError(typ,str(e))
def test_get_bytes(self): req = {'method':'return_bytes','params':None,'id':0} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) expected_result = 'Yo!!!' self.assertEqual(res['result'], expected_result)
def test_passback_bytes(self): val = 'Yo!!!' req = {'method':'passback_bytes','params':[val],'id':0} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertEqual(res['result'], val)
def parse_description(self): jsonwsp_response = self.post_request("", "", via_proxy=self.via_proxy) response_charset = probe_charset(jsonwsp_response.headers) self.jsonwsp_description = json.loads( PORTABLE_STRING(jsonwsp_response.response_body, response_charset)) self.parse_url(self.jsonwsp_description['url']) for method_name in self.jsonwsp_description['methods'].keys(): exec( "def placeholder(self,**kw):\n\treturn self.call_method('%s',**kw)" % method_name) exec("self.%s = types.MethodType(placeholder,self)" % method_name) self.description_loaded = True
def listBands(self, search_frase=PORTABLE_STRING('')): """ Fetch a list of albums matching search_frase """ global albums bands = [] for band_name, albums_dict in albums.items(): if len(search_frase) == 0 or band_name.find(search_frase) > -1: b = Band() b.name = band_name b.album_titles = [] for album_title, songs in albums_dict.items(): b.album_titles += [album_title] bands += [b] return bands
def uni_in_bytes_out(self, in_string): """ This test is desigened to take unicode string input. The incomming string is mirrored back to the client as bytes in latin-1 encoding. Inside the method we test that the incomming string is unicode. @param in_string: The input string that will be mirrored back to the client. """ # check type if type(in_string) != PORTABLE_STRING: return b'wrong_type' if sys.version_info[0] >= 3: in_string += 'æøåÆØÅß' else: in_string += PORTABLE_STRING('æøåÆØÅß', 'utf-8') return in_string.encode('latin-1')
def parse_request(self, json_body, sinfo, encoding): def parse_number(x): return PORTABLE_STRING(x) def parse_constant(x): if x == 'false': return PORTABLE_STRING("False") elif x == 'true': return PORTABLE_STRING("True") elif x == 'null': return PORTABLE_STRING("None") return PORTABLE_STRING(x) req_dict = json.loads(PORTABLE_STRING(json_body, encoding), parse_int=parse_number, parse_float=parse_number, parse_constant=parse_constant) return req_dict
def listAlbums(self,search_frase=PORTABLE_STRING('')): """ Fetch a list of albums matching search_frase """ global albums album_list = [] for band_name,albums_dict in albums.items(): b = Band() b.name = band_name b.album_titles = [] for album_title,songs in albums_dict.items(): b.album_titles += [ album_title ] if len(search_frase)==0 or album_title.find(search_frase)>-1: a = Album() a.band = b a.title = album_title a.songs = [ ] for idx,song_title in songs: a.songs += [song_title] album_list += [a] return album_list
def parse_request(self, json_body, sinfo, encoding): def parse_number(x): return PORTABLE_STRING(x) def parse_constant(x): if x == 'null': return PORTABLE_STRING("None") return PORTABLE_STRING(x) req_dict = json.loads(PORTABLE_STRING(json_body,encoding), parse_int=parse_number, parse_float=parse_number, \ parse_constant=parse_constant) passback_dict = self.get_passback_params(req_dict) if 'method' not in req_dict: raise RequestPropFault('method', passback_dict) if 'params' not in req_dict: raise RequestPropFault('params', passback_dict) if 'id' not in req_dict: raise RequestPropFault('id', passback_dict) minfo = sinfo.methods[req_dict['method']] params = req_dict['params'] if params is not None and type(params) is not list: raise RequestParamsArrayFault(passback_dict) params_len = len(params) if params is not None else 0 args_len = len(minfo.args()) if params_len == 0 and args_len > 0: raise RequestParamFault(minfo.args()[0]['name'], passback_dict) elif params_len < args_len: raise RequestParamFault(minfo.args()[params_len]['name'], passback_dict) elif params_len > args_len: raise MethodArgsCountFault(req_dict['method'], args_len, params_len, passback_dict) req_dict['args'] = {} if params is not None: for i in range(len(params)): req_dict['args'][minfo.args()[i]['name']] = params[i] req_dict['methodname'] = req_dict['method'] del req_dict['params'] del req_dict['method'] return req_dict
def string_integrety_tests_json(self, methodname): fp_req = open('data/stringtests/in_out_test.json', 'rb') req = PORTABLE_STRING(fp_req.read(), 'utf-8') fp_req.close() req = json.loads(req) req['methodname'] = methodname req = json.dumps(req) # utf-8 encoded request to bytesEncodingTest status, reason, resdata = self.post_helper.post_request( req.encode('utf-8'), encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata, 'utf-8')) expected_result = str_to_portable_string('äöüÄÖÄæøåÆØÅß') self.assertEqual(res['result'], expected_result) # latin-1 encoded request to bytesEncodingTest status, reason, resdata = self.post_helper.post_request( req.encode('latin-1'), encoding='latin-1') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata, 'latin-1')) self.assertEqual(res['result'], expected_result)
def getHostName(self): return PORTABLE_STRING(socket.gethostname())
def parse_number(x): return PORTABLE_STRING(x)
from ladon.compat import PORTABLE_STRING catalog_default_template = PORTABLE_STRING(""" <!DOCTYPE html> <html> <head> <meta content="text/html; charset={{ charset }}" http-equiv="Content-Type" /> <title>{{ catalog_name }}</title> <style> {{ css }} {{ extra_css }} </style> </head> <body> <div class="catName">{{ catalog_name }}</div> <div class="catDesc">{{ catalog_desc }}</div> <div class="catContent"> <ul class="catService"> {% for service in services %} <li> <b><a href="{{ client_path }}/{{ service.servicename }}{{ '?' if query_string }}{{query_string}}">{{ service.servicename }}</a></b><br/> {{ service.doc }} </li> {% endfor %} </ul> </div> <div class="catGen">Powered by Ladon for Python</div> </body> </html> """) service_default_template = PORTABLE_STRING("""
def createServerFault(self,search_frase=PORTABLE_STRING('')): # A problem occurred on the server-side while invoking a method. Signal # this back to the client as a server fault. raise ServerFault('Server problem occured while executing method')
def u(instring): if sys.version_info[0] == 2: return PORTABLE_STRING(instring, 'utf-8') else: return PORTABLE_STRING(instring)
# -*- coding: utf-8 -*- from ladon.interfaces.base import BaseInterface, ServiceDescriptor, BaseRequestHandler, BaseResponseHandler, BaseFaultHandler from ladon.interfaces import expose from ladon.compat import PORTABLE_STRING, type_to_xsd, pytype_support, BytesIO from xml.sax.handler import ContentHandler, feature_namespaces from xml.sax import make_parser from xml.sax.xmlreader import InputSource import sys, re, traceback rx_nil_attr = re.compile(PORTABLE_STRING('^\w*[:]{0,1}nil$'), re.I) class SOAP11ServiceDescriptor(ServiceDescriptor): xsd_type_map = type_to_xsd _content_type = 'text/xml' def generate(self, servicename, servicenumber, typemanager, methodlist, service_url, encoding, **kw): """ Generate WSDL file for SOAP11Interface """ type_dict = typemanager.type_dict type_order = typemanager.type_order def map_type(typ): if typ in SOAP11ServiceDescriptor.xsd_type_map: return SOAP11ServiceDescriptor.xsd_type_map[typ] else: return typ.__name__
def getCharacters(nodelist): raw = PORTABLE_STRING() for n in nodelist: if n.nodeType == n.TEXT_NODE: raw += n.data return raw
def test_validate_request_response_structure(self): req = {} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(type(res['error']), dict) self.assertTrue('id' is not res) self.assertIs(res['result'], None) self.assertTrue('"method"' in res['error']['string']) req = {'method':'passback_string'} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(type(res['error']), dict) self.assertTrue('id' is not res) self.assertIs(res['result'], None) self.assertTrue('"params"' in res['error']['string']) req = {'method':'passback_string','params':None} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(type(res['error']), dict) self.assertTrue('id' is not res) self.assertIs(res['result'], None) self.assertTrue('"id"' in res['error']['string']) req = {'method':'passback_string','params':None,'id':0} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(type(res['error']), dict) self.assertEqual(res['id'], '0') self.assertIs(res['result'], None) req = {'method':'passback_string','params':None,'id':'0'} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(type(res['error']), dict) self.assertEqual(res['id'], '0') self.assertIs(res['result'], None) req = {'method':'passback_string','params':['Yo!!!'],'id':0} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(res['error'], None) self.assertEqual(res['id'], '0') self.assertEqual(res['result'], 'Yo!!!') req = {'method':'params','params':[],'id':0} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(type(res['error']), dict) self.assertEqual(res['id'], '0') self.assertTrue('"arg0"' in res['error']['string']) req = {'method':'params','params':[11],'id':0} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(type(res['error']), dict) self.assertEqual(res['id'], '0') self.assertTrue('"arg1"' in res['error']['string']) req = {'method':'params','params':[11, 11.11],'id':0} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(type(res['error']), dict) self.assertEqual(res['id'], '0') self.assertTrue('"arg2"' in res['error']['string']) req = {'method':'params','params':[11,11.11,'Yo!!!','Yo!!!'],'id':0} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(type(res['error']), dict) self.assertEqual(res['id'], '0') self.assertTrue('3' in res['error']['string']) self.assertTrue('4' in res['error']['string']) req = {'method':'params','params':{},'id':0} jreq = json.dumps(req) status,reason,resdata = self.post_helper.post_request(jreq.encode('utf-8'),extra_path='jsonrpc10',encoding='utf-8') self.assertEqual(status, 200) res = json.loads(PORTABLE_STRING(resdata,'utf-8')) self.assertIs(type(res['error']), dict) self.assertEqual(res['id'], '0') self.assertTrue('Params must be array of objects.' == res['error']['string'])
from ladon.compat import PORTABLE_STRING catalog_default_template = PORTABLE_STRING(""" <!DOCTYPE html> <html> <head> <meta content="text/html; charset={{ charset }}" http-equiv="Content-Type" /> <title>{{ catalog_name }}</title> <style> {{ css }} {{ extra_css }} </style> </head> <body> <div class="catName">{{ catalog_name }}</div> <div class="catDesc">{{ catalog_desc }}</div> <div class="catContent"> <ul class="catService"> {% for service in services %} <li> <b><a href="{{ service.servicename }}/{{ '?' if query_string }}{{query_string}}">{{ service.servicename }}</a></b><br/> {{ service.doc }} </li> {% endfor %} </ul> </div> <div class="catGen">Powered by Ladon for Python</div> </body> </html> """) service_default_template = PORTABLE_STRING("""
def parse_constant(x): if x == 'null': return PORTABLE_STRING("None") return PORTABLE_STRING(x)