From 0f9c0c1cdfdbf702f7fbc306c4c6935801619062 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 23 Sep 2022 13:07:15 +0200 Subject: [PATCH 01/26] add jsonschema requirement --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8eacaf3..234590e 100644 --- a/setup.py +++ b/setup.py @@ -73,7 +73,7 @@ def read(*names, **kwargs): # eg: 'keyword1', 'keyword2', 'keyword3', ], python_requires=">=3.5", - install_requires=["click", "rdfLib", "python-dateutil"], + install_requires=["click", "rdfLib", "python-dateutil", "jsonschema"], tests_require=["tox", "pytest"], extras_require={ "dev": ["black", "isort", "pre-commit"] From e3f0c5128fa68a1f128d3287142c3dfa5669de37 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 23 Sep 2022 13:13:00 +0200 Subject: [PATCH 02/26] update gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index abaa6db..c707da4 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ htmlcov .idea *.iml *.komodoproject +/0_local_test # Complexity output/*.html @@ -63,6 +64,7 @@ docs/_build .bootstrap .appveyor.token *.bak +/1_env # Mypy Cache .mypy_cache/ From 3a5d62482d4a975bedf7a70c1331f09b4f39b36e Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 23 Sep 2022 13:13:31 +0200 Subject: [PATCH 03/26] add note that oemetadata is required as soon as new release os published on pypi --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 234590e..cea02fd 100644 --- a/setup.py +++ b/setup.py @@ -73,7 +73,7 @@ def read(*names, **kwargs): # eg: 'keyword1', 'keyword2', 'keyword3', ], python_requires=">=3.5", - install_requires=["click", "rdfLib", "python-dateutil", "jsonschema"], + install_requires=["click", "rdfLib", "python-dateutil", "jsonschema"], # TODO: add oemetadata as soon as new release on pypi (json files not inclides ATM) tests_require=["tox", "pytest"], extras_require={ "dev": ["black", "isort", "pre-commit"] From 1418955c67a410effae750493e52ef39f535c7ce Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Thu, 29 Sep 2022 12:11:25 +0200 Subject: [PATCH 04/26] add first draft of omi.dialect.oep.parser validation based on jsonschema and oemetadata schema.json --- src/omi/dialects/oep/parser.py | 117 +++++++++++++++++++++++++++------ 1 file changed, 97 insertions(+), 20 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index dfb2bb5..7e0032f 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -10,6 +10,24 @@ from omi.dialects.base.parser import ParserException from omi.oem_structures import oem_v15 +from jsonschema import ValidationError +from jsonschema import validate + +# oemetadata +from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA +from metadata.v130.schema import OEMETADATA_V130_SCHEMA +from metadata.v140.schema import OEMETADATA_V140_SCHEMA +from metadata.v141.schema import OEMETADATA_V141_SCHEMA +from metadata.v150.schema import OEMETADATA_V150_SCHEMA + +ALL_OEM_SCHEMAS = [ + OEMETADATA_LATEST_SCHEMA, + OEMETADATA_V130_SCHEMA, + OEMETADATA_V140_SCHEMA, + OEMETADATA_V141_SCHEMA, + OEMETADATA_V150_SCHEMA, +] + def parse_date_or_none(x, *args, **kwargs): if x is None: @@ -17,30 +35,71 @@ def parse_date_or_none(x, *args, **kwargs): else: return parse_date(x, *args, **kwargs) +def create_report_json(error_data: list[dict]): + with open("tests/data/report.json", "w", encoding="utf-8") as fp: + json.dump(error_data, fp, indent=4, sort_keys=False) class JSONParser(Parser): def load_string(self, string: str, *args, **kwargs): return json.loads(string) - def is_valid(self, inp: str): - """Checks the validity of a JSON string - + def validate(self, jsn: dict, schemas: list | dict = ALL_OEM_SCHEMAS): + """ + Check whether the given dictionary adheres to the the json-schema + specification Parameters ---------- - inp: str - The JSON string to be checked. - + jsn + The dictionary to validate Returns ------- - bool - True if valid JSON, False otherwise. + Nothing """ + is_valid = False + report = [] + if isinstance(schemas, list): + for schema in schemas: + try: + validate(jsn, schema) + except ValidationError as error: + # for error in sorted(v.iter_errors(jsn), key=str): + error_dict = { + "message": error.message, + "schema_path": error.schema_path + # "instance_path": error.instance_path + } + report.append(error_dict) + else: + try: + validate(jsn, schemas) + except ValidationError as error: + # for error in sorted(v.iter_errors(jsn), key=str): + error_dict = { + "message": error.message, + "schema_path": error.schema_path + # "instance_path": error.instance_path + } + report.append(error_dict) + print(report) + create_report_json(report) + # print(report) + + def is_valid(self, inp: str | dict): + + if isinstance(inp, str): + try: + jsn = json.loads(inp) + except ValueError: + return False + else: + jsn = inp try: - json.loads(inp) - except ValueError: + self.validate(jsn) + except ValidationError: return False - return True + else: + return True class JSONParser_1_3(JSONParser): @@ -579,15 +638,33 @@ def get_table_name(self, metadata_file): class JSONParser_1_5(JSONParser): - def is_valid(self, inp: str): - if not super(self, JSONParser_1_5).is_valid(inp): - return False - try: - self.assert_1_5_metastring(inp) - except: - return False - else: - return True + + # def validate(self, jsn: dict, schema: dict): + # """ + # Check whether the given dictionary adheres to the the json-schema + # specification + # Parameters + # ---------- + # jsn + # The dictionary to validate + # Returns + # ------- + # Nothing + # """ + # validate(jsn, self.schema) + + # def is_valid(self, inp: str, schema: dict): + # try: + # jsn = json.loads(inp) + # except ValueError: + # return False + # else: + # try: + # self.validate(jsn, ) + # except ValidationError: + # return False + # else: + # return True def parse_from_string( self, From d58da15432b18a38d11ba8163ee355d78bf7a79c Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Thu, 29 Sep 2022 12:12:07 +0200 Subject: [PATCH 05/26] add parser validation test --- tests/test_dialects/test_oep/test_parser.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_dialects/test_oep/test_parser.py b/tests/test_dialects/test_oep/test_parser.py index 12552f9..583d5fd 100644 --- a/tests/test_dialects/test_oep/test_parser.py +++ b/tests/test_dialects/test_oep/test_parser.py @@ -1,3 +1,4 @@ +from email import parser import unittest from omi.dialects.oep.parser import JSONParser_1_3 from omi.dialects.oep.parser import JSONParser_1_4 @@ -12,6 +13,8 @@ from ..internal_structures import metadata_v_1_5_minimal from omi.dialects.base.parser import ParserException +from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA + class ParserTest(unittest.TestCase): def test_parser_v1_3(self): @@ -50,3 +53,13 @@ def test_parser_v1_5(self): _input_file = "tests/data/metadata_v15.json" expected_result = metadata_v_1_5 _test_generic_parsing(parser, _input_file, expected_result) + + def test_parser_v1_5_is_valid(self): + parser = JSONParser_1_5() + _input_file = "tests/data/metadata_v15.json" + + with open(_input_file, "rb", encoding='utf-8') as inp: + file = inp.read() + + # file = parser.parse_from_file(_input_file) + parser.validate(file) From 6d15f2d7734b3abb5e5a61344c82cf96bffd6dc9 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Thu, 29 Sep 2022 23:27:09 +0200 Subject: [PATCH 06/26] update error dict and add to report --- src/omi/dialects/oep/parser.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index 7e0032f..e617522 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +from base64 import encode import json from dateutil.parser import parse as parse_date @@ -43,7 +44,7 @@ class JSONParser(Parser): def load_string(self, string: str, *args, **kwargs): return json.loads(string) - def validate(self, jsn: dict, schemas: list | dict = ALL_OEM_SCHEMAS): + def validate(self, jsn: dict, schemas: list or dict = ALL_OEM_SCHEMAS): # | not allowed below py3.10 use or instead """ Check whether the given dictionary adheres to the the json-schema specification @@ -75,20 +76,22 @@ def validate(self, jsn: dict, schemas: list | dict = ALL_OEM_SCHEMAS): except ValidationError as error: # for error in sorted(v.iter_errors(jsn), key=str): error_dict = { - "message": error.message, - "schema_path": error.schema_path - # "instance_path": error.instance_path + # "json path": error.json_path, + "instance path": [i for i in error.absolute_path], + "value that raised the error": error.instance, + "error message": error.message, + "schema_path": [i for i in error.schema_path], + } report.append(error_dict) - print(report) + create_report_json(report) - # print(report) - def is_valid(self, inp: str | dict): + def is_valid(self, inp: str or dict): if isinstance(inp, str): try: - jsn = json.loads(inp) + jsn = json.loads(inp, encode="utf-8") except ValueError: return False else: From 631cb2866d2ffdb741cd89770776bfc78b92a382 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 30 Sep 2022 00:56:04 +0200 Subject: [PATCH 07/26] refactor validation: use Validator class with format check and yield all errors; - currently the case for all schemas is nor working properly - all schemas are tested but just last one with errors is saved and if one is valid it is not acknowlaged --- src/omi/dialects/oep/parser.py | 65 +++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index e617522..a22c70b 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -3,6 +3,7 @@ from base64 import encode import json +import pathlib from dateutil.parser import parse as parse_date @@ -11,8 +12,8 @@ from omi.dialects.base.parser import ParserException from omi.oem_structures import oem_v15 -from jsonschema import ValidationError -from jsonschema import validate +from jsonschema import ValidationError, SchemaError +from jsonschema import Draft7Validator, FormatChecker # oemetadata from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA @@ -36,15 +37,22 @@ def parse_date_or_none(x, *args, **kwargs): else: return parse_date(x, *args, **kwargs) -def create_report_json(error_data: list[dict]): - with open("tests/data/report.json", "w", encoding="utf-8") as fp: + +def create_report_json(error_data: list[dict], save_at: pathlib.Path = "tests/data/report.json"): + if len(error_data) >= 1: + with open(save_at, "w", encoding="utf-8") as fp: json.dump(error_data, fp, indent=4, sort_keys=False) + + print(f"Created error report at: {save_at}") + class JSONParser(Parser): def load_string(self, string: str, *args, **kwargs): return json.loads(string) - def validate(self, jsn: dict, schemas: list or dict = ALL_OEM_SCHEMAS): # | not allowed below py3.10 use or instead + def validate( + self, jsn: dict, schemas: list or dict = ALL_OEM_SCHEMAS + ): # | not allowed below py3.10 use or instead """ Check whether the given dictionary adheres to the the json-schema specification @@ -56,36 +64,51 @@ def validate(self, jsn: dict, schemas: list or dict = ALL_OEM_SCHEMAS): # | not ------- Nothing """ + + # if all schemas are checked, continue until valid schema found is_valid = False - report = [] + # report = [] + # TODO: IS THIS EVEN POSSIBLE? :D + ############################# + # enable this function handle either a single schema passed as + # parameter or use the default (list of all available schemas). + # Incase one wants to test multiple metadata with various versions. + ############################# if isinstance(schemas, list): for schema in schemas: - try: - validate(jsn, schema) - except ValidationError as error: - # for error in sorted(v.iter_errors(jsn), key=str): + v = Draft7Validator(schema=schema, format_checker=FormatChecker()) # TODO: How to get the correct Validator based on the schema - dont like to use specific class + v.check_schema + report = [] + for error in sorted(v.iter_errors(instance=jsn), key=str): + # https://python-jsonschema.readthedocs.io/en/stable/errors/#handling-validation-errors error_dict = { - "message": error.message, - "schema_path": error.schema_path - # "instance_path": error.instance_path + "oemetadata schema version": schema.get("$id"), + # "json path": error.json_path, + "instance path": [i for i in error.absolute_path], + "value that raised the error": error.instance, + "error message": error.message, + "schema_path": [i for i in error.schema_path], } report.append(error_dict) + create_report_json(report) else: - try: - validate(jsn, schemas) - except ValidationError as error: - # for error in sorted(v.iter_errors(jsn), key=str): + report = [] + v = Draft7Validator(schema=schemas, format_checker=FormatChecker()) # TODO: How to get the correct Validator based on the schema - dont like to use specific class + v.check_schema + for error in sorted(v.iter_errors(instance=jsn), key=str): + # https://python-jsonschema.readthedocs.io/en/stable/errors/#handling-validation-errors error_dict = { - # "json path": error.json_path, + "oemetadata schema version": schema.get("$id"), + # "json path": error.json_path, "instance path": [i for i in error.absolute_path], "value that raised the error": error.instance, - "error message": error.message, + "error message": error.message, "schema_path": [i for i in error.schema_path], - } report.append(error_dict) + create_report_json(report) - create_report_json(report) + # create_report_json(report) def is_valid(self, inp: str or dict): From a90feb073497971973bb4fa55b7a71f44876d2b5 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 30 Sep 2022 14:58:38 +0200 Subject: [PATCH 08/26] refactor exeption, update create report method (now creates report dir), add draft to handel case if all available schemas are checked (not working properly atm) --- src/omi/dialects/oep/parser.py | 77 ++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index a22c70b..a506892 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -4,6 +4,7 @@ from base64 import encode import json import pathlib +import logging from dateutil.parser import parse as parse_date @@ -15,6 +16,8 @@ from jsonschema import ValidationError, SchemaError from jsonschema import Draft7Validator, FormatChecker +from enum import Enum + # oemetadata from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA from metadata.v130.schema import OEMETADATA_V130_SCHEMA @@ -30,71 +33,68 @@ OEMETADATA_V150_SCHEMA, ] - def parse_date_or_none(x, *args, **kwargs): if x is None: return None else: return parse_date(x, *args, **kwargs) - -def create_report_json(error_data: list[dict], save_at: pathlib.Path = "tests/data/report.json"): +def create_report_json(error_data: list[dict], save_at: pathlib.Path = "reports/", filename: str = "report.json"): if len(error_data) >= 1: - with open(save_at, "w", encoding="utf-8") as fp: + pathlib.Path(save_at).mkdir(parents=True, exist_ok=True) + with open(f"{save_at}{filename}", "w", encoding="utf-8") as fp: json.dump(error_data, fp, indent=4, sort_keys=False) - print(f"Created error report at: {save_at}") - + print(f"Created error report containing {len(error_data)} errors at: {save_at}{filename}") class JSONParser(Parser): + one_schema_was_valid = False + def load_string(self, string: str, *args, **kwargs): return json.loads(string) def validate( - self, jsn: dict, schemas: list or dict = ALL_OEM_SCHEMAS - ): # | not allowed below py3.10 use or instead + self, jsn: dict, schemas: list[dict] = ALL_OEM_SCHEMAS + ): """ Check whether the given dictionary adheres to the the json-schema - specification + and oemetadata specification. + Parameters ---------- jsn The dictionary to validate + schema + The jsonschema used for validation. + Default is a list of all available verion specific schemas from oemetadata. Returns ------- Nothing """ - + self.one_schema_was_valid = False # if all schemas are checked, continue until valid schema found - is_valid = False - # report = [] - # TODO: IS THIS EVEN POSSIBLE? :D + # or use latest schema that faild + # or detect schema version based on oemetadata metaMetadata[0].metadataVersion + + ############################# # enable this function handle either a single schema passed as # parameter or use the default (list of all available schemas). # Incase one wants to test multiple metadata with various versions. ############################# - if isinstance(schemas, list): - for schema in schemas: - v = Draft7Validator(schema=schema, format_checker=FormatChecker()) # TODO: How to get the correct Validator based on the schema - dont like to use specific class - v.check_schema - report = [] - for error in sorted(v.iter_errors(instance=jsn), key=str): - # https://python-jsonschema.readthedocs.io/en/stable/errors/#handling-validation-errors - error_dict = { - "oemetadata schema version": schema.get("$id"), - # "json path": error.json_path, - "instance path": [i for i in error.absolute_path], - "value that raised the error": error.instance, - "error message": error.message, - "schema_path": [i for i in error.schema_path], - } - report.append(error_dict) - create_report_json(report) - else: - report = [] - v = Draft7Validator(schema=schemas, format_checker=FormatChecker()) # TODO: How to get the correct Validator based on the schema - dont like to use specific class + try: + isinstance(schemas, list) + except TypeError as e: + logging.info("Schemas must be provides as list: [schmea1, schema2, ...]") + raise e("parameter 'schemas' must be of type list[dict].") + + report = [] + for schema in schemas: + # if not self.one_schema_was_valid: + # TODO: How to get the correct Validator based on the schema - dont like to use specific class + v = Draft7Validator(schema=schema, format_checker=FormatChecker()) v.check_schema + for error in sorted(v.iter_errors(instance=jsn), key=str): # https://python-jsonschema.readthedocs.io/en/stable/errors/#handling-validation-errors error_dict = { @@ -106,9 +106,14 @@ def validate( "schema_path": [i for i in error.schema_path], } report.append(error_dict) - create_report_json(report) - - # create_report_json(report) + # reset error collection if one schema was valid + # if sorted(v.iter_errors(instance=jsn), key=str) is None: + # self.one_schema_was_valid = True + # print(f"Valid with schema{schema.get('$id')}") + # continue + + create_report_json(report) + def is_valid(self, inp: str or dict): From 5b743f2f687b02abcac6c88f1441973b5745de28 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 30 Sep 2022 15:35:32 +0200 Subject: [PATCH 09/26] remove deprecated code --- src/omi/dialects/oep/parser.py | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index a506892..f3c0d8d 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -48,7 +48,7 @@ def create_report_json(error_data: list[dict], save_at: pathlib.Path = "reports/ print(f"Created error report containing {len(error_data)} errors at: {save_at}{filename}") class JSONParser(Parser): - one_schema_was_valid = False + # one_schema_was_valid = False def load_string(self, string: str, *args, **kwargs): return json.loads(string) @@ -670,33 +670,6 @@ def get_table_name(self, metadata_file): class JSONParser_1_5(JSONParser): - # def validate(self, jsn: dict, schema: dict): - # """ - # Check whether the given dictionary adheres to the the json-schema - # specification - # Parameters - # ---------- - # jsn - # The dictionary to validate - # Returns - # ------- - # Nothing - # """ - # validate(jsn, self.schema) - - # def is_valid(self, inp: str, schema: dict): - # try: - # jsn = json.loads(inp) - # except ValueError: - # return False - # else: - # try: - # self.validate(jsn, ) - # except ValidationError: - # return False - # else: - # return True - def parse_from_string( self, string: str, From ef2c69b5aba3170aa7fbe0d7c6baa192b95c275e Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 30 Sep 2022 15:36:30 +0200 Subject: [PATCH 10/26] update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c707da4..89da130 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ htmlcov *.iml *.komodoproject /0_local_test +/reports # Complexity output/*.html From 54769062ef90a2009f227cd3eb33d8d54b5a76b3 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Wed, 5 Oct 2022 12:28:33 +0200 Subject: [PATCH 11/26] update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 89da130..07756eb 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ htmlcov *.komodoproject /0_local_test /reports +.vscode # Complexity output/*.html From bc5df5972d62e97b085072cc7407485443625092 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Thu, 17 Nov 2022 20:06:31 +0100 Subject: [PATCH 12/26] update docstring --- src/omi/dialects/oep/parser.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index 48edec6..7ace09f 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -58,7 +58,8 @@ def validate( ): """ Check whether the given dictionary adheres to the the json-schema - and oemetadata specification. + and oemetadata specification. If errors are found a jsonschema error + report is created in directory reports/. Parameters ---------- @@ -71,7 +72,7 @@ def validate( ------- Nothing """ - self.one_schema_was_valid = False + # if all schemas are checked, continue until valid schema found # or use latest schema that faild # or detect schema version based on oemetadata metaMetadata[0].metadataVersion From bbe0622acf10ce0e70adc76d5b4d4533a4f2ee1e Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Thu, 17 Nov 2022 20:17:43 +0100 Subject: [PATCH 13/26] add helper to get correct validator from jsonschema, also some minor improvements --- src/omi/dialects/oep/parser.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index 7ace09f..7e1985e 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -15,6 +15,7 @@ from jsonschema import ValidationError, SchemaError from jsonschema import Draft7Validator, FormatChecker +import jsonschema from enum import Enum @@ -47,12 +48,23 @@ def create_report_json(error_data: list[dict], save_at: pathlib.Path = "reports/ print(f"Created error report containing {len(error_data)} errors at: {save_at}{filename}") + + class JSONParser(Parser): # one_schema_was_valid = False def load_string(self, string: str, *args, **kwargs): return json.loads(string) + + def get_json_validator(schema: OEMETADATA_LATEST_SCHEMA): + with open(schema, "rb") as file: + schema = json.load(file) + jsonschema.Draft202012Validator.check_schema(schema) + validator = jsonschema.Draft202012Validator(schema=schema) + return validator + + def validate( self, jsn: dict, schemas: list[dict] = ALL_OEM_SCHEMAS ): @@ -83,11 +95,10 @@ def validate( # parameter or use the default (list of all available schemas). # Incase one wants to test multiple metadata with various versions. ############################# - try: - isinstance(schemas, list) - except TypeError as e: + + if not isinstance(schemas, list): logging.info("Schemas must be provides as list: [schmea1, schema2, ...]") - raise e("parameter 'schemas' must be of type list[dict].") + raise TypeError("parameter 'schemas' must be of type list[dict].") report = [] for schema in schemas: From 3410f4cd5dc022e7be425149286bd745d2478fae Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 13:47:15 +0100 Subject: [PATCH 14/26] update core validation and add helper functions: - update validation -> use singe schema as input instead of list of all schemas. - add helper that gets the best schema for the metadata version - add helper to get first valid schema of all available schmeas - optional --- src/omi/dialects/oep/parser.py | 170 ++++++++++++++++++++++----------- 1 file changed, 113 insertions(+), 57 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index 7e1985e..da71031 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -25,13 +25,14 @@ from metadata.v140.schema import OEMETADATA_V140_SCHEMA from metadata.v141.schema import OEMETADATA_V141_SCHEMA from metadata.v150.schema import OEMETADATA_V150_SCHEMA +from metadata.v151.schema import OEMETADATA_V151_SCHEMA ALL_OEM_SCHEMAS = [ OEMETADATA_LATEST_SCHEMA, - OEMETADATA_V130_SCHEMA, - OEMETADATA_V140_SCHEMA, - OEMETADATA_V141_SCHEMA, OEMETADATA_V150_SCHEMA, + OEMETADATA_V141_SCHEMA, + OEMETADATA_V140_SCHEMA, + OEMETADATA_V130_SCHEMA, ] def parse_date_or_none(x, *args, **kwargs): @@ -40,13 +41,20 @@ def parse_date_or_none(x, *args, **kwargs): else: return parse_date(x, *args, **kwargs) + def create_report_json(error_data: list[dict], save_at: pathlib.Path = "reports/", filename: str = "report.json"): - if len(error_data) >= 1: - pathlib.Path(save_at).mkdir(parents=True, exist_ok=True) - with open(f"{save_at}{filename}", "w", encoding="utf-8") as fp: - json.dump(error_data, fp, indent=4, sort_keys=False) + # if len(error_data) >= 1: + pathlib.Path(save_at).mkdir(parents=True, exist_ok=True) + with open(f"{save_at}{filename}", "w", encoding="utf-8") as fp: + json.dump(error_data, fp, indent=4, sort_keys=False) + + print(f"Created error report containing {len(error_data)} errors at: {save_at}{filename}") + # else: + # pathlib.Path(save_at).mkdir(parents=True, exist_ok=True) + # with open(f"{save_at}{filename}", "w", encoding="utf-8") as fp: + # json.dump(error_data, fp, indent=4, sort_keys=False) - print(f"Created error report containing {len(error_data)} errors at: {save_at}{filename}") + # print(f"Created error report containing {len(error_data)} errors at: {save_at}{filename}") @@ -56,79 +64,125 @@ class JSONParser(Parser): def load_string(self, string: str, *args, **kwargs): return json.loads(string) - - def get_json_validator(schema: OEMETADATA_LATEST_SCHEMA): - with open(schema, "rb") as file: - schema = json.load(file) + + def get_json_validator(self, schema: OEMETADATA_LATEST_SCHEMA): + """ + Get the jsonschema validator that matches the schema. + Also checks if the schmea is valid. + + Args: + schema (OEMETADATA_LATEST_SCHEMA): + + Returns: + validator: jsonschema.Draft202012Validator + """ jsonschema.Draft202012Validator.check_schema(schema) validator = jsonschema.Draft202012Validator(schema=schema) return validator + def get_any_schema_valid(self, metadata: dict, schemas: list = ALL_OEM_SCHEMAS,): + """ + Additional helper funtion - get any schema that is valid for the metadata. + Returns The first valid schema or None + + Args: + schemas (list): _description_ + metadata (dict): _description_ + + Returns: + _type_: _description_ + """ + + valid_schemas = [] + for schema in schemas: + if len(valid_schemas) <= 1: + continue + elif self.is_valid(inp=metadata, schema=schema): + valid_schemas.append(schema) + + if len(valid_schemas) >= 1: + valid_schemas= None + return valid_schemas + + + def get_schema_by_metadata_version(self, metadata: dict): + oem_13 = ["1.3", "OEP-1.3"] + oem_14 = "OEP-1.4.0" + oem_141 = "OEP-1.4.1" + oem_15 = "OEP-1.5.0" + oem_151 = "OEP-1.5.1" + + schema = None + + if metadata.get("metadata_version"): + if metadata.get("metadata_version") in oem_13: + schema = OEMETADATA_V130_SCHEMA + + if metadata.get("metaMetadata"): + if metadata.get("metaMetadata")["metadataVersion"] == oem_14: + schema = OEMETADATA_V140_SCHEMA + if metadata.get("metaMetadata")["metadataVersion"] == oem_141: + schema = OEMETADATA_V141_SCHEMA + if metadata.get("metaMetadata")["metadataVersion"] == oem_15: + schema = OEMETADATA_V150_SCHEMA + if metadata.get("metaMetadata")["metadataVersion"] == oem_151: + schema = OEMETADATA_V151_SCHEMA + + # fallback to latest schema if metadata does not contian the exprected metadata version sting + if schema is None: + logging.info("Metadata does not contain the expected 'metaMetadata' or 'metadata_version' key. Fallback to latest schema.") + schema = OEMETADATA_LATEST_SCHEMA + + + print(schema.get("$id")) + + return schema + + def validate( - self, jsn: dict, schemas: list[dict] = ALL_OEM_SCHEMAS + self, metadata: dict, schema: dict = None ): """ Check whether the given dictionary adheres to the the json-schema and oemetadata specification. If errors are found a jsonschema error - report is created in directory reports/. + report is created in directory 'reports/'. Parameters ---------- - jsn + metadata The dictionary to validate - schema + schema: optional The jsonschema used for validation. - Default is a list of all available verion specific schemas from oemetadata. + Default is None. Returns ------- Nothing """ - # if all schemas are checked, continue until valid schema found - # or use latest schema that faild - # or detect schema version based on oemetadata metaMetadata[0].metadataVersion - - - ############################# - # enable this function handle either a single schema passed as - # parameter or use the default (list of all available schemas). - # Incase one wants to test multiple metadata with various versions. - ############################# - - if not isinstance(schemas, list): - logging.info("Schemas must be provides as list: [schmea1, schema2, ...]") - raise TypeError("parameter 'schemas' must be of type list[dict].") - report = [] - for schema in schemas: - # if not self.one_schema_was_valid: - # TODO: How to get the correct Validator based on the schema - dont like to use specific class - v = Draft7Validator(schema=schema, format_checker=FormatChecker()) - v.check_schema + if not schema: + schema = self.get_schema_by_metadata_version(metadata=metadata) + validator = self.get_json_validator(schema) - for error in sorted(v.iter_errors(instance=jsn), key=str): - # https://python-jsonschema.readthedocs.io/en/stable/errors/#handling-validation-errors - error_dict = { - "oemetadata schema version": schema.get("$id"), - # "json path": error.json_path, - "instance path": [i for i in error.absolute_path], - "value that raised the error": error.instance, - "error message": error.message, - "schema_path": [i for i in error.schema_path], - } - report.append(error_dict) - # reset error collection if one schema was valid - # if sorted(v.iter_errors(instance=jsn), key=str) is None: - # self.one_schema_was_valid = True - # print(f"Valid with schema{schema.get('$id')}") - # continue + for error in sorted(validator.iter_errors(instance=metadata), key=str): + # https://python-jsonschema.readthedocs.io/en/stable/errors/#handling-validation-errors + error_dict = { + "oemetadata schema version": schema.get("$id"), + "json path": error.absolute_path, + "instance path": [i for i in error.absolute_path], + "value that raised the error": error.instance, + "error message": error.message, + "schema_path": [i for i in error.schema_path], + } + report.append(error_dict) create_report_json(report) - def is_valid(self, inp: str or dict): + def is_valid(self, inp:dict, schema): + # 1 - valid JSON? if isinstance(inp, str): try: jsn = json.loads(inp, encode="utf-8") @@ -137,12 +191,14 @@ def is_valid(self, inp: str or dict): else: jsn = inp + # 2 - valid OEMETADATA try: - self.validate(jsn) + validator = self.get_json_validator(schema) + validator.validate(jsn) + return True except ValidationError: return False - else: - return True + class JSONParser_1_3(JSONParser): From f7804e4ea25f6c4bd36cf99f9d42935a8782660e Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 13:51:16 +0100 Subject: [PATCH 15/26] update changelog --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ca2c2a7..ca0d043 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,7 +4,7 @@ Changelog current (2022-XX-XX) -------------------- - +* Add validation and helper functionality - validation based on json schema and the oemetadata schema files that are published for each release (PR#63) 0.0.9 (2022-10-31) -------------------- From a2ba0bab98413561a90dda7c52423b98c6e70b00 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 14:04:24 +0100 Subject: [PATCH 16/26] Add insctructions on how to use the validation --- README.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.rst b/README.rst index 6e60744..a374d86 100644 --- a/README.rst +++ b/README.rst @@ -122,6 +122,23 @@ CLI - oemetadata conversion from v1.4 to v1.5:: omi convert -i {input/path} -o {output/path} +**Validation** + +The validation is based on `jsonschema`. We release a schema with each `oemetadata` release, that schema +can be used to validate the user metadata. The dialect currently does not support direct access on to the +validation. This will be updated soon. + +Module usage:: + # You can import the JSONParser directly like this: + import json + from omi.dialects.oep.parser import JSONParser + + with open("tests/data/metadata_v15.json", "r", encoding="utf-8") as f: + metadata = json.load(f) + + parser = JSONParser() + parser.validate(metadata) + Development =========== From 306217a4fc85a49b1041e0dbbf86d24d18203017 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 14:04:43 +0100 Subject: [PATCH 17/26] fix fomrat --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index a374d86..0981033 100644 --- a/README.rst +++ b/README.rst @@ -129,6 +129,7 @@ can be used to validate the user metadata. The dialect currently does not suppor validation. This will be updated soon. Module usage:: + # You can import the JSONParser directly like this: import json from omi.dialects.oep.parser import JSONParser From a5cb00bc163ed2d103192f05ff290cb142ee9662 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 14:07:38 +0100 Subject: [PATCH 18/26] update description --- README.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 0981033..7687e74 100644 --- a/README.rst +++ b/README.rst @@ -127,9 +127,12 @@ CLI - oemetadata conversion from v1.4 to v1.5:: The validation is based on `jsonschema`. We release a schema with each `oemetadata` release, that schema can be used to validate the user metadata. The dialect currently does not support direct access on to the validation. This will be updated soon. +This will create a report.json containing information to debug possible errors. The parser.validate() takes +two arguments the first one is the metadata and the second optional one is the schmea. By default (if no schema is passed) +the validation will try to get the matching schema for the current metadata. Module usage:: - + # You can import the JSONParser directly like this: import json from omi.dialects.oep.parser import JSONParser From 261152aeae9a481501839b046828364b45a6effa Mon Sep 17 00:00:00 2001 From: jh-RLI <38939526+jh-RLI@users.noreply.github.com> Date: Fri, 18 Nov 2022 14:12:09 +0100 Subject: [PATCH 19/26] Update Readme --- README.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.rst b/README.rst index 7687e74..8bcd339 100644 --- a/README.rst +++ b/README.rst @@ -142,6 +142,10 @@ Module usage:: parser = JSONParser() parser.validate(metadata) + + # check if your metadata is valid for the given schmea + schema = ... get a schema or import form oemetadata module + parser.is_valid(metadata, schema) Development From c94fd7b37436baf8e01e65bbc40e5464b10c117b Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 15:57:44 +0100 Subject: [PATCH 20/26] add oemetadata to requirements --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3432bdf..46533e1 100644 --- a/setup.py +++ b/setup.py @@ -70,7 +70,7 @@ def read(*names, **kwargs): # eg: 'keyword1', 'keyword2', 'keyword3', ], python_requires=">=3.5", - install_requires=["click", "rdfLib", "python-dateutil", "jsonschema"], # TODO: add oemetadata as soon as new release on pypi (json files not inclides ATM) + install_requires=["click", "rdfLib", "python-dateutil", "jsonschema", "oemetadata"], tests_require=["tox", "pytest"], extras_require={ "dev": ["black", "isort", "pre-commit"] From 102622067a98bc83a5dda006346431bb908ddc70 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 16:38:11 +0100 Subject: [PATCH 21/26] fix file read mode --- tests/test_dialects/test_oep/test_parser.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/test_dialects/test_oep/test_parser.py b/tests/test_dialects/test_oep/test_parser.py index 583d5fd..443b995 100644 --- a/tests/test_dialects/test_oep/test_parser.py +++ b/tests/test_dialects/test_oep/test_parser.py @@ -15,6 +15,8 @@ from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA +import json + class ParserTest(unittest.TestCase): def test_parser_v1_3(self): @@ -58,8 +60,8 @@ def test_parser_v1_5_is_valid(self): parser = JSONParser_1_5() _input_file = "tests/data/metadata_v15.json" - with open(_input_file, "rb", encoding='utf-8') as inp: - file = inp.read() + with open(_input_file, "r", encoding="utf-8") as f: + jsn = json.load(f) # file = parser.parse_from_file(_input_file) - parser.validate(file) + parser.validate(jsn) From 1536aaefbf3ed3928cf2debafe6407c1431adcd0 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 16:41:28 +0100 Subject: [PATCH 22/26] remove unused imports --- src/omi/dialects/oep/parser.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index da71031..55bee8b 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -1,7 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from base64 import encode import json import pathlib import logging @@ -13,12 +12,9 @@ from omi.dialects.base.parser import ParserException from omi.oem_structures import oem_v15 -from jsonschema import ValidationError, SchemaError -from jsonschema import Draft7Validator, FormatChecker +from jsonschema import ValidationError import jsonschema -from enum import Enum - # oemetadata from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA from metadata.v130.schema import OEMETADATA_V130_SCHEMA From 03fd3a05a2a34d10708b0c92025ccc1e4369e402 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 16:44:58 +0100 Subject: [PATCH 23/26] formatting --- src/omi/dialects/oep/parser.py | 60 ++++++++++++++++------------------ 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index 55bee8b..1c881eb 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -31,6 +31,7 @@ OEMETADATA_V130_SCHEMA, ] + def parse_date_or_none(x, *args, **kwargs): if x is None: return None @@ -38,20 +39,19 @@ def parse_date_or_none(x, *args, **kwargs): return parse_date(x, *args, **kwargs) -def create_report_json(error_data: list[dict], save_at: pathlib.Path = "reports/", filename: str = "report.json"): +def create_report_json( + error_data: list[dict], + save_at: pathlib.Path = "reports/", + filename: str = "report.json", +): # if len(error_data) >= 1: pathlib.Path(save_at).mkdir(parents=True, exist_ok=True) with open(f"{save_at}{filename}", "w", encoding="utf-8") as fp: json.dump(error_data, fp, indent=4, sort_keys=False) - - print(f"Created error report containing {len(error_data)} errors at: {save_at}{filename}") - # else: - # pathlib.Path(save_at).mkdir(parents=True, exist_ok=True) - # with open(f"{save_at}{filename}", "w", encoding="utf-8") as fp: - # json.dump(error_data, fp, indent=4, sort_keys=False) - - # print(f"Created error report containing {len(error_data)} errors at: {save_at}{filename}") + print( + f"Created error report containing {len(error_data)} errors at: {save_at}{filename}" + ) class JSONParser(Parser): @@ -60,7 +60,6 @@ class JSONParser(Parser): def load_string(self, string: str, *args, **kwargs): return json.loads(string) - def get_json_validator(self, schema: OEMETADATA_LATEST_SCHEMA): """ Get the jsonschema validator that matches the schema. @@ -76,8 +75,11 @@ def get_json_validator(self, schema: OEMETADATA_LATEST_SCHEMA): validator = jsonschema.Draft202012Validator(schema=schema) return validator - - def get_any_schema_valid(self, metadata: dict, schemas: list = ALL_OEM_SCHEMAS,): + def get_any_schema_valid( + self, + metadata: dict, + schemas: list = ALL_OEM_SCHEMAS, + ): """ Additional helper funtion - get any schema that is valid for the metadata. Returns The first valid schema or None @@ -96,11 +98,10 @@ def get_any_schema_valid(self, metadata: dict, schemas: list = ALL_OEM_SCHEMAS,) continue elif self.is_valid(inp=metadata, schema=schema): valid_schemas.append(schema) - + if len(valid_schemas) >= 1: - valid_schemas= None + valid_schemas = None return valid_schemas - def get_schema_by_metadata_version(self, metadata: dict): oem_13 = ["1.3", "OEP-1.3"] @@ -127,21 +128,19 @@ def get_schema_by_metadata_version(self, metadata: dict): # fallback to latest schema if metadata does not contian the exprected metadata version sting if schema is None: - logging.info("Metadata does not contain the expected 'metaMetadata' or 'metadata_version' key. Fallback to latest schema.") + logging.info( + "Metadata does not contain the expected 'metaMetadata' or 'metadata_version' key. Fallback to latest schema." + ) schema = OEMETADATA_LATEST_SCHEMA - print(schema.get("$id")) - - return schema + return schema - def validate( - self, metadata: dict, schema: dict = None - ): + def validate(self, metadata: dict, schema: dict = None): """ Check whether the given dictionary adheres to the the json-schema - and oemetadata specification. If errors are found a jsonschema error + and oemetadata specification. If errors are found a jsonschema error report is created in directory 'reports/'. Parameters @@ -149,8 +148,8 @@ def validate( metadata The dictionary to validate schema: optional - The jsonschema used for validation. - Default is None. + The jsonschema used for validation. + Default is None. Returns ------- Nothing @@ -160,7 +159,7 @@ def validate( if not schema: schema = self.get_schema_by_metadata_version(metadata=metadata) validator = self.get_json_validator(schema) - + for error in sorted(validator.iter_errors(instance=metadata), key=str): # https://python-jsonschema.readthedocs.io/en/stable/errors/#handling-validation-errors error_dict = { @@ -174,9 +173,8 @@ def validate( report.append(error_dict) create_report_json(report) - - def is_valid(self, inp:dict, schema): + def is_valid(self, inp: dict, schema): # 1 - valid JSON? if isinstance(inp, str): @@ -194,7 +192,6 @@ def is_valid(self, inp:dict, schema): return True except ValidationError: return False - class JSONParser_1_3(JSONParser): @@ -422,7 +419,7 @@ def parse(self, json_old: dict, *args, **kwargs): ) temporal = structure.Temporal( reference_date=parse_date_or_none(inp_temporal.get("referenceDate")), - **timeseries + **timeseries, ) # filling the source section @@ -733,7 +730,6 @@ def get_table_name(self, metadata_file): class JSONParser_1_5(JSONParser): - def parse_from_string( self, string: str, @@ -756,7 +752,7 @@ def parse_from_string( return self.parse( self.load_string(string, *(load_args or []), **(load_kwargs or {})), *(parse_args or []), - **(parse_kwargs or {}) + **(parse_kwargs or {}), ) def parse_term_of_use(self, old_license: dict): From 542e78a3a8145a64206ff3b071eddda3593e0e8d Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 16:48:02 +0100 Subject: [PATCH 24/26] run isort --- src/omi/dialects/oep/parser.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index 1c881eb..78251b0 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -2,19 +2,12 @@ # -*- coding: utf-8 -*- import json -import pathlib import logging +import pathlib +import jsonschema from dateutil.parser import parse as parse_date - -from omi import structure -from omi.dialects.base.parser import Parser -from omi.dialects.base.parser import ParserException -from omi.oem_structures import oem_v15 - from jsonschema import ValidationError -import jsonschema - # oemetadata from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA from metadata.v130.schema import OEMETADATA_V130_SCHEMA @@ -23,6 +16,11 @@ from metadata.v150.schema import OEMETADATA_V150_SCHEMA from metadata.v151.schema import OEMETADATA_V151_SCHEMA +from omi import structure +from omi.dialects.base.parser import Parser +from omi.dialects.base.parser import ParserException +from omi.oem_structures import oem_v15 + ALL_OEM_SCHEMAS = [ OEMETADATA_LATEST_SCHEMA, OEMETADATA_V150_SCHEMA, From e3b8235db4c810c2b55a14cead808544a560d594 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 16:53:38 +0100 Subject: [PATCH 25/26] update changelog for release v0.1.0 --- CHANGELOG.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ca0d043..2ef7568 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,9 @@ Changelog current (2022-XX-XX) -------------------- + +0.1.0 (2022-11-18) +-------------------- * Add validation and helper functionality - validation based on json schema and the oemetadata schema files that are published for each release (PR#63) 0.0.9 (2022-10-31) From 44759b9b472a7399956d713b734633ae9b1d4813 Mon Sep 17 00:00:00 2001 From: jh-RLI Date: Fri, 18 Nov 2022 16:54:14 +0100 Subject: [PATCH 26/26] raise version number and set oemetadata to minimum v1.5.2 --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 46533e1..79ef8ea 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ def read(*names, **kwargs): setup( name="omi", - version="0.0.9", + version="0.1.0", license="AGPL-3.0", description="A library to process and translate open energy metadata.", long_description="%s\n%s" @@ -70,7 +70,7 @@ def read(*names, **kwargs): # eg: 'keyword1', 'keyword2', 'keyword3', ], python_requires=">=3.5", - install_requires=["click", "rdfLib", "python-dateutil", "jsonschema", "oemetadata"], + install_requires=["click", "rdfLib", "python-dateutil", "jsonschema", "oemetadata>=1.5.2"], tests_require=["tox", "pytest"], extras_require={ "dev": ["black", "isort", "pre-commit"]