diff --git a/src/uproot/__init__.py b/src/uproot/__init__.py index 51c3c1914..fc32e433b 100644 --- a/src/uproot/__init__.py +++ b/src/uproot/__init__.py @@ -132,6 +132,7 @@ import uproot.models.TObjArray import uproot.models.TObjString import uproot.models.TAtt +import uproot.models.TDatime import uproot.models.TRef import uproot.models.TTree diff --git a/src/uproot/behaviors/TDatime.py b/src/uproot/behaviors/TDatime.py new file mode 100644 index 000000000..39b8e4967 --- /dev/null +++ b/src/uproot/behaviors/TDatime.py @@ -0,0 +1,18 @@ +# BSD 3-Clause License; see https://github.com/scikit-hep/uproot4/blob/main/LICENSE + +""" +This module defines the behaviors of ``TDatime``. +""" + +from __future__ import absolute_import + +import uproot + + +class TDatime(object): + """ + Behaviors for TDatime: return values as py:class:`datetime.datetime` + """ + + def to_datetime(self): + return uproot._util.code_to_datetime(self._members["fDatime"]) diff --git a/src/uproot/model.py b/src/uproot/model.py index 70e29d0c9..76f578c4c 100644 --- a/src/uproot/model.py +++ b/src/uproot/model.py @@ -90,6 +90,7 @@ def reset_classes(): reload(uproot.models.TObjArray) reload(uproot.models.TObjString) reload(uproot.models.TAtt) + reload(uproot.models.TDatime) reload(uproot.models.TRef) reload(uproot.models.TTree) reload(uproot.models.TBranch) diff --git a/src/uproot/models/TDatime.py b/src/uproot/models/TDatime.py new file mode 100644 index 000000000..5eb1b5207 --- /dev/null +++ b/src/uproot/models/TDatime.py @@ -0,0 +1,77 @@ +# BSD 3-Clause License; see https://github.com/scikit-hep/uproot4/blob/main/LICENSE + +""" +This module defines versioned models for ``TDatime``. +""" + +from __future__ import absolute_import + +import struct + +import numpy + +import uproot +import uproot.behaviors.TDatime + +_tdatime_format1 = struct.Struct(">I") + + +class Model_TDatime(uproot.behaviors.TDatime.TDatime, uproot.model.Model): + """ + A versionless :doc:`uproot.model.Model` for ``TDatime``. + """ + + def read_numbytes_version(self, chunk, cursor, context): + pass + + def read_members(self, chunk, cursor, context, file): + self._members["fDatime"] = cursor.field(chunk, _tdatime_format1, context) + + @classmethod + def strided_interpretation( + cls, file, header=False, tobject_header=True, breadcrumbs=(), original=None + ): + members = [] + if header: + members.append(("@num_bytes", numpy.dtype(">u4"))) + members.append(("@instance_version", numpy.dtype(">u2"))) + members.append(("fDatime", numpy.dtype(">u4"))) + return uproot.interpretation.objects.AsStridedObjects( + cls, members, original=original + ) + + @classmethod + def awkward_form( + cls, file, index_format="i64", header=False, tobject_header=True, breadcrumbs=() + ): + awkward = uproot.extras.awkward() + contents = {} + if header: + contents["@num_bytes"] = uproot._util.awkward_form( + numpy.dtype("u4"), + file, + index_format, + header, + tobject_header, + breadcrumbs, + ) + contents["@instance_version"] = uproot._util.awkward_form( + numpy.dtype("u2"), + file, + index_format, + header, + tobject_header, + breadcrumbs, + ) + contents["fDatime"] = uproot._util.awkward_form( + numpy.dtype(">u4"), file, index_format, header, tobject_header, breadcrumbs + ) + return awkward.forms.RecordForm(contents, parameters={"__record__": "TDatime"}) + + base_names_versions = [] + member_names = ["fDatime"] + class_flags = {} + class_code = None + + +uproot.classes["TDatime"] = Model_TDatime diff --git a/tests/test_0407-read-TDatime.py b/tests/test_0407-read-TDatime.py new file mode 100644 index 000000000..fddb6de77 --- /dev/null +++ b/tests/test_0407-read-TDatime.py @@ -0,0 +1,38 @@ +# BSD 3-Clause License; see https://github.com/scikit-hep/uproot4/blob/main/LICENSE + +from __future__ import absolute_import + +import datetime + +import numpy +import pytest +import skhep_testdata + +import uproot + + +@pytest.fixture(scope="module") +def datafile(tmpdir_factory): + yield skhep_testdata.data_path("uproot-issue-407.root") + + +@pytest.fixture(params=["foo", "foo_padded"]) +def _object(request, datafile): + with uproot.open(datafile) as f: + yield f[request.param] + + +@pytest.fixture +def tree(datafile): + with uproot.open(datafile) as f: + yield f["tree"] + + +def test_streamer(_object): + assert _object.members["d"].to_datetime() == datetime.datetime(2021, 1, 1, 0, 0, 0) + + +def test_strided_interpretation(tree): + assert list(tree.iterate(how=tuple))[0][0].fDatime[ + 0 + ] == uproot._util.datetime_to_code(datetime.datetime(2021, 1, 1, 0, 0, 0))