From 697e7797672cd339e190357e4347bdf11f1cf07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20Fernando=20S=C3=A1nchez?= Date: Mon, 14 May 2018 11:38:02 +0200 Subject: [PATCH] Fix schema issues and parameter validation --- Dockerfile.template | 2 -- requirements.txt | 3 +++ senpy/api.py | 2 +- senpy/blueprints.py | 16 +++++++++------- senpy/models.py | 4 ++++ senpy/plugins/__init__.py | 4 +--- senpy/schemas/evaluation.json | 2 +- tests/test_api.py | 22 +++++++++++++++++++++- tests/test_schemas.py | 5 ++++- 9 files changed, 44 insertions(+), 16 deletions(-) diff --git a/Dockerfile.template b/Dockerfile.template index 1aa5236..b58dd92 100644 --- a/Dockerfile.template +++ b/Dockerfile.template @@ -6,8 +6,6 @@ RUN apt-get update && apt-get install -y \ libblas-dev liblapack-dev liblapacke-dev gfortran \ && rm -rf /var/lib/apt/lists/* -RUN pip install --no-cache-dir --upgrade numpy scipy scikit-learn - RUN mkdir /cache/ /senpy-plugins /data/ VOLUME /data/ diff --git a/requirements.txt b/requirements.txt index 80cf572..8e75573 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,6 @@ jsonref PyYAML rdflib rdflib-jsonld +numpy +scipy +scikit-learn diff --git a/senpy/api.py b/senpy/api.py index 08a8a6d..dc0785d 100644 --- a/senpy/api.py +++ b/senpy/api.py @@ -147,7 +147,7 @@ def parse_params(indict, *specs): for param, options in iteritems(spec): for alias in options.get("aliases", []): # Replace each alias with the correct name of the parameter - if alias in indict and alias is not param: + if alias in indict and alias != param: outdict[param] = indict[alias] del outdict[alias] continue diff --git a/senpy/blueprints.py b/senpy/blueprints.py index c453665..d5dec56 100644 --- a/senpy/blueprints.py +++ b/senpy/blueprints.py @@ -19,7 +19,7 @@ Blueprints for Senpy """ from flask import (Blueprint, request, current_app, render_template, url_for, jsonify) -from .models import Error, Response, Help, Plugins, read_schema, Datasets +from .models import Error, Response, Help, Plugins, read_schema, dump_schema, Datasets from . import api from .version import __version__ from functools import wraps @@ -67,9 +67,9 @@ def index(): @api_blueprint.route('/schemas/') def schema(schema="definitions"): try: - return jsonify(read_schema(schema)) - except Exception: # Should be FileNotFoundError, but it's missing from py2 - return Error(message="Schema not found", status=404).flask() + return dump_schema(read_schema(schema)) + except Exception as ex: # Should be FileNotFoundError, but it's missing from py2 + return Error(message="Schema not found: {}".format(ex), status=404).flask() def basic_api(f): @@ -133,6 +133,7 @@ def api_root(): req = api.parse_call(request.parameters) return current_app.senpy.analyse(req) + @api_blueprint.route('/evaluate/', methods=['POST', 'GET']) @basic_api def evaluate(): @@ -145,6 +146,7 @@ def evaluate(): response = current_app.senpy.evaluate(params) return response + @api_blueprint.route('/plugins/', methods=['POST', 'GET']) @basic_api def plugins(): @@ -163,10 +165,10 @@ def plugin(plugin=None): return sp.get_plugin(plugin) -@api_blueprint.route('/datasets/', methods=['POST','GET']) +@api_blueprint.route('/datasets/', methods=['POST', 'GET']) @basic_api def datasets(): sp = current_app.senpy datasets = sp.datasets - dic = Datasets(datasets = list(datasets.values())) - return dic \ No newline at end of file + dic = Datasets(datasets=list(datasets.values())) + return dic diff --git a/senpy/models.py b/senpy/models.py index 25636a0..2d74087 100644 --- a/senpy/models.py +++ b/senpy/models.py @@ -51,6 +51,10 @@ def read_schema(schema_file, absolute=False): return jsonref.load(f, base_uri=schema_uri) +def dump_schema(schema): + return jsonref.dumps(schema) + + def load_context(context): logging.debug('Loading context: {}'.format(context)) if not context: diff --git a/senpy/plugins/__init__.py b/senpy/plugins/__init__.py index 66b56be..80fea08 100644 --- a/senpy/plugins/__init__.py +++ b/senpy/plugins/__init__.py @@ -19,8 +19,6 @@ import importlib import yaml import threading -import numpy as np - from .. import models, utils from .. import api @@ -291,7 +289,7 @@ class Box(AnalysisPlugin): return self def transform(self, X): - return np.array([self.predict_one(x) for x in X]) + return [self.predict_one(x) for x in X] def predict(self, X): return self.transform(X) diff --git a/senpy/schemas/evaluation.json b/senpy/schemas/evaluation.json index c8816e9..5af72d8 100644 --- a/senpy/schemas/evaluation.json +++ b/senpy/schemas/evaluation.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "name": "Evalation", + "name": "Evaluation", "properties": { "@id": { "type": "string" diff --git a/tests/test_api.py b/tests/test_api.py index 96bd9e3..80e16bc 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -32,7 +32,7 @@ class APITest(TestCase): query = {} plug_params = { 'hello': { - 'aliases': ['hello', 'hiya'], + 'aliases': ['hiya', 'hello'], 'required': True } } @@ -48,6 +48,26 @@ class APITest(TestCase): assert 'hello' in p assert p['hello'] == 'dlrow' + def test_parameters2(self): + in1 = { + 'meaningcloud-key': 5 + } + in2 = { + 'apikey': 25 + } + extra_params = { + "apikey": { + "aliases": [ + "apikey", + "meaningcloud-key" + ], + "required": True + } + } + p1 = parse_params(in1, extra_params) + p2 = parse_params(in2, extra_params) + assert (p2['apikey'] / p1['apikey']) == 5 + def test_default(self): spec = { 'hello': { diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 44c6b1e..5cb1ee4 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -8,6 +8,8 @@ from fnmatch import fnmatch from jsonschema import RefResolver, Draft4Validator, ValidationError +from senpy.models import read_schema + root_path = path.join(path.dirname(path.realpath(__file__)), '..') schema_folder = path.join(root_path, 'senpy', 'schemas') examples_path = path.join(root_path, 'docs', 'examples') @@ -15,7 +17,8 @@ bad_examples_path = path.join(root_path, 'docs', 'bad-examples') class JSONSchemaTests(unittest.TestCase): - pass + def test_definitions(self): + read_schema('definitions.json') def do_create_(jsfile, success):