blueprints.py 5.64 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
"""
Ignacio Corcuera's avatar
Ignacio Corcuera committed
20
from flask import Blueprint, request, current_app, Flask, redirect, url_for, render_template
21
from .models import Error, Response, Leaf
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
22
from future.utils import iteritems
23

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
24
import json
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
25
import logging
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
26

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

29
nif_blueprint = Blueprint("NIF Sentiment Analysis Server", __name__)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
30

31
BASIC_PARAMS = {
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
    "algorithm": {
        "aliases": ["algorithm", "a", "algo"],
        "required": False,
    },
    "inHeaders": {
        "aliases": ["inHeaders", "headers"],
        "required": True,
        "default": "0"
    }
}

LIST_PARAMS = {
    "params": {
        "aliases": ["params", "with_params"],
        "required": False,
        "default": "0"
    },
49
}
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
50

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

52
def get_params(req, params=BASIC_PARAMS):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
53
54
    if req.method == 'POST':
        indict = req.form
J. Fernando Sánchez's avatar
Oups    
J. Fernando Sánchez committed
55
    elif req.method == 'GET':
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
56
57
        indict = req.args
    else:
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
58
        raise Error(message="Invalid data")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
59
60

    outdict = {}
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
61
    wrong_params = {}
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
62
    for param, options in iteritems(params):
63
64
65
66
67
68
69
70
71
72
73
        if param[0] != "@":  # Exclude json-ld properties
            logger.debug("Param: %s - Options: %s", param, options)
            for alias in options["aliases"]:
                if alias in indict:
                    outdict[param] = indict[alias]
            if param not in outdict:
                if options.get("required", False) and "default" not in options:
                    wrong_params[param] = params[param]
                else:
                    if "default" in options:
                        outdict[param] = options["default"]
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
74
            else:
75
76
77
                if "options" in params[param] and \
                   outdict[param] not in params[param]["options"]:
                    wrong_params[param] = params[param]
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
78
    if wrong_params:
79
80
81
82
        message = Error({"status": 404,
                         "message": "Missing or invalid parameters",
                         "parameters": outdict,
                         "errors": {param: error for param, error in
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
83
                                    iteritems(wrong_params)}
84
                         })
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
85
        raise Error(message=message)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
86
87
    return outdict

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

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
89
def basic_analysis(params):
90
91
92
93
94
95
96
    response = {"@context":
                [("http://demos.gsi.dit.upm.es/"
                  "eurosentiment/static/context.jsonld"),
                 {
                    "@base": "{}#".format(request.url.encode('utf-8'))
                  }
                 ],
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
97
                "analysis": [{"@type": "marl:SentimentAnalysis"}],
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
98
99
100
101
                "entries": []
                }
    if "language" in params:
        response["language"] = params["language"]
102
    for idx, sentence in enumerate(params["input"].split(".")):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
103
        response["entries"].append({
104
            "@id": "Sentence{}".format(idx),
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
105
106
107
108
            "nif:isString": sentence
        })
    return response

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

Ignacio Corcuera's avatar
Ignacio Corcuera committed
110
111
112
113
114
115
116
@nif_blueprint.route('/')
def index():
    return render_template("index.html")


@nif_blueprint.route('/api', methods=['POST', 'GET'])
def api():
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
117
    try:
118
119
        params = get_params(request)
        algo = params.get("algorithm", None)
120
        specific_params = current_app.senpy.parameters(algo)
121
122
        logger.debug(
            "Specific params: %s", json.dumps(specific_params, indent=4))
123
        params.update(get_params(request, specific_params))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
124
        response = current_app.senpy.analyse(**params)
125
126
        in_headers = params["inHeaders"] != "0"
        return response.flask(in_headers=in_headers)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
127
    except Error as ex:
128
        return ex.message.flask()
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
129

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

Ignacio Corcuera's avatar
Ignacio Corcuera committed
131
@nif_blueprint.route("/api/default")
132
def default():
133
134
135
136
137
138
139
    # return current_app.senpy.default_plugin
    plug = current_app.senpy.default_plugin
    if plug:
        return plugins(action="list", plugin=plug.name)
    else:
        error = Error(status=404, message="No plugins found")
        return error.flask()
140

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

Ignacio Corcuera's avatar
Ignacio Corcuera committed
142
143
144
@nif_blueprint.route('/api/plugins/', methods=['POST', 'GET'])
@nif_blueprint.route('/api/plugins/<plugin>', methods=['POST', 'GET'])
@nif_blueprint.route('/api/plugins/<plugin>/<action>', methods=['POST', 'GET'])
145
def plugins(plugin=None, action="list"):
146
    filt = {}
147
    sp = current_app.senpy
148
    if plugin:
149
        filt["name"] = plugin
150
    plugs = sp.filter_plugins(**filt)
151
152
    if plugin and not plugs:
        return "Plugin not found", 400
153
    if action == "list":
154
155
        with_params = get_params(request, LIST_PARAMS)["params"] == "1"
        in_headers = get_params(request, BASIC_PARAMS)["inHeaders"] != "0"
156
        if plugin:
157
            dic = plugs[plugin]
158
        else:
159
160
161
162
            dic = Response(
                    {plug: plugs[plug].jsonld(with_params) for plug in plugs},
                    frame={})
        return dic.flask(in_headers=in_headers)
163
164
165
    method = "{}_plugin".format(action)
    if(hasattr(sp, method)):
        getattr(sp, method)(plugin)
166
        return Leaf(message="Ok").flask()
167
    else:
168
        return Error("action '{}' not allowed".format(action)).flask()
169

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

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
171
if __name__ == '__main__':
172
    import config
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
173

174
    app.register_blueprint(nif_blueprint)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
175
    app.debug = config.DEBUG
Ignacio Corcuera's avatar
Ignacio Corcuera committed
176
    app.run(host='0.0.0.0', port=5000)