blueprints.py 5.43 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
from .models import Error, Response
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
demo_blueprint = Blueprint("Demo of the service. It includes an HTML+Javascript playground to test senpy", __name__)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
31

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

44
def get_params(req, params=BASIC_PARAMS):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
45
46
    if req.method == 'POST':
        indict = req.form
J. Fernando Sánchez's avatar
Oups    
J. Fernando Sánchez committed
47
    elif req.method == 'GET':
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
48
49
        indict = req.args
    else:
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
50
        raise Error(message="Invalid data")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
51
52

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

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

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

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

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
101
@demo_blueprint.route('/')
Ignacio Corcuera's avatar
Ignacio Corcuera committed
102
103
104
105
def index():
    return render_template("index.html")


J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
106
@nif_blueprint.route('/', methods=['POST', 'GET'])
Ignacio Corcuera's avatar
Ignacio Corcuera committed
107
def api():
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
108
    try:
109
110
        params = get_params(request)
        algo = params.get("algorithm", None)
111
        specific_params = current_app.senpy.parameters(algo)
112
113
        logger.debug(
            "Specific params: %s", json.dumps(specific_params, indent=4))
114
        params.update(get_params(request, specific_params))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
115
        response = current_app.senpy.analyse(**params)
116
117
        in_headers = params["inHeaders"] != "0"
        return response.flask(in_headers=in_headers)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
118
    except Error as ex:
119
        return ex.message.flask()
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
120

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

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
122
@nif_blueprint.route("/default")
123
def default():
124
125
126
127
128
129
130
    # 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()
131

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

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
133
134
135
@nif_blueprint.route('/plugins/', methods=['POST', 'GET'])
@nif_blueprint.route('/plugins/<plugin>/', methods=['POST', 'GET'])
@nif_blueprint.route('/plugins/<plugin>/<action>', methods=['POST', 'GET'])
136
def plugins(plugin=None, action="list"):
137
    filt = {}
138
    sp = current_app.senpy
139
    if plugin:
140
        filt["name"] = plugin
141
    plugs = sp.filter_plugins(**filt)
142
143
    if plugin and not plugs:
        return "Plugin not found", 400
144
    if action == "list":
145
        in_headers = get_params(request, BASIC_PARAMS)["inHeaders"] != "0"
146
        if plugin:
147
            dic = plugs[plugin]
148
        else:
149
            dic = Response(
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
150
                    {plug: plugs[plug].serializable() for plug in plugs})
151
        return dic.flask(in_headers=in_headers)
152
153
154
    method = "{}_plugin".format(action)
    if(hasattr(sp, method)):
        getattr(sp, method)(plugin)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
155
        return Response(message="Ok").flask()
156
    else:
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
157
        return Error(message="action '{}' not allowed".format(action)).flask()
158

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

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
160
if __name__ == '__main__':
161
    import config
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
162

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