Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error on NWB files with external links #843

Merged
merged 3 commits into from
Dec 13, 2021
Merged

Error on NWB files with external links #843

merged 3 commits into from
Dec 13, 2021

Conversation

jwodder
Copy link
Member

@jwodder jwodder commented Nov 24, 2021

Closes #840.

@jwodder jwodder added the minor Increment the minor version when merged label Nov 24, 2021
@codecov
Copy link

codecov bot commented Nov 24, 2021

Codecov Report

Merging #843 (247a7cd) into master (dfb9770) will increase coverage by 0.07%.
The diff coverage is 95.91%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #843      +/-   ##
==========================================
+ Coverage   85.28%   85.35%   +0.07%     
==========================================
  Files          61       61              
  Lines        6322     6366      +44     
==========================================
+ Hits         5392     5434      +42     
- Misses        930      932       +2     
Flag Coverage Δ
unittests 85.35% <95.91%> (+0.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
dandi/metadata.py 81.99% <50.00%> (-0.18%) ⬇️
dandi/pynwb_utils.py 83.15% <95.00%> (+1.18%) ⬆️
dandi/tests/test_pynwb_utils.py 97.72% <100.00%> (+2.72%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update dfb9770...247a7cd. Read the comment docs.

@jwodder
Copy link
Member Author

jwodder commented Nov 24, 2021

@yarikoptic The tests appear to be failing because this call to copy_nwb_file() produces a file with an external link.

@bendichter What's the best way to copy an NWB file while giving it a new object_id without creating an external link?

@jwodder jwodder marked this pull request as draft November 24, 2021 15:29
Comment on lines +367 to +387
@metadata_cache.memoize_path
def nwb_has_external_links(filepath):
with h5py.File(filepath, "r") as fp:
visited = set()

# cannot use `file.visititems` because it skips external links
# (https://github.com/h5py/h5py/issues/671)
def visit(path="/"):
if isinstance(fp[path], h5py.Group):
for key in fp[path].keys():
key_path = path + "/" + key
if key_path not in visited:
visited.add(key_path)
if isinstance(
fp.get(key_path, getlink=True), h5py.ExternalLink
) or visit(key_path):
return True
elif isinstance(fp.get(path, getlink=True), h5py.ExternalLink):
return True
return False

return visit()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, thank you for tidying up this function.

@bendichter
Copy link
Member

@jwodder

What's the best way to copy an NWB file while giving it a new object_id without creating an external link?

I'm surprised you are running into this issue, especially since link_data is False. @rly would be the person to ask about copying NWB files using PyNWB.

@yarikoptic
Copy link
Member

pinged @rly on slack

@oruebel
Copy link

oruebel commented Nov 29, 2021

What's the best way to copy an NWB file while giving it a new object_id without creating an external link?

I think a combination of the generate_new_id and NWBHDFIO.export functions should work for this.

If you just want to resolve external links, the NWBHDF5IO.copy_file may also do the trick. This function works lower level by using the copy method from h5pyand has been deprecated in favor of ``export`, but I figured I'd mention is just in case the source code of that function are useful for you.

@jwodder
Copy link
Member Author

jwodder commented Nov 29, 2021

@oruebel

I think a combination of the generate_new_id and NWBHDFIO.export functions should work for this.

How exactly do I combine those two functions? If I try doing this:

with pynwb.NWBHDF5IO(src, "r") as ior, pynwb.NWBHDF5IO(dest, "w") as iow:
    data = ior.read()
    data.generate_new_id()
    iow.export(container=data)

I get TypeError: NWBHDF5IO.export: missing argument 'src_io', unrecognized argument: 'container'.

If I instead do this:

with pynwb.NWBHDF5IO(src, "r") as ior, pynwb.NWBHDF5IO(dest, "w") as iow:
    data = ior.read()
    data.generate_new_id()
    iow.export(src_io=ior)

then the copy will still have the same object ID as the original.

If I do this:

with pynwb.NWBHDF5IO(src, "r") as ior, pynwb.NWBHDF5IO(dest, "w") as iow:
    ior.generate_new_id()
    iow.export(src_io=ior)

then I get AttributeError: 'NWBHDF5IO' object has no attribute 'generate_new_id'.

@rly
Copy link
Contributor

rly commented Nov 29, 2021

Please try:

with pynwb.NWBHDF5IO(src, "r") as ior, pynwb.NWBHDF5IO(dest, "w") as iow:
    data = ior.read()
    data.generate_new_id()
    iow.export(ior, container=data)

@jwodder
Copy link
Member Author

jwodder commented Nov 29, 2021

@rly That fails with "TypeError: NWBHDF5IO.export: unrecognized argument: 'container'" (I'm using hdmf 3.1.1.)

@rly
Copy link
Contributor

rly commented Nov 29, 2021

My bad. 'container' is the argument name for HDF5IO. Please try:

with pynwb.NWBHDF5IO(src, "r") as ior, pynwb.NWBHDF5IO(dest, "w") as iow:
    data = ior.read()
    data.generate_new_id()
    iow.export(ior, nwbfile=data)

@jwodder
Copy link
Member Author

jwodder commented Nov 29, 2021

@rly That works; thanks.

@jwodder jwodder marked this pull request as ready for review November 29, 2021 21:59
@yarikoptic
Copy link
Member

tox.ini is very popular today - keeps conflicting

) or visit(key_path):
return True
elif isinstance(fp.get(path, getlink=True), h5py.ExternalLink):
return True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bendichter what use case could trigger this codepath? would be nice to add it to the test

@jwodder
Copy link
Member Author

jwodder commented Nov 30, 2021

@yarikoptic Conflict resolved.

@yarikoptic
Copy link
Member

ok, let's proceed with it as is. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
minor Increment the minor version when merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

detect external links
5 participants