2 # -*- coding: utf-8 -*-
5 from functools import wraps
8 from settings import default_settings, models
9 from handlers import swagger_handlers
14 class DocParser(object):
18 self.responseClass = None
19 self.responseMessages = []
23 def parse_docstring(self, text):
28 doc = epydoc.markup.parse(text, markup='epytext', errors=errors)
29 _, fields = doc.split_fields(errors)
34 body = field.body().to_plaintext(None).strip()
35 self._get_parser(tag)(arg=arg, body=body)
38 def _get_parser(self, tag):
40 'param': self._parse_param,
41 'type': self._parse_type,
42 'rtype': self._parse_rtype,
43 'property': self._parse_property,
44 'ptype': self._parse_ptype,
45 'return': self._parse_return,
46 'raise': self._parse_return,
47 'notes': self._parse_notes,
48 'description': self._parse_description,
50 return parser.get(tag, self._not_supported)
52 def _parse_param(self, **kwargs):
53 arg = kwargs.get('arg', None)
54 body = kwargs.get('body', None)
55 self.params.setdefault(arg, {}).update({
60 'allowMultiple': False
63 if 'paramType' not in self.params[arg]:
64 self.params[arg]['paramType'] = 'query'
66 def _parse_type(self, **kwargs):
67 arg = kwargs.get('arg', None)
68 body = kwargs.get('body', None)
69 self.params.setdefault(arg, {}).update({
74 def _parse_rtype(self, **kwargs):
75 body = kwargs.get('body', None)
76 self.responseClass = body
78 def _parse_property(self, **kwargs):
79 arg = kwargs.get('arg', None)
80 self.properties.setdefault(arg, {}).update({
84 def _parse_ptype(self, **kwargs):
85 arg = kwargs.get('arg', None)
86 body = kwargs.get('body', None)
87 self.properties.setdefault(arg, {}).update({
91 def _parse_return(self, **kwargs):
92 arg = kwargs.get('arg', None)
93 body = kwargs.get('body', None)
94 self.responseMessages.append({
99 def _parse_notes(self, **kwargs):
100 body = kwargs.get('body', '')
101 self.notes = self._sanitize_doc(body)
103 def _parse_description(self, **kwargs):
104 body = kwargs.get('body', '')
105 self.summary = self._sanitize_doc(body)
107 def _not_supported(self, **kwargs):
111 def _sanitize_doc(comment):
112 return comment.replace('\n', '<br/>') if comment else comment
115 class model(DocParser):
116 def __init__(self, cls=None, *args, **kwargs):
117 super(model, self).__init__()
118 self.id = cls.__name__
123 if '__init__' in dir(cls):
124 self._parse_args(cls.__init__)
125 self.parse_docstring(inspect.getdoc(cls))
128 def _parse_args(self, func):
129 argspec = inspect.getargspec(func)
130 argspec.args.remove("self")
133 defaults = list(zip(argspec.args[-len(argspec.defaults):], argspec.defaults))
134 required_args_count = len(argspec.args) - len(defaults)
135 for arg in argspec.args[:required_args_count]:
136 self.required.append(arg)
137 self.properties.setdefault(arg, {'type': 'string'})
138 for arg, default in defaults:
139 self.properties.setdefault(arg, {'type': 'string', "default": default})
143 class operation(DocParser):
144 def __init__(self, nickname=None, **kwds):
145 super(operation, self).__init__()
146 self.nickname = nickname
151 def __call__(self, *args, **kwds):
153 return self.func(*args, **kwds)
156 self._parse_operation(func)
159 def __wrapper__(*in_args, **in_kwds):
160 return self.func(*in_args, **in_kwds)
162 __wrapper__.rest_api = self
165 def _parse_operation(self, func):
168 self.__name__ = func.__name__
169 self._parse_args(func)
170 self.parse_docstring(inspect.getdoc(self.func))
172 def _parse_args(self, func):
173 argspec = inspect.getargspec(func)
174 argspec.args.remove("self")
178 defaults = argspec.args[-len(argspec.defaults):]
180 for arg in argspec.args:
185 self.params.setdefault(arg, {
187 'required': required,
191 self.func_args = argspec.args
195 default_settings.update(opts)
198 class Application(tornado.web.Application):
199 def __init__(self, handlers=None, default_host="", transforms=None, **settings):
200 super(Application, self).__init__(swagger_handlers() + handlers, default_host, transforms, **settings)