2424from typing import NewType
2525
2626from . import get_logger
27- from .consts import DandiInstance
27+ from .consts import DandiInstance , dandiset_metadata_file
2828from .dandiapi import DandiAPIClient , RemoteAsset , RemoteDandiset
2929from .dandiarchive import DandisetURL , parse_dandi_url
3030from .dandiset import Dandiset
@@ -244,7 +244,11 @@ def resolve(self, path: str) -> tuple[AssetPath, bool]:
244244 posixpath .normpath (posixpath .join (self .subpath .as_posix (), path ))
245245 )
246246 if p .parts and p .parts [0 ] == os .pardir :
247- raise ValueError (f"{ path !r} is outside of Dandiset" )
247+ raise ValueError (
248+ f"{ path !r} is outside of Dandiset. "
249+ "Paths cannot use '..' to navigate above the Dandiset root. "
250+ "All assets must remain within the Dandiset directory structure."
251+ )
248252 return (AssetPath (str (p )), path .endswith ("/" ))
249253
250254 def calculate_moves (
@@ -483,11 +487,17 @@ def get_path(self, path: str, is_src: bool = True) -> File | Folder:
483487 rpath , needs_dir = self .resolve (path )
484488 p = self .dandiset_path / rpath
485489 if not os .path .lexists (p ):
486- raise NotFoundError (f"No asset at local path { path !r} " )
490+ raise NotFoundError (
491+ f"No asset at local path { path !r} . "
492+ "Verify the path is correct and the file exists locally."
493+ )
487494 if p .is_dir ():
488495 if is_src :
489496 if p == self .dandiset_path / self .subpath :
490- raise ValueError ("Cannot move current working directory" )
497+ raise ValueError (
498+ "Cannot move current working directory. "
499+ "Change to a different directory before moving this location."
500+ )
491501 files = [
492502 df .filepath .relative_to (p ).as_posix ()
493503 for df in find_dandi_files (
@@ -499,7 +509,10 @@ def get_path(self, path: str, is_src: bool = True) -> File | Folder:
499509 files = []
500510 return Folder (rpath , files )
501511 elif needs_dir :
502- raise ValueError (f"Local path { path !r} is a file" )
512+ raise ValueError (
513+ f"Local path { path !r} is a file but a directory was expected. "
514+ "Use a path ending with '/' for directories."
515+ )
503516 else :
504517 return File (rpath )
505518
@@ -623,7 +636,10 @@ def get_path(self, path: str, is_src: bool = True) -> File | Folder:
623636 file_found = False
624637 if rpath == self .subpath .as_posix ():
625638 if is_src :
626- raise ValueError ("Cannot move current working directory" )
639+ raise ValueError (
640+ "Cannot move current working directory. "
641+ "Change to a different directory before moving this location."
642+ )
627643 else :
628644 return Folder (rpath , [])
629645 for p in self .assets .keys ():
@@ -640,7 +656,10 @@ def get_path(self, path: str, is_src: bool = True) -> File | Folder:
640656 if relcontents :
641657 return Folder (rpath , relcontents )
642658 if needs_dir and file_found :
643- raise ValueError (f"Remote path { path !r} is a file" )
659+ raise ValueError (
660+ f"Remote path { path !r} is a file but a directory was expected. "
661+ "Use a path ending with '/' for directories."
662+ )
644663 elif (
645664 not needs_dir
646665 and not is_src
@@ -652,7 +671,11 @@ def get_path(self, path: str, is_src: bool = True) -> File | Folder:
652671 # remote directory.
653672 return Folder (rpath , [])
654673 else :
655- raise NotFoundError (f"No asset at remote path { path !r} " )
674+ raise NotFoundError (
675+ f"No asset at remote path { path !r} . "
676+ "Verify the path is correct and the asset exists on the server. "
677+ "Use 'dandi ls' to list available assets."
678+ )
656679
657680 def is_dir (self , path : AssetPath ) -> bool :
658681 """Returns true if the given path points to a directory"""
@@ -902,7 +925,11 @@ def find_dandiset_and_subpath(path: Path) -> tuple[Dandiset, Path]:
902925 path = path .absolute ()
903926 ds = Dandiset .find (path )
904927 if ds is None :
905- raise ValueError (f"{ path } : not a Dandiset" )
928+ raise ValueError (
929+ f"{ path } : not a Dandiset. "
930+ f"The directory does not contain a '{ dandiset_metadata_file } ' file. "
931+ "Use 'dandi download' to download a dandiset first."
932+ )
906933 return (ds , path .relative_to (ds .path ))
907934
908935
0 commit comments