support list property in tornado_swagger_ui 79/13979/1
authorSerenaFeng <feng.xiaowei@zte.com.cn>
Thu, 12 May 2016 03:25:06 +0000 (11:25 +0800)
committerSerenaFeng <feng.xiaowei@zte.com.cn>
Thu, 12 May 2016 03:27:46 +0000 (11:27 +0800)
list property will be declared in format
'@ptype property4: C{list} of L{PropertySubclass}'

JIRA: FUNCTEST-248

Change-Id: I3ee31389f1eab39cc9f621cbab006f0a8764c8ca
Signed-off-by: SerenaFeng <feng.xiaowei@zte.com.cn>
utils/test/result_collection_api/tornado_swagger_ui/README.md
utils/test/result_collection_api/tornado_swagger_ui/example/basic.py
utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/swagger.py

index 1ae3834..707eec0 100644 (file)
@@ -28,9 +28,9 @@ class ItemNoParamHandler(GenericApiHandler):
     @swagger.operation(nickname='create')
     def post(self):
         """
-            @param body: create test results for a pod.
+            @param body: create test results for a item.
             @type body: L{Item}
-            @return 200: pod is created.
+            @return 200: item is created.
             @raise 400: invalid input
         """
 
@@ -49,9 +49,9 @@ class ItemNoParamHandler(GenericApiHandler):
 
 def make_app():
     return swagger.Application([
-        (r"/pods", ItemNoParamHandler),
-        (r"/pods/([^/]+)", ItemHandler),
-        (r"/projects/([^/]+)/cases/([^/]+)", ItemOptionParamHandler),
+        (r"/items", ItemNoParamHandler),
+        (r"/items/([^/]+)", ItemHandler),
+        (r"/items/([^/]+)/cases/([^/]+)", ItemOptionParamHandler),
     ])
 
 # You define models like this:
@@ -157,6 +157,48 @@ class Item:
             ]
         }
     }
