From 9655b1fb3b65c351909de0e03c9b357974355212 Mon Sep 17 00:00:00 2001 From: "c.winger" Date: Tue, 24 Jan 2023 13:44:47 +0100 Subject: [PATCH 1/7] formatting --- src/omi/dialects/oep/compiler.py | 2 +- src/omi/dialects/oep/parser.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/omi/dialects/oep/compiler.py b/src/omi/dialects/oep/compiler.py index d79ee4c..9be29ee 100644 --- a/src/omi/dialects/oep/compiler.py +++ b/src/omi/dialects/oep/compiler.py @@ -302,7 +302,7 @@ def visit_temporal(self, temporal: oem_v15.Temporal, *args, **kwargs): ("referenceDate", self._compile_date(temporal.reference_date, "%Y-%m-%d")), ("timeseries", temporal.timeseries_collection), ) - + def visit_license(self, lic: oem_v15.License, *args, **kwargs): return self._construct_dict( ("name", lic.name), diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index 7e701ea..0e4edfe 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -38,6 +38,7 @@ def parse_date_or_none(x, *args, **kwargs): return parse_date(x, *args, **kwargs) + def create_report_json( error_data, # type list[dict] save_at: pathlib.Path = "reports/", From 3a95f1ba62559a8666f5bbc5a5ea09126509efb3 Mon Sep 17 00:00:00 2001 From: "c.winger" Date: Tue, 24 Jan 2023 13:47:57 +0100 Subject: [PATCH 2/7] add dummy unit test --- .../test_oep/test_regression/__init__.py | 0 .../test_regression/test_issue86_datetime.py | 53 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 tests/test_dialects/test_oep/test_regression/__init__.py create mode 100644 tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py diff --git a/tests/test_dialects/test_oep/test_regression/__init__.py b/tests/test_dialects/test_oep/test_regression/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py b/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py new file mode 100644 index 0000000..061d909 --- /dev/null +++ b/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py @@ -0,0 +1,53 @@ +import json +import re +from unittest import TestCase + +from omi.dialects.oep import OEP_V_1_3_Dialect +from omi.dialects.oep import OEP_V_1_4_Dialect +from omi.dialects.oep import OEP_V_1_5_Dialect +from omi.dialects.oep.parser import ParserException +from omi.dialects.oep.parser import parse_date_or_none + +BAD_VALUES = ["", "202", "2020-1", {}] +OK_VALUES = [ + None, + 1970, + "1970", + "2020-10", + "2020-10-01", + "2020-10-01 10:12", + "2020-10-01T10:12:13", + "2020-10-01T10:12:13:14+02:00", + "2020-10-01T10:12:13-0200", + "2020-10-01 10:12:13 GMT", +] + +BAD_VALUES = [] +OK_VALUES = [] + + +class TestIssue86Datetime(TestCase): + def datetime_roundtrip(self, value): + """test function directly""" + return parse_date_or_none(value) + + def test_datetime_roundtrip(self): + for bad_value in BAD_VALUES: + self.assertRaises(ParserException, self.datetime_roundtrip, bad_value) + for ok_value in OK_VALUES: + self.assertEqual(ok_value, self.datetime_roundtrip(ok_value), ok_value) + + +class TestIssue86Datetime_V_1_5(TestIssue86Datetime): + """test roundtrip in OEP_V_1_5_Dialect""" + + def datetime_roundtrip(self, value): + dialect = OEP_V_1_5_Dialect() + metadata_in = { + "id": "test", + "temporal": {"timeseries": [{"start": value}]}, + } + metadata_str = json.dumps(metadata_in) + metadata_obj = dialect.parse(metadata_str) + metadata_out = dialect.compile(metadata_obj) + return metadata_out["temporal"]["timeseries"][0].get("start") From 22d81aac33f9ff27a523a34b873d571d59c5cb18 Mon Sep 17 00:00:00 2001 From: "c.winger" Date: Tue, 24 Jan 2023 13:50:28 +0100 Subject: [PATCH 3/7] refactor compile date function --- src/omi/dialects/oep/compiler.py | 43 +++++++++++++++++++------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/omi/dialects/oep/compiler.py b/src/omi/dialects/oep/compiler.py index 9be29ee..d083d77 100644 --- a/src/omi/dialects/oep/compiler.py +++ b/src/omi/dialects/oep/compiler.py @@ -1,5 +1,3 @@ -import json -from collections import OrderedDict from datetime import datetime from omi import structure @@ -7,15 +5,16 @@ from omi.oem_structures import oem_v15 +def compile_date_or_none(date: datetime, format): + if date: + return date.strftime(format) + else: + return None + + class JSONCompiler(Compiler): __METADATA_VERSION = "OEP-1.4.0" - def _compile_date(self, date: datetime, format): - if date: - return date.strftime(format) - else: - return None - def _construct_dict(self, *args, omit_none=True, **kwargs): """ Accepts a list of arguments of shape (name: str, field: Compileable) and returns a dictionary that maps @@ -61,7 +60,7 @@ def visit_contribution(self, contribution: structure.Contribution, *args, **kwar ("email", contribution.contributor.email), ("object", contribution.object), ("comment", contribution.comment), - ("date", self._compile_date(contribution.date, "%Y-%m-%d")), + ("date", compile_date_or_none(contribution.date, "%Y-%m-%d")), ) def visit_language(self, language: structure.Language, *args, **kwargs): @@ -90,11 +89,14 @@ def visit_temporal(self, temporal: structure.Temporal, *args, **kwargs): start = None end = None if temporal.ts_start is not None: - start = self._compile_date(temporal.ts_start, "%Y-%m-%dT%H:%M%z")[:-2] + start = compile_date_or_none(temporal.ts_start, "%Y-%m-%dT%H:%M%z")[:-2] if temporal.ts_end is not None: - end = self._compile_date(temporal.ts_end, "%Y-%m-%dT%H:%M%z")[:-2] + end = compile_date_or_none(temporal.ts_end, "%Y-%m-%dT%H:%M%z")[:-2] return self._construct_dict( - ("referenceDate", self._compile_date(temporal.reference_date, "%Y-%m-%d")), + ( + "referenceDate", + compile_date_or_none(temporal.reference_date, "%Y-%m-%d"), + ), timeseries=self._construct_dict( ("start", start), ("end", end), @@ -202,7 +204,9 @@ def visit_meta_comment(self, comment: structure.MetaComment, *args, **kwargs): def visit_metadata(self, metadata: structure.OEPMetadata, *args, **kwargs): publication_date = None if metadata.publication_date is not None: - publication_date = self._compile_date(metadata.publication_date, "%Y-%m-%d") + publication_date = compile_date_or_none( + metadata.publication_date, "%Y-%m-%d" + ) return self._construct_dict( ("name", metadata.name), ("title", metadata.title), @@ -286,9 +290,9 @@ def visit_timeseries(self, timeseries: oem_v15.Timeseries, *args, **kwargs): start = None end = None if timeseries.ts_start is not None: - start = self._compile_date(timeseries.ts_start, "%Y-%m-%dT%H:%M%z")[:-2] + start = compile_date_or_none(timeseries.ts_start, "%Y-%m-%dT%H:%M%z")[:-2] if timeseries.ts_end is not None: - end = self._compile_date(timeseries.ts_end, "%Y-%m-%dT%H:%M%z")[:-2] + end = compile_date_or_none(timeseries.ts_end, "%Y-%m-%dT%H:%M%z")[:-2] return self._construct_dict( ("start", start), ("end", end), @@ -299,7 +303,10 @@ def visit_timeseries(self, timeseries: oem_v15.Timeseries, *args, **kwargs): def visit_temporal(self, temporal: oem_v15.Temporal, *args, **kwargs): return self._construct_dict( - ("referenceDate", self._compile_date(temporal.reference_date, "%Y-%m-%d")), + ( + "referenceDate", + compile_date_or_none(temporal.reference_date, "%Y-%m-%d"), + ), ("timeseries", temporal.timeseries_collection), ) @@ -347,7 +354,9 @@ def visit_meta_comment(self, comment: oem_v15.MetaComment, *args, **kwargs): def visit_metadata(self, metadata: oem_v15.OEPMetadata, *args, **kwargs): publication_date = None if metadata.publication_date is not None: - publication_date = self._compile_date(metadata.publication_date, "%Y-%m-%d") + publication_date = compile_date_or_none( + metadata.publication_date, "%Y-%m-%d" + ) return self._construct_dict( ("name", metadata.name), ("title", metadata.title), From 8638d4642dd4dfa5e348c9907b599da1f4c3af7b Mon Sep 17 00:00:00 2001 From: "c.winger" Date: Tue, 24 Jan 2023 14:06:18 +0100 Subject: [PATCH 4/7] modify parser and compiler for date --- src/omi/dialects/oep/compiler.py | 8 +++---- src/omi/dialects/oep/parser.py | 40 ++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/omi/dialects/oep/compiler.py b/src/omi/dialects/oep/compiler.py index d083d77..e4d4770 100644 --- a/src/omi/dialects/oep/compiler.py +++ b/src/omi/dialects/oep/compiler.py @@ -1,15 +1,15 @@ -from datetime import datetime +import datetime from omi import structure from omi.dialects.base.compiler import Compiler from omi.oem_structures import oem_v15 -def compile_date_or_none(date: datetime, format): - if date: +def compile_date_or_none(date, format): + if isinstance(date, (datetime.datetime, datetime.date)): return date.strftime(format) else: - return None + return date class JSONCompiler(Compiler): diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index 0e4edfe..e20eb13 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -4,10 +4,12 @@ import json import logging import pathlib +import re +import dateutil import jsonschema -from dateutil.parser import parse as parse_date from jsonschema import ValidationError + # oemetadata from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA from metadata.v130.schema import OEMETADATA_V130_SCHEMA @@ -31,16 +33,33 @@ ] -def parse_date_or_none(x, *args, **kwargs): +def parse_date_or_none(x): if x is None: - return None + pass + elif isinstance(x, (int, float)): + # e.g just a year or a unix timestamp + pass + elif isinstance(x, str): + # IMPORTANT NOTE: only use dateutil.parser if date part is complete + # if you parse something like '2020' or '2020-01', it will silently + # fill in the missing month/day from the current date! + # in this case, we keep the string, if it is at least is the correct pattern + + # something date like (with month and day) + if re.match("^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}.*", x): + x = dateutil.parser.parse(x) + elif re.match("^[0-9]{4}(|-[0-9]{1,2})$", x): + # only year or year-month: keep string + pass + else: + raise ParserException(f"invalid value for date: {x}") else: - return parse_date(x, *args, **kwargs) - + raise ParserException(f"invalid type for date: {type(x)}") + return x def create_report_json( - error_data, # type list[dict] + error_data, # type list[dict] save_at: pathlib.Path = "reports/", filename: str = "report.json", ): @@ -55,7 +74,6 @@ def create_report_json( class JSONParser(Parser): - def normalize_key_names_of_input(iput: dict): pass @@ -216,7 +234,6 @@ def is_valid(self, inp: dict, schema=OEMETADATA_V130_SCHEMA): except ValidationError: return False - def parse(self, json_old, *args, **kwargs): # context section context = None @@ -796,7 +813,10 @@ def parse_from_string( ) def get_any_value_not_none( - self, element: dict, keys, get_return_default=None #keys: list[str] - reove as not support by py3.8 + self, + element: dict, + keys, + get_return_default=None, # keys: list[str] - reove as not support by py3.8 ): """ Get the value for a key in a dict - but try multiple key names, in @@ -1146,7 +1166,7 @@ def parse_licence_including_former_structure(licences_element): primary_key=resource["schema"].get("primaryKey"), foreign_keys=foreign_keys, ) - + old_dialect = resource.get("dialect") if old_dialect is None: dialect = None From 3cb43c8e2d8df7ffc08004b7ad6e73faea8fd681 Mon Sep 17 00:00:00 2001 From: "c.winger" Date: Tue, 24 Jan 2023 14:40:28 +0100 Subject: [PATCH 5/7] test fixed function --- src/omi/dialects/oep/compiler.py | 11 ++-- src/omi/dialects/oep/parser.py | 19 +++++-- .../test_regression/test_issue86_datetime.py | 52 ++++++------------- 3 files changed, 38 insertions(+), 44 deletions(-) diff --git a/src/omi/dialects/oep/compiler.py b/src/omi/dialects/oep/compiler.py index e4d4770..e16a227 100644 --- a/src/omi/dialects/oep/compiler.py +++ b/src/omi/dialects/oep/compiler.py @@ -5,11 +5,14 @@ from omi.oem_structures import oem_v15 -def compile_date_or_none(date, format): - if isinstance(date, (datetime.datetime, datetime.date)): - return date.strftime(format) +def compile_date_or_none(x, format=None): + if isinstance(x, (datetime.datetime, datetime.date)): + if format: + return x.strftime(format) + else: + return x.isoformat() else: - return date + return x class JSONCompiler(Compiler): diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index e20eb13..adcd1fe 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -36,8 +36,10 @@ def parse_date_or_none(x): if x is None: pass - elif isinstance(x, (int, float)): + elif type(x) == int: # e.g just a year or a unix timestamp + # NOTE: isinstance(x, int) is also True for a bool, + # which we dont want pass elif isinstance(x, str): # IMPORTANT NOTE: only use dateutil.parser if date part is complete @@ -45,12 +47,19 @@ def parse_date_or_none(x): # fill in the missing month/day from the current date! # in this case, we keep the string, if it is at least is the correct pattern - # something date like (with month and day) - if re.match("^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}.*", x): - x = dateutil.parser.parse(x) - elif re.match("^[0-9]{4}(|-[0-9]{1,2})$", x): + if re.match("^[123][0-9]{3}(|-[0-9]{1,2})$", x): # only year or year-month: keep string pass + elif re.match("^[123][0-9]{3}-[0-9]{1,2}-[0-9]{1,2}", x): + try: + date_time = dateutil.parser.parse(x) + except Exception: + raise ParserException(f"invalid value for date: {x}") + if re.match("^[123][0-9]{3}-[0-9]{1,2}-[0-9]{1,2}$", x): + # date only + x = date_time.date() + else: + x = date_time else: raise ParserException(f"invalid value for date: {x}") else: diff --git a/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py b/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py index 061d909..22828f8 100644 --- a/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py +++ b/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py @@ -1,53 +1,35 @@ import json -import re from unittest import TestCase from omi.dialects.oep import OEP_V_1_3_Dialect from omi.dialects.oep import OEP_V_1_4_Dialect from omi.dialects.oep import OEP_V_1_5_Dialect +from omi.dialects.oep.compiler import compile_date_or_none from omi.dialects.oep.parser import ParserException from omi.dialects.oep.parser import parse_date_or_none -BAD_VALUES = ["", "202", "2020-1", {}] -OK_VALUES = [ - None, - 1970, - "1970", - "2020-10", - "2020-10-01", - "2020-10-01 10:12", - "2020-10-01T10:12:13", - "2020-10-01T10:12:13:14+02:00", - "2020-10-01T10:12:13-0200", - "2020-10-01 10:12:13 GMT", -] - -BAD_VALUES = [] -OK_VALUES = [] +BAD_VALUES = [True, {}, "", "not a date", "200", "2020-30-40", "2020-01-01 WTF"] +OK_VALUES = { + None: None, + 2020: 2020, + "2020": "2020", + "2020-12": "2020-12", + "2020-12-02": "2020-12-02", + "2020-12-2": "2020-12-02", + "2020-10-01T10:12:13": "2020-10-01T10:12:13", + "2020-10-01 10:12": "2020-10-01T10:12:00", + "2020-10-01T10:12:13+0200": "2020-10-01T10:12:13+02:00", +} class TestIssue86Datetime(TestCase): def datetime_roundtrip(self, value): """test function directly""" - return parse_date_or_none(value) + value = parse_date_or_none(value) + return compile_date_or_none(value) def test_datetime_roundtrip(self): for bad_value in BAD_VALUES: self.assertRaises(ParserException, self.datetime_roundtrip, bad_value) - for ok_value in OK_VALUES: - self.assertEqual(ok_value, self.datetime_roundtrip(ok_value), ok_value) - - -class TestIssue86Datetime_V_1_5(TestIssue86Datetime): - """test roundtrip in OEP_V_1_5_Dialect""" - - def datetime_roundtrip(self, value): - dialect = OEP_V_1_5_Dialect() - metadata_in = { - "id": "test", - "temporal": {"timeseries": [{"start": value}]}, - } - metadata_str = json.dumps(metadata_in) - metadata_obj = dialect.parse(metadata_str) - metadata_out = dialect.compile(metadata_obj) - return metadata_out["temporal"]["timeseries"][0].get("start") + for ok_value, exp_value in OK_VALUES.items(): + self.assertEqual(self.datetime_roundtrip(ok_value), exp_value) From 8bb84a7fcf482c11ef1c91d9303f6cd19815e2f8 Mon Sep 17 00:00:00 2001 From: "c.winger" Date: Tue, 24 Jan 2023 15:19:13 +0100 Subject: [PATCH 6/7] fixed old tests, remove truncation --- src/omi/dialects/oep/compiler.py | 8 +- tests/data/metadata_v14.json | 4 +- tests/data/metadata_v15.json | 26 ++--- .../test_regression/test_issue86_datetime.py | 108 +++++++++++++++--- 4 files changed, 105 insertions(+), 41 deletions(-) diff --git a/src/omi/dialects/oep/compiler.py b/src/omi/dialects/oep/compiler.py index e16a227..1dbcbe4 100644 --- a/src/omi/dialects/oep/compiler.py +++ b/src/omi/dialects/oep/compiler.py @@ -92,9 +92,9 @@ def visit_temporal(self, temporal: structure.Temporal, *args, **kwargs): start = None end = None if temporal.ts_start is not None: - start = compile_date_or_none(temporal.ts_start, "%Y-%m-%dT%H:%M%z")[:-2] + start = compile_date_or_none(temporal.ts_start) if temporal.ts_end is not None: - end = compile_date_or_none(temporal.ts_end, "%Y-%m-%dT%H:%M%z")[:-2] + end = compile_date_or_none(temporal.ts_end) return self._construct_dict( ( "referenceDate", @@ -293,9 +293,9 @@ def visit_timeseries(self, timeseries: oem_v15.Timeseries, *args, **kwargs): start = None end = None if timeseries.ts_start is not None: - start = compile_date_or_none(timeseries.ts_start, "%Y-%m-%dT%H:%M%z")[:-2] + start = compile_date_or_none(timeseries.ts_start) if timeseries.ts_end is not None: - end = compile_date_or_none(timeseries.ts_end, "%Y-%m-%dT%H:%M%z")[:-2] + end = compile_date_or_none(timeseries.ts_end) return self._construct_dict( ("start", start), ("end", end), diff --git a/tests/data/metadata_v14.json b/tests/data/metadata_v14.json index b32323b..ca773ce 100644 --- a/tests/data/metadata_v14.json +++ b/tests/data/metadata_v14.json @@ -32,8 +32,8 @@ "temporal": { "referenceDate": "2016-01-01", "timeseries": { - "start": "2017-01-01T00:00+01", - "end": "2017-12-31T23:00+01", + "start": "2017-01-01T00:00:00+01:00", + "end": "2017-12-31T23:00:00+01:00", "resolution": "1 h", "alignment": "left", "aggregationType": "sum" diff --git a/tests/data/metadata_v15.json b/tests/data/metadata_v15.json index 81893a8..68d455d 100644 --- a/tests/data/metadata_v15.json +++ b/tests/data/metadata_v15.json @@ -44,15 +44,15 @@ "referenceDate": "2016-01-01", "timeseries": [ { - "start": "2017-01-01T00:00+01", - "end": "2017-12-31T23:00+01", + "start": "2017-01-01T00:00:00+01:00", + "end": "2017-12-31T23:00:00+01:00", "resolution": "1 h", "alignment": "left", "aggregationType": "sum" }, { - "start": "2018-01-01T00:00+01", - "end": "2019-06-01T23:00+01", + "start": "2018-01-01T00:00:00+01:00", + "end": "2019-06-01T23:00:00+01:00", "resolution": "15 min", "alignment": "right", "aggregationType": "sum" @@ -126,12 +126,10 @@ "description": "Unique identifier", "type": "serial", "isAbout": [ - { - } + {} ], "valueReference": [ - { - } + {} ] }, { @@ -145,8 +143,7 @@ } ], "valueReference": [ - { - } + {} ] }, { @@ -183,8 +180,7 @@ } ], "valueReference": [ - { - } + {} ] }, { @@ -199,8 +195,7 @@ } ], "valueReference": [ - { - } + {} ] }, { @@ -214,8 +209,7 @@ } ], "valueReference": [ - { - } + {} ] } ], diff --git a/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py b/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py index 22828f8..f701b2e 100644 --- a/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py +++ b/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py @@ -1,4 +1,5 @@ import json +from unittest import SkipTest from unittest import TestCase from omi.dialects.oep import OEP_V_1_3_Dialect @@ -8,28 +9,97 @@ from omi.dialects.oep.parser import ParserException from omi.dialects.oep.parser import parse_date_or_none -BAD_VALUES = [True, {}, "", "not a date", "200", "2020-30-40", "2020-01-01 WTF"] -OK_VALUES = { - None: None, - 2020: 2020, - "2020": "2020", - "2020-12": "2020-12", - "2020-12-02": "2020-12-02", - "2020-12-2": "2020-12-02", - "2020-10-01T10:12:13": "2020-10-01T10:12:13", - "2020-10-01 10:12": "2020-10-01T10:12:00", - "2020-10-01T10:12:13+0200": "2020-10-01T10:12:13+02:00", -} +# in the metadata, for some values we return the date,not the full datetime class TestIssue86Datetime(TestCase): - def datetime_roundtrip(self, value): - """test function directly""" + + BAD_VALUES = [True, {}, "", "not a date", "200", "2020-30-40", "2020-01-01 WTF"] + OK_VALUES = { + None: None, + 2020: 2020, + "2020": "2020", + "2020-12": "2020-12", + "2020-12-02": "2020-12-02", + "2020-12-2": "2020-12-02", + "2020-10-01T10:12:13": "2020-10-01T10:12:13", + "2020-10-01 10:12": "2020-10-01T10:12:00", + "2020-10-01T10:12:13+0200": "2020-10-01T10:12:13+02:00", + } + + def roundtrip_value(self, value): value = parse_date_or_none(value) - return compile_date_or_none(value) + value = compile_date_or_none(value) + return value + + def test_datetime_roundtrip(self): + for bad_value in self.BAD_VALUES: + self.assertRaises(ParserException, self.roundtrip_value, bad_value) + for ok_value, exp_value in self.OK_VALUES.items(): + self.assertEqual(self.roundtrip_value(ok_value), exp_value) + + +class TestIssue86Metadata(TestIssue86Datetime): + """test roundtrip in OEP_V_1_5_Dialect""" + + dialect = None + OK_VALUES = { + None: (None, None), + 2020: (2020, 2020), + "2020": ("2020", "2020"), + "2020-12": ("2020-12", "2020-12"), + "2020-12-02": ("2020-12-02", "2020-12-02"), + "2020-12-2": ("2020-12-02", "2020-12-02"), + "2020-10-01T10:12:13": ("2020-10-01T10:12:13", "2020-10-01"), + "2020-10-01 10:12": ("2020-10-01T10:12:00", "2020-10-01"), + "2020-10-01T10:12:13+0200": ("2020-10-01T10:12:13+02:00", "2020-10-01"), + } def test_datetime_roundtrip(self): - for bad_value in BAD_VALUES: - self.assertRaises(ParserException, self.datetime_roundtrip, bad_value) - for ok_value, exp_value in OK_VALUES.items(): - self.assertEqual(self.datetime_roundtrip(ok_value), exp_value) + # only actually run tests in subclasses + if self.dialect: + return super().test_datetime_roundtrip() + + def roundtrip_value(self, value): + metadata_in = {"id": "test"} + self.set_date_datetime_values(metadata_in, value) + metadata_str = json.dumps(metadata_in) + metadata_obj = self.dialect.parse(metadata_str) + metadata_out = self.dialect.compile(metadata_obj) + return self.get_date_datetime_values(metadata_out) + + def set_date_datetime_values(self, metadata, value): + raise NotImplementedError() + + def get_date_datetime_values(self, metadata): + raise NotImplementedError() + + +class TestIssue86Datetime_V_1_5(TestIssue86Metadata): + """test roundtrip in OEP_V_1_5_Dialect""" + + dialect = OEP_V_1_5_Dialect() + + def set_date_datetime_values(self, metadata, value): + metadata["publicationDate"] = value + metadata["temporal"] = {"timeseries": [{"start": value}]} + + def get_date_datetime_values(self, metadata): + v_datetime = metadata["temporal"]["timeseries"][0].get("start") + v_date = metadata.get("publicationDate") + return (v_datetime, v_date) + + +class TestIssue86Datetime_V_1_4(TestIssue86Metadata): + """test roundtrip in OEP_V_1_4_Dialect""" + + dialect = OEP_V_1_4_Dialect() + + def set_date_datetime_values(self, metadata, value): + metadata["publicationDate"] = value + metadata["temporal"] = {"timeseries": {"start": value}} + + def get_date_datetime_values(self, metadata): + v_datetime = metadata["temporal"]["timeseries"].get("start") + v_date = metadata.get("publicationDate") + return (v_datetime, v_date) From d6270ce5fbf17e2bff5d7722fe3f13a1cd087201 Mon Sep 17 00:00:00 2001 From: "c.winger" Date: Tue, 24 Jan 2023 15:44:29 +0100 Subject: [PATCH 7/7] empty line for isort --- src/omi/dialects/oep/parser.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py index adcd1fe..8378fa4 100644 --- a/src/omi/dialects/oep/parser.py +++ b/src/omi/dialects/oep/parser.py @@ -9,7 +9,6 @@ import dateutil import jsonschema from jsonschema import ValidationError - # oemetadata from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA from metadata.v130.schema import OEMETADATA_V130_SCHEMA