diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000..a2691ae --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,2 @@ +[settings] +known_third_party=webtest diff --git a/claimstore/core/json.py b/claimstore/core/json.py index 58c5958..118e00d 100644 --- a/claimstore/core/json.py +++ b/claimstore/core/json.py @@ -62,29 +62,25 @@ def validate_json(json_input, schema): :param schema: JSON schema to use in the validation. It must be a string with the format module.schema_name (e.g. claims.claimants). :type schema: str. - :returns: True if `json_input` follows the schema. False otherwise. - :rtype: bool. + :raises: :exc:`ValidationError` if the instance is invalid. """ - if schema: - schema_content = get_json_schema(schema) - module_name, schema_name = schema.split('.') - resolver = jsonschema.RefResolver('{}/'.format( - pathlib.Path( - os.path.join( - current_app.config['BASE_DIR'], - 'claimstore', - 'modules', - module_name, - 'static', - 'json', - 'schemas' - ) - ).as_uri()), - schema_content - ) - jsonschema.Draft4Validator( - json.loads(schema_content), - resolver=resolver - ).validate(json_input) - return True - return False + schema_content = get_json_schema(schema) + module_name, schema_name = schema.split('.') + resolver = jsonschema.RefResolver('{}/'.format( + pathlib.Path( + os.path.join( + current_app.config['BASE_DIR'], + 'claimstore', + 'modules', + module_name, + 'static', + 'json', + 'schemas' + ) + ).as_uri()), + schema_content + ) + jsonschema.Draft4Validator( + json.loads(schema_content), + resolver=resolver + ).validate(json_input) diff --git a/claimstore/modules/claims/cli.py b/claimstore/modules/claims/cli.py index deec763..080fc4b 100644 --- a/claimstore/modules/claims/cli.py +++ b/claimstore/modules/claims/cli.py @@ -63,7 +63,7 @@ def initdb(config): load_all_predicates(config) load_all_pids(config) load_all_claimants(config) - click.echo('Database successfully initialised.') + click.echo('Database initialisation completed.') @click.command() @@ -95,7 +95,7 @@ def populatedb(data): ) try: load_all_claims(config_path=data) - click.echo('Database successfully populated.') + click.echo('Database populate completed.') except Exception: click.echo( 'Claims could not be loaded. Try `claimstore initdb` first.' diff --git a/claimstore/modules/claims/fixtures/claim.py b/claimstore/modules/claims/fixtures/claim.py index 4a5bf1c..ee9397b 100644 --- a/claimstore/modules/claims/fixtures/claim.py +++ b/claimstore/modules/claims/fixtures/claim.py @@ -55,34 +55,39 @@ def load_all_claims(test_app=None, config_path=None): ) for claim_fp in glob.glob("{}/*.json".format(claims_filepath)): with open(claim_fp) as f: - test_app.post_json( + resp = test_app.post_json( '/claims', - json.loads(f.read())) + json.load(f), + expect_errors=True + ) + if resp.status_code != 200: + print('{} could not be loaded. {}.'.format( + claim_fp, + resp.json['message'] + )) @pytest.fixture def dummy_claim(): """Fixture that creates a dummy claim.""" - return json.loads(""" - { - "claimant": "dummy_claimant", - "subject": { + return { + "claimant": "dummy_claimant", + "subject": { "type": "CDS_RECORD_ID", "value": "2001192" - }, - "predicate": "is_same_as", - "certainty": 1.0, - "object": { + }, + "predicate": "is_same_as", + "certainty": 1.0, + "object": { "type": "CDS_REPORT_NUMBER", "value": "CMS-PAS-HIG-14-008" - }, - "arguments": { + }, + "arguments": { "human": 0, "actor": "CDS_submission" - }, - "created": "2015-03-25T11:00:00Z" - } - """) + }, + "created": "2015-03-25T11:00:00Z" + } def _remove_all_claims(): diff --git a/claimstore/modules/claims/fixtures/claimant.py b/claimstore/modules/claims/fixtures/claimant.py index 9536b89..74c74da 100644 --- a/claimstore/modules/claims/fixtures/claimant.py +++ b/claimstore/modules/claims/fixtures/claimant.py @@ -26,7 +26,9 @@ import pytest from flask import current_app +from jsonschema import ValidationError +from claimstore.core.json import validate_json from claimstore.ext.sqlalchemy import db from claimstore.modules.claims.models import Claimant @@ -56,34 +58,41 @@ def load_all_claimants(config_path=None): ) for claimant_fp in glob.glob("{}/*.json".format(claimants_filepath)): with open(claimant_fp) as f: - create_claimant(json.loads(f.read())) + json_data = json.load(f) + try: + validate_json(json_data, 'claims.claimant') + except ValidationError: + print( + '`{}` could not be loaded. It does not follow the proper ' + 'JSON schema specification.'.format(claimant_fp) + ) + continue + create_claimant(json_data) @pytest.fixture def dummy_claimant(): """Fixture that creates a dummy claimant.""" - return json.loads(""" - { - "name": "dummy_claimant", - "url": "http://dummy.net", - "persistent_identifiers": [ - { + return { + "name": "dummy_claimant", + "url": "http://dummy.net", + "persistent_identifiers": [ + { "type": "CDS_RECORD_ID", "description": "CDS record", "url": "http://cds.cern.ch/record/", "example_value": "123", "example_url": "http://cds.cern.ch/record/123" - }, - { + }, + { "type": "CDS_REPORT_NUMBER", "description": "CDS report number", "url": "http://cds.cern.ch/report/", "example_value": "CMS-PAS-HIG-14-008", "example_url": "http://cds.cern.ch/report/CMS-PAS-HIG-14-008" - } - ] - } - """) + } + ] + } @pytest.fixture diff --git a/claimstore/modules/claims/fixtures/pid.py b/claimstore/modules/claims/fixtures/pid.py index 59df052..bb78b0e 100644 --- a/claimstore/modules/claims/fixtures/pid.py +++ b/claimstore/modules/claims/fixtures/pid.py @@ -26,7 +26,9 @@ import pytest from flask import current_app +from jsonschema import ValidationError +from claimstore.core.json import validate_json from claimstore.ext.sqlalchemy import db from claimstore.modules.claims.models import IdentifierType @@ -57,7 +59,14 @@ def load_all_pids(config_path=None): ) for pid_fp in glob.glob("{}/*.json".format(pids_filepath)): with open(pid_fp) as f: - create_pid(json.loads(f.read())) + json_data = json.load(f) + try: + validate_json(json_data, 'claims.persistent_id') + except ValidationError: + print('`{}` could not be loaded. It does not follow the proper' + ' JSON schema specification.'.format(pid_fp)) + continue + create_pid(json_data) @pytest.fixture diff --git a/claimstore/modules/claims/fixtures/predicate.py b/claimstore/modules/claims/fixtures/predicate.py index 4026399..c0ce316 100644 --- a/claimstore/modules/claims/fixtures/predicate.py +++ b/claimstore/modules/claims/fixtures/predicate.py @@ -26,7 +26,9 @@ import pytest from flask import current_app +from jsonschema import ValidationError +from claimstore.core.json import validate_json from claimstore.ext.sqlalchemy import db from claimstore.modules.claims.models import Predicate @@ -54,9 +56,16 @@ def load_all_predicates(config_path=None): 'config', 'predicates' ) - for predicate_fp in glob.glob("{}/*.json".format(predicates_filepath)): - with open(predicate_fp) as f: - create_predicate(json.load(f)) + for pred_fp in glob.glob("{}/*.json".format(predicates_filepath)): + with open(pred_fp) as f: + json_data = json.load(f) + try: + validate_json(json_data, 'claims.predicate') + except ValidationError: + print('`{}` could not be loaded. It does not follow the proper' + ' JSON schema specification.'.format(pred_fp)) + continue + create_predicate(json_data) @pytest.fixture diff --git a/claimstore/modules/claims/restful.py b/claimstore/modules/claims/restful.py index 1ca5f6c..3f90d04 100644 --- a/claimstore/modules/claims/restful.py +++ b/claimstore/modules/claims/restful.py @@ -28,6 +28,7 @@ import isodate # noqa from flask import Blueprint, current_app, request from flask_restful import Api, Resource, abort, inputs, reqparse +from jsonschema import ValidationError from sqlalchemy import or_ from claimstore.core.datetime import loc_date_utc @@ -100,11 +101,11 @@ def validate_json(self, json_data): """Validate that json_data follows the appropiate JSON schema. :param json_data: JSON data to be validated. - :raises: InvalidJSONData + :raises: :exc:`InvalidJSONData` if the instance is invalid. """ try: validate_json(json_data, self.json_schema) - except Exception as e: + except ValidationError as e: raise InvalidJSONData('JSON data is not valid', extra=str(e))