diff --git a/senpy/blueprints.py b/senpy/blueprints.py index dccdb35..42e0c90 100644 --- a/senpy/blueprints.py +++ b/senpy/blueprints.py @@ -184,14 +184,19 @@ def basic_api(f): return decorated_function -@api_blueprint.route('/', methods=['POST', 'GET']) +@api_blueprint.route('/', defaults={'plugin': None}, methods=['POST', 'GET']) +@api_blueprint.route('/', methods=['POST', 'GET']) @basic_api -def api_root(): +def api_root(plugin): if request.parameters['help']: dic = dict(api.API_PARAMS, **api.NIF_PARAMS) response = Help(valid_parameters=dic) return response req = api.parse_call(request.parameters) + if plugin: + plugin = plugin.replace('+', '/') + plugin = plugin.split('/') + req.parameters['algorithm'] = plugin return current_app.senpy.analyse(req) @@ -221,7 +226,7 @@ def plugins(): @api_blueprint.route('/plugins//', methods=['POST', 'GET']) @basic_api -def plugin(plugin=None): +def plugin(plugin): sp = current_app.senpy return sp.get_plugin(plugin) diff --git a/senpy/extensions.py b/senpy/extensions.py index 46c1924..d545485 100644 --- a/senpy/extensions.py +++ b/senpy/extensions.py @@ -153,7 +153,6 @@ class Senpy(object): yield i return plugin = plugins[0] - self._activate(plugin) # Make sure the plugin is activated specific_params = api.parse_extra_params(req, plugin) req.analysis.append({'plugin': plugin, 'parameters': specific_params}) @@ -352,7 +351,7 @@ class Senpy(object): logger.info("Activating plugin: {}".format(plugin.name)) - if sync or 'async' in plugin and not plugin.async: + if sync or not getattr(plugin, 'async', True): return self._activate(plugin) else: th = Thread(target=partial(self._activate, plugin)) @@ -375,7 +374,7 @@ class Senpy(object): self._set_active(plugin, False) - if sync or 'async' in plugin and not plugin.async: + if sync or not getattr(plugin, 'async', True): self._deactivate(plugin) else: th = Thread(target=partial(self._deactivate, plugin)) diff --git a/tests/test_blueprints.py b/tests/test_blueprints.py index 3efbf2e..5648ece 100644 --- a/tests/test_blueprints.py +++ b/tests/test_blueprints.py @@ -70,7 +70,7 @@ class BlueprintsTest(TestCase): def test_analysis_extra(self): """ - Extra params that have a default should + Extra params that have a default should use it """ resp = self.client.get("/api/?i=My aloha mohame&algo=Dummy&with_parameters=true") self.assertCode(resp, 200) @@ -95,6 +95,44 @@ class BlueprintsTest(TestCase): resp = self.client.get("/api/?i=My aloha mohame&algo=DummyRequired&example=a") self.assertCode(resp, 200) + def test_analysis_url(self): + """ + The algorithm can also be specified as part of the URL + """ + self.app.config['TESTING'] = False # Errors are expected in this case + resp = self.client.get("/api/DummyRequired?i=My aloha mohame") + self.assertCode(resp, 400) + js = parse_resp(resp) + logging.debug("Got response: %s", js) + assert isinstance(js, models.Error) + resp = self.client.get("/api/DummyRequired?i=My aloha mohame&example=notvalid") + self.assertCode(resp, 400) + resp = self.client.get("/api/DummyRequired?i=My aloha mohame&example=a") + self.assertCode(resp, 200) + + def test_analysis_chain(self): + """ + More than one algorithm can be specified. Plugins will then be chained + """ + resp = self.client.get("/api/Dummy?i=My aloha mohame") + js = parse_resp(resp) + assert len(js['analysis']) == 1 + assert js['entries'][0]['nif:isString'] == 'My aloha mohame'[::-1] + + resp = self.client.get("/api/Dummy/Dummy?i=My aloha mohame") + # Calling dummy twice, should return the same string + self.assertCode(resp, 200) + js = parse_resp(resp) + assert len(js['analysis']) == 2 + assert js['entries'][0]['nif:isString'] == 'My aloha mohame' + + resp = self.client.get("/api/Dummy+Dummy?i=My aloha mohame") + # Same with pluses instead of slashes + self.assertCode(resp, 200) + js = parse_resp(resp) + assert len(js['analysis']) == 2 + assert js['entries'][0]['nif:isString'] == 'My aloha mohame' + def test_error(self): """ The dummy plugin returns an empty response,\