Skip to content

Commit

Permalink
Merge pull request #575 from NeurodataWithoutBorders/bug/recurse_proxy
Browse files Browse the repository at this point in the history
recurse on Proxy objects
  • Loading branch information
bendichter authored Jul 31, 2018
2 parents 432699f + 3b70c95 commit 44b6950
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 6 deletions.
33 changes: 27 additions & 6 deletions src/pynwb/form/build/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@


class Proxy(object):
"""
A temporary object to represent a Container. This gets used when resolving the true location of a
Container's parent.
Proxy objects allow simple bookeeping of all potential parents a Container may have.
This object is used by providing all the necessary information for describing the object. This object
gets passed around and candidates are accumulated. Upon calling resolve, all saved candidates are matched
against the information (provided to the constructor). The candidate that has an exact match is returned.
"""

def __init__(self, manager, source, location, namespace, data_type):
self.__source = source
Expand All @@ -24,24 +34,24 @@ def __init__(self, manager, source, location, namespace, data_type):
self.__manager = manager
self.__candidates = list()

@property
def candidates(self):
return self.__candidates

@property
def source(self):
"""The source of the object e.g. file source"""
return self.__source

@property
def location(self):
"""The location of the object. This can be thought of as a unique path"""
return self.__location

@property
def namespace(self):
"""The namespace from which the data_type of this Proxy came from"""
return self.__namespace

@property
def data_type(self):
"""The data_type of Container that should match this Proxy"""
return self.__data_type

@docval({"name": "object", "type": (BaseBuilder, Container), "doc": "the container or builder to get a proxy for"})
Expand Down Expand Up @@ -115,8 +125,12 @@ def __get_proxy_container(self, container):
stack = list()
tmp = container
while tmp is not None:
stack.append(tmp.name)
tmp = tmp.parent
if isinstance(tmp, Proxy):
stack.append(tmp.location)
break
else:
stack.append(tmp.name)
tmp = tmp.parent
loc = "/".join(reversed(stack))
return Proxy(self, container.container_source, loc, ns, dt)

Expand Down Expand Up @@ -523,6 +537,13 @@ def get_attr_value(self, **kwargs):
return None
attr_val = self.__get_override_attr(attr_name, container, manager)
if attr_val is None:
# TODO: A message like this should be used to warn users when an expected attribute
# does not exist on a Container object
#
# if not hasattr(container, attr_name):
# msg = "Container '%s' (%s) does not have attribute '%s'" \
# % (container.name, type(container), attr_name)
# #warnings.warn(msg)
attr_val = getattr(container, attr_name, None)
if attr_val is not None:
attr_val = self.__convert_value(attr_val, spec)
Expand Down
43 changes: 43 additions & 0 deletions tests/unit/form_tests/test_io_hdf5_h5tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from pynwb import NWBHDF5IO
from pynwb.spec import NWBNamespace, NWBGroupSpec, NWBDatasetSpec

from pynwb.ecephys import ElectricalSeries


import tempfile
import warnings
Expand Down Expand Up @@ -400,6 +402,47 @@ def __get_types(self, catalog):
return types


class TestLinkResolution(unittest.TestCase):

def test_link_resolve(self):
print("TEST_LINK_RESOLVE")

nwbfile = NWBFile("source", "a file with header data", "NB123A", '2018-06-01T00:00:00')
device = nwbfile.create_device('device_name', 'source')
electrode_group = nwbfile.create_electrode_group(
name='electrode_group_name',
source='source',
description='desc',
device=device,
location='unknown')
nwbfile.add_electrode(0,
1.0, 2.0, 3.0, # position?
imp=2.718,
location='unknown',
filtering='unknown',
description='desc',
group=electrode_group)
etr = nwbfile.create_electrode_table_region([0], 'etr_name')
for passband in ('theta', 'gamma'):
electrical_series = ElectricalSeries(name=passband + '_phase',
source='ephys_analysis',
data=[1., 2., 3.],
rate=0.0,
electrodes=etr)
nwbfile.add_acquisition(electrical_series)
with NWBHDF5IO(self.path, 'w') as io:
io.write(nwbfile)
with NWBHDF5IO(self.path, 'r') as io:
io.read()

def setUp(self):
self.path = "test_link_resolve.nwb"

def tearDown(self):
if os.path.exists(self.path):
os.remove(self.path)


class NWBHDF5IOMultiFileTest(unittest.TestCase):
"""Tests for h5tools IO tools"""

Expand Down

0 comments on commit 44b6950

Please sign in to comment.