From fd60166af894686968cdacff0f43007bbdcd9c3b Mon Sep 17 00:00:00 2001 From: Christophe de Vienne Date: Fri, 20 Apr 2012 15:28:25 +0200 Subject: [PATCH] The function documenter now add parameters and return value samples --- doc/document.rst | 2 +- wsme/protocols/__init__.py | 6 ++++ wsme/protocols/restjson.py | 18 +++++++++++ wsme/protocols/restxml.py | 19 ++++++++++-- wsme/sphinxext.py | 61 ++++++++++++++++++++++++++++++++++++-- 5 files changed, 100 insertions(+), 6 deletions(-) diff --git a/doc/document.rst b/doc/document.rst index 220a13c..76fbd09 100644 --- a/doc/document.rst +++ b/doc/document.rst @@ -151,7 +151,7 @@ Python source ~~~~~~~~~~~~~ .. literalinclude:: ../wsme/sphinxext.py - :lines: 23-49 + :lines: 35-60 :language: python Documentation source diff --git a/wsme/protocols/__init__.py b/wsme/protocols/__init__.py index 1c86bec..b0846b3 100644 --- a/wsme/protocols/__init__.py +++ b/wsme/protocols/__init__.py @@ -50,6 +50,12 @@ class Protocol(object): def encode_sample_value(self, datatype, value, format=False): return ('none', 'N/A') + def encode_sample_params(self, params, format=False): + return ('none', 'N/A') + + def encode_sample_result(self, datatype, value, format=False): + return ('none', 'N/A') + def register_protocol(protocol): registered_protocols[protocol.name] = protocol diff --git a/wsme/protocols/restjson.py b/wsme/protocols/restjson.py index d93d6ae..3980288 100644 --- a/wsme/protocols/restjson.py +++ b/wsme/protocols/restjson.py @@ -223,3 +223,21 @@ class RestJsonProtocol(RestProtocol): indent=4 if format else 0, sort_keys=format) return ('javascript', content) + + def encode_sample_params(self, params, format=False): + kw = {} + for name, datatype, value in params: + kw[name] = tojson(datatype, value) + content = json.dumps(kw, ensure_ascii=False, + indent=4 if format else 0, + sort_keys=format) + return ('javascript', content) + + def encode_sample_result(self, datatype, value, format=False): + r = tojson(datatype, value) + if self.nest_result: + r = {'result': r} + content = json.dumps(r, ensure_ascii=False, + indent=4 if format else 0, + sort_keys=format) + return ('javascript', content) diff --git a/wsme/protocols/restxml.py b/wsme/protocols/restxml.py index 417c9e2..b3b9855 100644 --- a/wsme/protocols/restxml.py +++ b/wsme/protocols/restxml.py @@ -28,7 +28,6 @@ def xml_indent(elem, level=0): elem.tail = i - @generic def toxml(datatype, key, value): """ @@ -243,6 +242,20 @@ class RestXmlProtocol(RestProtocol): if format: xml_indent(r) content = et.tostring(r) - #indent=4 if format else 0, - #sort_keys=format) + return ('xml', content) + + def encode_sample_params(self, params, format=False): + node = et.Element('parameters') + for name, datatype, value in params: + node.append(toxml(datatype, name, value)) + if format: + xml_indent(node) + content = et.tostring(node) + return ('xml', content) + + def encode_sample_result(self, datatype, value, format=False): + r = toxml(datatype, 'result', value) + if format: + xml_indent(r) + content = et.tostring(r) return ('xml', content) diff --git a/wsme/sphinxext.py b/wsme/sphinxext.py index f59d559..ed081fc 100644 --- a/wsme/sphinxext.py +++ b/wsme/sphinxext.py @@ -7,7 +7,7 @@ from sphinx.ext import autodoc from sphinx.domains.python import PyClasslike, PyClassmember from sphinx.domains import Domain, ObjType from sphinx.directives import ObjectDescription -from sphinx.util.docfields import Field, GroupedField, TypedField +from sphinx.util.docfields import Field from sphinx.util.nodes import make_refnode from sphinx.roles import XRefRole @@ -21,6 +21,17 @@ import wsme field_re = re.compile(r':(?P\w+)(\s+(?P\w+))?:') +def make_sample_object(datatype): + if datatype is str: + return 'samplestring' + if datatype is unicode: + return u'sample unicode' + if datatype is int: + return 5 + sample_obj = getattr(datatype, 'sample', datatype)() + return sample_obj + + class SampleType(object): """A Sample Type""" @@ -158,7 +169,7 @@ class TypeDocumenter(autodoc.ClassDocumenter): protocols = [wsme.protocols.getprotocol(p) for p in protocols] content = [] if protocols: - sample_obj = getattr(self.object, 'sample', self.object)() + sample_obj = make_sample_object(self.object) content.extend([ l_(u'Data samples:'), u'', @@ -315,6 +326,9 @@ class FunctionDocumenter(autodoc.MethodDocumenter): docstrings = super(FunctionDocumenter, self).get_doc(encoding) found_params = set() + protocols = self.options.protocols or self.env.app.config.wsme_protocols + protocols = [wsme.protocols.getprotocol(p) for p in protocols] + for si, docstring in enumerate(docstrings): for i, line in enumerate(docstring): m = field_re.match(line) @@ -360,6 +374,49 @@ class FunctionDocumenter(autodoc.MethodDocumenter): pos = next_param_pos docstring = docstrings[pos[0]] docstring[pos[1]:pos[1]] = content + + codesamples = [] + + if protocols: + params = [] + for arg in self.wsme_fd.arguments: + params.append((arg.name, arg.datatype, + make_sample_object(arg.datatype))) + codesamples.extend([ + u':%s:' % l_(u'Parameters samples'), + u' .. cssclass:: toggle', + u'' + ]) + for protocol in protocols: + language, sample = protocol.encode_sample_params( + params, format=True) + codesamples.extend([ + u' ' * 4 + (protocol.displayname or protocol.name), + u' .. code-block:: ' + language, + u'', + ]) + codesamples.extend(( + u' ' * 12 + line for line in sample.split('\n'))) + + if self.wsme_fd.return_type: + codesamples.extend([ + u':%s:' % l_(u'Return samples'), + u' .. cssclass:: toggle', + u'' + ]) + sample_obj = make_sample_object(self.wsme_fd.return_type) + for protocol in protocols: + language, sample = protocol.encode_sample_result( + self.wsme_fd.return_type, sample_obj, format=True) + codesamples.extend([ + u' ' * 4 + protocol.displayname or protocol.name, + u' .. code-block:: ' + language, + u'', + ]) + codesamples.extend(( + u' ' * 12 + line for line in sample.split('\n'))) + + docstrings[0:0] = [codesamples] return docstrings def add_content(self, more_content, no_docstring=False):