Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/hdmf/build/objectmapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,9 @@ def get_attr_value(self, **kwargs):
if isinstance(attr_val, TermSetWrapper):
attr_val = attr_val.value
if attr_val is not None:
attr_val = self.__convert_string(attr_val, spec)
if not isinstance(attr_val, Data):
# NOTE: Do not process Data objects here
attr_val = self.__convert_string(attr_val, spec)
spec_dt = self.__get_data_type(spec)
if spec_dt is not None:
try:
Expand Down Expand Up @@ -640,6 +642,7 @@ def __apply_string_type(value, string_type):
# NOTE: if a user passes a h5py.Dataset that is not wrapped with a hdmf.utils.StrDataset,
# then this conversion may not be correct. Users should unpack their string h5py.Datasets
# into a numpy array (or wrap them in StrDataset) before passing them to a container object.
# NOTE: this will convert datasets and arrays to lists of lists.
if hasattr(value, '__iter__') and not isinstance(value, (str, bytes)):
return [__apply_string_type(item, string_type) for item in value]
else:
Expand All @@ -653,8 +656,7 @@ def __apply_string_type(value, string_type):
else:
ret = str(value)
elif isinstance(spec, DatasetSpec):
# TODO: make sure we can handle specs with data_type_inc set
if spec.data_type_inc is None and spec.dtype is not None:
if spec.dtype is not None:
string_type = None
if 'text' in spec.dtype:
string_type = str
Expand Down Expand Up @@ -826,6 +828,7 @@ def build(self, **kwargs):
data = container.data.value
else:
data = container.data
data = self.__convert_string(data, spec)
bldr_data, dtype = self.convert_dtype(spec, data, spec_dtype=spec_dtype)
except Exception as ex:
msg = f"could not resolve dtype for {type(container).__name__} '{container.name}'"
Expand Down
60 changes: 59 additions & 1 deletion tests/unit/build_tests/mapper_tests/test_build_datetime.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from hdmf.utils import docval, getargs
from hdmf import Container
from hdmf import Container, Data
from hdmf.spec import GroupSpec, DatasetSpec
from hdmf.testing import TestCase
from datetime import datetime, date
Expand All @@ -25,6 +25,38 @@ def data(self):
return self.__data


class Column(Data):

@docval({'name': 'name', 'type': str, 'doc': 'the name of this Column'},
{'name': 'data', 'type': ('data', 'array_data'), 'doc': 'some data'})
def __init__(self, **kwargs):
name, data = getargs('name', 'data', kwargs)
super().__init__(name=name, data=data)

@property
def data_type(self):
return 'Column'


class BarWithColumnData(Container):

@docval({'name': 'name', 'type': str, 'doc': 'the name of this Bar'},
{'name': 'data', 'type': Column, 'doc': 'some data'})
def __init__(self, **kwargs):
name, data = getargs('name', 'data', kwargs)
super().__init__(name=name)
self.__data = data
data.parent = self

@property
def data_type(self):
return 'Bar'

@property
def data(self):
return self.__data


class TestBuildDatasetDateTime(TestCase):
"""Test that building a dataset with dtype isodatetime works with datetime and date objects."""

Expand Down Expand Up @@ -83,3 +115,29 @@ def test_date_array(self):
ret = builder.get('data')
assert ret.data == [b'2023-07-09', b'2023-07-10']
assert ret.dtype == 'ascii'


def test_datetime_array_ext_spec(self):
column_spec = DatasetSpec(data_type_def='Column', doc='an example dataset', dims=(None,))
bar_spec = GroupSpec(
doc='A test group specification with a data type',
data_type_def='Bar',
datasets=[
DatasetSpec(
data_type_inc='Column',
doc='an example dataset',
name='data',
dtype='isodatetime',
),
],
)
type_map = create_test_type_map([bar_spec, column_spec], {'Bar': BarWithColumnData, 'Column': Column})

bar_inst = BarWithColumnData(
name='my_bar',
data=Column(name='data', data=[datetime(2023, 7, 9), datetime(2023, 7, 10)]),
)
builder = type_map.build(bar_inst)
ret = builder.get('data')
assert ret.data == [b'2023-07-09T00:00:00', b'2023-07-10T00:00:00']
assert ret.dtype == 'ascii'
Loading