The tg1 adapter can now expose rest functions outside the WSRoot _and_ enable other other protocols. Soap is tested.
This commit is contained in:
parent
ade5325e13
commit
39cc2ffc8f
@ -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
|
||||||
|
2
tox.ini
2
tox.ini
@ -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}
|
||||||
|
|
||||||
|
81
wsme/tg1.py
81
wsme/tg1.py
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user