The tg1 adapter can now expose rest functions outside the WSRoot _and_ enable other other protocols. Soap is tested.

This commit is contained in:
Christophe de Vienne 2012-11-26 01:27:37 +01:00
parent ade5325e13
commit 39cc2ffc8f
3 changed files with 119 additions and 16 deletions

View File

@ -9,13 +9,21 @@ import unittest
import simplejson import simplejson
from wsmeext.soap.tests import test_soap
class WSController(WSRoot): class WSController(WSRoot):
pass pass
class Root(RootController): class Root(RootController):
ws = wsme.tg1.adapt( ws = WSController(webpath='/ws')
WSController(webpath='/ws', protocols=['restjson'])) ws.addprotocol(
'soap',
tns=test_soap.tns,
typenamespace=test_soap.typenamespace
)
ws = wsme.tg1.adapt(ws)
@wsexpose(int) @wsexpose(int)
@wsvalidate(int, int) @wsvalidate(int, int)
@ -50,9 +58,45 @@ class TestController(unittest.TestCase):
startup.stopTurboGears() startup.stopTurboGears()
config.update({"server_started": False}) config.update({"server_started": False})
def test_simplecall(self): def test_restcall(self):
response = self.app.post("/multiply", response = self.app.post("/multiply",
simplejson.dumps({'a': 5, 'b': 10}), simplejson.dumps({'a': 5, 'b': 10}),
{'Content-Type': 'application/json'}) {'Content-Type': 'application/json'}
)
print response print response
assert simplejson.loads(response.body) == 50 assert simplejson.loads(response.body) == 50
response = self.app.post("/multiply",
simplejson.dumps({'a': 5, 'b': 10}),
{'Content-Type': 'application/json', 'Accept': 'application/json'}
)
print response
assert simplejson.loads(response.body) == 50
response = self.app.post("/multiply",
simplejson.dumps({'a': 5, 'b': 10}),
{'Content-Type': 'application/json', 'Accept': 'text/javascript'}
)
print response
assert simplejson.loads(response.body) == 50
response = self.app.post("/multiply",
simplejson.dumps({'a': 5, 'b': 10}),
{'Content-Type': 'application/json',
'Accept': 'text/xml'}
)
print response
assert response.body == "<result>50</result>"
def test_soap_wsdl(self):
wsdl = self.app.get('/ws/api.wsdl').body
print wsdl
assert 'multiply' in wsdl
def test_soap_call(self):
ts = test_soap.TestSOAP('test_wsdl')
ts.app = self.app
ts.ws_path = '/ws'
print ts.ws_path
assert ts.call('multiply', a=5, b=10, _rt=int) == 50

View File

@ -48,11 +48,13 @@ commands=
[testenv:tg11] [testenv:tg11]
basepython=python2.5 basepython=python2.5
deps= deps=
d2to1
nose nose
webtest webtest
coverage coverage
simplejson simplejson
commands= commands=
{envbindir}/easy_install https://bitbucket.org/cdevienne/wsme-soap/get/tip.zip
{envbindir}/easy_install -i http://www.turbogears.org/1.1/downloads/current/index/ 'TurboGears<1.1.99' {envbindir}/easy_install -i http://www.turbogears.org/1.1/downloads/current/index/ 'TurboGears<1.1.99'
{envbindir}/coverage run -p {envbindir}/nosetests tests/test_tg1.py --verbose {posargs} {envbindir}/coverage run -p {envbindir}/nosetests tests/test_tg1.py --verbose {posargs}

View File

