2019-01-07 11:08:19 +00:00
|
|
|
#!/usr/local/bin/python
|
|
|
|
# -*- coding: utf-8 -*-
|
2019-07-17 14:29:30 +00:00
|
|
|
#
|
|
|
|
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
|
|
|
|
#
|
|
|
|
# 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
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# 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.
|
|
|
|
#
|
|
|
|
|
2019-01-07 11:08:19 +00:00
|
|
|
|
|
|
|
from future.standard_library import install_aliases
|
|
|
|
install_aliases()
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
from rdflib import Graph
|
|
|
|
from senpy.extensions import Senpy
|
|
|
|
from flask import Flask
|
|
|
|
from unittest import TestCase
|
|
|
|
|
|
|
|
from urllib.parse import urlencode
|
|
|
|
|
|
|
|
|
|
|
|
def parse_resp(resp, fmt):
|
|
|
|
return Graph().parse(data=resp.data.decode(), format=fmt)
|
|
|
|
|
|
|
|
|
|
|
|
class SemanticsTest(TestCase):
|
|
|
|
'''Tests for the semantics of the server.'''
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
"""Set up only once, and re-use in every individual test"""
|
|
|
|
cls.app = Flask("test_extensions")
|
|
|
|
cls.client = cls.app.test_client()
|
2024-12-12 23:01:27 +00:00
|
|
|
cls.senpy = Senpy(plugin_folder=None, default_plugins=True)
|
2019-01-07 11:08:19 +00:00
|
|
|
cls.senpy.init_app(cls.app)
|
2024-12-12 23:01:27 +00:00
|
|
|
#cls.dir = os.path.join(os.path.dirname(__file__), "..")
|
|
|
|
#cls.senpy.add_folder(cls.dir)
|
2019-01-07 11:08:19 +00:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.app.config['TESTING'] = True # Tell Flask not to catch Exceptions
|
|
|
|
|
|
|
|
def assertCode(self, resp, code):
|
|
|
|
self.assertEqual(resp.status_code, code)
|
|
|
|
|
|
|
|
def test_sentiment(self):
|
|
|
|
"""
|
2024-12-12 23:01:27 +00:00
|
|
|
a sentiment analysis call in json-ld
|
2019-01-07 11:08:19 +00:00
|
|
|
"""
|
2024-12-12 23:01:27 +00:00
|
|
|
# we use expanded json-ld and ignore the context, because in general
|
|
|
|
# the context is a uris to the service and that uri is not
|
2019-01-07 11:08:19 +00:00
|
|
|
# available outside of self.client
|
|
|
|
params = {
|
|
|
|
'input': 'hello',
|
|
|
|
'in-headers': True,
|
|
|
|
'outformat': 'json-ld',
|
|
|
|
'expanded': True,
|
|
|
|
'prefix': 'http://default.example/#'
|
|
|
|
}
|
2024-12-12 23:01:27 +00:00
|
|
|
resp = self.client.get("/api/sentiment-basic?{}".format(urlencode(params)))
|
2019-01-07 11:08:19 +00:00
|
|
|
self.assertCode(resp, 200)
|
|
|
|
g = parse_resp(resp, fmt='json-ld')
|
2024-12-12 23:01:27 +00:00
|
|
|
print('Got this graph: ', g.serialize(format='ttl'))
|
2019-01-07 11:08:19 +00:00
|
|
|
assert g
|
|
|
|
qres = g.query("""
|
2024-12-12 23:01:27 +00:00
|
|
|
prefix prov: <http://www.w3.org/ns/prov#>
|
|
|
|
prefix marl: <http://www.gsi.upm.es/ontologies/marl/ns#>
|
|
|
|
prefix nif: <http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#>
|
|
|
|
prefix onyx: <http://www.gsi.upm.es/ontologies/onyx/ns#>
|
|
|
|
prefix senpy: <http://www.gsi.upm.es/ontologies/senpy/ns#>
|
|
|
|
|
|
|
|
SELECT distinct ?entry ?text ?sentiment
|
|
|
|
WHERE {
|
|
|
|
?entry a senpy:Entry .
|
|
|
|
?entry marl:hasOpinion ?o .
|
|
|
|
?entry nif:isString ?text .
|
|
|
|
?o marl:hasPolarity ?sentiment .
|
|
|
|
}""")
|
|
|
|
assert len(qres) == 1, "There should only be one result"
|
2019-01-07 11:08:19 +00:00
|
|
|
entry, text, sentiment = list(qres)[0]
|
2024-12-12 23:01:27 +00:00
|
|
|
assert str(text) == 'hello', "The returned text does not match the input text."
|
2019-01-07 11:08:19 +00:00
|
|
|
assert str(sentiment) in ['marl:Positive', 'marl:Neutral', 'marl:Negative']
|
|
|
|
|
|
|
|
def test_sentiment_turtle(self):
|
|
|
|
"""
|
|
|
|
A sentiment analysis call in turtle format
|
|
|
|
"""
|
|
|
|
params = {
|
|
|
|
'input': 'hello',
|
|
|
|
'in-headers': True,
|
|
|
|
'outformat': 'turtle',
|
|
|
|
'expanded': True,
|
|
|
|
'prefix': 'http://default.example/#'
|
|
|
|
}
|
2024-12-12 23:01:27 +00:00
|
|
|
resp = self.client.get("/api/sentiment-basic?{}".format(urlencode(params)))
|
2019-01-07 11:08:19 +00:00
|
|
|
self.assertCode(resp, 200)
|
|
|
|
g = parse_resp(resp, 'ttl')
|
2024-12-12 23:01:27 +00:00
|
|
|
print('Got this graph: ', g.serialize(format='ttl'))
|
2019-01-07 11:08:19 +00:00
|
|
|
qres = g.query("""
|
|
|
|
PREFIX prov: <http://www.w3.org/ns/prov#>
|
2022-05-20 10:51:01 +00:00
|
|
|
PREFIX marl: <http://www.gsi.upm.es/ontologies/marl/ns#>
|
2019-01-07 11:08:19 +00:00
|
|
|
PREFIX nif: <http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#>
|
2022-05-20 10:51:01 +00:00
|
|
|
PREFIX onyx: <http://www.gsi.upm.es/ontologies/onyx/ns#>
|
2024-12-12 23:01:27 +00:00
|
|
|
PREFIX senpy: <http://www.gsi.upm.es/ontologies/senpy/ns#>
|
2019-01-07 11:08:19 +00:00
|
|
|
|
|
|
|
SELECT DISTINCT ?entry ?text ?sentiment
|
|
|
|
WHERE {
|
2024-12-12 23:01:27 +00:00
|
|
|
?entry a senpy:Entry ;
|
|
|
|
nif:isString ?text ;
|
|
|
|
marl:hasOpinion [
|
|
|
|
marl:hasPolarity ?sentiment
|
|
|
|
] .
|
2019-01-07 11:08:19 +00:00
|
|
|
}""")
|
2024-12-12 23:01:27 +00:00
|
|
|
assert len(qres) == 1, "There should only be one row in the result"
|
|
|
|
entry, text, sentiment = list(qres)[0]
|
|
|
|
assert str(text) == 'hello', "Returned text does not match input text"
|
|
|
|
assert str(sentiment) in ['marl:Positive', 'marl:Neutral', 'marl:Negative']
|
|
|
|
|
|
|
|
def test_moral(self):
|
|
|
|
"""
|
|
|
|
An example of a moral analysis, adapted from the examples for the AMOR project:
|
|
|
|
http://www.gsi.upm.es/ontologies/amor/examples
|
|
|
|
"""
|
|
|
|
# we use expanded json-ld and ignore the context, because in general
|
|
|
|
# the context is a uris to the service and that uri is not
|
|
|
|
# available outside of self.client
|
|
|
|
params = {
|
|
|
|
'input': 'hello',
|
|
|
|
'in-headers': True,
|
|
|
|
'outformat': 'json-ld',
|
|
|
|
'expanded': True,
|
|
|
|
'prefix': 'http://default.example/#'
|
|
|
|
}
|
|
|
|
resp = self.client.get("/api/sentiment-basic?{}".format(urlencode(params)))
|
|
|
|
self.assertCode(resp, 200)
|
|
|
|
g = parse_resp(resp, fmt='json-ld')
|
|
|
|
print('Got this graph: ', g.serialize(format='ttl'))
|
|
|
|
assert g
|
|
|
|
qres = g.query("""
|
|
|
|
prefix : <http://www.gsi.upm.es/ontologies/amor/examples#>
|
|
|
|
prefix amor: <http://www.gsi.upm.es/ontologies/amor/ns#>
|
|
|
|
prefix amor-bhv: <http://www.gsi.upm.es/ontologies/amor/models/bhv/ns#>
|
|
|
|
prefix amor-mft: <http://www.gsi.upm.es/ontologies/amor/models/mft/ns#>
|
|
|
|
prefix bhv: <http://www.gsi.upm.es/ontologies/bhv#>
|
|
|
|
prefix mft: <http://www.gsi.upm.es/ontologies/mft/ns#>
|
|
|
|
prefix mls: <http://www.w3.org/ns/mls#>
|
|
|
|
prefix owl: <http://www.w3.org/2002/07/owl#>
|
|
|
|
prefix prov: <http://www.w3.org/ns/prov#>
|
|
|
|
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
|
|
prefix schema: <http://schema.org/>
|
|
|
|
|
|
|
|
SELECT ?analysis ?agent ?model ?annotation ?origin ?category
|
|
|
|
WHERE {
|
|
|
|
?analysis a amor:MoralValueAnalysis ;
|
|
|
|
prov:wasAssociatedWith ?agent ;
|
|
|
|
amor:usedMoralValueModel ?model ;
|
|
|
|
amor:analysed ?origin ;
|
|
|
|
prov:generated ?annotation .
|
|
|
|
?annotation a amor:MoralValueAnnotation ;
|
|
|
|
amor:hasMoralValueCategory ?category .
|
|
|
|
}""")
|
2019-01-07 11:08:19 +00:00
|
|
|
assert len(qres) == 1
|
|
|
|
entry, text, sentiment = list(qres)[0]
|
|
|
|
assert entry
|
|
|
|
assert str(text) == 'hello'
|
2024-12-12 23:01:27 +00:00
|
|
|
assert str(sentiment) in ['marl:positive', 'marl:neutral', 'marl:negative']
|