Skip to content

Commit c58bd37

Browse files
Merge pull request #1791 from dandi/enh-lad-errors-api
Enhance API client error messages
2 parents 0c60106 + a80426b commit c58bd37

3 files changed

Lines changed: 57 additions & 13 deletions

File tree

dandi/dandiapi.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,11 @@ def __init__(
447447
dandi_instance = get_instance(instance_name)
448448
api_url = dandi_instance.api
449449
elif dandi_instance is not None:
450-
raise ValueError("api_url and dandi_instance are mutually exclusive")
450+
raise ValueError(
451+
"api_url and dandi_instance are mutually exclusive. "
452+
"Use either 'api_url' to specify a custom API URL, "
453+
"or 'dandi_instance' to use a registered DANDI instance, but not both."
454+
)
451455
else:
452456
dandi_instance = get_instance(api_url)
453457
super().__init__(api_url)
@@ -574,7 +578,10 @@ def get_dandiset(
574578
self, self.get(f"/dandisets/{dandiset_id}/")
575579
)
576580
except HTTP404Error:
577-
raise NotFoundError(f"No such Dandiset: {dandiset_id!r}")
581+
raise NotFoundError(
582+
f"No such Dandiset: {dandiset_id!r}. "
583+
"Verify the Dandiset ID is correct and that you have access. "
584+
)
578585
if version_id is not None and version_id != d.version_id:
579586
if version_id == DRAFT:
580587
return d.for_version(d.draft_version)
@@ -744,7 +751,11 @@ def get_asset(self, asset_id: str) -> BaseRemoteAsset:
744751
try:
745752
info = self.get(f"/assets/{asset_id}/info/")
746753
except HTTP404Error:
747-
raise NotFoundError(f"No such asset: {asset_id!r}")
754+
raise NotFoundError(
755+
f"No such asset: {asset_id!r}. "
756+
"Verify the asset ID is correct. "
757+
"Use 'dandi ls' to list available assets."
758+
)
748759
metadata = info.pop("metadata", None)
749760
return BaseRemoteAsset.from_base_data(self, info, metadata)
750761

@@ -1318,7 +1329,11 @@ def get_asset_by_path(self, path: str) -> RemoteAsset:
13181329
a for a in self.get_assets_with_path_prefix(path) if a.path == path
13191330
)
13201331
except ValueError:
1321-
raise NotFoundError(f"No asset at path {path!r}")
1332+
raise NotFoundError(
1333+
f"No asset at path {path!r} in version {self.version_id}. "
1334+
"Verify the path is correct and the asset exists in this version. "
1335+
"Use 'dandi ls' to list available assets."
1336+
)
13221337
else:
13231338
return asset
13241339

