1
0
mirror of https://github.com/gsi-upm/senpy synced 2025-08-23 18:12:20 +00:00

WIP simpler pipeline

This commit is contained in:
J. Fernando Sánchez
2017-06-21 19:58:18 +02:00
parent fca0ac00c4
commit a243f68bfc
19 changed files with 369 additions and 227 deletions

View File

@@ -3,7 +3,7 @@ from senpy.plugins import SentimentPlugin
class DummyPlugin(SentimentPlugin):
def analyse_entry(self, entry, params):
entry.text = entry.text[::-1]
entry['nif:iString'] = entry['nif:isString'][::-1]
entry.reversed = entry.get('reversed', 0) + 1
yield entry

View File

@@ -11,24 +11,24 @@ class APITest(TestCase):
def test_api_params(self):
"""The API should not define any required parameters without a default"""
parse_params({}, spec=API_PARAMS)
parse_params({}, API_PARAMS)
def test_web_params(self):
"""The WEB should not define any required parameters without a default"""
parse_params({}, spec=WEB_PARAMS)
parse_params({}, WEB_PARAMS)
def test_basic(self):
a = {}
try:
parse_params(a, spec=NIF_PARAMS)
parse_params(a, NIF_PARAMS)
raise AssertionError()
except Error:
pass
a = {'input': 'hello'}
p = parse_params(a, spec=NIF_PARAMS)
p = parse_params(a, NIF_PARAMS)
assert 'input' in p
b = {'i': 'hello'}
p = parse_params(b, spec=NIF_PARAMS)
p = parse_params(b, NIF_PARAMS)
assert 'input' in p
def test_plugin(self):
@@ -40,18 +40,18 @@ class APITest(TestCase):
}
}
try:
parse_params(query, spec=plug_params)
parse_params(query, plug_params)
raise AssertionError()
except Error:
pass
query['hello'] = 'world'
p = parse_params(query, spec=plug_params)
p = parse_params(query, plug_params)
assert 'hello' in p
assert p['hello'] == 'world'
del query['hello']
query['hiya'] = 'dlrow'
p = parse_params(query, spec=plug_params)
p = parse_params(query, plug_params)
assert 'hello' in p
assert 'hiya' in p
assert p['hello'] == 'dlrow'
@@ -63,6 +63,6 @@ class APITest(TestCase):
'default': 1
}
}
p = parse_params({}, spec=spec)
p = parse_params({}, spec)
assert 'hello' in p
assert p['hello'] == 1

View File

