blueprints.py 5.5 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
"""
20
from flask import Blueprint, request, current_app
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__)

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

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
58
59
60
        indict = req.args
    else:
        raise ValueError("Invalid data")

    outdict = {}
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
61
    wrong_params = {}
62
    for param, options in params.iteritems():
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
83
84
        message = Error({"status": 404,
                         "message": "Missing or invalid parameters",
                         "parameters": outdict,
                         "errors": {param: error for param, error in
                                    wrong_params.iteritems()}
                         })
85
        raise ValueError(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

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

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

126
127
@nif_blueprint.route("/default")
def default():
128
129
130
131
132
133
134
    # 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()
135

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

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

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

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
166
if __name__ == '__main__':
167
    import config
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
168
    from flask import Flask
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
169

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
170
    app = Flask(__name__)
171
    app.register_blueprint(nif_blueprint)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
172
173
    app.debug = config.DEBUG
    app.run()