Esempio n. 1
0
def parameters():
    parameters = OrderedDict()
    for (resource_name, rd) in app.config['DOMAIN'].items():
        if (resource_name.endswith('_versions')
                or rd.get('disable_documentation')):
            continue

        title = rd['item_title']
        lookup_field = rd['item_lookup_field']
        if lookup_field not in rd['schema']:
            rd['schema'][lookup_field] = {'type': 'objectid'}
        eve_type = rd['schema'][lookup_field]['type']
        descr = rd['schema'][lookup_field].get('description') or ''
        example = rd['schema'][lookup_field].get('example') or ''
        if 'data_relation' in rd['schema'][lookup_field]:
            # the lookup field is a copy of another field
            dr = rd['schema'][lookup_field]['data_relation']

            # resource definition of the data relation source
            source_rd = app.config['DOMAIN'][dr['resource']]

            # schema of the data relation source field
            source_def = source_rd['schema'][dr['field']]

            # key in #/definitions/...
            source_def_name = source_rd['item_title'] + '_' + dr['field']

            # copy description if necessary
            descr = descr or source_def.get('description')
            descr = descr + ' (links to {0})'.format(source_def_name)

        p = OrderedDict()
        p['in'] = 'path'
        p['name'] = title.lower() + 'Id'
        p['required'] = True
        p['description'] = descr
        p['example'] = example
        p['type'] = eve_type
        if eve_type == 'objectid':
            p['type'] = 'string'
            p['format'] = 'objectid'
        elif eve_type == 'datetime':
            p['type'] = 'string'
            p['format'] = 'date-time'
        elif eve_type == 'float':
            p['type'] = 'number'
            p['format'] = 'float'

        parameters[title + '_' + lookup_field] = p

    return parameters
Esempio n. 2
0
def delete_response(rd):
    return OrderedDict([('summary', 'Deletes all %s' % rd['resource_title']),
                        ('responses', {
                            '204': {
                                'description': 'operation has been successful'
                            }
                        }), ('tags', [rd['item_title']])])
Esempio n. 3
0
def get_parameters(rd):
    return OrderedDict([
        ('in', 'body'),
        ('name', rd['item_title']),
        ('required', True),
        ('schema', get_ref_schema(rd)),
    ])
Esempio n. 4
0
def index():
    def node(parent, key, value):
        if value:
            parent[key] = value

    root = OrderedDict()
    root['swagger'] = '2.0'
    node(root, 'info', info())
    node(root, 'host', host())
    node(root, 'basePath', base_path())
    node(root, 'schemes', schemes())
    node(root, 'consumes', consumes())
    node(root, 'produces', produces())
    node(root, 'paths', paths())
    node(root, 'definitions', definitions())
    node(root, 'parameters', parameters())
    node(root, 'responses', responses())
    node(root, 'securityDefinitions', security_definitions())
    node(root, 'security', security())
    node(root, 'tags', tags())
    node(root, 'externalDocs', external_docs())

    _nested_update(root, swagger.additional_documentation)

    return jsonify(root)
Esempio n. 5
0
def paths():
    def _clear_regex(_str):
        return '/'.join(
            map(lambda x: re.sub('regex(.*):', '', x), _str.split('/')))

    paths = OrderedDict()
    for resource, rd in app.config['DOMAIN'].items():
        if (rd.get('disable_documentation') or resource.endswith('_versions')):
            continue

        rd['url'] = _clear_regex(rd['url'])
        rd['resource_title'] = _clear_regex(rd['resource_title'])

        methods = rd['resource_methods']
        if methods:
            url = '/%s' % rd['url']
            paths[url] = _resource(resource, rd, methods)

        methods = rd['item_methods']
        if methods:
            item_id = '%sId' % rd['item_title'].lower()
            url = '/%s/{%s}' % (rd['url'], item_id)
            paths[url] = _item(resource, rd, methods)

    return paths
Esempio n. 6
0
def header_parameters():
    r = OrderedDict()
    r['in'] = 'header'
    r['name'] = 'If-Match'
    r['description'] = 'Current value of the _etag field'
    r['required'] = app.config['IF_MATCH'] and app.config['ENFORCE_IF_MATCH']
    r['type'] = 'string'
    return r
