Skip to content

Commit

Permalink
Merge pull request #341 from squidsoup/wip-validator-string-parsing
Browse files Browse the repository at this point in the history
String validators rendered as str.__doc__ in sphinxext
  • Loading branch information
leplatrem committed Jan 20, 2016
2 parents 046303d + 4e14ab2 commit 280601b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 26 deletions.
29 changes: 19 additions & 10 deletions cornice/ext/sphinxext.py
Expand Up @@ -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])
Expand All @@ -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']
Expand Down Expand Up @@ -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'])
Expand Down Expand Up @@ -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):
"""
Expand Down
12 changes: 9 additions & 3 deletions cornice/tests/ext/dummy/views.py
Expand Up @@ -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)

Expand Down
37 changes: 24 additions & 13 deletions cornice/tests/ext/test_sphinxext.py
Expand Up @@ -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]))

0 comments on commit 280601b

Please sign in to comment.