@ -13,25 +13,30 @@ from turbogears.startup import call_on_startup, call_on_shutdown
from wsme.rest import validate as wsvalidate from wsme.rest import validate as wsvalidate
import wsme.api import wsme.api
import wsme.protocols.restjson import wsme.rest.args
import wsme.rest.json
import inspect
APIPATH_MAXLEN = 50
__all__ = ['adapt', 'wsexpose', 'wsvalidate'] __all__ = ['adapt', 'wsexpose', 'wsvalidate']
def wsexpose(*args, **kwargs): def wsexpose(*args, **kwargs):
tg_json_expose = expose( tg_json_expose = expose(
'wsmejson', 'wsmejson:',
accept_format='application/json', accept_format='application/json',
content_type='application/json', content_type='application/json',
tg_format='json' tg_format='json'
) )
tg_altjson_expose = expose( tg_altjson_expose = expose(
'wsmejson', 'wsmejson:',
accept_format='text/javascript', accept_format='text/javascript',
content_type='application/json' content_type='application/json'
) )
tg_xml_expose = expose( tg_xml_expose = expose(
'wsmxml', 'wsmexml:',
accept_format='text/xml', accept_format='text/xml',
content_type='text/xml', content_type='text/xml',
tg_format='xml' tg_format='xml'
@ -44,8 +49,7 @@ def wsexpose(*args, **kwargs):
@functools.wraps(f) @functools.wraps(f)
def callfunction(self, *args, **kwargs): def callfunction(self, *args, **kwargs):
print args, kwargs, cherrypy.request.body args, kwargs = wsme.rest.args.get_args(
args, kwargs = wsme.protocols.commons.get_args(
funcdef, args, kwargs, funcdef, args, kwargs,
cherrypy.request.body, cherrypy.request.body,
cherrypy.request.headers['Content-Type'] cherrypy.request.headers['Content-Type']
@ -56,9 +60,10 @@ def wsexpose(*args, **kwargs):
result=result result=result
) )
callfunction = tg_json_expose(callfunction)
callfunction = tg_altjson_expose(callfunction)
callfunction = tg_xml_expose(callfunction) callfunction = tg_xml_expose(callfunction)
callfunction = tg_altjson_expose(callfunction)
callfunction = tg_json_expose(callfunction)
callfunction._wsme_original_function = f
return callfunction return callfunction
return decorate return decorate
@ -74,16 +79,38 @@ class AutoJSONTemplate(object):
def render(self, info, format="json", fragment=False, template=None): def render(self, info, format="json", fragment=False, template=None):
"Renders the template to a string using the provided info." "Renders the template to a string using the provided info."
data = wsme.protocols.restjson.tojson( return wsme.rest.json.encode_result(
info['datatype'], info['result'], info['datatype']
info['result']
) )
return json.dumps(data)
def get_content_type(self, user_agent): def get_content_type(self, user_agent):
return "application/json" return "application/json"
class AutoXMLTemplate(object):
def __init__(self, extra_vars_func=None, options=None):
pass
def load_template(self, templatename):
"There are no actual templates with this engine"
pass
def render(self, info, format="json", fragment=False, template=None):
"Renders the template to a string using the provided info."
return wsme.rest.xml.encode_result(
info['result'], info['datatype']
)
def get_content_type(self, user_agent):
return "text/xml"
import turbogears.view
turbogears.view.engines['wsmejson'] = AutoJSONTemplate(turbogears.view.stdvars)
turbogears.view.engines['wsmexml'] = AutoXMLTemplate(turbogears.view.stdvars)
class WSMECherrypyFilter(BaseFilter): class WSMECherrypyFilter(BaseFilter):
def __init__(self, controller): def __init__(self, controller):
self.controller = controller self.controller = controller
@ -109,6 +136,7 @@ class Controller(object):
def adapt(wsroot): def adapt(wsroot):
wsroot._scan_api = scan_api
controller = Controller(wsroot) controller = Controller(wsroot)
filter_ = WSMECherrypyFilter(controller) filter_ = WSMECherrypyFilter(controller)
@ -126,3 +154,32 @@ def adapt(wsroot):
call_on_startup.append(install_filter) call_on_startup.append(install_filter)
call_on_shutdown.insert(0, uninstall_filter) call_on_shutdown.insert(0, uninstall_filter)
return controller return controller
import wsme.rest
def _scan_api(controller, path=[], objects=[]):
"""
Recursively iterate a controller api entries.
"""
for name in dir(controller):
if name.startswith('_'):
continue
a = getattr(controller, name)
if a in objects:
continue
if inspect.ismethod(a):
if wsme.api.iswsmefunction(a):
yield path + [name], a._wsme_original_function, [controller]
elif inspect.isclass(a):
continue
else:
if len(path) > APIPATH_MAXLEN:
raise ValueError("Path is too long: " + str(path))
for i in _scan_api(a, path + [name], objects + [a]):
yield i
def scan_api(root=None):
return _scan_api(cherrypy.root)