From 4e45698096610cfa68e7813627f6ef3d99caec95 Mon Sep 17 00:00:00 2001 From: "Kernchen, Sophie" Date: Fri, 11 Jul 2025 14:11:59 +0200 Subject: [PATCH 01/32] First test for ld_container --- test/hermes_test/model/types/__init__.py | 0 .../model/types/test_ld_container.py | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 test/hermes_test/model/types/__init__.py create mode 100644 test/hermes_test/model/types/test_ld_container.py diff --git a/test/hermes_test/model/types/__init__.py b/test/hermes_test/model/types/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py new file mode 100644 index 00000000..0ddd541a --- /dev/null +++ b/test/hermes_test/model/types/test_ld_container.py @@ -0,0 +1,19 @@ +from hermes.model.types.ld_container import ld_container + +'''we expect user of this class to give the right input data types + +example extendeed json ld: + { + "http://schema.org/name": [{"@value": "bacon"}], + "eggs": [{"@id": "spam"}], + "green": [{"@id": "png"}] + } +''' + + +def test_container_basic(): + cont = ld_container({"spam": [{"@value": "bacon"}]}) + + assert cont.key is None + assert cont.context == [] + assert cont._data == {"spam": [{"@value": "bacon"}]} From f7ef65d958b9a6ca96c581a67f8deac0150f8798 Mon Sep 17 00:00:00 2001 From: "Kernchen, Sophie" Date: Mon, 14 Jul 2025 13:06:50 +0200 Subject: [PATCH 02/32] Add license information --- test/hermes_test/model/types/__init__.py | 5 +++++ test/hermes_test/model/types/test_ld_container.py | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/test/hermes_test/model/types/__init__.py b/test/hermes_test/model/types/__init__.py index e69de29b..9a1d6097 100644 --- a/test/hermes_test/model/types/__init__.py +++ b/test/hermes_test/model/types/__init__.py @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2025 German Aerospace Center (DLR) +# +# SPDX-License-Identifier: Apache-2.0 + +# SPDX-FileContributor: Sophie Kernchen \ No newline at end of file diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index 0ddd541a..27069a1f 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -1,3 +1,9 @@ +# SPDX-FileCopyrightText: 2025 German Aerospace Center (DLR) +# +# SPDX-License-Identifier: Apache-2.0 + +# SPDX-FileContributor: Sophie Kernchen + from hermes.model.types.ld_container import ld_container '''we expect user of this class to give the right input data types From ccec2ec71b49fba0f97f97ddd4fe44ff84a24179 Mon Sep 17 00:00:00 2001 From: "Kernchen, Sophie" Date: Thu, 24 Jul 2025 10:20:14 +0200 Subject: [PATCH 03/32] Test ld_container add_context --- .../model/types/test_ld_container.py | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index 27069a1f..68ce9cd9 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -1,14 +1,16 @@ # SPDX-FileCopyrightText: 2025 German Aerospace Center (DLR) # # SPDX-License-Identifier: Apache-2.0 +import re # SPDX-FileContributor: Sophie Kernchen +import pytest, requests from hermes.model.types.ld_container import ld_container '''we expect user of this class to give the right input data types -example extendeed json ld: +example extended json ld: { "http://schema.org/name": [{"@value": "bacon"}], "eggs": [{"@id": "spam"}], @@ -23,3 +25,41 @@ def test_container_basic(): assert cont.key is None assert cont.context == [] assert cont._data == {"spam": [{"@value": "bacon"}]} + + +def test_container_ld_value(): + cont = ld_container({"spam": [{"@value": "bacon"}]}) + + assert cont.ld_value == {"spam": [{"@value": "bacon"}]} + + +def test_container_add_context(httpserver): + content = {"@context": {"type": "@type", "id": "@id", "schema": "http://schema.org/", "ham": "https://fake.site/", + "Organization": {"@id": "schema:Organization"}}} + + url = httpserver.url_for("/url") + + httpserver.expect_request("/url").respond_with_json(content) + cont = ld_container({"spam": [{"@value": "bacon"}]}) + cont.add_context([url]) + + assert cont.context == [url] + assert cont.full_context == [url] + + +def test_container_parent(httpserver): + content = {"@context": {"type": "@type", "id": "@id", "schema": "http://schema.org/", "ham": "https://fake.site/", + "Organization": {"@id": "schema:Organization"}}} + + url = httpserver.url_for("/url") + + httpserver.expect_request("/url").respond_with_json(content) + + cont_parent = ld_container({"ham": [{"@value": "eggs"}]}) + cont = ld_container({"spam": [{"@value": "bacon"}]}, parent=cont_parent) + assert cont.full_context == [] + + cont_parent.add_context([url]) + + assert cont.parent == cont_parent + assert cont.full_context == [url] From 04a727d0bee5b8627897285aa31d56608871b176 Mon Sep 17 00:00:00 2001 From: "Kernchen, Sophie" Date: Thu, 24 Jul 2025 11:25:58 +0200 Subject: [PATCH 04/32] Refactor tests to class --- .../model/types/test_ld_container.py | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index 68ce9cd9..264e2930 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -19,47 +19,53 @@ ''' -def test_container_basic(): - cont = ld_container({"spam": [{"@value": "bacon"}]}) +class TestLdContainer: + @classmethod + @pytest.fixture(autouse=True) + def setup_class(cls, httpserver): + content = { + "@context": {"type": "@type", "id": "@id", "schema": "http://schema.org/", "ham": "https://fake.site/", + "Organization": {"@id": "schema:Organization"}}} - assert cont.key is None - assert cont.context == [] - assert cont._data == {"spam": [{"@value": "bacon"}]} + cls.url = httpserver.url_for("/url") + httpserver.expect_request("/url").respond_with_json(content) -def test_container_ld_value(): - cont = ld_container({"spam": [{"@value": "bacon"}]}) + def test_container_basic(self): + cont = ld_container({"spam": [{"@value": "bacon"}]}) - assert cont.ld_value == {"spam": [{"@value": "bacon"}]} + assert cont.key is None + assert cont.context == [] + assert cont._data == {"spam": [{"@value": "bacon"}]} + def test_container_ld_value(self): + cont = ld_container({"spam": [{"@value": "bacon"}]}) -def test_container_add_context(httpserver): - content = {"@context": {"type": "@type", "id": "@id", "schema": "http://schema.org/", "ham": "https://fake.site/", - "Organization": {"@id": "schema:Organization"}}} + assert cont.ld_value == {"spam": [{"@value": "bacon"}]} - url = httpserver.url_for("/url") + def test_container_add_context(self): - httpserver.expect_request("/url").respond_with_json(content) - cont = ld_container({"spam": [{"@value": "bacon"}]}) - cont.add_context([url]) + cont = ld_container({"spam": [{"@value": "bacon"}]}) + cont.add_context([self.url]) - assert cont.context == [url] - assert cont.full_context == [url] + assert cont.context == [self.url] + assert cont.full_context == [self.url] + def test_container_parent(self): -def test_container_parent(httpserver): - content = {"@context": {"type": "@type", "id": "@id", "schema": "http://schema.org/", "ham": "https://fake.site/", - "Organization": {"@id": "schema:Organization"}}} - url = httpserver.url_for("/url") + cont_parent = ld_container({"ham": [{"@value": "eggs"}]}) + cont = ld_container({"spam": [{"@value": "bacon"}]}, parent=cont_parent) + assert cont.full_context == [] - httpserver.expect_request("/url").respond_with_json(content) + cont_parent.add_context([self.url]) - cont_parent = ld_container({"ham": [{"@value": "eggs"}]}) - cont = ld_container({"spam": [{"@value": "bacon"}]}, parent=cont_parent) - assert cont.full_context == [] + assert cont.parent == cont_parent + assert cont.full_context == [self.url] - cont_parent.add_context([url]) + def test_container_full_context(self): + cont_grand_parent = ld_container({"ham": [{"@value": "eggs"}]}, context=[self.url]) + cont_parent = ld_container({"ham": [{"@value": "eggs"}]},parent=cont_grand_parent) + cont = ld_container({"spam": [{"@value": "bacon"}]}, parent=cont_parent) - assert cont.parent == cont_parent - assert cont.full_context == [url] + assert cont.full_context == [self.url] \ No newline at end of file From 6cb305bd5b97e9eaff1a490ae36ced06004f1690 Mon Sep 17 00:00:00 2001 From: "Kernchen, Sophie" Date: Thu, 24 Jul 2025 13:35:07 +0200 Subject: [PATCH 05/32] Test representation methods --- src/hermes/model/types/ld_container.py | 11 ++++++- .../model/types/test_ld_container.py | 31 ++++++++++++++----- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/hermes/model/types/ld_container.py b/src/hermes/model/types/ld_container.py index fd84e033..0f0048bf 100644 --- a/src/hermes/model/types/ld_container.py +++ b/src/hermes/model/types/ld_container.py @@ -70,6 +70,15 @@ def full_context(self): @property def path(self): """ Create a path representation for this item. """ + ''' + FIXME: #381 Decision if the path should look like this. Other option: + + if self.parent: + return self.parent.path + [self.key if self.index is None else self.index] + else: + return ["(self.key if self.index is None else self.index)"] braces to show you are here. + + ''' if self.parent: return self.parent.path + [self.key if self.index is None else self.index] else: @@ -130,7 +139,7 @@ def _to_expanded_json(self, key, value): return ld_value def __repr__(self): - return f'{type(self).__name__}({self._data[0]})' + return f'{type(self).__name__}({self._data[0]})' #FIXME: #397 KeyError, maybe removing the index def __str__(self): return str(self.to_python()) diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index 264e2930..768fc808 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -37,6 +37,7 @@ def test_container_basic(self): assert cont.key is None assert cont.context == [] assert cont._data == {"spam": [{"@value": "bacon"}]} + assert cont.path == ["$"] def test_container_ld_value(self): cont = ld_container({"spam": [{"@value": "bacon"}]}) @@ -52,8 +53,6 @@ def test_container_add_context(self): assert cont.full_context == [self.url] def test_container_parent(self): - - cont_parent = ld_container({"ham": [{"@value": "eggs"}]}) cont = ld_container({"spam": [{"@value": "bacon"}]}, parent=cont_parent) assert cont.full_context == [] @@ -63,9 +62,27 @@ def test_container_parent(self): assert cont.parent == cont_parent assert cont.full_context == [self.url] - def test_container_full_context(self): - cont_grand_parent = ld_container({"ham": [{"@value": "eggs"}]}, context=[self.url]) - cont_parent = ld_container({"ham": [{"@value": "eggs"}]},parent=cont_grand_parent) - cont = ld_container({"spam": [{"@value": "bacon"}]}, parent=cont_parent) + def test_container_full_context_and_path(self, httpserver): + httpserver.expect_request("/url2").respond_with_json({"spam": "eggs"}) + httpserver.expect_request("/url3").respond_with_json({"ham": "bacon"}) + httpserver.expect_request("/url4").respond_with_json({"@context": {"id": "@id"}}) + + cont_grand_parent = ld_container({"ham": [{"@value": "eggs"}]}, context=[self.url], index=1) + cont_parent = ld_container({"ham": [{"@value": "eggs"}]}, context=[httpserver.url_for("/url2"), + httpserver.url_for("/url4")], + parent=cont_grand_parent) + cont = ld_container({"spam": [{"@value": "bacon"}]}, context=[httpserver.url_for("/url3")], parent=cont_parent, + index=3) + assert cont_parent.full_context == [self.url, httpserver.url_for("/url2"), httpserver.url_for("/url4")] + assert cont.full_context == [self.url, httpserver.url_for("/url2"), httpserver.url_for("/url4"), + httpserver.url_for("/url3")] + assert cont_grand_parent.path == ["$"] # FIXME: #381 Decision if the path should look like this + assert cont_parent.path == ["$", None] + assert cont.path == ["$", None, 3] + + def test_container_str_and_repr(self): + cont = ld_container({"spam": [{"@value": "bacon"}]}, index=3) + assert repr(cont) == ld_container({"spam": [{"@value": "bacon"}]}) #FIXME: #397 KeyError + with pytest.raises(NotImplementedError): + str(cont) - assert cont.full_context == [self.url] \ No newline at end of file From 14373f88df55c8e5d2855ba19625f9667571751f Mon Sep 17 00:00:00 2001 From: "Kernchen, Sophie" Date: Thu, 31 Jul 2025 10:04:58 +0200 Subject: [PATCH 06/32] Correct container parameters --- src/hermes/model/types/ld_container.py | 2 +- .../model/types/test_ld_container.py | 44 ++++++++++--------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/hermes/model/types/ld_container.py b/src/hermes/model/types/ld_container.py index 0f0048bf..710fc6a0 100644 --- a/src/hermes/model/types/ld_container.py +++ b/src/hermes/model/types/ld_container.py @@ -139,7 +139,7 @@ def _to_expanded_json(self, key, value): return ld_value def __repr__(self): - return f'{type(self).__name__}({self._data[0]})' #FIXME: #397 KeyError, maybe removing the index + return f'{type(self).__name__}({self._data[0]})' def __str__(self): return str(self.to_python()) diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index 768fc808..f39768a9 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -5,17 +5,17 @@ # SPDX-FileContributor: Sophie Kernchen -import pytest, requests +import pytest from hermes.model.types.ld_container import ld_container '''we expect user of this class to give the right input data types example extended json ld: - { + [{ "http://schema.org/name": [{"@value": "bacon"}], "eggs": [{"@id": "spam"}], "green": [{"@id": "png"}] - } + }] ''' @@ -32,29 +32,30 @@ def setup_class(cls, httpserver): httpserver.expect_request("/url").respond_with_json(content) def test_container_basic(self): - cont = ld_container({"spam": [{"@value": "bacon"}]}) + cont = ld_container([{"spam": [{"@value": "bacon"}]}]) assert cont.key is None assert cont.context == [] - assert cont._data == {"spam": [{"@value": "bacon"}]} + assert cont._data == [{"spam": [{"@value": "bacon"}]}] assert cont.path == ["$"] def test_container_ld_value(self): - cont = ld_container({"spam": [{"@value": "bacon"}]}) + cont = ld_container([{"spam": [{"@value": "bacon"}]}]) - assert cont.ld_value == {"spam": [{"@value": "bacon"}]} + assert cont.ld_value == [{"spam": [{"@value": "bacon"}]}] def test_container_add_context(self): - cont = ld_container({"spam": [{"@value": "bacon"}]}) + cont = ld_container([{"spam": [{"@value": "bacon"}]}]) cont.add_context([self.url]) assert cont.context == [self.url] assert cont.full_context == [self.url] def test_container_parent(self): - cont_parent = ld_container({"ham": [{"@value": "eggs"}]}) - cont = ld_container({"spam": [{"@value": "bacon"}]}, parent=cont_parent) + cont_data = [{"spam": [{"@value": "bacon"}]}] + cont_parent = ld_container([{"ham": cont_data}]) + cont = ld_container(cont_data, parent=cont_parent, key="ham") assert cont.full_context == [] cont_parent.add_context([self.url]) @@ -67,22 +68,23 @@ def test_container_full_context_and_path(self, httpserver): httpserver.expect_request("/url3").respond_with_json({"ham": "bacon"}) httpserver.expect_request("/url4").respond_with_json({"@context": {"id": "@id"}}) - cont_grand_parent = ld_container({"ham": [{"@value": "eggs"}]}, context=[self.url], index=1) - cont_parent = ld_container({"ham": [{"@value": "eggs"}]}, context=[httpserver.url_for("/url2"), + cont_data = [{"spam": [{"@value": "bacon"}]}] + cont_parent_data = [cont_data] + cont_grand_parent = ld_container([{"ham": cont_parent_data}], context=[self.url]) + cont_parent = ld_container(cont_parent_data, context=[httpserver.url_for("/url2"), httpserver.url_for("/url4")], - parent=cont_grand_parent) - cont = ld_container({"spam": [{"@value": "bacon"}]}, context=[httpserver.url_for("/url3")], parent=cont_parent, - index=3) + parent=cont_grand_parent, key="ham") + cont = ld_container(cont_data, context=[httpserver.url_for("/url3")], parent=cont_parent, + index=0) assert cont_parent.full_context == [self.url, httpserver.url_for("/url2"), httpserver.url_for("/url4")] assert cont.full_context == [self.url, httpserver.url_for("/url2"), httpserver.url_for("/url4"), httpserver.url_for("/url3")] - assert cont_grand_parent.path == ["$"] # FIXME: #381 Decision if the path should look like this - assert cont_parent.path == ["$", None] - assert cont.path == ["$", None, 3] + assert cont_grand_parent.path == ["$"] + assert cont_parent.path == ["$", "ham"] + assert cont.path == ["$", "ham", 0] def test_container_str_and_repr(self): - cont = ld_container({"spam": [{"@value": "bacon"}]}, index=3) - assert repr(cont) == ld_container({"spam": [{"@value": "bacon"}]}) #FIXME: #397 KeyError + cont = ld_container([{"spam": [{"@value": "bacon"}]}]) + assert repr(cont) == "ld_container({'spam': [{'@value': 'bacon'}]})" with pytest.raises(NotImplementedError): str(cont) - From 5e8e693fe0a2c5e00131670291f015c45b60408c Mon Sep 17 00:00:00 2001 From: "Kernchen, Sophie" Date: Thu, 31 Jul 2025 11:38:40 +0200 Subject: [PATCH 07/32] Fix method name and test convertion methods --- src/hermes/model/types/ld_container.py | 2 +- src/hermes/model/types/pyld_util.py | 2 +- .../model/types/test_ld_container.py | 18 +++++++++++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/hermes/model/types/ld_container.py b/src/hermes/model/types/ld_container.py index 710fc6a0..981227aa 100644 --- a/src/hermes/model/types/ld_container.py +++ b/src/hermes/model/types/ld_container.py @@ -47,7 +47,7 @@ def __init__(self, data, *, parent=None, key=None, index=None, context=None): else: self.active_ctx = parent.active_ctx else: - self.active_ctx = self.ld_proc.inital_ctx( + self.active_ctx = self.ld_proc.initial_ctx( self.full_context, {"documentLoader": bundled_loader} ) diff --git a/src/hermes/model/types/pyld_util.py b/src/hermes/model/types/pyld_util.py index f652cce8..1d3f9bff 100644 --- a/src/hermes/model/types/pyld_util.py +++ b/src/hermes/model/types/pyld_util.py @@ -106,7 +106,7 @@ def expand_iri(self, active_ctx: t.Any, short_iri: str) -> str: def compact_iri(self, active_ctx: t.Any, long_iri: str) -> str: return self._compact_iri(active_ctx, long_iri, vocab=True) - def inital_ctx(self, local_ctx, options=None): + def initial_ctx(self, local_ctx, options=None): return self.process_context(self._INITIAL_CONTEXT, local_ctx, options or {}) @classmethod diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index f39768a9..a159907f 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -5,7 +5,7 @@ # SPDX-FileContributor: Sophie Kernchen -import pytest +import pytest, uuid from hermes.model.types.ld_container import ld_container '''we expect user of this class to give the right input data types @@ -38,6 +38,7 @@ def test_container_basic(self): assert cont.context == [] assert cont._data == [{"spam": [{"@value": "bacon"}]}] assert cont.path == ["$"] + assert cont.active_ctx == {'mappings': {}} def test_container_ld_value(self): cont = ld_container([{"spam": [{"@value": "bacon"}]}]) @@ -88,3 +89,18 @@ def test_container_str_and_repr(self): assert repr(cont) == "ld_container({'spam': [{'@value': 'bacon'}]})" with pytest.raises(NotImplementedError): str(cont) + + def test_to_python(self): + cont = ld_container([{"spam": [{"@value": "bacon", "@id": "ham", "@type": ["@id"]}]}]) + assert cont._to_python("spam", [{"@value": "bacon"}]) == 'bacon' + assert cont._to_python("@id", "ham") == "ham" + + cont.active_ctx['_uuid'] = str(uuid.uuid1()) # FIXME: 406 + assert cont._to_python("@type", ["@id"]) == '@id' + + def test_to_expanded(self): + cont = ld_container([{"spam": [{"@value": "bacon", "@id": "ham", "@type": "@id"}]}]) + cont.active_ctx['_uuid'] = str(uuid.uuid1()) # FIXME: 406 + assert cont._to_expanded_json("spam", "bacon") == [{"@value": "bacon"}] + assert cont._to_expanded_json("@id", "ham") == "ham" + assert cont._to_expanded_json("@type", "@id") == ["@id"] From 4847d661dcd58b93c840935c88592a2464c43c70 Mon Sep 17 00:00:00 2001 From: "Kernchen, Sophie" Date: Thu, 31 Jul 2025 11:42:42 +0200 Subject: [PATCH 08/32] Remove docstring from closed issue --- src/hermes/model/types/ld_container.py | 9 --------- test/hermes_test/model/types/test_ld_container.py | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/hermes/model/types/ld_container.py b/src/hermes/model/types/ld_container.py index 981227aa..9d8b10c2 100644 --- a/src/hermes/model/types/ld_container.py +++ b/src/hermes/model/types/ld_container.py @@ -70,15 +70,6 @@ def full_context(self): @property def path(self): """ Create a path representation for this item. """ - ''' - FIXME: #381 Decision if the path should look like this. Other option: - - if self.parent: - return self.parent.path + [self.key if self.index is None else self.index] - else: - return ["(self.key if self.index is None else self.index)"] braces to show you are here. - - ''' if self.parent: return self.parent.path + [self.key if self.index is None else self.index] else: diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index a159907f..00c93db5 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -73,7 +73,7 @@ def test_container_full_context_and_path(self, httpserver): cont_parent_data = [cont_data] cont_grand_parent = ld_container([{"ham": cont_parent_data}], context=[self.url]) cont_parent = ld_container(cont_parent_data, context=[httpserver.url_for("/url2"), - httpserver.url_for("/url4")], + httpserver.url_for("/url4")], parent=cont_grand_parent, key="ham") cont = ld_container(cont_data, context=[httpserver.url_for("/url3")], parent=cont_parent, index=0) From e2995b338b0efbf577fdabcb0f0b8e77bf32cb06 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Thu, 31 Jul 2025 21:34:05 +0200 Subject: [PATCH 09/32] Add dependency for tests. --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index bf19ccca..8223b75e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,6 +62,7 @@ pytest-cov = "^3.0.0" taskipy = "^1.10.3" flake8 = "^5.0.4" requests-mock = "^1.10.0" +pytest-httpserver = "^1.1.3" # Packages for developers for creating documentation [tool.poetry.group.docs] From 8da44cb6a4fc8703d349fc6ff2489bbf49af3e56 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Thu, 31 Jul 2025 21:43:06 +0200 Subject: [PATCH 10/32] Adapt test of _To_expanded_json. See MR #398 for more information. --- test/hermes_test/model/types/test_ld_container.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index 00c93db5..73877bff 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -99,8 +99,17 @@ def test_to_python(self): assert cont._to_python("@type", ["@id"]) == '@id' def test_to_expanded(self): - cont = ld_container([{"spam": [{"@value": "bacon", "@id": "ham", "@type": "@id"}]}]) - cont.active_ctx['_uuid'] = str(uuid.uuid1()) # FIXME: 406 + # Define a mock vocabulary to work with + mock_context = { + "ham": {"@id": "http://ham.eggs/ham", "@type": "@id"}, + "spam": {"@id": "http://ham.eggs/spam"}, + "Eggs": {"@id": "http://ham.eggs/Eggs"}, + } + + # Create container with mock context + cont = ld_container([{}], context=[mock_context]) + + # Try simple cases of expansion assert cont._to_expanded_json("spam", "bacon") == [{"@value": "bacon"}] - assert cont._to_expanded_json("@id", "ham") == "ham" + assert cont._to_expanded_json("@id", "ham") == "http://ham.eggs/ham" assert cont._to_expanded_json("@type", "@id") == ["@id"] From f0148a585fcc9f66ee54644819cfdbcccda4ab42 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 20:57:02 +0200 Subject: [PATCH 11/32] Add test helpers that provide JSON-LD data. Basically, this is a small but somewhat representative vocabulary that can be used. In addition, there are two representations of the same document (compact, expanded). --- test/hermes_test/model/types/conftest.py | 64 ++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 test/hermes_test/model/types/conftest.py diff --git a/test/hermes_test/model/types/conftest.py b/test/hermes_test/model/types/conftest.py new file mode 100644 index 00000000..aa61252b --- /dev/null +++ b/test/hermes_test/model/types/conftest.py @@ -0,0 +1,64 @@ +# SPDX-FileCopyrightText: 2025 German Aerospace Center (DLR) +# +# SPDX-License-Identifier: Apache-2.0 + +from datetime import datetime + +import pytest + + +class MockDocument: + @classmethod + def vocabulary(cls, base_url="http://spam.eggs/"): + return { + "spam": {"@id": f"{base_url}spam"}, + "ham": {"@id": f"{base_url}ham", "@type": "@id"}, + "eggs": {"@id": f"{base_url}eggs", "@container": "@list"}, + "use_until": {"@id": f"{base_url}use_until", "@type": "http://schema.org/DateTime"}, + + "Egg": {"@id": f"{base_url}Egg"}, + } + + @classmethod + def compact(cls, base_url="http://spam.eggs/"): + return { + "@context": cls.vocabulary(base_url), + + "spam": "bacon", + "ham": f"{base_url}identifier", + "eggs": [ + {"@type": "Egg", "use_until": datetime(2024, 4, 20, 16, 20).isoformat()}, + {"@type": "Egg", "use_until": datetime(2026, 12, 31, 23, 59, 59).isoformat()}, + ] + } + + @classmethod + def expanded(cls, base_url="http://spam.eggs/"): + return [{ + f"{base_url}spam": [{"@value": "bacon"}], + f"{base_url}ham": [{"@id": f"{base_url}identifier"}], + f"{base_url}eggs": [{"@list": [ + { + "@type": [f"{base_url}Egg"], + f"{base_url}use_until": [ + {"@type": "http://schema.org/DateTime", "@value": "2024-04-20T16:20:00"} + ], + }, + { + "@type": [f"{base_url}Egg"], + f"{base_url}use_until": [ + {"@type": "http://schema.org/DateTime", "@value": "2026-12-31T23:59:59"} + ], + } + ]}] + }] + + +@pytest.fixture +def mock_context(): + return MockDocument.vocabulary() + + +@pytest.fixture +def mock_document(): + return MockDocument From 2dfed2dfc5ccce3648707c5725cec37cb68ecc6e Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 21:10:59 +0200 Subject: [PATCH 12/32] Add documentation to helpers. --- test/hermes_test/model/types/conftest.py | 32 +++++++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/test/hermes_test/model/types/conftest.py b/test/hermes_test/model/types/conftest.py index aa61252b..3a5eb106 100644 --- a/test/hermes_test/model/types/conftest.py +++ b/test/hermes_test/model/types/conftest.py @@ -8,8 +8,18 @@ class MockDocument: + """ + Helper that provides valid JSON-LD data. + """ + @classmethod - def vocabulary(cls, base_url="http://spam.eggs/"): + def vocabulary(cls, base_url: str = "http://spam.eggs/") -> dict: + """ + Retrieve the vocabulary used for the document. + + :param base_url: Optional base URL to use for IRIs in the vocabulary. + :returns: A JSON-LD vocabulary usable in as document context. + """ return { "spam": {"@id": f"{base_url}spam"}, "ham": {"@id": f"{base_url}ham", "@type": "@id"}, @@ -20,9 +30,17 @@ def vocabulary(cls, base_url="http://spam.eggs/"): } @classmethod - def compact(cls, base_url="http://spam.eggs/"): + def compact(cls, base_url: str = "http://spam.eggs/", embed_vocabulary: bool = True) -> dict: + """ + Get compact representation of the example document. + + :param base_url: Optional base URL used to generate the context. + :param embed_vocabulary: Optional switch to indicate whether the vocabulary should be embedded in the context + or only refrenced by the base url. + :returns: The rendered compact document. + """ return { - "@context": cls.vocabulary(base_url), + "@context": [cls.vocabulary(base_url) if embed_vocabulary else base_url], "spam": "bacon", "ham": f"{base_url}identifier", @@ -33,7 +51,13 @@ def compact(cls, base_url="http://spam.eggs/"): } @classmethod - def expanded(cls, base_url="http://spam.eggs/"): + def expanded(cls, base_url: str = "http://spam.eggs/") -> list[dict]: + """ + Get expanded representation of the example document. + + :param base_url: Optional base URL to use for IRIs. + :returns: The rendered expanded document. + """ return [{ f"{base_url}spam": [{"@value": "bacon"}], f"{base_url}ham": [{"@id": f"{base_url}identifier"}], From a527fb0a201497e0e8dbdd238973fb7250016322 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 21:11:37 +0200 Subject: [PATCH 13/32] Add test for helpers. --- test/hermes_test/model/types/test_pyld_util.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 test/hermes_test/model/types/test_pyld_util.py diff --git a/test/hermes_test/model/types/test_pyld_util.py b/test/hermes_test/model/types/test_pyld_util.py new file mode 100644 index 00000000..b84afe35 --- /dev/null +++ b/test/hermes_test/model/types/test_pyld_util.py @@ -0,0 +1,18 @@ +import pytest + +from hermes.model.types import pyld_util + + +@pytest.fixture +def ld_proc(): + return pyld_util.JsonLdProcessor() + + +def test_mock_document_compact(ld_proc, mock_document): + compact_document = ld_proc.compact(mock_document.expanded(), [mock_document.vocabulary], {}) + assert compact_document == mock_document.compact() + + +def test_mock_document_compact(ld_proc, mock_document): + expanded_document = ld_proc.expand(mock_document.compact(), {}) + assert expanded_document == mock_document.expanded() From 2fbe1e055763d7ce4a7b0613e7d38f87ce24a178 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 21:12:16 +0200 Subject: [PATCH 14/32] Using mock_document for setup. --- test/hermes_test/model/types/test_ld_container.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index 73877bff..e398a337 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -22,14 +22,9 @@ class TestLdContainer: @classmethod @pytest.fixture(autouse=True) - def setup_class(cls, httpserver): - content = { - "@context": {"type": "@type", "id": "@id", "schema": "http://schema.org/", "ham": "https://fake.site/", - "Organization": {"@id": "schema:Organization"}}} - - cls.url = httpserver.url_for("/url") - - httpserver.expect_request("/url").respond_with_json(content) + def setup_class(cls, httpserver, mock_document): + cls.url = httpserver.url_for("/") + httpserver.expect_request("/").respond_with_json({"@context": mock_document.vocabulary(cls.url)}) def test_container_basic(self): cont = ld_container([{"spam": [{"@value": "bacon"}]}]) From e362b15bf358893673d092657911c93e0271436d Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 21:13:50 +0200 Subject: [PATCH 15/32] Remove test for pyld internals. cont.active_ctx is very special with regards to the implementation of a dependency. This is ugly and tests will be added to test_pyld_utils. --- test/hermes_test/model/types/test_ld_container.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index e398a337..c3e08168 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -33,7 +33,6 @@ def test_container_basic(self): assert cont.context == [] assert cont._data == [{"spam": [{"@value": "bacon"}]}] assert cont.path == ["$"] - assert cont.active_ctx == {'mappings': {}} def test_container_ld_value(self): cont = ld_container([{"spam": [{"@value": "bacon"}]}]) @@ -41,7 +40,6 @@ def test_container_ld_value(self): assert cont.ld_value == [{"spam": [{"@value": "bacon"}]}] def test_container_add_context(self): - cont = ld_container([{"spam": [{"@value": "bacon"}]}]) cont.add_context([self.url]) From 8b2e59f054c41c467a658f86032348eb4e31a709 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 21:15:09 +0200 Subject: [PATCH 16/32] Switch test to use mock_context from helpers. --- .../model/types/test_ld_container.py | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index c3e08168..429c0f50 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -1,11 +1,10 @@ # SPDX-FileCopyrightText: 2025 German Aerospace Center (DLR) # # SPDX-License-Identifier: Apache-2.0 -import re # SPDX-FileContributor: Sophie Kernchen -import pytest, uuid +import pytest from hermes.model.types.ld_container import ld_container '''we expect user of this class to give the right input data types @@ -83,21 +82,17 @@ def test_container_str_and_repr(self): with pytest.raises(NotImplementedError): str(cont) - def test_to_python(self): - cont = ld_container([{"spam": [{"@value": "bacon", "@id": "ham", "@type": ["@id"]}]}]) - assert cont._to_python("spam", [{"@value": "bacon"}]) == 'bacon' - assert cont._to_python("@id", "ham") == "ham" + def test_to_python(self, mock_context): + # Create container with mock context + cont = ld_container([{}], context=[mock_context]) - cont.active_ctx['_uuid'] = str(uuid.uuid1()) # FIXME: 406 + # Try simple cases of conversion + assert cont._to_python("@id", "ham") == "ham" assert cont._to_python("@type", ["@id"]) == '@id' - def test_to_expanded(self): - # Define a mock vocabulary to work with - mock_context = { - "ham": {"@id": "http://ham.eggs/ham", "@type": "@id"}, - "spam": {"@id": "http://ham.eggs/spam"}, - "Eggs": {"@id": "http://ham.eggs/Eggs"}, - } + def test_to_python_list(self, mock_context): + cont = ld_container([{}], context=[mock_context]) + list_data = [{"@list": [{"@id": "spam"}, {"@id": "eggs"}]}] # Create container with mock context cont = ld_container([{}], context=[mock_context]) From 4b8c3b754d4d4f2ebb94d5d1c85b320ee2f07881 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 21:16:24 +0200 Subject: [PATCH 17/32] Added more tests. The conversion tests (`_to_python` and `_to_expanded_json`) are pretty long now... --- .../model/types/test_ld_container.py | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index 429c0f50..df730bb2 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -89,15 +89,40 @@ def test_to_python(self, mock_context): # Try simple cases of conversion assert cont._to_python("@id", "ham") == "ham" assert cont._to_python("@type", ["@id"]) == '@id' + assert cont._to_python("@type", ["@id", "http://spam.eggs/Egg"]) == ["@id", "Egg"] + + # Try type conversions + assert cont._to_python("http://spam.eggs/ham", [{"@id": "spam"}]) == 'spam' + + assert cont._to_python("http://soam.eggs/spam", [{"@value": "bacon"}]) == 'bacon' + assert cont._to_python("http://spam.eggs/spam", [{"@value": True}]) == True + assert cont._to_python("http://spam.eggs/spam", [{"@value": 123}]) == 123 + + assert cont._to_python("http://spam.eggs/eggs", [{ + "@value": "2022-02-22T00:00:00", "@type": "https://schema.org/DateTime" + }]) == "2022-02-22T00:00:00" def test_to_python_list(self, mock_context): cont = ld_container([{}], context=[mock_context]) list_data = [{"@list": [{"@id": "spam"}, {"@id": "eggs"}]}] + assert cont._to_python("ham", list_data).to_python() == ["spam", "eggs"] + + def test_to_expanded(self, mock_context): # Create container with mock context cont = ld_container([{}], context=[mock_context]) # Try simple cases of expansion + assert cont._to_expanded_json("@id", "ham") == "ham" + assert cont._to_expanded_json("@type", "Egg") == ["http://spam.eggs/Egg"] + + # Type conversions + assert cont._to_expanded_json("ham", "spam") == [{"@id": "spam"}] + assert cont._to_expanded_json("spam", "bacon") == [{"@value": "bacon"}] - assert cont._to_expanded_json("@id", "ham") == "http://ham.eggs/ham" - assert cont._to_expanded_json("@type", "@id") == ["@id"] + assert cont._to_expanded_json("spam", 123) == [{"@value": 123}] + assert cont._to_expanded_json("spam", True) == [{"@value": True}] + + assert cont._to_expanded_json("eggs", datetime(2022, 2,22)) == [ + {"@value": "2022-02-22T00:00:00", "@type": "http://schema.org/DateTime"} + ] From 3bceb496878cf9a79b18f11444b39d3b3ce9ca08 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 22:04:46 +0200 Subject: [PATCH 18/32] Restructured tests for ld_container (type conversions). --- .../model/types/test_ld_container.py | 53 ++++++++++++++----- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index df730bb2..873a7d65 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -3,8 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileContributor: Sophie Kernchen +# SPDX-FileContributor: Michael Meinel + +from datetime import datetime import pytest + from hermes.model.types.ld_container import ld_container '''we expect user of this class to give the right input data types @@ -82,47 +86,68 @@ def test_container_str_and_repr(self): with pytest.raises(NotImplementedError): str(cont) - def test_to_python(self, mock_context): - # Create container with mock context + def test_to_python_id(self, mock_context): cont = ld_container([{}], context=[mock_context]) + assert cont._to_python("@id", "http://spam.eggs/ham") == "http://spam.eggs/ham" - # Try simple cases of conversion - assert cont._to_python("@id", "ham") == "ham" + def test_to_python_id_with_prefix(self, mock_context): + cont = ld_container([{}], context=[mock_context, {"prefix": self.url}]) + assert cont._to_python("@id", f"{self.url}identifier") == "prefix:identifier" + + def test_to_python_type(self, mock_context): + cont = ld_container([{}], context=[mock_context]) assert cont._to_python("@type", ["@id"]) == '@id' assert cont._to_python("@type", ["@id", "http://spam.eggs/Egg"]) == ["@id", "Egg"] - # Try type conversions - assert cont._to_python("http://spam.eggs/ham", [{"@id": "spam"}]) == 'spam' + def test_to_python_id_value(self, mock_context): + cont = ld_container([{}], context=[mock_context]) + assert cont._to_python("http://spam.eggs/ham", [{"@id": "http://spam.eggs/spam"}]) == "http://spam.eggs/spam" + assert cont._to_python("http://spam.eggs/ham", [{"@id": "http://spam.eggs/identifier"}]) == "http://spam.eggs/identifier" + def test_to_python_basic_value(self, mock_context): + cont = ld_container([{}], context=[mock_context]) assert cont._to_python("http://soam.eggs/spam", [{"@value": "bacon"}]) == 'bacon' assert cont._to_python("http://spam.eggs/spam", [{"@value": True}]) == True assert cont._to_python("http://spam.eggs/spam", [{"@value": 123}]) == 123 + def test_to_python_datetime_value(self, mock_context): + cont = ld_container([{}], context=[mock_context]) assert cont._to_python("http://spam.eggs/eggs", [{ "@value": "2022-02-22T00:00:00", "@type": "https://schema.org/DateTime" }]) == "2022-02-22T00:00:00" - def test_to_python_list(self, mock_context): + def test_to_expanded_id(self, mock_context): cont = ld_container([{}], context=[mock_context]) - list_data = [{"@list": [{"@id": "spam"}, {"@id": "eggs"}]}] + assert cont._to_expanded_json("@id", f"{self.url}identifier") == f"{self.url}identifier" - assert cont._to_python("ham", list_data).to_python() == ["spam", "eggs"] + # Regression test: "ham" is vocabulary and must not be expanded. + assert cont._to_expanded_json("@id", "ham") == "ham" - def test_to_expanded(self, mock_context): - # Create container with mock context - cont = ld_container([{}], context=[mock_context]) + def test_to_expanded_id_with_prefix(self, mock_context): + cont = ld_container([{}], context=[mock_context, {"prefix": self.url}]) + assert cont._to_expanded_json("@id", "prefix:identifier") == f"{self.url}identifier" - # Try simple cases of expansion + # Regression test: "ham" should still not be expaned, but "prefix:ham" should be. assert cont._to_expanded_json("@id", "ham") == "ham" + assert cont._to_expanded_json("@id", "prefix:ham") == f"{self.url}ham" + + def test_to_expanded_type(self, mock_context): + cont = ld_container([{}], context=[mock_context]) assert cont._to_expanded_json("@type", "Egg") == ["http://spam.eggs/Egg"] + assert cont._to_expanded_json("@type", ["Egg", "@id"]) == ["http://spam.eggs/Egg", "@id"] - # Type conversions + def test_to_expanded_id_value(self, mock_context): + cont = ld_container([{}], context=[mock_context]) assert cont._to_expanded_json("ham", "spam") == [{"@id": "spam"}] + def test_to_expanded_basic_value(self, mock_context): + cont = ld_container([{}], context=[mock_context]) assert cont._to_expanded_json("spam", "bacon") == [{"@value": "bacon"}] assert cont._to_expanded_json("spam", 123) == [{"@value": 123}] assert cont._to_expanded_json("spam", True) == [{"@value": True}] + def test_to_expanded_datetime_value(self, mock_context): + cont = ld_container([{}], context=[mock_context]) assert cont._to_expanded_json("eggs", datetime(2022, 2,22)) == [ {"@value": "2022-02-22T00:00:00", "@type": "http://schema.org/DateTime"} ] From ef2eb70f879fd4b49c730b3f2d48cd3b5788d07a Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 22:08:49 +0200 Subject: [PATCH 19/32] Update poetry lock to get CI running. --- poetry.lock | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index f7104e16..bb7d9074 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. [[package]] name = "accessible-pygments" @@ -906,7 +906,7 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["docs"] +groups = ["dev", "docs"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -1553,6 +1553,21 @@ pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +[[package]] +name = "pytest-httpserver" +version = "1.1.3" +description = "pytest-httpserver is a httpserver for pytest" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest_httpserver-1.1.3-py3-none-any.whl", hash = "sha256:5f84757810233e19e2bb5287f3826a71c97a3740abe3a363af9155c0f82fdbb9"}, + {file = "pytest_httpserver-1.1.3.tar.gz", hash = "sha256:af819d6b533f84b4680b9416a5b3f67f1df3701f1da54924afd4d6e4ba5917ec"}, +] + +[package.dependencies] +Werkzeug = ">=2.0.0" + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -2418,6 +2433,24 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "werkzeug" +version = "3.1.3" +description = "The comprehensive WSGI web application library." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"}, + {file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"}, +] + +[package.dependencies] +MarkupSafe = ">=2.1.1" + +[package.extras] +watchdog = ["watchdog (>=2.3)"] + [[package]] name = "wheel" version = "0.45.1" @@ -2525,4 +2558,4 @@ files = [ [metadata] lock-version = "2.1" python-versions = "^3.10" -content-hash = "b6eb72a05b4bb10207b3618310c1fc9709e4a2cbd051caf6d9892f2eea299c16" +content-hash = "51553ed03b09cf6bb243a9dcb581826e74fbf8e4f27d582dbdd948671386b2c9" From af21aced986ff87d9334c3d3c37ac4fbe1f98159 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 22:13:42 +0200 Subject: [PATCH 20/32] Fix linting errors. --- test/hermes_test/model/types/__init__.py | 2 +- test/hermes_test/model/types/test_ld_container.py | 10 ++++++---- test/hermes_test/model/types/test_pyld_util.py | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/test/hermes_test/model/types/__init__.py b/test/hermes_test/model/types/__init__.py index 9a1d6097..ef943d95 100644 --- a/test/hermes_test/model/types/__init__.py +++ b/test/hermes_test/model/types/__init__.py @@ -2,4 +2,4 @@ # # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileContributor: Sophie Kernchen \ No newline at end of file +# SPDX-FileContributor: Sophie Kernchen diff --git a/test/hermes_test/model/types/test_ld_container.py b/test/hermes_test/model/types/test_ld_container.py index 873a7d65..9da5b461 100644 --- a/test/hermes_test/model/types/test_ld_container.py +++ b/test/hermes_test/model/types/test_ld_container.py @@ -101,13 +101,15 @@ def test_to_python_type(self, mock_context): def test_to_python_id_value(self, mock_context): cont = ld_container([{}], context=[mock_context]) - assert cont._to_python("http://spam.eggs/ham", [{"@id": "http://spam.eggs/spam"}]) == "http://spam.eggs/spam" - assert cont._to_python("http://spam.eggs/ham", [{"@id": "http://spam.eggs/identifier"}]) == "http://spam.eggs/identifier" + assert cont._to_python("http://spam.eggs/ham", + [{"@id": "http://spam.eggs/spam"}]) == "http://spam.eggs/spam" + assert cont._to_python("http://spam.eggs/ham", + [{"@id": "http://spam.eggs/identifier"}]) == "http://spam.eggs/identifier" def test_to_python_basic_value(self, mock_context): cont = ld_container([{}], context=[mock_context]) assert cont._to_python("http://soam.eggs/spam", [{"@value": "bacon"}]) == 'bacon' - assert cont._to_python("http://spam.eggs/spam", [{"@value": True}]) == True + assert cont._to_python("http://spam.eggs/spam", [{"@value": True}]) is True assert cont._to_python("http://spam.eggs/spam", [{"@value": 123}]) == 123 def test_to_python_datetime_value(self, mock_context): @@ -148,6 +150,6 @@ def test_to_expanded_basic_value(self, mock_context): def test_to_expanded_datetime_value(self, mock_context): cont = ld_container([{}], context=[mock_context]) - assert cont._to_expanded_json("eggs", datetime(2022, 2,22)) == [ + assert cont._to_expanded_json("eggs", datetime(2022, 2, 22)) == [ {"@value": "2022-02-22T00:00:00", "@type": "http://schema.org/DateTime"} ] diff --git a/test/hermes_test/model/types/test_pyld_util.py b/test/hermes_test/model/types/test_pyld_util.py index b84afe35..00f008c4 100644 --- a/test/hermes_test/model/types/test_pyld_util.py +++ b/test/hermes_test/model/types/test_pyld_util.py @@ -13,6 +13,6 @@ def test_mock_document_compact(ld_proc, mock_document): assert compact_document == mock_document.compact() -def test_mock_document_compact(ld_proc, mock_document): +def test_mock_document_expanded(ld_proc, mock_document): expanded_document = ld_proc.expand(mock_document.compact(), {}) assert expanded_document == mock_document.expanded() From 8b4f9a33777de45931dcece39edf5406c86864f4 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 22:28:03 +0200 Subject: [PATCH 21/32] Delete tests for old data model. --- test/hermes_test/model/test_base_context.py | 38 ----- .../model/test_codemeta_context.py | 71 ---------- .../hermes_test/model/test_harvest_context.py | 134 ------------------ 3 files changed, 243 deletions(-) delete mode 100644 test/hermes_test/model/test_base_context.py delete mode 100644 test/hermes_test/model/test_codemeta_context.py delete mode 100644 test/hermes_test/model/test_harvest_context.py diff --git a/test/hermes_test/model/test_base_context.py b/test/hermes_test/model/test_base_context.py deleted file mode 100644 index bdf016b7..00000000 --- a/test/hermes_test/model/test_base_context.py +++ /dev/null @@ -1,38 +0,0 @@ -# SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR) -# -# SPDX-License-Identifier: Apache-2.0 - -# SPDX-FileContributor: Michael Meinel - -from pathlib import Path - -from hermes.model.context import HermesContext - - -def test_context_hermes_dir_default(): - ctx = HermesContext() - assert ctx.hermes_dir == Path('.') / '.hermes' - - -def test_context_hermes_dir_custom(): - ctx = HermesContext('spam') - assert ctx.hermes_dir == Path('spam') / '.hermes' - - -def test_context_get_cache_default(): - ctx = HermesContext() - assert ctx.get_cache('spam', 'eggs') == Path('.') / '.hermes' / 'spam' / 'eggs.json' - - -def test_context_get_cache_cached(): - ctx = HermesContext() - ctx._caches[('spam', 'eggs')] = Path('spam_and_eggs') - assert ctx.get_cache('spam', 'eggs') == Path('spam_and_eggs') - - -def test_context_get_cache_create(tmpdir): - ctx = HermesContext(tmpdir) - subdir = Path(tmpdir) / '.hermes' / 'spam' - - assert ctx.get_cache('spam', 'eggs', create=True) == subdir / 'eggs.json' - assert subdir.exists() diff --git a/test/hermes_test/model/test_codemeta_context.py b/test/hermes_test/model/test_codemeta_context.py deleted file mode 100644 index b9a5ec3e..00000000 --- a/test/hermes_test/model/test_codemeta_context.py +++ /dev/null @@ -1,71 +0,0 @@ -# SPDX-FileCopyrightText: 2023 German Aerospace Center (DLR) -# -# SPDX-License-Identifier: Apache-2.0 - -# SPDX-FileContributor: Stephan Druskat - -import pytest -from unittest.mock import Mock - -from hermes.model.context import CodeMetaContext, HermesHarvestContext - - -@pytest.fixture -def mock_ep(): - ep = Mock() - ep.name = 'mock_name' - return ep - - -@pytest.fixture -def _context(): - return 'foo', 'bar' - - -@pytest.fixture -def _codemeta_context(): - return CodeMetaContext() - - -@pytest.fixture -def _data(_codemeta_context): - return { - '@context': [ - 'https://doi.org/10.5063/schema/codemeta-2.0', - {'hermes': 'https://software-metadata.pub/ns/hermes/'}], - '@type': 'SoftwareSourceCode' - } - - -@pytest.fixture -def _data_with_contexts(_codemeta_context): - return { - '@type': 'SoftwareSourceCode', - '@context': [ - 'https://doi.org/10.5063/schema/codemeta-2.0', - {'foo': 'bar', - 'hermes': 'https://software-metadata.pub/ns/hermes/'} - ] - } - - -def test_merge_contexts_from(mock_ep, _context, _codemeta_context): - assert _codemeta_context.contexts == {_codemeta_context.hermes_lod_context} - other = HermesHarvestContext(None, mock_ep) - other.contexts.add(_context) - _codemeta_context.merge_contexts_from(other) - assert _codemeta_context.contexts == {_context, _codemeta_context.hermes_lod_context} - - -def test_prepare_codemeta(_codemeta_context, _context, _data): - assert not _codemeta_context.keys() - _codemeta_context.prepare_codemeta() - assert _codemeta_context.get_data() == _data - - -def test_prepare_codemeta_with_contexts(_codemeta_context, _context, _data_with_contexts): - assert not _codemeta_context.keys() - assert _codemeta_context.contexts == {_codemeta_context.hermes_lod_context} - _codemeta_context.add_context(_context) - _codemeta_context.prepare_codemeta() - assert _codemeta_context.get_data() == _data_with_contexts diff --git a/test/hermes_test/model/test_harvest_context.py b/test/hermes_test/model/test_harvest_context.py deleted file mode 100644 index afb1ff70..00000000 --- a/test/hermes_test/model/test_harvest_context.py +++ /dev/null @@ -1,134 +0,0 @@ -# SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR) -# -# SPDX-License-Identifier: Apache-2.0 - -# SPDX-FileContributor: Michael Meinel - -import pytest - -from hermes.model.context import HermesContext, HermesHarvestContext - - -@pytest.fixture -def harvest_ctx(request: pytest.FixtureRequest): - ctx = HermesContext() - return HermesHarvestContext(ctx, request.function.__name__) - - -def test_context_default(harvest_ctx): - harvest_ctx.update('spam', 'eggs', test=True) - - assert harvest_ctx._data['spam'] == [ - ['eggs', {'test': True, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_default'}] - ] - - -def test_context_update_append(harvest_ctx): - harvest_ctx.update('spam', 'noodles', index=0) - harvest_ctx.update('spam', 'eggs', index=1) - - assert harvest_ctx._data['spam'] == [ - ['noodles', {'index': 0, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_update_append'}], - ['eggs', {'index': 1, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_update_append'}] - ] - - -def test_context_update_replace(harvest_ctx): - harvest_ctx.update('spam', 'noodles', test=True) - harvest_ctx.update('spam', 'eggs', test=True) - - assert harvest_ctx._data['spam'] == [ - ['eggs', {'test': True, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_update_replace'}] - ] - - -def test_context_bulk_flat(harvest_ctx): - harvest_ctx.update_from({ - 'ans': 42, - 'spam': 'eggs' - }, test=True) - - assert harvest_ctx._data['ans'] == [ - [42, {'test': True, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_flat'}] - ] - assert harvest_ctx._data['spam'] == [ - ['eggs', {'test': True, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_flat'}] - ] - - -def test_context_bulk_complex(harvest_ctx): - harvest_ctx.update_from({ - 'ans': 42, - 'author': [ - {'name': 'Monty Python', 'email': 'eggs@spam.io'}, - {'name': 'Herr Mes'}, - ] - }, test=True) - - assert harvest_ctx._data['ans'] == [ - [42, {'test': True, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_complex'}] - ] - assert harvest_ctx._data['author[0].name'] == [ - ['Monty Python', {'test': True, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_complex'}] - ] - assert harvest_ctx._data['author[0].email'] == [ - ['eggs@spam.io', {'test': True, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_complex'}] - ] - assert harvest_ctx._data['author[1].name'] == [ - ['Herr Mes', {'test': True, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_complex'}] - ] - - -def test_context_bulk_replace(harvest_ctx): - harvest_ctx.update('author[0].name', 'Monty Python', test=True) - harvest_ctx.update_from({'author': [{'name': 'Herr Mes', 'email': 'eggs@spam.io'}]}, test=True) - - assert harvest_ctx._data['author[0].name'] == [ - ['Herr Mes', {'test': True, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_replace'}] - ] - assert harvest_ctx._data['author[0].email'] == [ - ['eggs@spam.io', {'test': True, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_replace'}] - ] - - -def test_context_bulk_append(harvest_ctx): - harvest_ctx.update('author[0].name', 'Monty Python', index=0) - harvest_ctx.update_from({'author': [{'name': 'Herr Mes', 'email': 'eggs@spam.io'}]}, index=1) - - assert harvest_ctx._data['author[0].name'] == [ - ['Monty Python', {'index': 0, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_append'}], - ['Herr Mes', {'index': 1, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_append'}] - ] - assert harvest_ctx._data['author[0].email'] == [ - ['eggs@spam.io', {'index': 1, - 'timestamp': HermesContext.default_timestamp, - 'harvester': 'test_context_bulk_append'}] - ] From d825217f8bd65d02ca218b14caa13d189aae6ee8 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 22:28:41 +0200 Subject: [PATCH 22/32] Disable tests that fail due to missing old data model. --- test/hermes_test/commands/deposit/test_invenio.py | 2 ++ test/hermes_test/commands/init/test_init.py | 3 +++ test/hermes_test/test_cli.py | 2 ++ test/hermes_test/test_main.py | 4 ++++ test/hermes_test/test_marketplace.py | 4 ++++ 5 files changed, 15 insertions(+) diff --git a/test/hermes_test/commands/deposit/test_invenio.py b/test/hermes_test/commands/deposit/test_invenio.py index 38c64d1d..01190d53 100644 --- a/test/hermes_test/commands/deposit/test_invenio.py +++ b/test/hermes_test/commands/deposit/test_invenio.py @@ -10,6 +10,8 @@ import click import pytest +pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) + from hermes.commands.deposit import invenio from hermes.error import MisconfigurationError diff --git a/test/hermes_test/commands/init/test_init.py b/test/hermes_test/commands/init/test_init.py index c32138f3..4fe03c76 100644 --- a/test/hermes_test/commands/init/test_init.py +++ b/test/hermes_test/commands/init/test_init.py @@ -4,6 +4,9 @@ import json import pytest + +pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) + from hermes.commands.init.base import string_in_file, download_file_from_url from unittest.mock import patch, MagicMock import hermes.commands.init.util.oauth_process as oauth_process diff --git a/test/hermes_test/test_cli.py b/test/hermes_test/test_cli.py index 85b40e5e..ac831792 100644 --- a/test/hermes_test/test_cli.py +++ b/test/hermes_test/test_cli.py @@ -6,6 +6,8 @@ import pytest +pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) + from hermes.commands import cli diff --git a/test/hermes_test/test_main.py b/test/hermes_test/test_main.py index 64d6abc0..19dbf365 100644 --- a/test/hermes_test/test_main.py +++ b/test/hermes_test/test_main.py @@ -4,6 +4,10 @@ # SPDX-FileContributor: Michael Meinel +import pytest + +pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) + import subprocess import sys diff --git a/test/hermes_test/test_marketplace.py b/test/hermes_test/test_marketplace.py index 9fe31045..50dc1350 100644 --- a/test/hermes_test/test_marketplace.py +++ b/test/hermes_test/test_marketplace.py @@ -2,6 +2,10 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileContributor: David Pape +import pytest + +pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) + import requests_mock from hermes.commands.marketplace import ( From d9761ab6df61bfa15d76f024eee5e90c30241f17 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 22:29:09 +0200 Subject: [PATCH 23/32] Fix test for mock document. --- test/hermes_test/model/types/test_pyld_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hermes_test/model/types/test_pyld_util.py b/test/hermes_test/model/types/test_pyld_util.py index 00f008c4..fa4e539d 100644 --- a/test/hermes_test/model/types/test_pyld_util.py +++ b/test/hermes_test/model/types/test_pyld_util.py @@ -9,7 +9,7 @@ def ld_proc(): def test_mock_document_compact(ld_proc, mock_document): - compact_document = ld_proc.compact(mock_document.expanded(), [mock_document.vocabulary], {}) + compact_document = ld_proc.compact(mock_document.expanded(), [mock_document.vocabulary()], {}) assert compact_document == mock_document.compact() From 9113c7bbd869c104b47e6c01280c893076544355 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 22:29:25 +0200 Subject: [PATCH 24/32] Fix mock document. --- test/hermes_test/model/types/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hermes_test/model/types/conftest.py b/test/hermes_test/model/types/conftest.py index 3a5eb106..8a1c7c2e 100644 --- a/test/hermes_test/model/types/conftest.py +++ b/test/hermes_test/model/types/conftest.py @@ -40,7 +40,7 @@ def compact(cls, base_url: str = "http://spam.eggs/", embed_vocabulary: bool = T :returns: The rendered compact document. """ return { - "@context": [cls.vocabulary(base_url) if embed_vocabulary else base_url], + "@context": cls.vocabulary(base_url) if embed_vocabulary else base_url, "spam": "bacon", "ham": f"{base_url}identifier", From df5b0efa73c1f6a439db1f058463e93558997683 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 22:37:36 +0200 Subject: [PATCH 25/32] Silence flake8 on inactive tests. --- test/hermes_test/commands/deposit/test_invenio.py | 1 + test/hermes_test/commands/init/test_init.py | 1 + test/hermes_test/test_cli.py | 1 + test/hermes_test/test_main.py | 1 + test/hermes_test/test_marketplace.py | 1 + 5 files changed, 5 insertions(+) diff --git a/test/hermes_test/commands/deposit/test_invenio.py b/test/hermes_test/commands/deposit/test_invenio.py index 01190d53..969d3496 100644 --- a/test/hermes_test/commands/deposit/test_invenio.py +++ b/test/hermes_test/commands/deposit/test_invenio.py @@ -12,6 +12,7 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) +# noqa: E402 from hermes.commands.deposit import invenio from hermes.error import MisconfigurationError diff --git a/test/hermes_test/commands/init/test_init.py b/test/hermes_test/commands/init/test_init.py index 4fe03c76..791b0baf 100644 --- a/test/hermes_test/commands/init/test_init.py +++ b/test/hermes_test/commands/init/test_init.py @@ -7,6 +7,7 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) +# noqa: E402 from hermes.commands.init.base import string_in_file, download_file_from_url from unittest.mock import patch, MagicMock import hermes.commands.init.util.oauth_process as oauth_process diff --git a/test/hermes_test/test_cli.py b/test/hermes_test/test_cli.py index ac831792..dbc366e8 100644 --- a/test/hermes_test/test_cli.py +++ b/test/hermes_test/test_cli.py @@ -8,6 +8,7 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) +# noqa: E402 from hermes.commands import cli diff --git a/test/hermes_test/test_main.py b/test/hermes_test/test_main.py index 19dbf365..3314307c 100644 --- a/test/hermes_test/test_main.py +++ b/test/hermes_test/test_main.py @@ -8,6 +8,7 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) +# noqa: E402 import subprocess import sys diff --git a/test/hermes_test/test_marketplace.py b/test/hermes_test/test_marketplace.py index 50dc1350..f76284cc 100644 --- a/test/hermes_test/test_marketplace.py +++ b/test/hermes_test/test_marketplace.py @@ -6,6 +6,7 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) +# noqa: E402 import requests_mock from hermes.commands.marketplace import ( From 4fe4ffb5ccf4cbba58947de5efed970a2b81d0e6 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 22:39:52 +0200 Subject: [PATCH 26/32] Silence flake8 on inactive tests more agressively. --- test/hermes_test/commands/deposit/test_invenio.py | 3 ++- test/hermes_test/commands/init/test_init.py | 3 ++- test/hermes_test/test_cli.py | 3 ++- test/hermes_test/test_main.py | 3 ++- test/hermes_test/test_marketplace.py | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/test/hermes_test/commands/deposit/test_invenio.py b/test/hermes_test/commands/deposit/test_invenio.py index 969d3496..0ade0b82 100644 --- a/test/hermes_test/commands/deposit/test_invenio.py +++ b/test/hermes_test/commands/deposit/test_invenio.py @@ -5,6 +5,8 @@ # SPDX-FileContributor: Michael Meinel # SPDX-FileContributor: David Pape +# flake8: noqa + from unittest import mock import click @@ -12,7 +14,6 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) -# noqa: E402 from hermes.commands.deposit import invenio from hermes.error import MisconfigurationError diff --git a/test/hermes_test/commands/init/test_init.py b/test/hermes_test/commands/init/test_init.py index 791b0baf..98653dda 100644 --- a/test/hermes_test/commands/init/test_init.py +++ b/test/hermes_test/commands/init/test_init.py @@ -2,12 +2,13 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileContributor: Nitai Heeb +# flake8: noqa + import json import pytest pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) -# noqa: E402 from hermes.commands.init.base import string_in_file, download_file_from_url from unittest.mock import patch, MagicMock import hermes.commands.init.util.oauth_process as oauth_process diff --git a/test/hermes_test/test_cli.py b/test/hermes_test/test_cli.py index dbc366e8..26d8c7ef 100644 --- a/test/hermes_test/test_cli.py +++ b/test/hermes_test/test_cli.py @@ -4,11 +4,12 @@ # SPDX-FileContributor: Michael Meinel +# flake8: noqa + import pytest pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) -# noqa: E402 from hermes.commands import cli diff --git a/test/hermes_test/test_main.py b/test/hermes_test/test_main.py index 3314307c..74023020 100644 --- a/test/hermes_test/test_main.py +++ b/test/hermes_test/test_main.py @@ -4,11 +4,12 @@ # SPDX-FileContributor: Michael Meinel +# flake8: noqa + import pytest pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) -# noqa: E402 import subprocess import sys diff --git a/test/hermes_test/test_marketplace.py b/test/hermes_test/test_marketplace.py index f76284cc..ec76f240 100644 --- a/test/hermes_test/test_marketplace.py +++ b/test/hermes_test/test_marketplace.py @@ -2,11 +2,12 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileContributor: David Pape +# flake8: noqa + import pytest pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) -# noqa: E402 import requests_mock from hermes.commands.marketplace import ( From d577aaba8c0b5bb91f83481f23f868d2c990a7bd Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 23:08:34 +0200 Subject: [PATCH 27/32] Revert "Silence flake8 on inactive tests more agressively." This reverts commit 4fe4ffb5ccf4cbba58947de5efed970a2b81d0e6. --- test/hermes_test/commands/deposit/test_invenio.py | 3 +-- test/hermes_test/commands/init/test_init.py | 3 +-- test/hermes_test/test_cli.py | 3 +-- test/hermes_test/test_main.py | 3 +-- test/hermes_test/test_marketplace.py | 3 +-- 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/test/hermes_test/commands/deposit/test_invenio.py b/test/hermes_test/commands/deposit/test_invenio.py index 0ade0b82..969d3496 100644 --- a/test/hermes_test/commands/deposit/test_invenio.py +++ b/test/hermes_test/commands/deposit/test_invenio.py @@ -5,8 +5,6 @@ # SPDX-FileContributor: Michael Meinel # SPDX-FileContributor: David Pape -# flake8: noqa - from unittest import mock import click @@ -14,6 +12,7 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) +# noqa: E402 from hermes.commands.deposit import invenio from hermes.error import MisconfigurationError diff --git a/test/hermes_test/commands/init/test_init.py b/test/hermes_test/commands/init/test_init.py index 98653dda..791b0baf 100644 --- a/test/hermes_test/commands/init/test_init.py +++ b/test/hermes_test/commands/init/test_init.py @@ -2,13 +2,12 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileContributor: Nitai Heeb -# flake8: noqa - import json import pytest pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) +# noqa: E402 from hermes.commands.init.base import string_in_file, download_file_from_url from unittest.mock import patch, MagicMock import hermes.commands.init.util.oauth_process as oauth_process diff --git a/test/hermes_test/test_cli.py b/test/hermes_test/test_cli.py index 26d8c7ef..dbc366e8 100644 --- a/test/hermes_test/test_cli.py +++ b/test/hermes_test/test_cli.py @@ -4,12 +4,11 @@ # SPDX-FileContributor: Michael Meinel -# flake8: noqa - import pytest pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) +# noqa: E402 from hermes.commands import cli diff --git a/test/hermes_test/test_main.py b/test/hermes_test/test_main.py index 74023020..3314307c 100644 --- a/test/hermes_test/test_main.py +++ b/test/hermes_test/test_main.py @@ -4,12 +4,11 @@ # SPDX-FileContributor: Michael Meinel -# flake8: noqa - import pytest pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) +# noqa: E402 import subprocess import sys diff --git a/test/hermes_test/test_marketplace.py b/test/hermes_test/test_marketplace.py index ec76f240..f76284cc 100644 --- a/test/hermes_test/test_marketplace.py +++ b/test/hermes_test/test_marketplace.py @@ -2,12 +2,11 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileContributor: David Pape -# flake8: noqa - import pytest pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) +# noqa: E402 import requests_mock from hermes.commands.marketplace import ( From b432ccfe2f6be5c6d10e8ab69ab43b254733499e Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 23:08:34 +0200 Subject: [PATCH 28/32] Revert "Silence flake8 on inactive tests." This reverts commit df5b0efa73c1f6a439db1f058463e93558997683. --- test/hermes_test/commands/deposit/test_invenio.py | 1 - test/hermes_test/commands/init/test_init.py | 1 - test/hermes_test/test_cli.py | 1 - test/hermes_test/test_main.py | 1 - test/hermes_test/test_marketplace.py | 1 - 5 files changed, 5 deletions(-) diff --git a/test/hermes_test/commands/deposit/test_invenio.py b/test/hermes_test/commands/deposit/test_invenio.py index 969d3496..01190d53 100644 --- a/test/hermes_test/commands/deposit/test_invenio.py +++ b/test/hermes_test/commands/deposit/test_invenio.py @@ -12,7 +12,6 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) -# noqa: E402 from hermes.commands.deposit import invenio from hermes.error import MisconfigurationError diff --git a/test/hermes_test/commands/init/test_init.py b/test/hermes_test/commands/init/test_init.py index 791b0baf..4fe03c76 100644 --- a/test/hermes_test/commands/init/test_init.py +++ b/test/hermes_test/commands/init/test_init.py @@ -7,7 +7,6 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) -# noqa: E402 from hermes.commands.init.base import string_in_file, download_file_from_url from unittest.mock import patch, MagicMock import hermes.commands.init.util.oauth_process as oauth_process diff --git a/test/hermes_test/test_cli.py b/test/hermes_test/test_cli.py index dbc366e8..ac831792 100644 --- a/test/hermes_test/test_cli.py +++ b/test/hermes_test/test_cli.py @@ -8,7 +8,6 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) -# noqa: E402 from hermes.commands import cli diff --git a/test/hermes_test/test_main.py b/test/hermes_test/test_main.py index 3314307c..19dbf365 100644 --- a/test/hermes_test/test_main.py +++ b/test/hermes_test/test_main.py @@ -8,7 +8,6 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) -# noqa: E402 import subprocess import sys diff --git a/test/hermes_test/test_marketplace.py b/test/hermes_test/test_marketplace.py index f76284cc..50dc1350 100644 --- a/test/hermes_test/test_marketplace.py +++ b/test/hermes_test/test_marketplace.py @@ -6,7 +6,6 @@ pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) -# noqa: E402 import requests_mock from hermes.commands.marketplace import ( From 6a101290416e562a36fd5be371459d18d45bfe25 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 23:08:35 +0200 Subject: [PATCH 29/32] Revert "Disable tests that fail due to missing old data model." This reverts commit d825217f8bd65d02ca218b14caa13d189aae6ee8. --- test/hermes_test/commands/deposit/test_invenio.py | 2 -- test/hermes_test/commands/init/test_init.py | 3 --- test/hermes_test/test_cli.py | 2 -- test/hermes_test/test_main.py | 4 ---- test/hermes_test/test_marketplace.py | 4 ---- 5 files changed, 15 deletions(-) diff --git a/test/hermes_test/commands/deposit/test_invenio.py b/test/hermes_test/commands/deposit/test_invenio.py index 01190d53..38c64d1d 100644 --- a/test/hermes_test/commands/deposit/test_invenio.py +++ b/test/hermes_test/commands/deposit/test_invenio.py @@ -10,8 +10,6 @@ import click import pytest -pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) - from hermes.commands.deposit import invenio from hermes.error import MisconfigurationError diff --git a/test/hermes_test/commands/init/test_init.py b/test/hermes_test/commands/init/test_init.py index 4fe03c76..c32138f3 100644 --- a/test/hermes_test/commands/init/test_init.py +++ b/test/hermes_test/commands/init/test_init.py @@ -4,9 +4,6 @@ import json import pytest - -pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) - from hermes.commands.init.base import string_in_file, download_file_from_url from unittest.mock import patch, MagicMock import hermes.commands.init.util.oauth_process as oauth_process diff --git a/test/hermes_test/test_cli.py b/test/hermes_test/test_cli.py index ac831792..85b40e5e 100644 --- a/test/hermes_test/test_cli.py +++ b/test/hermes_test/test_cli.py @@ -6,8 +6,6 @@ import pytest -pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) - from hermes.commands import cli diff --git a/test/hermes_test/test_main.py b/test/hermes_test/test_main.py index 19dbf365..64d6abc0 100644 --- a/test/hermes_test/test_main.py +++ b/test/hermes_test/test_main.py @@ -4,10 +4,6 @@ # SPDX-FileContributor: Michael Meinel -import pytest - -pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) - import subprocess import sys diff --git a/test/hermes_test/test_marketplace.py b/test/hermes_test/test_marketplace.py index 50dc1350..9fe31045 100644 --- a/test/hermes_test/test_marketplace.py +++ b/test/hermes_test/test_marketplace.py @@ -2,10 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileContributor: David Pape -import pytest - -pytest.skip("FIXME: Re-enable test after data model refactoring is done.", allow_module_level=True) - import requests_mock from hermes.commands.marketplace import ( From de09fdb3ebee065d2cb7fc1657fdd333088a3ba3 Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Fri, 1 Aug 2025 23:15:57 +0200 Subject: [PATCH 30/32] Revert "Delete tests for old data model." This reverts commit 8b4f9a33777de45931dcece39edf5406c86864f4. --- test/hermes_test/model/test_base_context.py | 38 +++++ .../model/test_codemeta_context.py | 71 ++++++++++ .../hermes_test/model/test_harvest_context.py | 134 ++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 test/hermes_test/model/test_base_context.py create mode 100644 test/hermes_test/model/test_codemeta_context.py create mode 100644 test/hermes_test/model/test_harvest_context.py diff --git a/test/hermes_test/model/test_base_context.py b/test/hermes_test/model/test_base_context.py new file mode 100644 index 00000000..bdf016b7 --- /dev/null +++ b/test/hermes_test/model/test_base_context.py @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR) +# +# SPDX-License-Identifier: Apache-2.0 + +# SPDX-FileContributor: Michael Meinel + +from pathlib import Path + +from hermes.model.context import HermesContext + + +def test_context_hermes_dir_default(): + ctx = HermesContext() + assert ctx.hermes_dir == Path('.') / '.hermes' + + +def test_context_hermes_dir_custom(): + ctx = HermesContext('spam') + assert ctx.hermes_dir == Path('spam') / '.hermes' + + +def test_context_get_cache_default(): + ctx = HermesContext() + assert ctx.get_cache('spam', 'eggs') == Path('.') / '.hermes' / 'spam' / 'eggs.json' + + +def test_context_get_cache_cached(): + ctx = HermesContext() + ctx._caches[('spam', 'eggs')] = Path('spam_and_eggs') + assert ctx.get_cache('spam', 'eggs') == Path('spam_and_eggs') + + +def test_context_get_cache_create(tmpdir): + ctx = HermesContext(tmpdir) + subdir = Path(tmpdir) / '.hermes' / 'spam' + + assert ctx.get_cache('spam', 'eggs', create=True) == subdir / 'eggs.json' + assert subdir.exists() diff --git a/test/hermes_test/model/test_codemeta_context.py b/test/hermes_test/model/test_codemeta_context.py new file mode 100644 index 00000000..b9a5ec3e --- /dev/null +++ b/test/hermes_test/model/test_codemeta_context.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2023 German Aerospace Center (DLR) +# +# SPDX-License-Identifier: Apache-2.0 + +# SPDX-FileContributor: Stephan Druskat + +import pytest +from unittest.mock import Mock + +from hermes.model.context import CodeMetaContext, HermesHarvestContext + + +@pytest.fixture +def mock_ep(): + ep = Mock() + ep.name = 'mock_name' + return ep + + +@pytest.fixture +def _context(): + return 'foo', 'bar' + + +@pytest.fixture +def _codemeta_context(): + return CodeMetaContext() + + +@pytest.fixture +def _data(_codemeta_context): + return { + '@context': [ + 'https://doi.org/10.5063/schema/codemeta-2.0', + {'hermes': 'https://software-metadata.pub/ns/hermes/'}], + '@type': 'SoftwareSourceCode' + } + + +@pytest.fixture +def _data_with_contexts(_codemeta_context): + return { + '@type': 'SoftwareSourceCode', + '@context': [ + 'https://doi.org/10.5063/schema/codemeta-2.0', + {'foo': 'bar', + 'hermes': 'https://software-metadata.pub/ns/hermes/'} + ] + } + + +def test_merge_contexts_from(mock_ep, _context, _codemeta_context): + assert _codemeta_context.contexts == {_codemeta_context.hermes_lod_context} + other = HermesHarvestContext(None, mock_ep) + other.contexts.add(_context) + _codemeta_context.merge_contexts_from(other) + assert _codemeta_context.contexts == {_context, _codemeta_context.hermes_lod_context} + + +def test_prepare_codemeta(_codemeta_context, _context, _data): + assert not _codemeta_context.keys() + _codemeta_context.prepare_codemeta() + assert _codemeta_context.get_data() == _data + + +def test_prepare_codemeta_with_contexts(_codemeta_context, _context, _data_with_contexts): + assert not _codemeta_context.keys() + assert _codemeta_context.contexts == {_codemeta_context.hermes_lod_context} + _codemeta_context.add_context(_context) + _codemeta_context.prepare_codemeta() + assert _codemeta_context.get_data() == _data_with_contexts diff --git a/test/hermes_test/model/test_harvest_context.py b/test/hermes_test/model/test_harvest_context.py new file mode 100644 index 00000000..afb1ff70 --- /dev/null +++ b/test/hermes_test/model/test_harvest_context.py @@ -0,0 +1,134 @@ +# SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR) +# +# SPDX-License-Identifier: Apache-2.0 + +# SPDX-FileContributor: Michael Meinel + +import pytest + +from hermes.model.context import HermesContext, HermesHarvestContext + + +@pytest.fixture +def harvest_ctx(request: pytest.FixtureRequest): + ctx = HermesContext() + return HermesHarvestContext(ctx, request.function.__name__) + + +def test_context_default(harvest_ctx): + harvest_ctx.update('spam', 'eggs', test=True) + + assert harvest_ctx._data['spam'] == [ + ['eggs', {'test': True, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_default'}] + ] + + +def test_context_update_append(harvest_ctx): + harvest_ctx.update('spam', 'noodles', index=0) + harvest_ctx.update('spam', 'eggs', index=1) + + assert harvest_ctx._data['spam'] == [ + ['noodles', {'index': 0, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_update_append'}], + ['eggs', {'index': 1, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_update_append'}] + ] + + +def test_context_update_replace(harvest_ctx): + harvest_ctx.update('spam', 'noodles', test=True) + harvest_ctx.update('spam', 'eggs', test=True) + + assert harvest_ctx._data['spam'] == [ + ['eggs', {'test': True, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_update_replace'}] + ] + + +def test_context_bulk_flat(harvest_ctx): + harvest_ctx.update_from({ + 'ans': 42, + 'spam': 'eggs' + }, test=True) + + assert harvest_ctx._data['ans'] == [ + [42, {'test': True, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_flat'}] + ] + assert harvest_ctx._data['spam'] == [ + ['eggs', {'test': True, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_flat'}] + ] + + +def test_context_bulk_complex(harvest_ctx): + harvest_ctx.update_from({ + 'ans': 42, + 'author': [ + {'name': 'Monty Python', 'email': 'eggs@spam.io'}, + {'name': 'Herr Mes'}, + ] + }, test=True) + + assert harvest_ctx._data['ans'] == [ + [42, {'test': True, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_complex'}] + ] + assert harvest_ctx._data['author[0].name'] == [ + ['Monty Python', {'test': True, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_complex'}] + ] + assert harvest_ctx._data['author[0].email'] == [ + ['eggs@spam.io', {'test': True, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_complex'}] + ] + assert harvest_ctx._data['author[1].name'] == [ + ['Herr Mes', {'test': True, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_complex'}] + ] + + +def test_context_bulk_replace(harvest_ctx): + harvest_ctx.update('author[0].name', 'Monty Python', test=True) + harvest_ctx.update_from({'author': [{'name': 'Herr Mes', 'email': 'eggs@spam.io'}]}, test=True) + + assert harvest_ctx._data['author[0].name'] == [ + ['Herr Mes', {'test': True, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_replace'}] + ] + assert harvest_ctx._data['author[0].email'] == [ + ['eggs@spam.io', {'test': True, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_replace'}] + ] + + +def test_context_bulk_append(harvest_ctx): + harvest_ctx.update('author[0].name', 'Monty Python', index=0) + harvest_ctx.update_from({'author': [{'name': 'Herr Mes', 'email': 'eggs@spam.io'}]}, index=1) + + assert harvest_ctx._data['author[0].name'] == [ + ['Monty Python', {'index': 0, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_append'}], + ['Herr Mes', {'index': 1, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_append'}] + ] + assert harvest_ctx._data['author[0].email'] == [ + ['eggs@spam.io', {'index': 1, + 'timestamp': HermesContext.default_timestamp, + 'harvester': 'test_context_bulk_append'}] + ] From 68aec7f8bacc2f6de4c23d6737dad259c03f89bb Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Tue, 5 Aug 2025 22:35:44 +0200 Subject: [PATCH 31/32] Update poetry.lock for added test dependencies. --- poetry.lock | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 47ce16c1..932f4b45 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. [[package]] name = "accessible-pygments" @@ -914,7 +914,7 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["docs"] +groups = ["dev", "docs"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -1543,6 +1543,21 @@ pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +[[package]] +name = "pytest-httpserver" +version = "1.1.3" +description = "pytest-httpserver is a httpserver for pytest" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest_httpserver-1.1.3-py3-none-any.whl", hash = "sha256:5f84757810233e19e2bb5287f3826a71c97a3740abe3a363af9155c0f82fdbb9"}, + {file = "pytest_httpserver-1.1.3.tar.gz", hash = "sha256:af819d6b533f84b4680b9416a5b3f67f1df3701f1da54924afd4d6e4ba5917ec"}, +] + +[package.dependencies] +Werkzeug = ">=2.0.0" + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -2370,6 +2385,24 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "werkzeug" +version = "3.1.3" +description = "The comprehensive WSGI web application library." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"}, + {file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"}, +] + +[package.dependencies] +MarkupSafe = ">=2.1.1" + +[package.extras] +watchdog = ["watchdog (>=2.3)"] + [[package]] name = "wheel" version = "0.45.1" @@ -2477,4 +2510,4 @@ files = [ [metadata] lock-version = "2.1" python-versions = ">=3.10, <4.0.0" -content-hash = "58304fd33d6ec1ce3400b43ecffb16b3f48a5621e513c3e8057f9e3e050835e8" +content-hash = "53ac01822d5f15562af78d86245f1d7302873452f979cfd90d5c8bebed3d29a9" From ea081055c0b784df7ed2fe896bc966a510a2517b Mon Sep 17 00:00:00 2001 From: Michael Meinel Date: Tue, 5 Aug 2025 22:41:37 +0200 Subject: [PATCH 32/32] Add missing dependencies again. Update poetry.lock for added test dependencies. --- poetry.lock | 73 ++++++++++++++++++++++++++++++++++++++++++++++++-- pyproject.toml | 2 ++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 932f4b45..d09e8e97 100644 --- a/poetry.lock +++ b/poetry.lock @@ -700,6 +700,19 @@ files = [ {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] +[[package]] +name = "isodate" +version = "0.7.2" +description = "An ISO 8601 date/time/duration parser and formatter" +optional = false +python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\"" +files = [ + {file = "isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15"}, + {file = "isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6"}, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -1139,6 +1152,24 @@ files = [ dev = ["abi3audit", "black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "vulture", "wheel"] test = ["pytest", "pytest-xdist", "setuptools"] +[[package]] +name = "pyaml" +version = "25.7.0" +description = "PyYAML-based module to produce a bit more pretty and readable YAML-serialized data" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "pyaml-25.7.0-py3-none-any.whl", hash = "sha256:ce5d7867cc2b455efdb9b0448324ff7b9f74d99f64650f12ca570102db6b985f"}, + {file = "pyaml-25.7.0.tar.gz", hash = "sha256:e113a64ec16881bf2b092e2beb84b7dcf1bd98096ad17f5f14e8fb782a75d99b"}, +] + +[package.dependencies] +PyYAML = "*" + +[package.extras] +anchors = ["unidecode"] + [[package]] name = "pycodestyle" version = "2.9.1" @@ -1609,7 +1640,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["docs"] +groups = ["main", "docs"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1666,6 +1697,29 @@ files = [ {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] +[[package]] +name = "rdflib" +version = "7.1.4" +description = "RDFLib is a Python library for working with RDF, a simple yet powerful language for representing information." +optional = false +python-versions = "<4.0.0,>=3.8.1" +groups = ["main"] +files = [ + {file = "rdflib-7.1.4-py3-none-any.whl", hash = "sha256:72f4adb1990fa5241abd22ddaf36d7cafa5d91d9ff2ba13f3086d339b213d997"}, + {file = "rdflib-7.1.4.tar.gz", hash = "sha256:fed46e24f26a788e2ab8e445f7077f00edcf95abb73bcef4b86cefa8b62dd174"}, +] + +[package.dependencies] +isodate = {version = ">=0.7.2,<1.0.0", markers = "python_version < \"3.11\""} +pyparsing = ">=2.1.0,<4" + +[package.extras] +berkeleydb = ["berkeleydb (>=18.1.0,<19.0.0)"] +html = ["html5rdf (>=1.2,<2)"] +lxml = ["lxml (>=4.3,<6.0)"] +networkx = ["networkx (>=2,<4)"] +orjson = ["orjson (>=3.9.14,<4)"] + [[package]] name = "requests" version = "2.32.4" @@ -1821,6 +1875,21 @@ files = [ {file = "ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f"}, ] +[[package]] +name = "schemaorg" +version = "0.1.1" +description = "Python functions for applied use of schema.org" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "schemaorg-0.1.1.tar.gz", hash = "sha256:567f1735df666221c893d2c206dd70f9cddcc983c8cdc39f3a7b7726884d2c51"}, +] + +[package.dependencies] +lxml = ">=4.1.1" +pyaml = ">=17.12.1" + [[package]] name = "setuptools" version = "80.9.0" @@ -2510,4 +2579,4 @@ files = [ [metadata] lock-version = "2.1" python-versions = ">=3.10, <4.0.0" -content-hash = "53ac01822d5f15562af78d86245f1d7302873452f979cfd90d5c8bebed3d29a9" +content-hash = "a8cbf610eb2e4405175914d22c8383c796ccb443724d04d2f3e58fcb08205e66" diff --git a/pyproject.toml b/pyproject.toml index a8fa06e9..d28f60fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,8 @@ dependencies = [ "pydantic-settings>=2.1.0, <3.0.0", "requests-oauthlib>=2.0.0, <3.0.0", "pynacl>=1.5.0, <2.0.0", + "rdflib (>=7.1.4,<8.0.0)", + "schemaorg (>=0.1.1,<0.2.0)", ] requires-python = ">=3.10, <4.0.0"