Skip to content
Merged
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
20 changes: 20 additions & 0 deletions trx/tests/test_memmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,26 @@ def test_trxfile_close():
pass


@pytest.mark.parametrize("path", [("small.trx")])
def test_close_releases_mmap_from_zip(path):
"""close() must release mmap handles even when loaded via load_from_zip()."""
path = os.path.join(get_home(), "memmap_test_data", path)
trx = tmm.load_from_zip(path)

assert trx._uncompressed_folder_handle is None

mmap_obj = trx.streamlines._data._mmap
assert mmap_obj is not None, "expected a live mmap before close()"
assert not mmap_obj.closed, "mmap should be open before close()"

trx.close()

assert mmap_obj.closed, (
"mmap is still open after close() — the mmap teardown was skipped "
"because _uncompressed_folder_handle was None"
)


# Endianness tests for cross-platform compatibility (Issue #83)
@pytest.mark.parametrize(
"dtype_input,expected_byteorder",
Expand Down
23 changes: 11 additions & 12 deletions trx/trx_file_memmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -2260,23 +2260,22 @@ def close(self) -> None:
None
Releases file handles and removes temporary storage.
"""
if self._uncompressed_folder_handle is not None:
close_or_delete_mmap(self.streamlines)
close_or_delete_mmap(self.streamlines)

# # Close or delete attributes in dictionaries
for key in self.data_per_vertex:
close_or_delete_mmap(self.data_per_vertex[key])
for key in self.data_per_vertex:
close_or_delete_mmap(self.data_per_vertex[key])

for key in self.data_per_streamline:
close_or_delete_mmap(self.data_per_streamline[key])
for key in self.data_per_streamline:
close_or_delete_mmap(self.data_per_streamline[key])

for key in self.groups:
close_or_delete_mmap(self.groups[key])
for key in self.groups:
close_or_delete_mmap(self.groups[key])

for key in self.data_per_group:
for dpg in self.data_per_group[key]:
close_or_delete_mmap(self.data_per_group[key][dpg])
for key in self.data_per_group:
for dpg in self.data_per_group[key]:
close_or_delete_mmap(self.data_per_group[key][dpg])

if self._uncompressed_folder_handle is not None:
try:
self._uncompressed_folder_handle.cleanup()
except PermissionError:
Expand Down