Esempio n. 7
0
def definitions():
    definitions = OrderedDict()
    dr_sources = {}
    for rd in app.config['DOMAIN'].values():
        dr_sources.update(_get_dr_sources(rd['schema']))

    for rd in app.config['DOMAIN'].values():
        if rd.get('disable_documentation'):
            continue
        title = rd['item_title']
        definitions[title] = _object(rd, dr_sources)
        if 'description' in rd:
            definitions[title]['description'] = rd['description']

    # add data_relation source fields to #/definitions/
    definitions.update(dr_sources)
    return definitions
Esempio n. 8
0
def definitions():
    definitions = OrderedDict()
    dr_sources = {}
    for rd in app.config["DOMAIN"].values():
        dr_sources.update(_get_dr_sources(rd["schema"]))

    for rd in app.config["DOMAIN"].values():
        if rd.get("disable_documentation"):
            continue
        title = rd["item_title"]
        definitions[title] = _object(rd, dr_sources)
        if "description" in rd:
            definitions[title]["description"] = rd["description"]

    # add data_relation source fields to #/definitions/
    definitions.update(dr_sources)
    return definitions
Esempio n. 9
0
def definitions():
    definitions = OrderedDict()
    dr_sources = {}
    for rd in app.config['DOMAIN'].values():
        dr_sources.update(_get_dr_sources(rd['schema']))

    for rd in app.config['DOMAIN'].values():
        if rd.get('disable_documentation'):
            continue
        title = rd['item_title']
        definitions[title] = _object(rd, dr_sources)
        if 'description' in rd:
            definitions[title]['description'] = rd['description']

    # add data_relation source fields to #/definitions/
    definitions.update(dr_sources)
    return definitions
Esempio n. 10
0
def header_parameters():
    r = OrderedDict()
    r['in'] = 'header'
    r['name'] = 'If-Match'
    r['description'] = 'Current value of the _etag field'
    r['required'] = True
    r['type'] = 'string'
    return r
Esempio n. 11
0
def post_response(rd):
    return OrderedDict([('summary',
                         'Stores one or more %s' % rd['resource_title']),
                        ('parameters', [get_parameters(rd)]),
                        ('responses', {
                            '201': {
                                'description': 'operation has been successful'
                            }
                        }), ('tags', [rd['item_title']])])
Esempio n. 12
0
def getitem_response(rd):
    title = rd['item_title']
    return OrderedDict([('summary', 'Retrieves a %s document' % title),
                        ('responses', {
                            '200': {
                                'description':
                                '%s document fetched successfully' % title,
                                'schema':
                                get_ref_schema(rd)
                            },
                        }), ('parameters', [id_parameter(rd)]),
                        ('tags', [rd['item_title']])])
Esempio n. 13
0
def get_response(rd):
    title = rd['resource_title']
    return OrderedDict([('summary', 'Retrieves one or more %s' % title),
                        ('responses', {
                            '200': {
                                'description': 'An array of %s' % title,
                                'schema': {
                                    'type': 'array',
                                    'items': get_ref_schema(rd)
                                }
                            }
                        }), ('tags', [rd['item_title']])])
Esempio n. 14
0
def deleteitem_response(rd):
    title = rd['item_title']
    return OrderedDict([('summary', 'Deletes a %s document' % title),
                        ('responses', {
                            '204': {
                                'description':
                                '%s document deleted successfully' % title
                            }
                        }),
                        ('parameters', [id_parameter(rd),
                                        header_parameters()]),
                        ('tags', [rd['item_title']])])
Esempio n. 15
0
def put_response(rd):
    title = rd['item_title']
    return OrderedDict([
        ('summary', 'Replaces a %s document' % title),
        ('responses', {
            '200': {
                'description': '%s document replaced successfully' % title
            }
        }),
        ('parameters',
         [id_parameter(rd),
          get_parameters(rd),
          header_parameters()]), ('tags', [rd['item_title']])
    ])