+
+# if you want to declare an list property, you can do it like this:
+class Item:
+    """
+        @ptype property3: L{PropertySubclass}
+        @ptype property4: C{list} of L{PropertySubclass}
+    """
+    def __init__(self, property1, property2, property3, property4=None):
+        self.property1 = property1
+        self.property2 = property2
+        self.property3 = property3
+        self.property4 = property4
+
+# Swagger json:
+    "models": {
+        "Item": {
+            "description": "A description...",
+            "id": "Item",
+            "required": [
+                "property1",
+            ],
+            "properties": [
+                "property1": {
+                    "type": "string"
+                },
+                "property2": {
+                    "type": "string"
+                },
+                "property3": {
+                    "type": "PropertySubclass"
+                    "default": null
+                },
+                "property4": {
+                    "default": null,
+                    "items": {
+                        "type": "PropertySubclass"},
+                        "type": "array"
+                    }
+                }
+            ]
+        }
+    }
 ```
 
 # Running and testing
index ded99d5..20ad9cb 100644 (file)
@@ -28,11 +28,13 @@ class Item:
             In this case we would have property1, name as required parameters and property3 as optional parameter.
         @property property3: Item description
         @ptype property3: L{PropertySubclass}
+        @ptype property4: C{list} of L{PropertySubclass}
     """
-    def __init__(self, property1, property2=None, property3=None):
+    def __init__(self, property1, property2=None, property3=None, property4=None):
         self.property1 = property1
         self.property2 = property2
         self.property3 = property3
+        self.property4 = property4
 
 items = {}
 
@@ -71,9 +73,9 @@ class ItemNoParamHandler(GenericApiHandler):
     @swagger.operation(nickname='create')
     def post(self):
         """
-            @param body: create test results for a pod.
+            @param body: create a item.
             @type body: L{Item}
-            @return 200: pod is created.
+            @return 200: item is created.
             @raise 400: invalid input
         """
         property1 = self.json_args.get('property1')
@@ -99,9 +101,9 @@ class ItemHandler(GenericApiHandler):
     def get(self, arg):
         """
             @rtype: L{Item}
-            @description: get pod's test results
+            @description: get information of a item
             @notes:
-                get a pod test results,
+                get a item,
 
                 This will be added to the Implementation Notes.It lets you put very long text in your api.
         """
@@ -110,9 +112,9 @@ class ItemHandler(GenericApiHandler):
     @swagger.operation(nickname='delete')
     def delete(self, arg):
         """
-            @description: delete pod by pod_id
+            @description: delete a item
             @notes:
-                delete test results of a pod
+                delete a item in items
 
                 This will be added to the Implementation Notes.It lets you put very long text in your api.
         """
index 2d688a8..0939b0d 100644 (file)
@@ -4,6 +4,7 @@
 import inspect
 from functools import wraps
 import epydoc.markup
+from HTMLParser import HTMLParser
 import tornado.web
 from settings import default_settings, models
 from handlers import swagger_handlers
@@ -11,6 +12,30 @@ from handlers import swagger_handlers
 __author__ = 'serena'
 
 
+class EpytextParser(HTMLParser):
+    a_text = False
+
+    def __init__(self, tag):
+        HTMLParser.__init__(self)
+        self.tag = tag
+        self.data = None
+
+    def handle_starttag(self, tag, attr):
+        if tag == self.tag:
+            self.a_text = True
+
+    def handle_endtag(self, tag):
+        if tag == self.tag:
+            self.a_text = False
+
+    def handle_data(self, data):
+        if self.a_text:
+            self.data = data
+
+    def get_data(self):
+        return self.data
+
+
 class DocParser(object):
     def __init__(self):
         self.notes = None
@@ -31,7 +56,7 @@ class DocParser(object):
         for field in fields:
             tag = field.tag()
             arg = field.arg()
-            body = field.body().to_plaintext(None).strip()
+            body = field.body()
             self._get_parser(tag)(arg=arg, body=body)
         return doc
 
@@ -51,7 +76,7 @@ class DocParser(object):
 
     def _parse_param(self, **kwargs):
         arg = kwargs.get('arg', None)
-        body = kwargs.get('body', None)
+        body = self._get_body(**kwargs)
         self.params.setdefault(arg, {}).update({
             'name': arg,
             'description': body,
@@ -65,14 +90,14 @@ class DocParser(object):
 
     def _parse_type(self, **kwargs):
         arg = kwargs.get('arg', None)
-        body = kwargs.get('body', None)
+        body = self._get_body(**kwargs)
         self.params.setdefault(arg, {}).update({
             'name': arg,
             'dataType': body
         })
 
     def _parse_rtype(self, **kwargs):
-        body = kwargs.get('body', None)
+        body = self._get_body(**kwargs)
         self.responseClass = body
 
     def _parse_property(self, **kwargs):
@@ -83,25 +108,32 @@ class DocParser(object):
 
     def _parse_ptype(self, **kwargs):
         arg = kwargs.get('arg', None)
-        body = kwargs.get('body', None)
-        self.properties.setdefault(arg, {}).update({
-            'type': body
-        })
+        code = self._parse_epytext_para('code', **kwargs)
+        link = self._parse_epytext_para('link', **kwargs)
+        if code is None:
+            self.properties.setdefault(arg, {}).update({
+                'type': link
+           })
+        elif code == 'list':
+            self.properties.setdefault(arg, {}).update({
+                'type': 'array',
+                'items': {'type': link}
+            })
 
     def _parse_return(self, **kwargs):
         arg = kwargs.get('arg', None)
-        body = kwargs.get('body', None)
+        body = self._get_body(**kwargs)
         self.responseMessages.append({
             'code': arg,
             'message': body
         })
 
     def _parse_notes(self, **kwargs):
-        body = kwargs.get('body', '')
+        body = self._get_body(**kwargs)
         self.notes = self._sanitize_doc(body)
 
     def _parse_description(self, **kwargs):
-        body = kwargs.get('body', '')
+        body = self._get_body(**kwargs)
         self.summary = self._sanitize_doc(body)
 
     def _not_supported(self, **kwargs):
@@ -111,6 +143,23 @@ class DocParser(object):
     def _sanitize_doc(comment):
         return comment.replace('\n', '<br/>') if comment else comment
 
+    @staticmethod
+    def _get_body(**kwargs):
+        body = kwargs.get('body', None)
+        return body.to_plaintext(None).strip() if body else body
+
+    @staticmethod
+    def _parse_epytext_para(tag, **kwargs):
+        def _parse_epytext(tag, body):
+            epytextParser = EpytextParser(tag)
+            epytextParser.feed(str(body))
+            data = epytextParser.get_data()
+            epytextParser.close()
+            return data
+
+        body = kwargs.get('body', None)
+        return _parse_epytext(tag, body) if body else body
+
 
 class model(DocParser):
     def __init__(self, cls=None, *args, **kwargs):