Ejemplo n.º 1
0
    def get(self):
        """
        The Swagger view get method outputs to /apispecs_1.json
        """
        data = {
            "swagger":
            self.config.get('swagger')
            or self.config.get('swagger_version', "2.0"),
            # try to get from config['SWAGGER']['info']
            # then config['SWAGGER']['specs'][x]
            # then config['SWAGGER']
            # then default
            "info":
            self.config.get('info') or {
                "version":
                self.spec.get('version', self.config.get('version', "0.0.1")),
                "title":
                self.spec.get('title',
                              self.config.get('title', "A swagger API 2")),
                "description":
                self.spec.get(
                    'description',
                    self.config.get('description', "powered by Flasgger")),
                "termsOfService":
                self.spec.get('termsOfService',
                              self.config.get('termsOfService', "/tos")),
            },
            "paths":
            self.config.get('paths') or defaultdict(dict),
            "definitions":
            self.config.get('definitions') or defaultdict(dict)
        }

        # Support extension properties in the top level config
        top_level_extension_options = get_vendor_extension_fields(self.config)
        if top_level_extension_options:
            data.update(top_level_extension_options)

        # if True schemaa ids will be prefized by function_method_{id}
        # for backwards compatibility with <= 0.5.14
        prefix_ids = self.config.get('prefix_ids')

        if self.config.get('host'):
            data['host'] = self.config.get('host')
        if self.config.get("basePath"):
            data["basePath"] = self.config.get('basePath')
        if self.config.get("securityDefinitions"):
            data["securityDefinitions"] = self.config.get(
                'securityDefinitions')
        # set defaults from template
        if self.template is not None:
            data.update(self.template)

        paths = data['paths']
        definitions = data['definitions']
        ignore_verbs = set(self.config.get('ignore_verbs',
                                           ("HEAD", "OPTIONS")))

        # technically only responses is non-optional
        optional_fields = self.config.get('optional_fields') or OPTIONAL_FIELDS

        for name, def_model in self.get_def_models(
                self.spec.get('definition_filter')).items():
            description, swag = parse_definition_docstring(
                def_model, self.process_doc)
            if name and swag:
                if description:
                    swag.update({'description': description})
                definitions[name].update(swag)

        for rule in self.get_url_mappings(self.spec.get('rule_filter')):
            endpoint = current_app.view_functions[rule.endpoint]
            methods = dict()
            is_mv = is_valid_method_view(endpoint)

            for verb in rule.methods.difference(ignore_verbs):
                if not is_mv and has_valid_dispatch_view_docs(endpoint):
                    endpoint.methods = endpoint.methods or ['GET']
                    if verb in endpoint.methods:
                        methods[verb.lower()] = endpoint
                elif getattr(endpoint, 'methods', None) is not None:
                    if verb in endpoint.methods:
                        verb = verb.lower()
                        methods[verb] = getattr(endpoint.view_class, verb)
                else:
                    methods[verb.lower()] = endpoint

            operations = dict()

            for verb, method in methods.items():
                klass = method.__dict__.get('view_class', None)
                if not is_mv and klass and hasattr(klass, 'verb'):
                    method = klass.__dict__.get('verb')
                elif klass and hasattr(klass, 'dispatch_request'):
                    method = klass.__dict__.get('dispatch_request')
                if method is None:  # for MethodView
                    method = klass.__dict__.get(verb)

                if method is None:
                    if is_mv:  # #76 Empty MethodViews
                        continue
                    raise RuntimeError(
                        'Cannot detect view_func for rule {0}'.format(rule))

                swag = {}
                swagged = False

                view_class = getattr(endpoint, 'view_class', None)
                if view_class and issubclass(view_class, SwaggerView):
                    apispec_swag = {}
                    apispec_attrs = optional_fields + [
                        'parameters', 'definitions', 'responses', 'summary',
                        'description'
                    ]
                    for attr in apispec_attrs:
                        value = getattr(view_class, attr)
                        if value:
                            apispec_swag[attr] = value

                    apispec_definitions = apispec_swag.get('definitions', {})
                    swag.update(
                        convert_schemas(apispec_swag, apispec_definitions))

                    swagged = True

                if getattr(method, 'specs_dict', None):
                    swag.update(deepcopy(method.specs_dict))
                    swagged = True

                doc_summary, doc_description, doc_swag = parse_docstring(
                    method,
                    self.process_doc,
                    endpoint=rule.endpoint,
                    verb=verb)
                if doc_swag:
                    swag.update(doc_swag or {})
                    swagged = True

                # we only add swagged endpoints
                if swagged:
                    if doc_summary:
                        swag['summary'] = doc_summary
                    if doc_description:
                        swag['description'] = doc_description

                    definitions.update(swag.get('definitions', {}))
                    defs = []  # swag.get('definitions', [])
                    defs += extract_definitions(defs,
                                                endpoint=rule.endpoint,
                                                verb=verb,
                                                prefix_ids=prefix_ids)

                    params = swag.get('parameters', [])
                    defs += extract_definitions(params,
                                                endpoint=rule.endpoint,
                                                verb=verb,
                                                prefix_ids=prefix_ids)

                    responses = None
                    if 'responses' in swag:
                        responses = swag.get('responses', {})
                        responses = {
                            str(key): value
                            for key, value in responses.items()
                        }
                        if responses is not None:
                            defs = defs + extract_definitions(
                                responses.values(),
                                endpoint=rule.endpoint,
                                verb=verb,
                                prefix_ids=prefix_ids)
                        for definition in defs:
                            if 'id' not in definition:
                                definitions.update(definition)
                                continue
                            def_id = definition.pop('id')
                            if def_id is not None:
                                definitions[def_id].update(definition)

                    operation = {}
                    if swag.get('summary'):
                        operation['summary'] = swag.get('summary')
                    if swag.get('description'):
                        operation['description'] = swag.get('description')
                    if responses:
                        operation['responses'] = responses
                    # parameters - swagger ui dislikes empty parameter lists
                    if len(params) > 0:
                        operation['parameters'] = params
                    # other optionals
                    for key in optional_fields:
                        if key in swag:
                            value = swag.get(key)
                            if key in ('produces', 'consumes'):
                                if not isinstance(value, (list, tuple)):
                                    value = [value]

                            operation[key] = value
                    operations[verb] = operation

            if len(operations):
                srule = str(rule)
                # old regex '(<(.*?\:)?(.*?)>)'
                for arg in re.findall('(<([^<>]*:)?([^<>]*)>)', srule):
                    srule = srule.replace(arg[0], '{%s}' % arg[2])

                for key, val in operations.items():
                    if key in paths[srule]:
                        paths[srule][key].update(val)
                    else:
                        paths[srule][key] = val
        return jsonify(data)
