blueprints.py 5.61 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
22

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

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

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

30
BASIC_PARAMS = {
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
    "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"
    },
48
}
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
49

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

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

    outdict = {}
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
60
    wrong_params = {}
61
    for param, options in params.iteritems():
62
63
64
65
66
67
68
69
70
71
72
        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
73
            else:
74
75
76
                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
77
    if wrong_params:
78
79
80
81
82
83
        message = Error({"status": 404,
                         "message": "Missing or invalid parameters",
                         "parameters": outdict,
                         "errors": {param: error for param, error in
                                    wrong_params.iteritems()}
                         })
84
        raise ValueError(message)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
85
86
    return outdict

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

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
88
def basic_analysis(params):
89
90
91
92
93
94
95
    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
96
                "analysis": [{"@type": "marl:SentimentAnalysis"}],
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
97
98
99
100
                "entries": []
                }
    if "language" in params:
        response["language"] = params["language"]
101
    for idx, sentence in enumerate(params["input"].split(".")):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
102
        response["entries"].append({
103
            "@id": "Sentence{}".format(idx),
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
104
105
106
107
            "nif:isString": sentence
        })
    return response

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

Ignacio Corcuera's avatar
Ignacio Corcuera committed
109
110
111
112
113
114
115
@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
116
    try:
117
118
        params = get_params(request)
        algo = params.get("algorithm", None)
119
        specific_params = current_app.senpy.parameters(algo)
120
121
        logger.debug(
            "Specific params: %s", json.dumps(specific_params, indent=4))
122
        params.update(get_params(request, specific_params))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
123
        response = current_app.senpy.analyse(**params)
124
125
        in_headers = params["inHeaders"] != "0"
        return response.flask(in_headers=in_headers)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
126
    except ValueError as ex:
127
        return ex.message.flask()
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
128

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

Ignacio Corcuera's avatar
Ignacio Corcuera committed
130
@nif_blueprint.route("/api/default")
131
def default():
132
133
134
135
136
137
138
    # 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()
139

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

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

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

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

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