From a6198a3cfe7e3e40b849611fa26166fc11b2424c Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Mon, 9 Oct 2023 18:03:35 +0200 Subject: [PATCH 1/5] Add specimen for khaeru/sdmx#142 --- sdmx/testing/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sdmx/testing/__init__.py b/sdmx/testing/__init__.py index 0b058ef82..dfe19d566 100644 --- a/sdmx/testing/__init__.py +++ b/sdmx/testing/__init__.py @@ -275,6 +275,7 @@ def __init__(self, base_path): ("UNICEF", "GLOBAL_DATAFLOW-structure.xml"), ("UNSD", "codelist_partial.xml"), ("SGR", "common-structure.xml"), + ("TEST", "gh-142.xml"), ] ) From 044735e23459f229193e9566145ba70339af347d Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Mon, 9 Oct 2023 18:07:27 +0200 Subject: [PATCH 2/5] Add tests for khaeru/sdmx#142 --- sdmx/tests/reader/test_reader_xml_v21.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sdmx/tests/reader/test_reader_xml_v21.py b/sdmx/tests/reader/test_reader_xml_v21.py index b5c984071..e6b9925d2 100644 --- a/sdmx/tests/reader/test_reader_xml_v21.py +++ b/sdmx/tests/reader/test_reader_xml_v21.py @@ -117,6 +117,21 @@ def test_gh_116(specimen): assert cl4.is_partial and 0 < len(cl4) < len(cl3) +def test_gh_142(specimen): + """Test of https://github.com/khaeru/sdmx/issues/142.""" + with specimen("TEST/gh-142.xml") as f: + msg = sdmx.read_sdmx(f) + + # Annotations, valid_from and valid_to properties stored on the Codelist *per se* + cl = msg.codelist["CL_NAICS"] + assert 3 == len(cl.annotations) + assert "2021-01-24T08:00:00" == cl.valid_from + assert "2021-09-24T08:00:00" == cl.valid_to + + # No annotations attached to any Code + assert all(0 == len(code.annotations) for code in cl) + + # Each entry is a tuple with 2 elements: # 1. an instance of lxml.etree.Element to be parsed. # 2. Either: From ad90c6d3a7c489afd1f3c4288fbeac754fd7c5b1 Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Mon, 9 Oct 2023 18:09:48 +0200 Subject: [PATCH 3/5] Stash Annotations before parsing Item in ItemScheme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …in addition to the Name and Description. --- sdmx/reader/xml/v21.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdmx/reader/xml/v21.py b/sdmx/reader/xml/v21.py index 4af610deb..a71fcdf69 100644 --- a/sdmx/reader/xml/v21.py +++ b/sdmx/reader/xml/v21.py @@ -956,7 +956,7 @@ def _item_start(reader, elem): # No child elements; stash() anyway, but it will be a no-op pass - reader.stash("Name", "Description") + reader.stash(model.Annotation, "Name", "Description") @end( From 75921baca02b2785bb03237b6bca403f7b821b55 Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Mon, 9 Oct 2023 18:12:19 +0200 Subject: [PATCH 4/5] Handle valid{From,To} attrs in xml.v21.Reader.maintainable() --- sdmx/reader/xml/v21.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sdmx/reader/xml/v21.py b/sdmx/reader/xml/v21.py index a71fcdf69..bfae6847b 100644 --- a/sdmx/reader/xml/v21.py +++ b/sdmx/reader/xml/v21.py @@ -576,7 +576,15 @@ def maintainable(self, cls, elem, **kwargs): the same object ID will return references to the same object. """ kwargs.setdefault("is_external_reference", elem is None) - setdefault_attrib(kwargs, elem, "isExternalReference", "isFinal", "version") + setdefault_attrib( + kwargs, + elem, + "isExternalReference", + "isFinal", + "validFrom", + "validTo", + "version", + ) kwargs["is_final"] = kwargs.get("is_final", None) == "true" # Create a candidate object @@ -1393,7 +1401,6 @@ def _cc(reader, elem): else: content.add(resolved) - # return reader.nameable( return reader.maintainable( cls, elem, From 4cdd7d203607c390618048e15d4c4b7126f069b7 Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Tue, 10 Oct 2023 17:02:59 +0200 Subject: [PATCH 5/5] Add #143 to doc/whatsnew --- doc/whatsnew.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/whatsnew.rst b/doc/whatsnew.rst index 725dad4dc..4c22d4c49 100644 --- a/doc/whatsnew.rst +++ b/doc/whatsnew.rst @@ -6,6 +6,7 @@ What's new? Next release ============ +- Fix two bugs in parsing :class:`.ItemScheme` from SDMX-ML: :attr:`.VersionableArtefact.valid_from`, :attr:`~.VersionableArtefact.valid_to` not stored, and :class:`Annotations <.Annotation>` for the scheme itself erroneously collected by the first :class:`.Item` in the scheme (:pull:`143`; thanks :gh-user:`goatsweater` for :issue:`142`). - Update :ref:`OECD ` to support the provider's recently-added SDMX-ML API (:pull:`140`). Rename the corresponding, older SDMX-JSON source :ref:`OECD_JSON `; work around a known issue with its SSL configuration (see :func:`.oecd_json.Client`).