class SentiTextTest(unittest.TestCase): def setUp(self): self.app = Flask("test_plugin") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) def tearDown(self): self.senpy.deactivate_plugin("SentiText", sync=True) def test_analyse(self): plugin = self.senpy.plugins["SentiText"] plugin.activate() texts = { 'Odio ir al cine': 'marl:Neutral', 'El cielo esta nublado': 'marl:Positive', 'Esta tarta esta muy buena': 'marl:Neutral' } for text in texts: response = plugin.analyse(input=text) sentimentSet = response.entries[0].sentiments[0] print sentimentSet expected = texts[text] assert sentimentSet['marl:hasPolarity'] == expected plugin.deactivate()
class emoTextWAFTest(unittest.TestCase): def setUp(self): self.app = Flask("test_plugin") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) def tearDown(self): self.senpy.deactivate_plugin("EmoTextWAF", sync=True) def test_analyse(self): plugin = self.senpy.plugins["EmoTextWAF"] plugin.activate() texts = {'I hate you': 'anger', 'i am sad': 'sadness', 'i am happy with my marks': 'joy', 'This movie is scary': 'negative-fear'} for text in texts: response = plugin.analyse(input=text) expected = texts[text] emotionSet = response.entries[0].emotions[0] max_emotion = max(emotionSet['onyx:hasEmotion'], key=lambda x: x['onyx:hasEmotionIntensity']) assert max_emotion['onyx:hasEmotionCategory'] == expected plugin.deactivate()
def create_app(self): self.app = Flask("test_extensions") self.dir = os.path.join(os.path.dirname(__file__), "..") self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) self.senpy.activate_plugin("Dummy", sync=True) return self.app
class emoTextANEWTest(unittest.TestCase): def setUp(self): self.app = Flask("test_plugin") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) def tearDown(self): self.senpy.deactivate_plugin("EmoTextANEW", sync=True) def test_analyse(self): plugin = self.senpy.plugins["EmoTextANEW"] plugin.activate() ontology = "http://gsi.dit.upm.es/ontologies/wnaffect/ns#" texts = { 'I hate you': 'anger', 'i am sad': 'sadness', 'i am happy with my marks': 'joy', 'This movie is scary': 'negative-fear', 'this cake is disgusting': 'negative-fear' } for text in texts: response = plugin.analyse(input=text) expected = texts[text] emotionSet = response.entries[0].emotions[0] assert emotionSet['onyx:hasEmotion'][0][ 'onyx:hasEmotionCategory'] == ontology + expected plugin.deactivate()
class emoTextWAFTest(unittest.TestCase): def setUp(self): self.app = Flask("test_plugin") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) def tearDown(self): self.senpy.deactivate_plugin("EmoTextWAF", sync=True) def test_analyse(self): plugin = self.senpy.plugins["EmoTextWAF"] plugin.activate() texts = { 'I hate you': 'anger', 'i am sad': 'sadness', 'i am happy with my marks': 'joy', 'This movie is scary': 'negative-fear' } for text in texts: response = plugin.analyse(input=text) expected = texts[text] emotionSet = response.entries[0].emotions[0] max_emotion = max(emotionSet['onyx:hasEmotion'], key=lambda x: x['onyx:hasEmotionIntensity']) assert max_emotion['onyx:hasEmotionCategory'] == expected plugin.deactivate()
def setUp(self): self.app = Flask('test_extensions') self.dir = os.path.dirname(__file__) self.senpy = Senpy(plugin_folder=self.dir, app=self.app, default_plugins=False) self.senpy.activate_plugin("Dummy", sync=True)
class vaderTest(unittest.TestCase): def setUp(self): self.app = Flask("test_plugin") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) def tearDown(self): self.senpy.deactivate_plugin("vaderSentiment", sync=True) def test_analyse(self): plugin = self.senpy.plugins["vaderSentiment"] plugin.activate() texts = { 'I am tired :(': 'marl:Negative', 'I love pizza': 'marl:Positive', 'I like going to the cinema :)': 'marl:Positive', 'This cake is disgusting': 'marl:Negative' } for text in texts: response = plugin.analyse(input=text) expected = texts[text] sentimentSet = response.entries[0].sentiments max_sentiment = max(sentimentSet, key=lambda x: x['marl:polarityValue']) assert max_sentiment['marl:hasPolarity'] == expected plugin.deactivate()
def test_adding_folder(self): """ It should be possible for senpy to look for plugins in more folders. """ senpy = Senpy(plugin_folder=None, app=self.app, default_plugins=False) assert not senpy.analysis_plugins senpy.add_folder(self.examples_dir) assert senpy.analysis_plugins self.assertRaises(AttributeError, senpy.add_folder, 'DOES NOT EXIST')
class SentiTextTest(unittest.TestCase): def setUp(self): self.app = Flask("test_plugin") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) def tearDown(self): self.senpy.deactivate_plugin("SentiText", sync=True) def test_analyse(self): plugin = self.senpy.plugins["SentiText"] plugin.activate() texts = {'Odio ir al cine' : 'marl:Neutral', 'El cielo esta nublado' : 'marl:Positive', 'Esta tarta esta muy buena' : 'marl:Neutral'} for text in texts: response = plugin.analyse(input=text) sentimentSet = response.entries[0].sentiments[0] print sentimentSet expected = texts[text] assert sentimentSet['marl:hasPolarity'] == expected plugin.deactivate()
def setUp(self): self.app = Flask('test_extensions') self.examples_dir = os.path.join(os.path.dirname(__file__), '..', 'example-plugins') self.senpy = Senpy(plugin_folder=self.examples_dir, app=self.app, default_plugins=False) self.senpy.deactivate_all() self.senpy.activate_plugin("Dummy", sync=True)
def setUp(self): self.app = Flask("test_extensions") self.client = self.app.test_client() self.senpy = Senpy() self.senpy.init_app(self.app) self.dir = os.path.join(os.path.dirname(__file__), "..") self.senpy.add_folder(self.dir) self.senpy.activate_plugin("Dummy", sync=True)
def test_adding_folder(self): """ It should be possible for senpy to look for plugins in more folders. """ senpy = Senpy(plugin_folder=None, app=self.app, default_plugins=False) assert not senpy.analysis_plugins() senpy.add_folder(self.examples_dir) assert senpy.plugins(plugin_type=plugins.Analyser, is_activated=False) self.assertRaises(AttributeError, senpy.add_folder, 'DOES NOT EXIST')
def main(): parser = argparse.ArgumentParser(description='Run a Senpy server') parser.add_argument('--level', '-l', metavar='logging_level', type=str, default="INFO", help='Logging level') parser.add_argument('--debug', '-d', action='store_true', default=False, help='Run the application in debug mode') parser.add_argument('--default-plugins', action='store_true', default=False, help='Load the default plugins') parser.add_argument('--host', type=str, default="127.0.0.1", help='Use 0.0.0.0 to accept requests from any host.') parser.add_argument('--port', '-p', type=int, default=SERVER_PORT, help='Port to listen on.') parser.add_argument('--plugins-folder', '-f', type=str, default='plugins', help='Where to look for plugins.') parser.add_argument('--only-install', '-i', action='store_true', default=False, help='Do not run a server, only install the dependencies of the plugins.') args = parser.parse_args() logging.basicConfig() rl = logging.getLogger() rl.setLevel(getattr(logging, args.level)) app = Flask(__name__) app.debug = args.debug sp = Senpy(app, args.plugins_folder, default_plugins=args.default_plugins) if args.only_install: sp.install_deps() return sp.activate_all() http_server = WSGIServer((args.host, args.port), app) try: print('Senpy version {}'.format(senpy.__version__)) print('Server running on port %s:%d. Ctrl+C to quit' % (args.host, args.port)) http_server.serve_forever() except KeyboardInterrupt: http_server.stop() print('Bye!')
def main(): parser = argparse.ArgumentParser(description='Run a Senpy server') parser.add_argument('--level', '-l', metavar='logging_level', type=str, default="INFO", help='Logging level') parser.add_argument('--debug', '-d', action='store_true', default=False, help='Run the application in debug mode') parser.add_argument('--default-plugins', action='store_true', default=False, help='Load the default plugins') parser.add_argument('--host', type=str, default="0.0.0.0", help='Use 0.0.0.0 to accept requests from any host.') parser.add_argument('--port', '-p', type=int, default=SERVER_PORT, help='Port to listen on.') parser.add_argument('--plugins-folder', '-f', type=str, default='plugins', help='Where to look for plugins.') parser.add_argument( '--only-install', '-i', action='store_true', default=False, help='Do not run a server, only install plugin dependencies') args = parser.parse_args() logging.basicConfig() rl = logging.getLogger() rl.setLevel(getattr(logging, args.level)) app = Flask(__name__) app.debug = args.debug if args.debug: sys.excepthook = info sp = Senpy(app, args.plugins_folder, default_plugins=args.default_plugins) if args.only_install: sp.install_deps() return sp.activate_all() http_server = WSGIServer((args.host, args.port), app) try: print('Senpy version {}'.format(senpy.__version__)) print('Server running on port %s:%d. Ctrl+C to quit' % (args.host, args.port)) http_server.serve_forever() except KeyboardInterrupt: print('Bye!') http_server.stop() sp.deactivate_all()
class emoTextWAFTest(unittest.TestCase): def setUp(self): self.app = Flask("Example") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) def tearDown(self): self.senpy.deactivate_plugin("ExamplePlugin", sync=True) def test_analyse(self): assert len(self.senpy.plugins.keys()) == 1 assert True
def create_app(self): self.app = Flask("test_extensions") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) self.senpy.activate_plugin("Dummy", sync=True) return self.app
def create_app(self): self.app = Flask("test_extensions") self.senpy = Senpy() self.senpy.init_app(self.app) self.dir = os.path.join(os.path.dirname(__file__), "..") self.senpy.add_folder(self.dir) self.senpy.activate_plugin("Dummy", sync=True) return self.app
def main(): parser = argparse.ArgumentParser(description='Run a Senpy server') parser.add_argument('--level', "-l", metavar="logging_level", type=str, default="INFO", help='Logging level') parser.add_argument('--debug', "-d", action='store_true', default=False, help='Run the application in debug mode') parser.add_argument('--default-plugins', action='store_true', default=False, help='Load the default plugins') parser.add_argument('--host', type=str, default="127.0.0.1", help='Use 0.0.0.0 to accept requests from any host.') parser.add_argument('--port', '-p', type=int, default=5000, help='Port to listen on.') parser.add_argument('--plugins-folder', '-f', type=str, default="plugins", help='Where to look for plugins.') args = parser.parse_args() logging.basicConfig(level=getattr(logging, args.level)) app = Flask(__name__) app.debug = args.debug sp = Senpy(app, args.plugins_folder, default_plugins=args.default_plugins) sp.activate_all() http_server = WSGIServer((args.host, args.port), app) try: print("Server running on port %s:%d. Ctrl+C to quit" % (args.host, args.port)) http_server.serve_forever() except KeyboardInterrupt: http_server.stop() print("Bye!")
def setUp(self): self.app = Flask('test_extensions') self.examples_dir = os.path.join(os.path.dirname(__file__), '..', 'example-plugins') self.senpy = Senpy(plugin_folder=self.examples_dir, app=self.app, default_plugins=False) self.senpy.deactivate_all() self.senpy.activate_plugin("Dummy", sync=True) self.app.config['TESTING'] = True # Tell Flask not to catch Exceptions
def setUp(self): self.app = Flask("test_extensions") self.client = self.app.test_client() self.senpy = Senpy() self.senpy.init_app(self.app) self.dir = os.path.join(os.path.dirname(__file__), "..") self.senpy.add_folder(self.dir) self.senpy.activate_plugin("Dummy", sync=True) self.senpy.activate_plugin("DummyRequired", sync=True) self.senpy.default_plugin = 'Dummy'
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() cls.senpy = Senpy(default_plugins=True) cls.senpy.init_app(cls.app) cls.dir = os.path.join(os.path.dirname(__file__), "..") cls.senpy.add_folder(cls.dir) cls.senpy.activate_all() cls.senpy.default_plugin = 'Dummy'
class ExtensionsTest(TestCase): def create_app(self): self.app = Flask("test_extensions") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) self.senpy.activate_plugin("Dummy", sync=True) return self.app def test_init(self): """ Initialising the app with the extension. """ assert hasattr(self.app, "senpy") tapp = Flask("temp app") self.senpy.init_app(tapp) assert hasattr(tapp, "senpy") def test_discovery(self): """ Discovery of plugins in given folders. """ # noinspection PyProtectedMember assert self.dir in self.senpy._search_folders print(self.senpy.plugins) assert "Dummy" in self.senpy.plugins def test_enabling(self): """ Enabling a plugin """ self.senpy.activate_all(sync=True) assert len(self.senpy.plugins) == 2 assert self.senpy.plugins["Sleep"].is_activated def test_disabling(self): """ Disabling a plugin """ self.senpy.deactivate_all(sync=True) assert not self.senpy.plugins["Dummy"].is_activated assert not self.senpy.plugins["Sleep"].is_activated def test_default(self): """ Default plugin should be set """ assert self.senpy.default_plugin assert self.senpy.default_plugin.name == "Dummy" self.senpy.deactivate_all(sync=True) logging.debug("Default: {}".format(self.senpy.default_plugin)) assert self.senpy.default_plugin is None 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")) def test_analyse(self): """ 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") assert r1.analysis[0].id[:5] == "Dummy" assert r2.analysis[0].id[:5] == "Dummy" def test_filtering(self): """ Filtering plugins """ assert len(self.senpy.filter_plugins(name="Dummy")) > 0 assert not len(self.senpy.filter_plugins(name="notdummy")) assert self.senpy.filter_plugins(name="Dummy", is_activated=True) self.senpy.deactivate_plugin("Dummy", sync=True) assert not len( self.senpy.filter_plugins(name="Dummy", is_activated=True))
def main(): parser = argparse.ArgumentParser(description='Run a Senpy server') parser.add_argument( '--level', '-l', metavar='logging_level', type=str, default="WARN", help='Logging level') parser.add_argument( '--debug', '-d', action='store_true', default=False, help='Run the application in debug mode') parser.add_argument( '--default-plugins', action='store_true', default=False, help='Load the default plugins') parser.add_argument( '--host', type=str, default="0.0.0.0", help='Use 0.0.0.0 to accept requests from any host.') parser.add_argument( '--port', '-p', type=int, default=SERVER_PORT, help='Port to listen on.') parser.add_argument( '--plugins-folder', '-f', type=str, default='.', help='Where to look for plugins.') parser.add_argument( '--only-install', '-i', action='store_true', default=False, help='Do not run a server, only install plugin dependencies') parser.add_argument( '--only-test', action='store_true', default=False, help='Do not run a server, just test all plugins') parser.add_argument( '--test', '-t', action='store_true', default=False, help='Test all plugins before launching the server') parser.add_argument( '--only-list', '--list', action='store_true', default=False, help='Do not run a server, only list plugins found') parser.add_argument( '--data-folder', '--data', type=str, default=None, help='Where to look for data. It be set with the SENPY_DATA environment variable as well.') parser.add_argument( '--threaded', action='store_false', default=True, help='Run a threaded server') parser.add_argument( '--no-deps', '-n', action='store_true', default=False, help='Skip installing dependencies') parser.add_argument( '--version', '-v', action='store_true', default=False, help='Output the senpy version and exit') parser.add_argument( '--allow-fail', '--fail', action='store_true', default=False, help='Do not exit if some plugins fail to activate') args = parser.parse_args() if args.version: print('Senpy version {}'.format(senpy.__version__)) print(sys.version) exit(1) rl = logging.getLogger() rl.setLevel(getattr(logging, args.level)) app = Flask(__name__) app.debug = args.debug sp = Senpy(app, args.plugins_folder, default_plugins=args.default_plugins, data_folder=args.data_folder) if args.only_list: plugins = sp.plugins() maxname = max(len(x.name) for x in plugins) maxversion = max(len(x.version) for x in plugins) print('Found {} plugins:'.format(len(plugins))) for plugin in plugins: import inspect fpath = inspect.getfile(plugin.__class__) print('\t{: <{maxname}} @ {: <{maxversion}} -> {}'.format(plugin.name, plugin.version, fpath, maxname=maxname, maxversion=maxversion)) return if not args.no_deps: sp.install_deps() if args.only_install: return sp.activate_all(allow_fail=args.allow_fail) if args.test or args.only_test: easy_test(sp.plugins(), debug=args.debug) if args.only_test: return print('Senpy version {}'.format(senpy.__version__)) print('Server running on port %s:%d. Ctrl+C to quit' % (args.host, args.port)) app.run(args.host, args.port, threaded=args.threaded, debug=app.debug) sp.deactivate_all()
class ExtensionsTest(TestCase): def setUp(self): self.app = Flask('test_extensions') self.examples_dir = os.path.join(os.path.dirname(__file__), '..', 'example-plugins') self.senpy = Senpy(plugin_folder=self.examples_dir, app=self.app, default_plugins=False) self.senpy.deactivate_all() self.senpy.activate_plugin("Dummy", sync=True) self.app.config['TESTING'] = True # Tell Flask not to catch Exceptions def test_init(self): """ Initialising the app with the extension. """ assert hasattr(self.app, "senpy") tapp = Flask("temp app") self.senpy.init_app(tapp) assert hasattr(tapp, "senpy") def test_discovery(self): """ Discovery of plugins in given folders. """ # noinspection PyProtectedMember print(self.senpy.plugins()) assert self.senpy.get_plugin("dummy") def test_add_delete(self): '''Should be able to add and delete new plugins. ''' new = plugins.Analyser(name='new', description='new', version=0) self.senpy.add_plugin(new) assert new in self.senpy.plugins(is_activated=False) self.senpy.delete_plugin(new) assert new not in self.senpy.plugins(is_activated=False) def test_adding_folder(self): """ It should be possible for senpy to look for plugins in more folders. """ senpy = Senpy(plugin_folder=None, app=self.app, default_plugins=False) assert not senpy.analysis_plugins() senpy.add_folder(self.examples_dir) assert senpy.plugins(plugin_type=plugins.Analyser, is_activated=False) self.assertRaises(AttributeError, senpy.add_folder, 'DOES NOT EXIST') def test_installing(self): """ Installing a plugin """ info = { 'name': 'TestPip', 'module': 'mynoop', 'description': None, 'requirements': ['noop'], 'version': 0 } module = plugins.from_info(info, root=self.examples_dir, install=True) assert module.name == 'TestPip' assert module import noop dir(noop) def test_enabling(self): """ Enabling a plugin """ self.senpy.activate_all(sync=True) assert len(self.senpy.plugins()) >= 3 assert self.senpy.get_plugin("Sleep").is_activated def test_installing_nonexistent(self): """ Fail if the dependencies cannot be met """ info = { 'name': 'TestPipFail', 'module': 'dummy', 'description': None, 'requirements': ['IAmMakingThisPackageNameUpToFail'], 'version': 0 } with self.assertRaises(Error): plugins.install_deps(info) def test_disabling(self): """ Disabling a plugin """ self.senpy.deactivate_all(sync=True) assert not self.senpy.get_plugin("dummy").is_activated assert not self.senpy.get_plugin("sleep").is_activated def test_default(self): """ Default plugin should be set """ assert self.senpy.default_plugin assert self.senpy.default_plugin.name == "dummy" self.senpy.deactivate_all(sync=True) logging.debug("Default: {}".format(self.senpy.default_plugin)) assert self.senpy.default_plugin is None def test_noplugin(self): """ Don't analyse if there isn't any plugin installed """ self.senpy.deactivate_all(sync=True) self.assertRaises(Error, partial(analyse, self.senpy, input="tupni")) def test_analyse(self): """ Using a plugin """ # I was using mock until plugin started inheriting # Leaf (defaultdict with __setattr__ and __getattr__. r1 = analyse(self.senpy, algorithm="Dummy", input="tupni", output="tuptuo") r2 = analyse(self.senpy, input="tupni", output="tuptuo") assert r1.activities[0].algorithm == "endpoint:plugins/dummy_0.1" assert r2.activities[0].algorithm == "endpoint:plugins/dummy_0.1" assert r1.entries[0]['nif:isString'] == 'input' def test_analyse_empty(self): """ Trying to analyse when no plugins are installed should raise an error.""" senpy = Senpy(plugin_folder=None, app=self.app, default_plugins=False) self.assertRaises(Error, senpy.analyse, Results(), []) def test_analyse_wrong(self): """ Trying to analyse with a non-existent plugin should raise an error.""" self.assertRaises(Error, analyse, self.senpy, algorithm='DOES NOT EXIST', input='test') def test_analyse_jsonld(self): """ Using a plugin with JSON-LD input""" js_input = '''{ "@id": "prueba", "@type": "results", "entries": [ {"@id": "entry1", "nif:isString": "tupni", "@type": "entry" } ] }''' r1 = analyse(self.senpy, algorithm="Dummy", input=js_input, informat="json-ld", output="tuptuo") r2 = analyse(self.senpy, input="tupni", output="tuptuo") assert r1.activities[0].algorithm == "endpoint:plugins/dummy_0.1" assert r2.activities[0].algorithm == "endpoint:plugins/dummy_0.1" assert r1.entries[0]['nif:isString'] == 'input' def test_analyse_error(self): class ErrorPlugin(plugins.Analyser): author = 'nobody' version = 0 ex = Error() def process(self, *args, **kwargs): raise self.ex m = ErrorPlugin(ex=Error('error in analysis', status=500)) self.senpy.add_plugin(m) try: analyse(self.senpy, input='nothing', algorithm='ErrorPlugin') assert False except Error as ex: assert 'error in analysis' in ex['message'] assert ex['status'] == 500 m.ex = Exception('generic exception on analysis') try: analyse(self.senpy, input='nothing', algorithm='ErrorPlugin') assert False except Exception as ex: assert 'generic exception on analysis' in str(ex) def test_filtering(self): """ Filtering plugins """ assert len(self.senpy.plugins(name="Dummy")) > 0 assert not len(self.senpy.plugins(name="NotDummy")) assert self.senpy.plugins(name="Dummy", is_activated=True) self.senpy.deactivate_plugin("Dummy", sync=True) assert not len(self.senpy.plugins(name="Dummy", is_activated=True)) def test_load_default_plugins(self): senpy = Senpy(plugin_folder=self.examples_dir, default_plugins=True) assert len(senpy.plugins(is_activated=False)) > 1 def test_convert_emotions(self): self.senpy.activate_all(sync=True) plugin = Plugin({ 'id': 'imaginary', 'onyx:usesEmotionModel': 'emoml:fsre-dimensions' }) eSet1 = EmotionSet() activity = plugin.activity() eSet1.prov(activity) eSet1['onyx:hasEmotion'].append( Emotion({ 'emoml:arousal': 1, 'emoml:potency': 0, 'emoml:valence': 0 })) response = Results({ 'activities': [activity], 'entries': [ Entry({ 'nif:isString': 'much ado about nothing', 'onyx:hasEmotionSet': [eSet1] }) ] }) params = { 'emotion-model': 'emoml:big6', 'algorithm': ['conversion'], 'conversion': 'full' } r1 = deepcopy(response) r1.parameters = params self.senpy.analyse(r1) assert len(r1.entries[0].emotions) == 2 params['conversion'] = 'nested' r2 = deepcopy(response) r2.parameters = params self.senpy.analyse(r2) assert len(r2.entries[0].emotions) == 1 assert r2.entries[0].emotions[0]['prov:wasDerivedFrom'] == eSet1 params['conversion'] = 'filtered' r3 = deepcopy(response) r3.parameters = params self.senpy.analyse(r3) assert len(r3.entries[0].emotions) == 1 r3.jsonld()
def test_load_default_plugins(self): senpy = Senpy(plugin_folder=self.examples_dir, default_plugins=True) assert len(senpy.plugins(is_activated=False)) > 1
def test_analyse_empty(self): """ Trying to analyse when no plugins are installed should raise an error.""" senpy = Senpy(plugin_folder=None, app=self.app, default_plugins=False) self.assertRaises(Error, senpy.analyse, Results(), [])
class ExtensionsTest(TestCase): def setUp(self): self.app = Flask('test_extensions') self.dir = os.path.dirname(__file__) self.senpy = Senpy(plugin_folder=self.dir, app=self.app, default_plugins=False) self.senpy.activate_plugin("Dummy", sync=True) def test_init(self): """ Initialising the app with the extension. """ assert hasattr(self.app, "senpy") tapp = Flask("temp app") self.senpy.init_app(tapp) assert hasattr(tapp, "senpy") def test_discovery(self): """ Discovery of plugins in given folders. """ # noinspection PyProtectedMember assert self.dir in self.senpy._search_folders print(self.senpy.plugins) assert "Dummy" in self.senpy.plugins def test_installing(self): """ Installing a plugin """ info = { 'name': 'TestPip', 'module': 'dummy', 'description': None, 'requirements': ['noop'], 'version': 0 } root = os.path.join(self.dir, 'plugins', 'dummy_plugin') module = plugins.load_plugin_from_info(info, root=root) plugins.install_deps(info) assert module.name == 'TestPip' assert module import noop dir(noop) def test_enabling(self): """ Enabling a plugin """ self.senpy.activate_all(sync=True) assert len(self.senpy.plugins) >= 3 assert self.senpy.plugins["Sleep"].is_activated def test_installing_nonexistent(self): """ Fail if the dependencies cannot be met """ info = { 'name': 'TestPipFail', 'module': 'dummy', 'description': None, 'requirements': ['IAmMakingThisPackageNameUpToFail'], 'version': 0 } with self.assertRaises(Error): plugins.install_deps(info) def test_disabling(self): """ Disabling a plugin """ self.senpy.deactivate_all(sync=True) assert not self.senpy.plugins["Dummy"].is_activated assert not self.senpy.plugins["Sleep"].is_activated def test_default(self): """ Default plugin should be set """ assert self.senpy.default_plugin assert self.senpy.default_plugin.name == "Dummy" self.senpy.deactivate_all(sync=True) logging.debug("Default: {}".format(self.senpy.default_plugin)) assert self.senpy.default_plugin is None def test_noplugin(self): """ Don't analyse if there isn't any plugin installed """ self.senpy.deactivate_all(sync=True) self.assertRaises(Error, partial(analyse, self.senpy, input="tupni")) def test_analyse(self): """ Using a plugin """ # I was using mock until plugin started inheriting # Leaf (defaultdict with __setattr__ and __getattr__. 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]['nif:iString'] == 'input' def test_analyse_jsonld(self): """ Using a plugin with JSON-LD input""" js_input = '''{ "@id": "prueba", "@type": "results", "entries": [ {"@id": "entry1", "nif:isString": "tupni", "@type": "entry" } ] }''' 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]['nif:iString'] == 'input' def test_analyse_error(self): mm = mock.MagicMock() mm.id = 'magic_mock' mm.is_activated = True mm.analyse_entries.side_effect = Error('error in analysis', status=500) self.senpy.plugins['MOCK'] = mm try: analyse(self.senpy, input='nothing', algorithm='MOCK') assert False except Error as ex: assert 'error in analysis' in ex['message'] assert ex['status'] == 500 mm.analyse.side_effect = Exception('generic exception on analysis') mm.analyse_entries.side_effect = Exception( 'generic exception on analysis') try: analyse(self.senpy, input='nothing', algorithm='MOCK') assert False except Error as ex: assert 'generic exception on analysis' in ex['message'] assert ex['status'] == 500 def test_filtering(self): """ Filtering plugins """ assert len(self.senpy.filter_plugins(name="Dummy")) > 0 assert not len(self.senpy.filter_plugins(name="notdummy")) assert self.senpy.filter_plugins(name="Dummy", is_activated=True) self.senpy.deactivate_plugin("Dummy", sync=True) assert not len( self.senpy.filter_plugins(name="Dummy", is_activated=True)) def test_load_default_plugins(self): senpy = Senpy(plugin_folder=self.dir, default_plugins=True) assert len(senpy.plugins) > 1 def test_convert_emotions(self): self.senpy.activate_all(sync=True) plugin = Plugin({ 'id': 'imaginary', 'onyx:usesEmotionModel': 'emoml:fsre-dimensions' }) eSet1 = EmotionSet() eSet1.prov__wasGeneratedBy = plugin['@id'] eSet1['onyx:hasEmotion'].append(Emotion({ 'emoml:arousal': 1, 'emoml:potency': 0, 'emoml:valence': 0 })) response = Results({ 'analysis': [{'plugin': plugin}], 'entries': [Entry({ 'nif:iString': 'much ado about nothing', 'emotions': [eSet1] })] }) params = {'emotionModel': 'emoml:big6', 'conversion': 'full'} r1 = deepcopy(response) r1.parameters = params self.senpy.convert_emotions(r1) assert len(r1.entries[0].emotions) == 2 params['conversion'] = 'nested' r2 = deepcopy(response) 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) r3.parameters = params self.senpy.convert_emotions(r3) assert len(r3.entries[0].emotions) == 1 r3.jsonld()
def main(): parser = argparse.ArgumentParser(description='Run a Senpy server') parser.add_argument( '--level', '-l', metavar='logging_level', type=str, default="INFO", help='Logging level') parser.add_argument( '--log-format', metavar='log_format', type=str, default='%(asctime)s %(levelname)-10s %(name)-30s \t %(message)s', help='Logging format') parser.add_argument( '--debug', '-d', action='store_true', default=False, help='Run the application in debug mode') parser.add_argument( '--no-default-plugins', action='store_true', default=False, help='Do not load the default plugins') parser.add_argument( '--host', type=str, default="0.0.0.0", help='Use 0.0.0.0 to accept requests from any host.') parser.add_argument( '--port', '-p', type=int, default=SERVER_PORT, help='Port to listen on.') parser.add_argument( '--plugins-folder', '-f', type=str, action='append', help='Where to look for plugins.') parser.add_argument( '--only-install', '-i', action='store_true', default=False, help='Do not run a server, only install plugin dependencies') parser.add_argument( '--only-test', action='store_true', default=False, help='Do not run a server, just test all plugins') parser.add_argument( '--test', '-t', action='store_true', default=False, help='Test all plugins before launching the server') parser.add_argument( '--only-list', '--list', action='store_true', default=False, help='Do not run a server, only list plugins found') parser.add_argument( '--data-folder', '--data', type=str, default=None, help='Where to look for data. It be set with the SENPY_DATA environment variable as well.') parser.add_argument( '--no-threaded', action='store_true', default=False, help='Run a single-threaded server') parser.add_argument( '--no-deps', '-n', action='store_true', default=False, help='Skip installing dependencies') parser.add_argument( '--version', '-v', action='store_true', default=False, help='Output the senpy version and exit') parser.add_argument( '--allow-fail', '--fail', action='store_true', default=False, help='Do not exit if some plugins fail to activate') args = parser.parse_args() print('Senpy version {}'.format(senpy.__version__)) print(sys.version) if args.version: exit(1) rl = logging.getLogger() rl.setLevel(getattr(logging, args.level)) logger_handler = rl.handlers[0] # First, generic formatter: logger_handler.setFormatter(logging.Formatter(args.log_format)) app = Flask(__name__) app.debug = args.debug sp = Senpy(app, plugin_folder=None, default_plugins=not args.no_default_plugins, data_folder=args.data_folder) folders = list(args.plugins_folder) if args.plugins_folder else [] if not folders: folders.append(".") for p in folders: sp.add_folder(p) plugins = sp.plugins(plugin_type=None, is_activated=False) maxname = max(len(x.name) for x in plugins) maxversion = max(len(str(x.version)) for x in plugins) print('Found {} plugins:'.format(len(plugins))) for plugin in plugins: import inspect fpath = inspect.getfile(plugin.__class__) print('\t{: <{maxname}} @ {: <{maxversion}} -> {}'.format(plugin.name, plugin.version, fpath, maxname=maxname, maxversion=maxversion)) if args.only_list: return if not args.no_deps: sp.install_deps() if args.only_install: return sp.activate_all(allow_fail=args.allow_fail) if args.test or args.only_test: easy_test(sp.plugins(), debug=args.debug) if args.only_test: return print('Senpy version {}'.format(senpy.__version__)) print('Server running on port %s:%d. Ctrl+C to quit' % (args.host, args.port)) try: app.run(args.host, args.port, threaded=not args.no_threaded, debug=app.debug) except KeyboardInterrupt: print('Bye!') sp.deactivate_all()
class ExtensionsTest(TestCase): def setUp(self): self.app = Flask('test_extensions') self.examples_dir = os.path.join(os.path.dirname(__file__), '..', 'example-plugins') self.senpy = Senpy(plugin_folder=self.examples_dir, app=self.app, default_plugins=False) self.senpy.deactivate_all() self.senpy.activate_plugin("Dummy", sync=True) self.app.config['TESTING'] = True # Tell Flask not to catch Exceptions def test_init(self): """ Initialising the app with the extension. """ assert hasattr(self.app, "senpy") tapp = Flask("temp app") self.senpy.init_app(tapp) assert hasattr(tapp, "senpy") def test_discovery(self): """ Discovery of plugins in given folders. """ # noinspection PyProtectedMember print(self.senpy.plugins()) assert self.senpy.get_plugin("dummy") def test_add_delete(self): '''Should be able to add and delete new plugins. ''' new = plugins.Analyser(name='new', description='new', version=0) self.senpy.add_plugin(new) assert new in self.senpy.plugins(is_activated=False) self.senpy.delete_plugin(new) assert new not in self.senpy.plugins(is_activated=False) def test_adding_folder(self): """ It should be possible for senpy to look for plugins in more folders. """ senpy = Senpy(plugin_folder=None, app=self.app, default_plugins=False) assert not senpy.analysis_plugins() senpy.add_folder(self.examples_dir) assert senpy.plugins(plugin_type=plugins.Analyser, is_activated=False) self.assertRaises(AttributeError, senpy.add_folder, 'DOES NOT EXIST') def test_installing(self): """ Installing a plugin """ info = { 'name': 'TestPip', 'module': 'mynoop', 'description': None, 'requirements': ['noop'], 'version': 0 } module = plugins.from_info(info, root=self.examples_dir, install=True) assert module.name == 'TestPip' assert module import noop dir(noop) def test_enabling(self): """ Enabling a plugin """ self.senpy.activate_all(sync=True) assert len(self.senpy.plugins()) >= 3 assert self.senpy.get_plugin("Sleep").is_activated def test_installing_nonexistent(self): """ Fail if the dependencies cannot be met """ info = { 'name': 'TestPipFail', 'module': 'dummy', 'description': None, 'requirements': ['IAmMakingThisPackageNameUpToFail'], 'version': 0 } with self.assertRaises(Error): plugins.install_deps(info) def test_disabling(self): """ Disabling a plugin """ self.senpy.deactivate_all(sync=True) assert not self.senpy.get_plugin("dummy").is_activated assert not self.senpy.get_plugin("sleep").is_activated def test_default(self): """ Default plugin should be set """ assert self.senpy.default_plugin assert self.senpy.default_plugin.name == "dummy" self.senpy.deactivate_all(sync=True) logging.debug("Default: {}".format(self.senpy.default_plugin)) assert self.senpy.default_plugin is None def test_noplugin(self): """ Don't analyse if there isn't any plugin installed """ self.senpy.deactivate_all(sync=True) self.assertRaises(Error, partial(analyse, self.senpy, input="tupni")) def test_analyse(self): """ Using a plugin """ # I was using mock until plugin started inheriting # Leaf (defaultdict with __setattr__ and __getattr__. r1 = analyse(self.senpy, algorithm="Dummy", input="tupni", output="tuptuo") r2 = analyse(self.senpy, input="tupni", output="tuptuo") assert r1.activities[0].algorithm == "endpoint:plugins/dummy_0.1" assert r2.activities[0].algorithm == "endpoint:plugins/dummy_0.1" assert r1.entries[0]['nif:isString'] == 'input' def test_analyse_empty(self): """ Trying to analyse when no plugins are installed should raise an error.""" senpy = Senpy(plugin_folder=None, app=self.app, default_plugins=False) self.assertRaises(Error, senpy.analyse, Results(), []) def test_analyse_wrong(self): """ Trying to analyse with a non-existent plugin should raise an error.""" self.assertRaises(Error, analyse, self.senpy, algorithm='DOES NOT EXIST', input='test') def test_analyse_jsonld(self): """ Using a plugin with JSON-LD input""" js_input = '''{ "@id": "prueba", "@type": "results", "entries": [ {"@id": "entry1", "nif:isString": "tupni", "@type": "entry" } ] }''' r1 = analyse(self.senpy, algorithm="Dummy", input=js_input, informat="json-ld", output="tuptuo") r2 = analyse(self.senpy, input="tupni", output="tuptuo") assert r1.activities[0].algorithm == "endpoint:plugins/dummy_0.1" assert r2.activities[0].algorithm == "endpoint:plugins/dummy_0.1" assert r1.entries[0]['nif:isString'] == 'input' def test_analyse_error(self): class ErrorPlugin(plugins.Analyser): author = 'nobody' version = 0 ex = Error() def process(self, *args, **kwargs): raise self.ex m = ErrorPlugin(ex=Error('error in analysis', status=500)) self.senpy.add_plugin(m) try: analyse(self.senpy, input='nothing', algorithm='ErrorPlugin') assert False except Error as ex: assert 'error in analysis' in ex['message'] assert ex['status'] == 500 m.ex = Exception('generic exception on analysis') try: analyse(self.senpy, input='nothing', algorithm='ErrorPlugin') assert False except Exception as ex: assert 'generic exception on analysis' in str(ex) def test_filtering(self): """ Filtering plugins """ assert len(self.senpy.plugins(name="Dummy")) > 0 assert not len(self.senpy.plugins(name="NotDummy")) assert self.senpy.plugins(name="Dummy", is_activated=True) self.senpy.deactivate_plugin("Dummy", sync=True) assert not len(self.senpy.plugins(name="Dummy", is_activated=True)) def test_load_default_plugins(self): senpy = Senpy(plugin_folder=self.examples_dir, default_plugins=True) assert len(senpy.plugins(is_activated=False)) > 1 def test_convert_emotions(self): self.senpy.activate_all(sync=True) plugin = Plugin({ 'id': 'imaginary', 'onyx:usesEmotionModel': 'emoml:fsre-dimensions' }) eSet1 = EmotionSet() activity = plugin.activity() eSet1.prov(activity) eSet1['onyx:hasEmotion'].append(Emotion({ 'emoml:arousal': 1, 'emoml:potency': 0, 'emoml:valence': 0 })) response = Results({ 'activities': [activity], 'entries': [Entry({ 'nif:isString': 'much ado about nothing', 'onyx:hasEmotionSet': [eSet1] })] }) params = {'emotion-model': 'emoml:big6', 'algorithm': ['conversion'], 'conversion': 'full'} r1 = deepcopy(response) r1.parameters = params self.senpy.analyse(r1) assert len(r1.entries[0].emotions) == 2 params['conversion'] = 'nested' r2 = deepcopy(response) r2.parameters = params self.senpy.analyse(r2) assert len(r2.entries[0].emotions) == 1 assert r2.entries[0].emotions[0]['prov:wasDerivedFrom'] == eSet1 params['conversion'] = 'filtered' r3 = deepcopy(response) r3.parameters = params self.senpy.analyse(r3) assert len(r3.entries[0].emotions) == 1 r3.jsonld()
# 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. """ This is a helper for development. If you want to run Senpy use: python -m senpy """ from gevent.monkey import patch_all; patch_all() import gevent import config from flask import Flask from senpy.extensions import Senpy import logging import os from gevent.wsgi import WSGIServer logging.basicConfig(level=logging.DEBUG) app = Flask(__name__) mypath = os.path.dirname(os.path.realpath(__file__)) sp = Senpy(app, os.path.join(mypath, "plugins"), default_plugins=True) sp.activate_all() if __name__ == '__main__': import logging logging.basicConfig(level=config.DEBUG) app.debug = config.DEBUG http_server = WSGIServer(('', config.SERVER_PORT), app) http_server.serve_forever()
class BlueprintsTest(TestCase): def create_app(self): self.app = Flask("test_extensions") self.senpy = Senpy() self.senpy.init_app(self.app) self.dir = os.path.join(os.path.dirname(__file__), "..") self.senpy.add_folder(self.dir) self.senpy.activate_plugin("Dummy", sync=True) return self.app def test_home(self): """ Calling with no arguments should ask the user for more arguments """ resp = self.client.get("/api/") self.assert404(resp) logging.debug(resp.json) assert resp.json["status"] == 404 atleast = { "status": 404, "message": "Missing or invalid parameters", } assert check_dict(resp.json, atleast) def test_analysis(self): """ The dummy plugin returns an empty response,\ it should contain the context """ resp = self.client.get("/api/?i=My aloha mohame") self.assert200(resp) logging.debug("Got response: %s", resp.json) assert "@context" in resp.json assert "entries" in resp.json def test_list(self): """ List the plugins """ resp = self.client.get("/api/plugins/") self.assert200(resp) logging.debug(resp.json) assert 'plugins' in resp.json plugins = resp.json['plugins'] assert len(plugins) > 1 assert list(p for p in plugins if p['name'] == "Dummy") assert "@context" in resp.json def test_headers(self): for i, j in product(["/api/plugins/?nothing=", "/api/?i=test&"], ["inHeaders"]): resp = self.client.get("%s" % (i)) assert "@context" in resp.json resp = self.client.get("%s&%s=0" % (i, j)) assert "@context" in resp.json resp = self.client.get("%s&%s=1" % (i, j)) assert "@context" not in resp.json resp = self.client.get("%s&%s=true" % (i, j)) assert "@context" not in resp.json def test_detail(self): """ Show only one plugin""" resp = self.client.get("/api/plugins/Dummy/") self.assert200(resp) logging.debug(resp.json) assert "@id" in resp.json assert resp.json["@id"] == "Dummy_0.1" def test_activate(self): """ Activate and deactivate one plugin """ resp = self.client.get("/api/plugins/Dummy/deactivate") self.assert200(resp) sleep(0.5) resp = self.client.get("/api/plugins/Dummy/") self.assert200(resp) assert "is_activated" in resp.json assert resp.json["is_activated"] == False resp = self.client.get("/api/plugins/Dummy/activate") self.assert200(resp) sleep(0.5) resp = self.client.get("/api/plugins/Dummy/") self.assert200(resp) assert "is_activated" in resp.json assert resp.json["is_activated"] == True def test_default(self): """ Show only one plugin""" resp = self.client.get("/api/plugins/default/") self.assert200(resp) logging.debug(resp.json) assert "@id" in resp.json assert resp.json["@id"] == "Dummy_0.1" resp = self.client.get("/api/plugins/Dummy/deactivate") self.assert200(resp) sleep(0.5) resp = self.client.get("/api/plugins/default/") self.assert404(resp) def test_context(self): resp = self.client.get("/api/contexts/context.jsonld") self.assert200(resp) assert "@context" in resp.json assert check_dict( resp.json["@context"], {"marl": "http://www.gsi.dit.upm.es/ontologies/marl/ns#"}) def test_schema(self): resp = self.client.get("/api/schemas/definitions.json") self.assert200(resp) assert "$schema" in resp.json
# limitations under the License. """ This is a helper for development. If you want to run Senpy use: python -m senpy """ from gevent.monkey import patch_all patch_all() import gevent import config from flask import Flask from senpy.extensions import Senpy import logging import os from gevent.wsgi import WSGIServer logging.basicConfig(level=logging.DEBUG) app = Flask(__name__) mypath = os.path.dirname(os.path.realpath(__file__)) sp = Senpy(app, os.path.join(mypath, "plugins"), default_plugins=True) sp.activate_all() if __name__ == '__main__': import logging logging.basicConfig(level=config.DEBUG) app.debug = config.DEBUG http_server = WSGIServer(('', config.SERVER_PORT), app) http_server.serve_forever()
class BlueprintsTest(TestCase): def create_app(self): self.app = Flask("test_extensions") self.senpy = Senpy() self.senpy.init_app(self.app) self.dir = os.path.join(os.path.dirname(__file__), "..") self.senpy.add_folder(self.dir) self.senpy.activate_plugin("Dummy", sync=True) return self.app def test_home(self): """ Calling with no arguments should ask the user for more arguments """ resp = self.client.get("/") self.assert404(resp) logging.debug(resp.json) assert resp.json["status"] == 404 atleast = { "status": 404, "message": "Missing or invalid parameters", } assert check_dict(resp.json, atleast) def test_analysis(self): """ The dummy plugin returns an empty response,\ it should contain the context """ resp = self.client.get("/?i=My aloha mohame") self.assert200(resp) logging.debug("Got response: %s", resp.json) assert "@context" in resp.json assert check_dict( resp.json["@context"], {"marl": "http://www.gsi.dit.upm.es/ontologies/marl/ns#"}) assert "entries" in resp.json def test_list(self): """ List the plugins """ resp = self.client.get("/plugins/") self.assert200(resp) logging.debug(resp.json) assert "Dummy" in resp.json assert "@context" in resp.json def test_headers(self): for i, j in product(["/plugins/?nothing=", "/?i=test&"], ["headers", "inHeaders"]): resp = self.client.get("%s" % (i)) assert "@context" in resp.json resp = self.client.get("%s&%s=0" % (i, j)) assert "@context" in resp.json resp = self.client.get("%s&%s=1" % (i, j)) assert "@context" not in resp.json resp = self.client.get("%s&%s=true" % (i, j)) assert "@context" not in resp.json def test_detail(self): """ Show only one plugin""" resp = self.client.get("/plugins/Dummy") self.assert200(resp) logging.debug(resp.json) assert "@id" in resp.json assert resp.json["@id"] == "Dummy_0.1" def test_activate(self): """ Activate and deactivate one plugin """ resp = self.client.get("/plugins/Dummy/deactivate") self.assert200(resp) sleep(0.5) resp = self.client.get("/plugins/Dummy") self.assert200(resp) assert "is_activated" in resp.json assert resp.json["is_activated"] == False resp = self.client.get("/plugins/Dummy/activate") self.assert200(resp) sleep(0.5) resp = self.client.get("/plugins/Dummy") self.assert200(resp) assert "is_activated" in resp.json assert resp.json["is_activated"] == True def test_default(self): """ Show only one plugin""" resp = self.client.get("/default") self.assert200(resp) logging.debug(resp.json) assert "@id" in resp.json assert resp.json["@id"] == "Dummy_0.1" resp = self.client.get("/plugins/Dummy/deactivate") self.assert200(resp) sleep(0.5) resp = self.client.get("/default") self.assert404(resp)
class ExtensionsTest(TestCase): def create_app(self): self.app = Flask("test_extensions") self.dir = os.path.join(os.path.dirname(__file__), "..") self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) self.senpy.activate_plugin("Dummy", sync=True) return self.app def test_init(self): """ Initialising the app with the extension. """ assert hasattr(self.app, "senpy") tapp = Flask("temp app") self.senpy.init_app(tapp) assert hasattr(tapp, "senpy") def test_discovery(self): """ Discovery of plugins in given folders. """ # noinspection PyProtectedMember assert self.dir in self.senpy._search_folders print self.senpy.plugins assert "Dummy" in self.senpy.plugins def test_enabling(self): """ Enabling a plugin """ self.senpy.activate_all(sync=True) assert len(self.senpy.plugins) == 2 assert self.senpy.plugins["Sleep"].is_activated def test_disabling(self): """ Disabling a plugin """ self.senpy.deactivate_all(sync=True) assert not self.senpy.plugins["Dummy"].is_activated assert not self.senpy.plugins["Sleep"].is_activated def test_default(self): """ Default plugin should be set """ assert self.senpy.default_plugin assert self.senpy.default_plugin.name == "Dummy" self.senpy.deactivate_all(sync=True) logging.debug("Default: {}".format(self.senpy.default_plugin)) assert self.senpy.default_plugin is None def test_noplugin(self): """ Don't analyse if there isn't any plugin installed """ self.senpy.deactivate_all(sync=True) resp = self.senpy.analyse(input="tupni") logging.debug("Response: {}".format(resp)) assert resp["status"] == 404 def test_analyse(self): """ 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") assert r1.analysis[0].id[:5] == "Dummy" assert r2.analysis[0].id[:5] == "Dummy" for plug in self.senpy.plugins: self.senpy.deactivate_plugin(plug, sync=True) resp = self.senpy.analyse(input="tupni") logging.debug("Response: {}".format(resp)) assert resp["status"] == 404 def test_filtering(self): """ Filtering plugins """ assert len(self.senpy.filter_plugins(name="Dummy")) > 0 assert not len(self.senpy.filter_plugins(name="notdummy")) assert self.senpy.filter_plugins(name="Dummy", is_activated=True) self.senpy.deactivate_plugin("Dummy", sync=True) assert not len( self.senpy.filter_plugins(name="Dummy", is_activated=True))
def setUp(self): self.app = Flask("test_plugin") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app)
def main(): parser = argparse.ArgumentParser(description='Run a Senpy server') parser.add_argument( '--level', '-l', metavar='logging_level', type=str, default="INFO", help='Logging level') parser.add_argument( '--debug', '-d', action='store_true', default=False, help='Run the application in debug mode') parser.add_argument( '--default-plugins', action='store_true', default=False, help='Load the default plugins') parser.add_argument( '--host', type=str, default="0.0.0.0", help='Use 0.0.0.0 to accept requests from any host.') parser.add_argument( '--port', '-p', type=int, default=SERVER_PORT, help='Port to listen on.') parser.add_argument( '--plugins-folder', '-f', type=str, default='plugins', help='Where to look for plugins.') parser.add_argument( '--only-install', '-i', action='store_true', default=False, help='Do not run a server, only install plugin dependencies') parser.add_argument( '--threaded', action='store_false', default=True, help='Run a threaded server') parser.add_argument( '--version', '-v', action='store_true', default=False, help='Output the senpy version and exit') args = parser.parse_args() if args.version: print('Senpy version {}'.format(senpy.__version__)) exit(1) logging.basicConfig() rl = logging.getLogger() rl.setLevel(getattr(logging, args.level)) app = Flask(__name__) app.debug = args.debug sp = Senpy(app, args.plugins_folder, default_plugins=args.default_plugins) sp.install_deps() if args.only_install: return sp.activate_all() print('Senpy version {}'.format(senpy.__version__)) print('Server running on port %s:%d. Ctrl+C to quit' % (args.host, args.port)) app.run(args.host, args.port, threaded=args.threaded, debug=app.debug) sp.deactivate_all()
class ExtensionsTest(TestCase): def setUp(self): self.app = Flask("test_extensions") self.dir = os.path.join(os.path.dirname(__file__)) self.senpy = Senpy(plugin_folder=self.dir, default_plugins=False) self.senpy.init_app(self.app) self.senpy.activate_plugin("Dummy", sync=True) def test_init(self): """ Initialising the app with the extension. """ assert hasattr(self.app, "senpy") tapp = Flask("temp app") self.senpy.init_app(tapp) assert hasattr(tapp, "senpy") def test_discovery(self): """ Discovery of plugins in given folders. """ # noinspection PyProtectedMember assert self.dir in self.senpy._search_folders print(self.senpy.plugins) assert "Dummy" in self.senpy.plugins def test_enabling(self): """ Enabling a plugin """ info = { 'name': 'TestPip', 'module': 'dummy', 'requirements': ['noop'], 'version': 0 } root = os.path.join(self.dir, 'dummy_plugin') name, module = self.senpy._load_plugin_from_info(info, root=root) assert name == 'TestPip' assert module import noop def test_installing(self): """ Enabling a plugin """ self.senpy.activate_all(sync=True) assert len(self.senpy.plugins) == 2 assert self.senpy.plugins["Sleep"].is_activated def test_disabling(self): """ Disabling a plugin """ self.senpy.deactivate_all(sync=True) assert not self.senpy.plugins["Dummy"].is_activated assert not self.senpy.plugins["Sleep"].is_activated def test_default(self): """ Default plugin should be set """ assert self.senpy.default_plugin assert self.senpy.default_plugin.name == "Dummy" self.senpy.deactivate_all(sync=True) logging.debug("Default: {}".format(self.senpy.default_plugin)) assert self.senpy.default_plugin is None 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")) def test_analyse(self): """ 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") assert r1.analysis[0].id[:5] == "Dummy" assert r2.analysis[0].id[:5] == "Dummy" def test_filtering(self): """ Filtering plugins """ assert len(self.senpy.filter_plugins(name="Dummy")) > 0 assert not len(self.senpy.filter_plugins(name="notdummy")) assert self.senpy.filter_plugins(name="Dummy", is_activated=True) self.senpy.deactivate_plugin("Dummy", sync=True) assert not len( self.senpy.filter_plugins(name="Dummy", is_activated=True))
class BlueprintsTest(TestCase): def setUp(self): self.app = Flask("test_extensions") self.client = self.app.test_client() self.senpy = Senpy() self.senpy.init_app(self.app) self.dir = os.path.join(os.path.dirname(__file__), "..") self.senpy.add_folder(self.dir) self.senpy.activate_plugin("Dummy", sync=True) self.senpy.activate_plugin("DummyRequired", sync=True) self.senpy.default_plugin = 'Dummy' def assertCode(self, resp, code): self.assertEqual(resp.status_code, code) def test_home(self): """ Calling with no arguments should ask the user for more arguments """ resp = self.client.get("/api/") self.assertCode(resp, 400) js = parse_resp(resp) logging.debug(js) assert js["status"] == 400 atleast = { "status": 400, "message": "Missing or invalid parameters", } assert check_dict(js, atleast) def test_analysis(self): """ The dummy plugin returns an empty response,\ it should contain the context """ resp = self.client.get("/api/?i=My aloha mohame") self.assertCode(resp, 200) js = parse_resp(resp) logging.debug("Got response: %s", js) assert "@context" in js assert "entries" in js def test_analysis_extra(self): """ Extra params that have a default should """ resp = self.client.get("/api/?i=My aloha mohame&algo=Dummy") self.assertCode(resp, 200) js = parse_resp(resp) logging.debug("Got response: %s", js) assert "@context" in js assert "entries" in js def test_analysis_extra_required(self): """ Extra params that have a required argument that does not have a default should raise an error. """ resp = self.client.get("/api/?i=My aloha mohame&algo=DummyRequired") self.assertCode(resp, 400) js = parse_resp(resp) logging.debug("Got response: %s", js) assert isinstance(js, models.Error) def test_error(self): """ The dummy plugin returns an empty response,\ it should contain the context """ resp = self.client.get("/api/?i=My aloha mohame&algo=DOESNOTEXIST") self.assertCode(resp, 404) js = parse_resp(resp) logging.debug("Got response: %s", js) assert isinstance(js, models.Error) def test_list(self): """ List the plugins """ resp = self.client.get("/api/plugins/") self.assertCode(resp, 200) js = parse_resp(resp) logging.debug(js) assert 'plugins' in js plugins = js['plugins'] assert len(plugins) > 1 assert list(p for p in plugins if p['name'] == "Dummy") assert "@context" in js def test_headers(self): for i, j in product(["/api/plugins/?nothing=", "/api/?i=test&"], ["inHeaders"]): resp = self.client.get("%s" % (i)) js = parse_resp(resp) assert "@context" in js resp = self.client.get("%s&%s=0" % (i, j)) js = parse_resp(resp) assert "@context" in js resp = self.client.get("%s&%s=1" % (i, j)) js = parse_resp(resp) assert "@context" not in js resp = self.client.get("%s&%s=true" % (i, j)) js = parse_resp(resp) assert "@context" not in js def test_detail(self): """ Show only one plugin""" resp = self.client.get("/api/plugins/Dummy/") self.assertCode(resp, 200) js = parse_resp(resp) logging.debug(js) assert "@id" in js assert js["@id"] == "plugins/Dummy_0.1" def test_default(self): """ Show only one plugin""" resp = self.client.get("/api/plugins/default/") self.assertCode(resp, 200) js = parse_resp(resp) logging.debug(js) assert "@id" in js assert js["@id"] == "plugins/Dummy_0.1" def test_context(self): resp = self.client.get("/api/contexts/context.jsonld") self.assertCode(resp, 200) js = parse_resp(resp) assert "@context" in js assert check_dict( js["@context"], {"marl": "http://www.gsi.dit.upm.es/ontologies/marl/ns#"}) def test_schema(self): resp = self.client.get("/api/schemas/definitions.json") self.assertCode(resp, 200) js = parse_resp(resp) assert "$schema" in js
def test_load_default_plugins(self): senpy = Senpy(plugin_folder=self.dir, default_plugins=True) assert len(senpy.plugins) > 1