blueprints.py 4.93 KB
Newer Older
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
1
2
#!/usr/bin/python
# -*- coding: utf-8 -*-
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
3
4
# Copyright 2014 J. Fernando Sánchez Rada - Grupo de Sistemas Inteligentes
# DIT, UPM
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
5
#
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
6
7
8
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
9
#
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
10
# http://www.apache.org/licenses/LICENSE-2.0
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
11
#
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
12
# Unless required by applicable law or agreed to in writing, software
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
13
14
15
16
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
17
18
19
"""
Blueprints for Senpy
"""
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
20
21
from flask import (Blueprint, request, current_app, render_template, url_for,
                   jsonify)
22
from .models import Error, Response, Plugins, read_schema
23
from .api import WEB_PARAMS, API_PARAMS, CLI_PARAMS, NIF_PARAMS, parse_params
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
24
from .version import __version__
25
from functools import wraps
26

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
27
import logging
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
28
import json
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
29

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
30
31
logger = logging.getLogger(__name__)

32
33
api_blueprint = Blueprint("api", __name__)
demo_blueprint = Blueprint("demo", __name__)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
34
ns_blueprint = Blueprint("ns", __name__)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
35

J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
36

37
def get_params(req):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
38
    if req.method == 'POST':
39
        indict = req.form.to_dict(flat=True)
J. Fernando Sánchez's avatar
Oups    
J. Fernando Sánchez committed
40
    elif req.method == 'GET':
41
        indict = req.args.to_dict(flat=True)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
42
    else:
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
43
        raise Error(message="Invalid data")
44
    return indict
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
45

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
46

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
47
@demo_blueprint.route('/')
Ignacio Corcuera's avatar
Ignacio Corcuera committed
48
def index():
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
49
    return render_template("index.html", version=__version__)
Ignacio Corcuera's avatar
Ignacio Corcuera committed
50

J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
51

52
53
@api_blueprint.route('/contexts/<entity>.jsonld')
def context(entity="context"):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
54
55
56
57
58
59
60
61
62
63
    context = Response._context
    context['@vocab'] = url_for('ns.index', _external=True)
    return jsonify({"@context": context})


@ns_blueprint.route('/')  # noqa: F811
def index():
    context = Response._context
    context['@vocab'] = url_for('.ns', _external=True)
    return jsonify({"@context": context})
Ignacio Corcuera's avatar
Ignacio Corcuera committed
64

J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
65

66
67
@api_blueprint.route('/schemas/<schema>')
def schema(schema="definitions"):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
68
    try:
69
        return jsonify(read_schema(schema))
J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
70
    except Exception:  # Should be FileNotFoundError, but it's missing from py2
71
72
        return Error(message="Schema not found", status=404).flask()

J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
73

74
75
76
def basic_api(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
77
        raw_params = get_params(request)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
78
        headers = {'X-ORIGINAL-PARAMS': json.dumps(raw_params)}
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
79
80
81
        # Get defaults
        web_params = parse_params({}, spec=WEB_PARAMS)
        api_params = parse_params({}, spec=API_PARAMS)
82

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
83
        outformat = 'json-ld'
84
        try:
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
85
86
87
88
89
90
91
92
            print('Getting request:')
            print(request)
            web_params = parse_params(raw_params, spec=WEB_PARAMS)
            api_params = parse_params(raw_params, spec=API_PARAMS)
            if hasattr(request, 'params'):
                request.params.update(api_params)
            else:
                request.params = api_params
93
94
95
            response = f(*args, **kwargs)
        except Error as ex:
            response = ex
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
96
97
98
            logger.error(ex)
            if current_app.debug:
                raise
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
99
100
101
102
103

        in_headers = web_params['inHeaders'] != "0"
        expanded = api_params['expanded-jsonld']
        outformat = api_params['outformat']

J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
104
105
106
        return response.flask(
            in_headers=in_headers,
            headers=headers,
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
107
108
109
110
111
112
            prefix=url_for('.api', _external=True),
            context_uri=url_for('api.context',
                                entity=type(response).__name__,
                                _external=True),
            outformat=outformat,
            expanded=expanded)
J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
113

114
    return decorated_function
J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
115
116


117
118
119
@api_blueprint.route('/', methods=['POST', 'GET'])
@basic_api
def api():
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
120
121
    response = current_app.senpy.analyse(**request.params)
    return response
122
123
124
125


@api_blueprint.route('/plugins/', methods=['POST', 'GET'])
@basic_api
126
127
def plugins():
    sp = current_app.senpy
128
129
130
    ptype = request.params.get('plugin_type')
    plugins = sp.filter_plugins(plugin_type=ptype)
    dic = Plugins(plugins=list(plugins.values()))
131
    return dic
J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
132
133


134
135
@api_blueprint.route('/plugins/<plugin>/', methods=['POST', 'GET'])
@basic_api
136
def plugin(plugin=None):
137
    sp = current_app.senpy
138
    if plugin == 'default' and sp.default_plugin:
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
139
140
141
142
143
        return sp.default_plugin
    plugins = sp.filter_plugins(
        id='plugins/{}'.format(plugin)) or sp.filter_plugins(name=plugin)
    if plugins:
        response = list(plugins.values())[0]
144
    else:
145
        return Error(message="Plugin not found", status=404)
146
    return response
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

@api_blueprint.route('/params/', methods=['POST', 'GET'])
@basic_api
def params():
    phelp = request.params.get('help')
    if eval(phelp):
        dic = {'WEB_PARAMS': WEB_PARAMS, 
               'CLI_PARAMS': CLI_PARAMS, 
               'NIF_PARAMS': NIF_PARAMS, 
               'API_PARAMS': API_PARAMS
            }
        response = Response(dic)
        return response
    else:
        response = Response(request.params)
        return response