diff --git a/cornice/ext/sphinxext.py b/cornice/ext/sphinxext.py index 46802e6b..27e2497b 100644 --- a/cornice/ext/sphinxext.py +++ b/cornice/ext/sphinxext.py @@ -97,6 +97,19 @@ def run(self): return [self._render_service(s) for s in services] + def _resolve_obj_to_docstring(self, obj, args): + # Resolve a view or validator to an object if type string + # and return docstring. + if is_string(obj): + if 'klass' in args: + ob = args['klass'] + obj_ = getattr(ob, obj.lower()) + return format_docstring(obj_) + else: + return '' + else: + return format_docstring(obj) + def _render_service(self, service): service_id = "service-%d" % self.env.new_serialno('service') service_node = nodes.section(ids=[service_id]) @@ -115,13 +128,7 @@ def _render_service(self, service): method_node = nodes.section(ids=[method_id]) method_node += nodes.title(text=method) - if is_string(view): - if 'klass' in args: - ob = args['klass'] - view_ = getattr(ob, view.lower()) - docstring = trim(view_.__doc__ or "") + '\n' - else: - docstring = trim(view.__doc__ or "") + '\n' + docstring = self._resolve_obj_to_docstring(view, args) if 'schema' in args: schema = args['schema'] @@ -167,8 +174,7 @@ def _render_service(self, service): method_node += attrs_node for validator in args.get('validators', ()): - if validator.__doc__ is not None: - docstring += trim(validator.__doc__) + docstring += self._resolve_obj_to_docstring(validator, args) if 'accept' in args: accept = to_list(args['accept']) @@ -203,12 +209,15 @@ def _render_service(self, service): method_node += response service_node += method_node - return service_node # Utils +def format_docstring(obj): + """Return trimmed docstring with newline from object.""" + return trim(obj.__doc__ or "") + '\n' + def trim(docstring): """ diff --git a/cornice/tests/ext/dummy/views.py b/cornice/tests/ext/dummy/views.py index 9a4b4303..064cc24e 100644 --- a/cornice/tests/ext/dummy/views.py +++ b/cornice/tests/ext/dummy/views.py @@ -12,19 +12,25 @@ def __init__(self, request, context=None): self.context = context def collection_get(self): - """returns yay""" + """Returns yay.""" return 'yay' def get_info(request): - "returns the user data" + """Returns the user data.""" username = request.matchdict['username'] return _USERS[username] +def validate(request): + """Dummy validation.""" + return request + + def includeme(config): # FIXME this should also work in includeme - user_info = Service(name='users', path='/{username}/info') + user_info = Service(name='users', path='/{username}/info', + validators=('validate')) user_info.add_view('get', get_info) config.add_cornice_service(user_info) diff --git a/cornice/tests/ext/test_sphinxext.py b/cornice/tests/ext/test_sphinxext.py index 26682a13..5cee96cd 100644 --- a/cornice/tests/ext/test_sphinxext.py +++ b/cornice/tests/ext/test_sphinxext.py @@ -18,21 +18,32 @@ def test_rendering(self): class TestServiceDirective(TestCase): + def setUp(self): + super(TestServiceDirective, self).setUp() + param = mock.Mock() + param.document.settings.env.new_serialno.return_value = 1 + + self.directive = ServiceDirective( + 'test', [], {}, [], 1, 1, 'test', param, 1) + self.directive.options['app'] = 'cornice.tests.ext.dummy' + self.directive.options['services'] = ['users', "thing_service"] + def test_module_reload(self): - directive = ServiceDirective( - 'test', [], {}, [], 1, 1, 'test', mock.Mock(), 1) - directive.options['modules'] = ['cornice'] - ret = directive.run() + self.directive.options['app'] = None + self.directive.options['services'] = None + self.directive.options['modules'] = ['cornice'] + ret = self.directive.run() self.assertEqual(ret, []) def test_dummy(self): - param = mock.Mock() - param.document.settings.env.new_serialno.return_value = 1 - directive = ServiceDirective( - 'test', [], {}, [], 1, 1, 'test', param, 1) - directive.options['app'] = 'cornice.tests.ext.dummy' - directive.options['services'] = ['users', "thing_service"] - ret = directive.run() + ret = self.directive.run() self.assertEqual(len(ret), 2) - self.assertTrue('Users service at' in str(ret[0])) - self.assertTrue('Thing_Service service at ' in str(ret[1])) + self.assertIn('Users service at', str(ret[0])) + self.assertIn('Thing_Service service at ', str(ret[1])) + + def test_string_validator_resolved(self): + # A validator defined as a string should be parsed as an obj, + # ensuring the docstring contains validator.__doc__ rather + # than str.__doc__. + ret = self.directive.run() + self.assertNotIn("str(object='') -> string", str(ret[0]))