Skip to content
Open
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
23 changes: 21 additions & 2 deletions brainglobe_atlasapi/bg_atlas.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Defines the BrainGlobeAtlas class for accessing brain atlas data."""

import shutil
import tarfile
import warnings
from collections.abc import Callable
from io import StringIO
from pathlib import Path
Expand Down Expand Up @@ -96,7 +98,24 @@ def __init__(
self.download_extract_file()

# Instantiate after eventual download:
super().__init__(self.brainglobe_dir / self.local_full_name)
for attempt in (0, 1):
try:
super().__init__(self.brainglobe_dir / self.local_full_name)
break
except (FileNotFoundError, ValueError):
if attempt == 1:
raise

atlas_path = self.brainglobe_dir / self.local_full_name
if atlas_path.exists() and atlas_path.is_dir():
warnings.warn(
"Atlas metadata appears corrupted or incomplete. "
"Re-downloading atlas...",
UserWarning,
)
shutil.rmtree(atlas_path)

self.download_extract_file()

if check_latest:
self.check_latest_version()
Expand Down Expand Up @@ -155,7 +174,7 @@ def local_full_name(self) -> Optional[str]:

@property
def remote_url(self) -> Optional[str]:
"""Format complete url for download."""
"""Format complete url for download, or None if unavailable."""
if self.remote_version is not None:
name = (
f"{self.atlas_name}_v{self.remote_version[0]}."
Expand Down
37 changes: 37 additions & 0 deletions tests/atlasapi/test_recovery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Tests for recovery behavior when atlas metadata is missing."""

from brainglobe_atlasapi.bg_atlas import BrainGlobeAtlas


def test_recovers_missing_metadata(mocker):
"""Test recovery when atlas metadata is missing."""
# Mock Atlas.__init__: fail once, succeed second time
mock_atlas_init = mocker.patch(
"brainglobe_atlasapi.core.Atlas.__init__",
side_effect=[FileNotFoundError("Missing metadata"), None],
autospec=True,
)

# Mock local_full_name to simulate a valid atlas folder
mocker.patch(
"brainglobe_atlasapi.bg_atlas.BrainGlobeAtlas.local_full_name",
new_callable=mocker.PropertyMock,
return_value="example_mouse_100um_v1.0",
)

# Prevent real IO
mock_download = mocker.patch(
"brainglobe_atlasapi.bg_atlas.BrainGlobeAtlas.download_extract_file"
)
mocker.patch(
"brainglobe_atlasapi.bg_atlas.BrainGlobeAtlas.check_latest_version"
)

mocker.patch("brainglobe_atlasapi.bg_atlas.shutil.rmtree")

# Act
BrainGlobeAtlas("example_mouse_100um", check_latest=False)

# Assert
assert mock_atlas_init.call_count == 2
mock_download.assert_called_once()
Loading