Refactoring get_name/get_description

This commit is contained in:
Tom Christie 2012-01-25 20:39:01 +00:00
parent f5e54c7c32
commit c1fe5da85f
2 changed files with 77 additions and 37 deletions

View File

@ -177,6 +177,13 @@ _flat_repr = '{"foo": ["bar", "baz"]}'
_indented_repr = '{\n "foo": [\n "bar",\n "baz"\n ]\n}'
def strip_trailing_whitespace(content):
"""
Seems to be some inconsistencies re. trailing whitespace with
different versions of the json lib.
"""
return re.sub(' +\n', '\n', content)
class JSONRendererTests(TestCase):
"""
Tests specific to the JSON Renderer
@ -190,7 +197,6 @@ class JSONRendererTests(TestCase):
renderer = JSONRenderer(None)
content = renderer.render(obj, 'application/json')
# Fix failing test case which depends on version of JSON library.
content = re.sub(' +\n', '\n', content)
self.assertEquals(content, _flat_repr)
def test_with_content_type_args(self):
@ -200,7 +206,7 @@ class JSONRendererTests(TestCase):
obj = {'foo': ['bar', 'baz']}
renderer = JSONRenderer(None)
content = renderer.render(obj, 'application/json; indent=2')
self.assertEquals(content, _indented_repr)
self.assertEquals(strip_trailing_whitespace(content), _indented_repr)
def test_render_and_parse(self):
"""

View File

@ -27,6 +27,46 @@ __all__ = (
)
def _remove_trailing_string(content, trailing):
"""
Strip trailing component `trailing` from `content` if it exists.
Used when generating names from view/resource classes.
"""
if content.endswith(trailing) and content != trailing:
return content[:-len(trailing)]
return content
def _remove_leading_indent(content):
"""
Remove leading indent from a block of text.
Used when generating descriptions from docstrings.
"""
whitespace_counts = [len(line) - len(line.lstrip(' '))
for line in content.splitlines()[1:] if line.lstrip()]
# unindent the content if needed
if whitespace_counts:
whitespace_pattern = '^' + (' ' * min(whitespace_counts))
return re.sub(re.compile(whitespace_pattern, re.MULTILINE), '', content)
return content
def _camelcase_to_spaces(content):
"""
Translate 'CamelCaseNames' to 'Camel Case Names'.
Used when generating names from view/resource classes.
"""
camelcase_boundry = '(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))'
return re.sub(camelcase_boundry, ' \\1', content).strip()
_resource_classes = (
None,
resources.Resource,
resources.FormResource,
resources.ModelResource
)
class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
"""
Handles incoming requests and maps them to REST operations.
@ -84,52 +124,46 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
Override to customize.
"""
# If this view has a resource that's been overridden, then use that resource for the name
if getattr(self, 'resource', None) not in (None, resources.Resource, resources.FormResource, resources.ModelResource):
if getattr(self, 'resource', None) not in _resource_classes:
name = self.resource.__name__
name = _remove_trailing_string(name, 'Resource')
name += getattr(self, '_suffix', '')
# Chomp of any non-descriptive trailing part of the resource class name
if name.endswith('Resource') and name != 'Resource':
name = name[:-len('Resource')]
# If the view has a descriptive suffix, eg '*** List', '*** Instance'
if getattr(self, '_suffix', None):
name += self._suffix
# If it's a view class with no resource then grok the name from the class name
elif getattr(self, '__class__', None) is not None:
name = self.__class__.__name__
# Chomp of any non-descriptive trailing part of the view class name
if name.endswith('View') and name != 'View':
name = name[:-len('View')]
else:
name = ''
return re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', name).strip()
name = self.__class__.__name__
name = _remove_trailing_string(name, 'View')
return _camelcase_to_spaces(name)
def get_description(self, html=False):
"""
Return the resource or view docstring for use as this view's description.
Override to customize.
"""
# If this view has a resource that's been overridden, then use the resource's doctring
if getattr(self, 'resource', None) not in (None, resources.Resource, resources.FormResource, resources.ModelResource):
doc = self.resource.__doc__
# Otherwise use the view doctring
elif getattr(self, '__doc__', None):
doc = self.__doc__
description = None
# If this view has a resource that's been overridden,
# then try to use the resource's docstring
if getattr(self, 'resource', None) not in _resource_classes:
description = self.resource.__doc__
# Otherwise use the view docstring
if not description:
description = self.__doc__ or ''
description = _remove_leading_indent(description)
if html:
return self.markup_description(description)
return description
def markup_description(self, description):
if apply_markdown:
return apply_markdown(description)
else:
doc = ''
whitespace_counts = [len(line) - len(line.lstrip(' ')) for line in doc.splitlines()[1:] if line.lstrip()]
# unindent the docstring if needed
if whitespace_counts:
whitespace_pattern = '^' + (' ' * min(whitespace_counts))
doc = re.sub(re.compile(whitespace_pattern, re.MULTILINE), '', doc)
if doc and html:
if apply_markdown:
doc = apply_markdown(doc)
else:
doc = escape(doc)
doc = mark_safe(doc.replace('\n', '<br />'))
return doc
return mark_safe(escape(description).replace('\n', '<br />'))
def http_method_not_allowed(self, request, *args, **kwargs):
"""