Esempio n. 16
0
def _resource(resource, rd, methods):
    item = OrderedDict()
    describe_hooks = app.config.get('ENABLE_HOOK_DESCRIPTION', False)
    if 'GET' in methods:
        item['get'] = get_response(rd)
    if 'POST' in methods:
        item['post'] = post_response(rd)
    if 'DELETE' in methods:
        item['delete'] = delete_response(rd)

    if describe_hooks:
        for m in methods:
            hook_desc = _hook_descriptions(resource, m)
            if hook_desc != '':
                item[m.lower()]['description'] = '**Hooks**:' + hook_desc

    return item
Esempio n. 17
0
def paths():
    paths = OrderedDict()
    for resource, rd in app.config['DOMAIN'].items():
        if (rd.get('disable_documentation') or resource.endswith('_versions')):
            continue

        methods = rd['resource_methods']
        if methods:
            url = '/%s' % rd['url']
            paths[url] = _resource(resource, rd, methods)

        methods = rd['item_methods']
        if methods:
            item_id = '%sId' % rd['item_title'].lower()
            url = '/%s/{%s}' % (rd['url'], item_id)
            paths[url] = _item(resource, rd, methods)

    return paths
Esempio n. 18
0
def info():
    validate_info()

    cfg = app.config[eve_swagger.INFO]

    def node(parent, cfg, key):
        value = cfg.get(key)
        if value:
            parent[key] = cfg[key]

    info = OrderedDict()
    node(info, cfg, 'title')
    node(info, cfg, 'description')
    node(info, cfg, 'termsOfService')
    node(info, cfg, 'contact')
    node(info, cfg, 'license')
    node(info, cfg, 'version')

    return info
Esempio n. 19
0
def _item(resource, rd, methods):
    item = OrderedDict()
    describe_hooks = app.config.get('ENABLE_HOOK_DESCRIPTION', False)
    if 'GET' in methods:
        item['get'] = getitem_response(rd)
    if 'PUT' in methods:
        item['put'] = put_response(rd)
    if 'PATCH' in methods:
        item['patch'] = patch_response(rd)
    if 'DELETE' in methods:
        item['delete'] = deleteitem_response(rd)

    if describe_hooks:
        for m in methods:
            hook_desc = _hook_descriptions(resource, m, item=True)
            if hook_desc != '':
                item[m.lower()]['description'] = '**Hooks**:' + hook_desc

    return item
Esempio n. 20
0
def _object(rd, dr_sources):
    props = {}
    required = []
    for field, rules in rd['schema'].items():
        if rules.get('required') is True:
            required.append(field)

        def_name = rd['item_title'] + '_' + field
        props[field] = _field_props(rules, dr_sources, def_name)

        if def_name in dr_sources:
            # the current field is a source of a data_relation

            # replace None in dr_sources with the field properties
            dr_sources[def_name] = OrderedDict(props[field])

            props[field] = {'$ref': '#/definitions/{0}'.format(def_name)}

        if 'data_relation' in rules:
            # the current field is a copy of another field
            dr = rules['data_relation']
            if dr['resource'] not in app.config['DOMAIN']:
                # source of data_relation does not exist
                continue
            title = app.config['DOMAIN'][dr['resource']]['item_title']
            source_def_name = title + '_' + dr['field']
            props[field] = {
                '$ref': '#/definitions/{0}'.format(source_def_name)
            }

    field_def = {}
    field_def['type'] = 'object'
    field_def['properties'] = props
    if len(required):
        field_def['required'] = required
    return field_def