@@ -38,6 +38,7 @@ class BlueprintsTest(TestCase):
"""
Calling with no arguments should ask the user for more arguments
"""
self.app.debug = False
resp = self.client.get("/api/")
self.assertCode(resp, 400)
js = parse_resp(resp)
@@ -54,7 +55,7 @@ class BlueprintsTest(TestCase):
The dummy plugin returns an empty response,\
it should contain the context
"""
resp = self.client.get("/api/?i=My aloha mohame")
resp = self.client.get("/api/?i=My aloha mohame&with_parameters=True")
self.assertCode(resp, 200)
js = parse_resp(resp)
logging.debug("Got response: %s", js)
@@ -77,6 +78,7 @@ class BlueprintsTest(TestCase):
Extra params that have a required argument that does not
have a default should raise an error.
"""
self.app.debug = False
resp = self.client.get("/api/?i=My aloha mohame&algo=DummyRequired")
self.assertCode(resp, 400)
js = parse_resp(resp)
@@ -88,6 +90,7 @@ class BlueprintsTest(TestCase):
The dummy plugin returns an empty response,\
it should contain the context
"""
self.app.debug = False
resp = self.client.get("/api/?i=My aloha mohame&algo=DOESNOTEXIST")
self.assertCode(resp, 404)
js = parse_resp(resp)
@@ -154,3 +157,10 @@ class BlueprintsTest(TestCase):
self.assertCode(resp, 200)
js = parse_resp(resp)
assert "$schema" in js
def test_help(self):
resp = self.client.get("/api/?help=true")
self.assertCode(resp, 200)
js = parse_resp(resp)
assert "parameters" in js
assert "help" in js["parameters"]

View File

@@ -1,11 +1,6 @@
import logging
from functools import partial
try:
from unittest.mock import patch
except ImportError:
from mock import patch
logger = logging.getLogger(__name__)
from unittest import TestCase
@@ -17,11 +12,7 @@ class CLITest(TestCase):
def test_basic(self):
self.assertRaises(Error, partial(main_function, []))
with patch('senpy.extensions.Senpy.analyse') as patched:
main_function(['--input', 'test'])
patched.assert_called_with(input='test')
with patch('senpy.extensions.Senpy.analyse') as patched:
main_function(['--input', 'test', '--algo', 'rand'])
patched.assert_called_with(input='test', algo='rand')
res = main_function(['--input', 'test', '--algo', 'rand', '--with-parameters'])
assert res.parameters['input'] == 'test'
assert 'rand' in res.parameters['algorithm']
assert res.parameters['input'] == 'test'

View File

@@ -12,10 +12,16 @@ from functools import partial
from senpy.extensions import Senpy
from senpy import plugins
from senpy.models import Error, Results, Entry, EmotionSet, Emotion, Plugin
from senpy import api
from flask import Flask
from unittest import TestCase
def analyse(instance, **kwargs):
request = api.parse_call(kwargs)
return instance.analyse(request)
class ExtensionsTest(TestCase):
def setUp(self):
self.app = Flask('test_extensions')
@@ -91,10 +97,11 @@ class ExtensionsTest(TestCase):
def test_noplugin(self):
""" Don't analyse if there isn't any plugin installed """
self.senpy.deactivate_all(sync=True)
self.assertRaises(Error, partial(self.senpy.analyse, input="tupni"))
self.assertRaises(Error, partial(analyse, self.senpy, input="tupni"))
self.assertRaises(Error,
partial(
self.senpy.analyse,
analyse,
self.senpy,
input="tupni",
algorithm='Dummy'))
@@ -102,12 +109,11 @@ class ExtensionsTest(TestCase):
""" Using a plugin """
# I was using mock until plugin started inheriting
# Leaf (defaultdict with __setattr__ and __getattr__.
r1 = self.senpy.analyse(
algorithm="Dummy", input="tupni", output="tuptuo")
r2 = self.senpy.analyse(input="tupni", output="tuptuo")
r1 = analyse(self.senpy, algorithm="Dummy", input="tupni", output="tuptuo")
r2 = analyse(self.senpy, input="tupni", output="tuptuo")
assert r1.analysis[0] == "plugins/Dummy_0.1"
assert r2.analysis[0] == "plugins/Dummy_0.1"
assert r1.entries[0].text == 'input'
assert r1.entries[0]['nif:iString'] == 'input'
def test_analyse_jsonld(self):
""" Using a plugin with JSON-LD input"""
@@ -116,30 +122,33 @@ class ExtensionsTest(TestCase):
"@type": "results",
"entries": [
{"@id": "entry1",
"text": "tupni",
"nif:isString": "tupni",
"@type": "entry"
}
]
}'''
r1 = self.senpy.analyse(algorithm="Dummy",
input=js_input,
informat="json-ld",
output="tuptuo")
r2 = self.senpy.analyse(input="tupni", output="tuptuo")
r1 = analyse(self.senpy,
algorithm="Dummy",
input=js_input,
informat="json-ld",
output="tuptuo")
r2 = analyse(self.senpy,
input="tupni",
output="tuptuo")
assert r1.analysis[0] == "plugins/Dummy_0.1"
assert r2.analysis[0] == "plugins/Dummy_0.1"
assert r1.entries[0].text == 'input'
assert r1.entries[0]['nif:iString'] == 'input'
def test_analyse_error(self):
mm = mock.MagicMock()
mm.id = 'magic_mock'
mm.analyse_entries.side_effect = Error('error on analysis', status=500)
mm.analyse_entries.side_effect = Error('error in analysis', status=500)
self.senpy.plugins['MOCK'] = mm
try:
self.senpy.analyse(input='nothing', algorithm='MOCK')
analyse(self.senpy, input='nothing', algorithm='MOCK')
assert False
except Error as ex:
assert ex['message'] == 'error on analysis'
assert 'error in analysis' in ex['message']
assert ex['status'] == 500
mm.analyse.side_effect = Exception('generic exception on analysis')
@@ -147,10 +156,10 @@ class ExtensionsTest(TestCase):
'generic exception on analysis')
try:
self.senpy.analyse(input='nothing', algorithm='MOCK')
analyse(self.senpy, input='nothing', algorithm='MOCK')
assert False
except Error as ex:
assert ex['message'] == 'generic exception on analysis'
assert 'generic exception on analysis' in ex['message']
assert ex['status'] == 500
def test_filtering(self):
@@ -180,40 +189,27 @@ class ExtensionsTest(TestCase):
'emoml:valence': 0
}))
response = Results({
'analysis': [{'plugin': plugin}],
'entries': [Entry({
'text': 'much ado about nothing',
'nif:iString': 'much ado about nothing',
'emotions': [eSet1]
})]
})
params = {'emotionModel': 'emoml:big6',
'conversion': 'full'}
r1 = deepcopy(response)
self.senpy.convert_emotions(r1,
[plugin, ],
params)
r1.parameters = params
self.senpy.convert_emotions(r1)
assert len(r1.entries[0].emotions) == 2
params['conversion'] = 'nested'
r2 = deepcopy(response)
self.senpy.convert_emotions(r2,
[plugin, ],
params)
r2.parameters = params
self.senpy.convert_emotions(r2)
assert len(r2.entries[0].emotions) == 1
assert r2.entries[0].emotions[0]['prov:wasDerivedFrom'] == eSet1
params['conversion'] = 'filtered'
r3 = deepcopy(response)
self.senpy.convert_emotions(r3,
[plugin, ],
params)
r3.parameters = params
self.senpy.convert_emotions(r3)
assert len(r3.entries[0].emotions) == 1
r3.jsonld()
# def test_async_plugin(self):
# """ We should accept multiprocessing plugins with async=False"""
# thread1 = self.senpy.activate_plugin("Async", sync=False)
# thread1.join(timeout=1)
# assert len(self.senpy.plugins['Async'].value) == 4
# resp = self.senpy.analyse(input='nothing', algorithm='Async')
# assert len(resp.entries[0].async_values) == 2
# self.senpy.activate_plugin("Async", sync=True)

View File

@@ -185,7 +185,7 @@ class ModelsTest(TestCase):
'entries': [{
'@id': 'entry1',
'@type': 'entry',
'text': 'TEST'
'nif:isString': 'TEST'
}]
}
recovered = from_dict(results)