From d24b00d975786b1a0f6e2c20ace78c5180536d8c Mon Sep 17 00:00:00 2001 From: ioanaif Date: Thu, 21 Mar 2024 15:06:31 +0100 Subject: [PATCH 01/10] feat: add support for reading free floating std::vector --- src/uproot/reading.py | 13 ++++++++++ ...999_read_free_floating_object_issue_586.py | 24 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 tests/test_9999_read_free_floating_object_issue_586.py diff --git a/src/uproot/reading.py b/src/uproot/reading.py index 362a87307..5206e82e8 100644 --- a/src/uproot/reading.py +++ b/src/uproot/reading.py @@ -9,6 +9,7 @@ """ from __future__ import annotations +import re import struct import sys import uuid @@ -1107,6 +1108,18 @@ def class_named(self, classname, version=None): if len(streamers) == 0 and self._custom_classes is not None: cls = uproot.classes.get(classname) + if ( + cls is None + and re.match( + r"(std\s*::\s*)?(vector)?(map)?(set)?(string)?(bitset)?\s*<", classname + ) + is not None + ): + cls = uproot.interpretation.identify.parse_typename(classname) + cls._header = False + + return cls + if cls is None: if len(streamers) == 0: unknown_cls = uproot.unknown_classes.get(classname) diff --git a/tests/test_9999_read_free_floating_object_issue_586.py b/tests/test_9999_read_free_floating_object_issue_586.py new file mode 100644 index 000000000..d518a5d2a --- /dev/null +++ b/tests/test_9999_read_free_floating_object_issue_586.py @@ -0,0 +1,24 @@ +# BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE + +import uproot +import os +import ROOT +import numpy as np + + +def test_read_free_floating_vector(tmp_path): + newfile = os.path.join(tmp_path, "test_freevec.root") + f = ROOT.TFile(newfile, "recreate") + a = np.array([1.0, 2.0, 3.0, 4.0], dtype=np.float64) + c = np.array([0, 1, 4, 5, 6, 7, 8, 9], dtype=np.uint32) + avec = ROOT.std.vector("double")(a) + bvec = ROOT.std.vector("unsigned int")(c) + f.WriteObject(avec, "avec") + f.WriteObject(bvec, "bvec") + f.Write() + f.Close() + + + with uproot.open(newfile) as f: + assert f['avec'].tolist() == [1.0, 2.0, 3.0, 4.0] + assert f['bvec'].tolist() == [0, 1, 4, 5, 6, 7, 8, 9] \ No newline at end of file From 36aec0228f6f000198fc25806283079b0e7fd6a4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 14:08:42 +0000 Subject: [PATCH 02/10] style: pre-commit fixes --- tests/test_9999_read_free_floating_object_issue_586.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/test_9999_read_free_floating_object_issue_586.py b/tests/test_9999_read_free_floating_object_issue_586.py index d518a5d2a..c14d5c0a9 100644 --- a/tests/test_9999_read_free_floating_object_issue_586.py +++ b/tests/test_9999_read_free_floating_object_issue_586.py @@ -18,7 +18,6 @@ def test_read_free_floating_vector(tmp_path): f.Write() f.Close() - with uproot.open(newfile) as f: - assert f['avec'].tolist() == [1.0, 2.0, 3.0, 4.0] - assert f['bvec'].tolist() == [0, 1, 4, 5, 6, 7, 8, 9] \ No newline at end of file + assert f["avec"].tolist() == [1.0, 2.0, 3.0, 4.0] + assert f["bvec"].tolist() == [0, 1, 4, 5, 6, 7, 8, 9] From fdbd4e873e0f6bc39a7d62b91d7f5787bb511ff9 Mon Sep 17 00:00:00 2001 From: ioanaif Date: Thu, 21 Mar 2024 15:17:37 +0100 Subject: [PATCH 03/10] Update test file name and ROOT import --- ...586.py => test_1180_read_free_floating_vector_issue_1179.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/{test_9999_read_free_floating_object_issue_586.py => test_1180_read_free_floating_vector_issue_1179.py} (95%) diff --git a/tests/test_9999_read_free_floating_object_issue_586.py b/tests/test_1180_read_free_floating_vector_issue_1179.py similarity index 95% rename from tests/test_9999_read_free_floating_object_issue_586.py rename to tests/test_1180_read_free_floating_vector_issue_1179.py index c14d5c0a9..197304d27 100644 --- a/tests/test_9999_read_free_floating_object_issue_586.py +++ b/tests/test_1180_read_free_floating_vector_issue_1179.py @@ -2,9 +2,9 @@ import uproot import os -import ROOT import numpy as np +ROOT = pytest.importorskip("ROOT") def test_read_free_floating_vector(tmp_path): newfile = os.path.join(tmp_path, "test_freevec.root") From aae609b23ac23879fecda66c0da8379c52edecff Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 14:18:33 +0000 Subject: [PATCH 04/10] style: pre-commit fixes --- tests/test_1180_read_free_floating_vector_issue_1179.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_1180_read_free_floating_vector_issue_1179.py b/tests/test_1180_read_free_floating_vector_issue_1179.py index 197304d27..a565a9878 100644 --- a/tests/test_1180_read_free_floating_vector_issue_1179.py +++ b/tests/test_1180_read_free_floating_vector_issue_1179.py @@ -6,6 +6,7 @@ ROOT = pytest.importorskip("ROOT") + def test_read_free_floating_vector(tmp_path): newfile = os.path.join(tmp_path, "test_freevec.root") f = ROOT.TFile(newfile, "recreate") From d37e3a6390bd3c8ca66c4d325a932b4a69623f87 Mon Sep 17 00:00:00 2001 From: ioanaif Date: Thu, 21 Mar 2024 15:25:23 +0100 Subject: [PATCH 05/10] pytest import --- tests/test_1180_read_free_floating_vector_issue_1179.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_1180_read_free_floating_vector_issue_1179.py b/tests/test_1180_read_free_floating_vector_issue_1179.py index a565a9878..c854c1502 100644 --- a/tests/test_1180_read_free_floating_vector_issue_1179.py +++ b/tests/test_1180_read_free_floating_vector_issue_1179.py @@ -1,5 +1,6 @@ # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE +import pytest import uproot import os import numpy as np From 3245259a9dec3c168ed12bc9711a1e1c58bbb92b Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Thu, 21 Mar 2024 16:16:26 -0500 Subject: [PATCH 06/10] move the check for STL classes earlier and ensure at least one type matches in the regex --- src/uproot/reading.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/uproot/reading.py b/src/uproot/reading.py index eb49c6d20..aba866d75 100644 --- a/src/uproot/reading.py +++ b/src/uproot/reading.py @@ -1100,18 +1100,10 @@ def class_named(self, classname, version=None): global ``uproot.classes``. """ classname = uproot.model.classname_regularize(classname) - classes = uproot.model.maybe_custom_classes(classname, self._custom_classes) - cls = classes.get(classname) - - if cls is None: - streamers = self.streamers_named(classname) - if len(streamers) == 0 and self._custom_classes is not None: - cls = uproot.classes.get(classname) if ( - cls is None - and re.match( - r"(std\s*::\s*)?(vector)?(map)?(set)?(string)?(bitset)?\s*<", classname + re.match( + r"(std\s*::\s*)?(vector|map|set|string|bitset)\s*<", classname ) is not None ): @@ -1120,6 +1112,14 @@ def class_named(self, classname, version=None): return cls + classes = uproot.model.maybe_custom_classes(classname, self._custom_classes) + cls = classes.get(classname) + + if cls is None: + streamers = self.streamers_named(classname) + if len(streamers) == 0 and self._custom_classes is not None: + cls = uproot.classes.get(classname) + if cls is None: if len(streamers) == 0: unknown_cls = uproot.unknown_classes.get(classname) From a371023235e1bbca021a4faeaa5b79a5ae6c77a8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 21:16:45 +0000 Subject: [PATCH 07/10] style: pre-commit fixes --- src/uproot/reading.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/uproot/reading.py b/src/uproot/reading.py index aba866d75..46891ba56 100644 --- a/src/uproot/reading.py +++ b/src/uproot/reading.py @@ -1102,9 +1102,7 @@ def class_named(self, classname, version=None): classname = uproot.model.classname_regularize(classname) if ( - re.match( - r"(std\s*::\s*)?(vector|map|set|string|bitset)\s*<", classname - ) + re.match(r"(std\s*::\s*)?(vector|map|set|string|bitset)\s*<", classname) is not None ): cls = uproot.interpretation.identify.parse_typename(classname) From ded07a9cf79fa0760b503c8736598d650896f10b Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Thu, 21 Mar 2024 16:22:36 -0500 Subject: [PATCH 08/10] changed my mind; std::vector might need T to be defined by streamers --- src/uproot/reading.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/uproot/reading.py b/src/uproot/reading.py index 46891ba56..53c15b580 100644 --- a/src/uproot/reading.py +++ b/src/uproot/reading.py @@ -1100,6 +1100,13 @@ def class_named(self, classname, version=None): global ``uproot.classes``. """ classname = uproot.model.classname_regularize(classname) + classes = uproot.model.maybe_custom_classes(classname, self._custom_classes) + cls = classes.get(classname) + + if cls is None: + streamers = self.streamers_named(classname) + if len(streamers) == 0 and self._custom_classes is not None: + cls = uproot.classes.get(classname) if ( re.match(r"(std\s*::\s*)?(vector|map|set|string|bitset)\s*<", classname) @@ -1110,14 +1117,6 @@ def class_named(self, classname, version=None): return cls - classes = uproot.model.maybe_custom_classes(classname, self._custom_classes) - cls = classes.get(classname) - - if cls is None: - streamers = self.streamers_named(classname) - if len(streamers) == 0 and self._custom_classes is not None: - cls = uproot.classes.get(classname) - if cls is None: if len(streamers) == 0: unknown_cls = uproot.unknown_classes.get(classname) From 178021d8a8dc299e79eba091abe0013e27643f4d Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Thu, 21 Mar 2024 16:30:14 -0500 Subject: [PATCH 09/10] update the fix for #1160 to be like this one, and remove the double-check for std::string --- src/uproot/reading.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uproot/reading.py b/src/uproot/reading.py index 53c15b580..7a4458207 100644 --- a/src/uproot/reading.py +++ b/src/uproot/reading.py @@ -1109,7 +1109,7 @@ def class_named(self, classname, version=None): cls = uproot.classes.get(classname) if ( - re.match(r"(std\s*::\s*)?(vector|map|set|string|bitset)\s*<", classname) + re.match(r"(std\s*::\s*)?(vector|map|set|bitset)\s*<", classname) is not None ): cls = uproot.interpretation.identify.parse_typename(classname) @@ -2507,7 +2507,7 @@ def get(self): start_cursor = cursor.copy() context = {"breadcrumbs": (), "TKey": self} - if self._fClassName == "string": + if re.match(r"(std\s*::\s*)?string", self._fClassName): return cursor.string(chunk, context) cls = self._file.class_named(self._fClassName) From ab215e71d20f3e785a8d8a063b2401e933149895 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Thu, 21 Mar 2024 16:34:31 -0500 Subject: [PATCH 10/10] forgot to reinstate the 'cls is None and' --- src/uproot/reading.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/uproot/reading.py b/src/uproot/reading.py index 7a4458207..5511066af 100644 --- a/src/uproot/reading.py +++ b/src/uproot/reading.py @@ -1109,7 +1109,8 @@ def class_named(self, classname, version=None): cls = uproot.classes.get(classname) if ( - re.match(r"(std\s*::\s*)?(vector|map|set|bitset)\s*<", classname) + cls is None + and re.match(r"(std\s*::\s*)?(vector|map|set|bitset)\s*<", classname) is not None ): cls = uproot.interpretation.identify.parse_typename(classname)