##// END OF EJS Templates
api: add get_method API call....
marcink -
r1417:8af06cf7 default
parent child Browse files
Show More
@@ -0,0 +1,58 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import pytest
23
24 from rhodecode.api.tests.utils import build_data, api_call, assert_ok
25
26
27 @pytest.mark.usefixtures("testuser_api", "app")
28 class TestGetMethod(object):
29 def test_get_methods_no_matches(self):
30 id_, params = build_data(self.apikey, 'get_method', pattern='hello')
31 response = api_call(self.app, params)
32
33 expected = []
34 assert_ok(id_, expected, given=response.body)
35
36 def test_get_methods(self):
37 id_, params = build_data(self.apikey, 'get_method', pattern='*comment*')
38 response = api_call(self.app, params)
39
40 expected = ['changeset_comment', 'comment_pull_request',
41 'comment_commit']
42 assert_ok(id_, expected, given=response.body)
43
44 def test_get_methods_on_single_match(self):
45 id_, params = build_data(self.apikey, 'get_method', pattern='*comment_commit*')
46 response = api_call(self.app, params)
47
48 expected = ['comment_commit',
49 {'apiuser': '<RequiredType>',
50 'comment_type': "<Optional:u'note'>",
51 'commit_id': '<RequiredType>',
52 'message': '<RequiredType>',
53 'repoid': '<RequiredType>',
54 'request': '<RequiredType>',
55 'resolves_comment_id': '<Optional:None>',
56 'status': '<Optional:None>',
57 'userid': '<Optional:<OptionalAttr:apiuser>>'}]
58 assert_ok(id_, expected, given=response.body)
@@ -22,6 +22,7 b' import inspect'
22 import itertools
22 import itertools
23 import logging
23 import logging
24 import types
24 import types
25 import fnmatch
25
26
26 import decorator
27 import decorator
27 import venusian
28 import venusian
@@ -47,6 +48,18 b" DEFAULT_RENDERER = 'jsonrpc_renderer'"
47 DEFAULT_URL = '/_admin/apiv2'
48 DEFAULT_URL = '/_admin/apiv2'
48
49
49
50
51 def find_methods(jsonrpc_methods, pattern):
52 matches = OrderedDict()
53 if not isinstance(pattern, (list, tuple)):
54 pattern = [pattern]
55
56 for single_pattern in pattern:
57 for method_name, method in jsonrpc_methods.items():
58 if fnmatch.fnmatch(method_name, single_pattern):
59 matches[method_name] = method
60 return matches
61
62
50 class ExtJsonRenderer(object):
63 class ExtJsonRenderer(object):
51 """
64 """
52 Custom renderer that mkaes use of our ext_json lib
65 Custom renderer that mkaes use of our ext_json lib
@@ -143,7 +156,19 b' def exception_view(exc, request):'
143 log.debug('json-rpc method `%s` not found in list of '
156 log.debug('json-rpc method `%s` not found in list of '
144 'api calls: %s, rpc_id:%s',
157 'api calls: %s, rpc_id:%s',
145 method, request.registry.jsonrpc_methods.keys(), rpc_id)
158 method, request.registry.jsonrpc_methods.keys(), rpc_id)
146 fault_message = "No such method: {}".format(method)
159
160 similar = 'none'
161 try:
162 similar_paterns = ['*{}*'.format(x) for x in method.split('_')]
163 similar_found = find_methods(
164 request.registry.jsonrpc_methods, similar_paterns)
165 similar = ', '.join(similar_found.keys()) or similar
166 except Exception:
167 # make the whole above block safe
168 pass
169
170 fault_message = "No such method: {}. Similar methods: {}".format(
171 method, similar)
147
172
148 return jsonrpc_error(request, fault_message, rpc_id)
173 return jsonrpc_error(request, fault_message, rpc_id)
149
174
@@ -348,9 +373,10 b' class RoutePredicate(object):'
348 class NotFoundPredicate(object):
373 class NotFoundPredicate(object):
349 def __init__(self, val, config):
374 def __init__(self, val, config):
350 self.val = val
375 self.val = val
376 self.methods = config.registry.jsonrpc_methods
351
377
352 def text(self):
378 def text(self):
353 return 'jsonrpc method not found = %s' % self.val
379 return 'jsonrpc method not found = {}.'.format(self.val)
354
380
355 phash = text
381 phash = text
356
382
@@ -80,7 +80,13 b' class TestApi(object):'
80 def test_api_non_existing_method(self, request):
80 def test_api_non_existing_method(self, request):
81 id_, params = build_data(self.apikey, 'not_existing', args='xx')
81 id_, params = build_data(self.apikey, 'not_existing', args='xx')
82 response = api_call(self.app, params)
82 response = api_call(self.app, params)
83 expected = 'No such method: not_existing'
83 expected = 'No such method: not_existing. Similar methods: none'
84 assert_error(id_, expected, given=response.body)
85
86 def test_api_non_existing_method_have_similar(self, request):
87 id_, params = build_data(self.apikey, 'comment', args='xx')
88 response = api_call(self.app, params)
89 expected = 'No such method: comment. Similar methods: changeset_comment, comment_pull_request, comment_commit'
84 assert_error(id_, expected, given=response.body)
90 assert_error(id_, expected, given=response.body)
85
91
86 def test_api_disabled_user(self, request):
92 def test_api_disabled_user(self, request):
@@ -18,10 +18,12 b''
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21 import inspect
22 import logging
22 import logging
23 import itertools
23
24
24 from rhodecode.api import jsonrpc_method, JSONRPCError, JSONRPCForbidden
25 from rhodecode.api import (
26 jsonrpc_method, JSONRPCError, JSONRPCForbidden, find_methods)
25
27
26 from rhodecode.api.utils import (
28 from rhodecode.api.utils import (
27 Optional, OAttr, has_superadmin_permission, get_user_or_error)
29 Optional, OAttr, has_superadmin_permission, get_user_or_error)
@@ -243,3 +245,77 b' def cleanup_sessions(request, apiuser, o'
243 raise JSONRPCError(
245 raise JSONRPCError(
244 'Error occurred during session cleanup'
246 'Error occurred during session cleanup'
245 )
247 )
248
249
250 @jsonrpc_method()
251 def get_method(request, apiuser, pattern=Optional('*')):
252 """
253 Returns list of all available API methods. By default match pattern
254 os "*" but any other pattern can be specified. eg *comment* will return
255 all methods with comment inside them. If just single method is matched
256 returned data will also include method specification
257
258 This command can only be run using an |authtoken| with admin rights to
259 the specified repository.
260
261 This command takes the following options:
262
263 :param apiuser: This is filled automatically from the |authtoken|.
264 :type apiuser: AuthUser
265 :param pattern: pattern to match method names against
266 :type older_then: Optional("*")
267
268 Example output:
269
270 .. code-block:: bash
271
272 id : <id_given_in_input>
273 "result": [
274 "changeset_comment",
275 "comment_pull_request",
276 "comment_commit"
277 ]
278 error : null
279
280 .. code-block:: bash
281
282 id : <id_given_in_input>
283 "result": [
284 "comment_commit",
285 {
286 "apiuser": "<RequiredType>",
287 "comment_type": "<Optional:u'note'>",
288 "commit_id": "<RequiredType>",
289 "message": "<RequiredType>",
290 "repoid": "<RequiredType>",
291 "request": "<RequiredType>",
292 "resolves_comment_id": "<Optional:None>",
293 "status": "<Optional:None>",
294 "userid": "<Optional:<OptionalAttr:apiuser>>"
295 }
296 ]
297 error : null
298 """
299 if not has_superadmin_permission(apiuser):
300 raise JSONRPCForbidden()
301
302 pattern = Optional.extract(pattern)
303
304 matches = find_methods(request.registry.jsonrpc_methods, pattern)
305
306 args_desc = []
307 if len(matches) == 1:
308 func = matches[matches.keys()[0]]
309
310 argspec = inspect.getargspec(func)
311 arglist = argspec[0]
312 defaults = map(repr, argspec[3] or [])
313
314 default_empty = '<RequiredType>'
315
316 # kw arguments required by this method
317 func_kwargs = dict(itertools.izip_longest(
318 reversed(arglist), reversed(defaults), fillvalue=default_empty))
319 args_desc.append(func_kwargs)
320
321 return matches.keys() + args_desc
General Comments 0
You need to be logged in to leave comments. Login now