Ejemplo n.º 2
0
    def get(self):
        """
        The Swagger view get method outputs to /apispecs_1.json
        """
        data = {
            "swagger":
            self.config.get('swagger')
            or self.config.get('swagger_version', "2.0"),
            # try to get from config['SWAGGER']['info']
            # then config['SWAGGER']['specs'][x]
            # then config['SWAGGER']
            # then default
            "info":
            self.config.get('info') or {
                "version":
                self.spec.get('version', self.config.get('version', "0.0.1")),
                "title":
                self.spec.get('title',
                              self.config.get('title', "A swagger API 2")),
                "description":
                self.spec.get(
                    'description',
                    self.config.get('description', "powered by Flasgger")),
                "termsOfService":
                self.spec.get('termsOfService',
                              self.config.get('termsOfService', "/tos")),
            },
            "paths":
            self.config.get('paths') or defaultdict(dict),
            "definitions":
            self.config.get('definitions') or defaultdict(dict)
        }

        # Support extension properties in the top level config
        top_level_extension_options = get_vendor_extension_fields(self.config)
        if top_level_extension_options:
            data.update(top_level_extension_options)

        # if True schemaa ids will be prefized by function_method_{id}
        # for backwards compatibility with <= 0.5.14
        prefix_ids = self.config.get('prefix_ids')

        if self.config.get('host'):
            data['host'] = self.config.get('host')
        if self.config.get("basePath"):
            data["basePath"] = self.config.get('basePath')
        if self.config.get("securityDefinitions"):
            data["securityDefinitions"] = self.config.get(
                'securityDefinitions')
        # set defaults from template
        if self.template is not None:
            data.update(self.template)

        paths = data['paths']
        definitions = data['definitions']
        ignore_verbs = set(self.config.get('ignore_verbs',
                                           ("HEAD", "OPTIONS")))

        # technically only responses is non-optional
        optional_fields = self.config.get('optional_fields') or OPTIONAL_FIELDS

        for name, def_model in self.get_def_models(
                self.spec.get('definition_filter')).items():
            description, swag = parse_definition_docstring(
                def_model, self.process_doc)
            if name and swag:
                if description:
                    swag.update({'description': description})
                definitions[name].update(swag)

        specs = get_specs(self.get_url_mappings(self.spec.get('rule_filter')),
                          ignore_verbs, optional_fields, self.process_doc)

        for rule, verbs in specs:
            operations = dict()
            for verb, swag in verbs:
                definitions.update(swag.get('definitions', {}))
                defs = []  # swag.get('definitions', [])
                defs += extract_definitions(defs,
                                            endpoint=rule.endpoint,
                                            verb=verb,
                                            prefix_ids=prefix_ids)

                params = swag.get('parameters', [])
                defs += extract_definitions(params,
                                            endpoint=rule.endpoint,
                                            verb=verb,
                                            prefix_ids=prefix_ids)

                responses = None
                if 'responses' in swag:
                    responses = swag.get('responses', {})
                    responses = {
                        str(key): value
                        for key, value in responses.items()
                    }
                    if responses is not None:
                        defs = defs + extract_definitions(
                            responses.values(),
                            endpoint=rule.endpoint,
                            verb=verb,
                            prefix_ids=prefix_ids)
                    for definition in defs:
                        if 'id' not in definition:
                            definitions.update(definition)
                            continue
                        def_id = definition.pop('id')
                        if def_id is not None:
                            definitions[def_id].update(definition)

                operation = {}
                if swag.get('summary'):
                    operation['summary'] = swag.get('summary')
                if swag.get('description'):
                    operation['description'] = swag.get('description')
                if responses:
                    operation['responses'] = responses
                # parameters - swagger ui dislikes empty parameter lists
                if len(params) > 0:
                    operation['parameters'] = params
                # other optionals
                for key in optional_fields:
                    if key in swag:
                        value = swag.get(key)
                        if key in ('produces', 'consumes'):
                            if not isinstance(value, (list, tuple)):
                                value = [value]

                        operation[key] = value
                operations[verb] = operation

            if len(operations):
                srule = str(rule)
                # old regex '(<(.*?\:)?(.*?)>)'
                for arg in re.findall('(<([^<>]*:)?([^<>]*)>)', srule):
                    srule = srule.replace(arg[0], '{%s}' % arg[2])

                for key, val in operations.items():
                    if key in paths[srule]:
                        paths[srule][key].update(val)
                    else:
                        paths[srule][key] = val
        return jsonify(data)