dandi/tests/test_dandiarchive.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -588,11 +588,17 @@ def test_get_nonexistent_dandiset(
588588
parsed_url.get_dandiset(client) # No error
589589
with pytest.raises(NotFoundError) as excinfo:
590590
parsed_url.get_dandiset(client, lazy=False)
591-
assert str(excinfo.value) == "No such Dandiset: '999999'"
591+
assert str(excinfo.value) == (
592+
"No such Dandiset: '999999'. "
593+
"Verify the Dandiset ID is correct and that you have access. "
594+
)
592595
assert list(parsed_url.get_assets(client)) == []
593596
with pytest.raises(NotFoundError) as excinfo:
594597
next(parsed_url.get_assets(client, strict=True))
595-
assert str(excinfo.value) == "No such Dandiset: '999999'"
598+
assert str(excinfo.value) == (
599+
"No such Dandiset: '999999'. "
600+
"Verify the Dandiset ID is correct and that you have access. "
601+
)
596602

597603

598604
@pytest.mark.parametrize("version", ["draft", "0.999999.9999"])
@@ -608,7 +614,10 @@ def test_get_nonexistent_dandiset_asset_id(
608614
assert list(parsed_url.get_assets(client)) == []
609615
with pytest.raises(NotFoundError) as excinfo:
610616
next(parsed_url.get_assets(client, strict=True))
611-
assert str(excinfo.value) == "No such Dandiset: '999999'"
617+
assert str(excinfo.value) == (
618+
"No such Dandiset: '999999'. "
619+
"Verify the Dandiset ID is correct and that you have access. "
620+
)
612621

613622

614623
def test_get_dandiset_nonexistent_asset_id(text_dandiset: SampleDandiset) -> None:
@@ -635,7 +644,11 @@ def test_get_nonexistent_asset_id(local_dandi_api: DandiAPI) -> None:
635644
assert list(parsed_url.get_assets(client)) == []
636645
with pytest.raises(NotFoundError) as excinfo:
637646
next(parsed_url.get_assets(client, strict=True))
638-
assert str(excinfo.value) == "No such asset: '00000000-0000-0000-0000-000000000000'"
647+
assert str(excinfo.value) == (
648+
"No such asset: '00000000-0000-0000-0000-000000000000'. "
649+
"Verify the asset ID is correct. "
650+
"Use 'dandi ls' to list available assets."
651+
)
639652

640653

641654
@pytest.mark.parametrize("version_suffix", ["", "@draft", "@0.999999.9999"])
@@ -648,7 +661,10 @@ def test_get_nonexistent_dandiset_asset_path(
648661
assert list(parsed_url.get_assets(client)) == []
649662
with pytest.raises(NotFoundError) as excinfo:
650663
next(parsed_url.get_assets(client, strict=True))
651-
assert str(excinfo.value) == "No such Dandiset: '999999'"
664+
assert str(excinfo.value) == (
665+
"No such Dandiset: '999999'. "
666+
"Verify the Dandiset ID is correct and that you have access. "
667+
)
652668

653669

654670
def test_get_nonexistent_asset_path(text_dandiset: SampleDandiset) -> None:
@@ -661,7 +677,11 @@ def test_get_nonexistent_asset_path(text_dandiset: SampleDandiset) -> None:
661677
assert list(parsed_url.get_assets(client)) == []
662678
with pytest.raises(NotFoundError) as excinfo:
663679
next(parsed_url.get_assets(client, strict=True))
664-
assert str(excinfo.value) == "No asset at path 'does/not/exist'"
680+
assert str(excinfo.value) == (
681+
"No asset at path 'does/not/exist' in version draft. "
682+
"Verify the path is correct and the asset exists in this version. "
683+
"Use 'dandi ls' to list available assets."
684+
)
665685

666686

667687
@pytest.mark.parametrize("version_suffix", ["", "@draft", "@0.999999.9999"])
@@ -677,7 +697,10 @@ def test_get_nonexistent_dandiset_asset_folder(
677697
assert list(parsed_url.get_assets(client)) == []
678698
with pytest.raises(NotFoundError) as excinfo:
679699
next(parsed_url.get_assets(client, strict=True))
680-
assert str(excinfo.value) == "No such Dandiset: '999999'"
700+
assert str(excinfo.value) == (
701+
"No such Dandiset: '999999'. "
702+
"Verify the Dandiset ID is correct and that you have access. "
703+
)
681704

682705

683706
def test_get_nonexistent_asset_folder(text_dandiset: SampleDandiset) -> None:
@@ -706,7 +729,10 @@ def test_get_nonexistent_dandiset_asset_prefix(
706729
assert list(parsed_url.get_assets(client)) == []
707730
with pytest.raises(NotFoundError) as excinfo:
708731
next(parsed_url.get_assets(client, strict=True))
709-
assert str(excinfo.value) == "No such Dandiset: '999999'"
732+
assert str(excinfo.value) == (
733+
"No such Dandiset: '999999'. "
734+
"Verify the Dandiset ID is correct and that you have access. "
735+
)
710736

711737

712738
def test_get_nonexistent_asset_prefix(text_dandiset: SampleDandiset) -> None:

dandi/tests/test_delete.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,10 @@ def test_delete_nonexistent_dandiset(
252252
devel_debug=True,
253253
force=True,
254254
)
255-
assert str(excinfo.value) == "No such Dandiset: '999999'"
255+
assert str(excinfo.value) == (
256+
"No such Dandiset: '999999'. "
257+
"Verify the Dandiset ID is correct and that you have access. "
258+
)
256259
delete_spy.assert_not_called()
257260

258261

0 commit comments

Comments
 (0)