diff --git a/wsme/root.py b/wsme/root.py index 6b27a9b..a4caf33 100644 --- a/wsme/root.py +++ b/wsme/root.py @@ -11,6 +11,7 @@ import webob from wsme import exc from wsme.protocols import getprotocol from wsme.api import scan_api +from wsme import spore import wsme.types log = logging.getLogger(__name__) @@ -203,6 +204,11 @@ class WSRoot(object): res = webob.Response() res_content_type = None + if request.path == self._webpath + '/api.spore': + res.body = spore.getdesc(self) + res.content_type = 'application/json' + return res + try: msg = None protocol = self._select_protocol(request) diff --git a/wsme/spore.py b/wsme/spore.py new file mode 100644 index 0000000..b45554c --- /dev/null +++ b/wsme/spore.py @@ -0,0 +1,64 @@ +from wsme import types + +try: + import simplejson as json +except ImportError: + import json + + +def getdesc(root): + methods = {} + + for path, funcdef in root.getapi(): + method = funcdef.extra_options.get('method', None) + name = '_'.join(path) + if method is not None: + path = path[:-1] + else: + method = 'GET' + for argdef in funcdef.arguments: + if types.iscomplex(argdef.datatype) \ + or types.isarray(argdef.datatype) \ + or types.isdict(argdef.datatype): + method = 'POST' + break + + required_params = [] + optional_params = [] + for argdef in funcdef.arguments: + if method == 'GET' and argdef.mandatory: + required_params.append(argdef.name) + else: + optional_params.append(argdef.name) + + methods[name] = { + 'method': method, + 'path': '/'.join([root._webpath] + path) + } + if required_params: + methods[name]['required_params'] = required_params + if optional_params: + methods[name]['optional_params'] = optional_params + if funcdef.doc: + methods[name]['documentation'] = funcdef.doc + + formats = [] + for p in root.protocols: + if p.name == 'restxml': + formats.append('xml') + if p.name == 'restjson': + formats.append('json') + + api = { + 'base_url': root._webpath, + 'version': '0.1', + 'name': getattr(root, 'name', 'name'), + 'authority': '', + 'formats': [ + 'json', + 'xml' + ], + 'methods': methods + } + + return json.dumps(api, indent=4) diff --git a/wsme/tests/test_spore.py b/wsme/tests/test_spore.py new file mode 100644 index 0000000..644c8a1 --- /dev/null +++ b/wsme/tests/test_spore.py @@ -0,0 +1,30 @@ +import unittest + +try: + import simplejson as json +except ImportError: + import json + +from wsme.tests.protocol import WSTestRoot +import wsme.spore + + +class TestSpore(unittest.TestCase): + def test_spore(self): + spore = wsme.spore.getdesc(WSTestRoot()) + + print spore + + spore = json.loads(spore) + + assert len(spore['methods']) == 36, len(spore['methods']) + + m = spore['methods']['argtypes_setbytesarray'] + assert m['path'] == '/argtypes/setbytesarray' + assert m['optional_params'] == ['value'] + assert m['method'] == 'POST' + + m = spore['methods']['argtypes_setdecimal'] + assert m['path'] == '/argtypes/setdecimal' + assert m['required_params'] == ['value'] + assert m['method'] == 'GET'