Esempio n. 21
0
"""
import re
from collections import Mapping
from flask import Blueprint, jsonify, make_response, request, \
    current_app as app
from functools import wraps

from eve_swagger import OrderedDict
from .definitions import definitions
from .objects import info, host, base_path, schemes, consumes, produces, \
    parameters, responses, security_definitions, security, tags, \
    external_docs
from .paths import paths

swagger = Blueprint('eve_swagger', __name__)
swagger.additional_documentation = OrderedDict()


def add_documentation(doc):
    _nested_update(swagger.additional_documentation, doc)


def _modify_response(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if request.method == 'OPTIONS':
            resp = app.make_default_options_response()
        else:
            resp = make_response(f(*args, **kwargs))

        # CORS
Esempio n. 22
0
def parameters():
    parameters = OrderedDict()
    for (resource_name, rd) in app.config['DOMAIN'].items():
        if (resource_name.endswith('_versions')
                or rd.get('disable_documentation')):
            continue

        title = rd['item_title']
        lookup_field = rd['item_lookup_field']
        if lookup_field not in rd['schema']:
            rd['schema'][lookup_field] = {'type': 'objectid'}
        eve_type = rd['schema'][lookup_field]['type']
        descr = rd['schema'][lookup_field].get('description') or ''
        example = rd['schema'][lookup_field].get('example') or ''
        if 'data_relation' in rd['schema'][lookup_field]:
            # the lookup field is a copy of another field
            dr = rd['schema'][lookup_field]['data_relation']

            # resource definition of the data relation source
            source_rd = app.config['DOMAIN'][dr['resource']]

            # schema of the data relation source field
            source_def = source_rd['schema'][dr['field']]

            # key in #/definitions/...
            source_def_name = source_rd['item_title'] + '_' + dr['field']

            # copy description if necessary
            descr = descr or source_def.get('description')
            descr = descr + ' (links to {0})'.format(source_def_name)

        p = OrderedDict()
        p['in'] = 'path'
        p['name'] = title.lower() + 'Id'
        p['required'] = True
        p['description'] = descr
        p['example'] = example
        p['type'] = eve_type
        if eve_type == 'objectid':
            p['type'] = 'string'
            p['format'] = 'objectid'
        elif eve_type == 'datetime':
            p['type'] = 'string'
            p['format'] = 'date-time'
        elif eve_type == 'float':
            p['type'] = 'number'
            p['format'] = 'float'

        parameters[title + '_' + lookup_field] = p

    # Let's add the technical eve parameters : projection(field selection),
    # embedded(relationship) and where (sort)
    if rd['projection']:
        p = OrderedDict()
        p['in'] = 'query'
        p['name'] = 'projection'
        p['required'] = False
        p['description'] = 'Allow to select fields :\n' \
                           ' by addition : {"lastname": 1, "born": 1}=> only '\
                           'these two fields\n' \
                           ' or by subtraction {"born": 0} => wihtout ' \
                           'the "born" field'
        p['example'] = '{"lastname": 1, "born": 1} or {"born": 0}'
        p['type'] = 'string'
        parameters[p['name']] = p

    if rd['embedding']:
        p = OrderedDict()
        p['in'] = 'query'
        p['name'] = 'embedded'
        p['required'] = False
        p['description'] = 'Allow to embed the other side of a relationship' \
                           ' into the current payload :\n' \
                           ' format {"author":1, "phones":0} => embed the ' \
                           'author but don\'t embed the phone\n' \
                           'see http://docs.python-eve.org/en/latest' \
                           'features.html#projections'
        p['example'] = '{"author":1,"cosignees":1}'
        p['type'] = 'string'
        parameters[p['name']] = p

    if rd['sorting']:
        p = OrderedDict()
        p['in'] = 'query'
        p['name'] = 'where'
        p['required'] = False
        p['description'] = 'see https://eve-sqlalchemy.readthedocs.io/en/' \
                           'latest/tutorial.html#sqlalchemy-expressions'
        p['example'] = '{"firstname":"in(\"(\'John\',\'Fred\'\"))" ' \
                       'or {"lastname":"like(\"Smi%\")"}'
        p['type'] = 'string'
        parameters[p['name']] = p

    if rd['allowed_filters']:
        p = OrderedDict()
        p['in'] = 'query'
        p['name'] = 'sort'
        p['required'] = False
        p['description'] = 'see https://eve-sqlalchemy.readthedocs.io/en' \
                           '/latest/tutorial.html#sqlalchemy-sorting'
        p['example'] = '[("lastname", -1, "nullslast")] ' \
                       'or lastname,-created_at'
        p['type'] = 'string'
        parameters[p['name']] = p

    return parameters