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):
         """
     @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}
             @type body: L{Item}
-            @return 200: pod is created.
+            @return 200: item is created.
             @raise 400: invalid input
         """
 
             @raise 400: invalid input
         """
 
@@ -49,9 +49,9 @@ class ItemNoParamHandler(GenericApiHandler):
 
 def make_app():
     return swagger.Application([
 
 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:
     ])
 
 # 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
 ```
 
 # 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}
             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.property1 = property1
         self.property2 = property2
         self.property3 = property3
+        self.property4 = property4
 
 items = {}
 
 
 items = {}
 
@@ -71,9 +73,9 @@ class ItemNoParamHandler(GenericApiHandler):
     @swagger.operation(nickname='create')
     def post(self):
         """
     @swagger.operation(nickname='create')
     def post(self):
         """
-            @param body: create test results for a pod.
+            @param body: create a item.
             @type body: L{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')
             @raise 400: invalid input
         """
         property1 = self.json_args.get('property1')
@@ -99,9 +101,9 @@ class ItemHandler(GenericApiHandler):
     def get(self, arg):
         """
             @rtype: L{Item}
     def get(self, arg):
         """
             @rtype: L{Item}
-            @description: get pod's test results
+            @description: get information of a item
             @notes:
             @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.
         """
 
                 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):
         """
     @swagger.operation(nickname='delete')
     def delete(self, arg):
         """
-            @description: delete pod by pod_id
+            @description: delete a item
             @notes:
             @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.
         """
 
                 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
 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
 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'
 
 
 __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
 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()
         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
 
             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)
 
     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,
         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)
 
     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):
         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):
         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)
 
     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)
 
     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):
         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):
         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):
         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
 
     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):
 
 class model(DocParser):
     def __init__(self, cls=None, *args, **kwargs):