5151from  zarr .core .metadata  import  ArrayV2Metadata , ArrayV3Metadata 
5252from  zarr .core .metadata .v3  import  V3JsonEncoder , _replace_special_floats 
5353from  zarr .core .sync  import  SyncMixin , sync 
54- from  zarr .errors  import  ContainsArrayError , ContainsGroupError , MetadataValidationError 
54+ from  zarr .errors  import  (
55+     ArrayNotFoundError ,
56+     ContainsArrayError ,
57+     ContainsGroupError ,
58+     GroupNotFoundError ,
59+     MetadataValidationError ,
60+     NodeNotFoundError ,
61+ )
5562from  zarr .storage  import  StoreLike , StorePath 
5663from  zarr .storage ._common  import  ensure_no_existing_node , make_store_path 
5764from  zarr .storage ._utils  import  _join_paths , _normalize_path_keys , normalize_path 
@@ -509,7 +516,11 @@ async def open(
509516                * [path .get () for  path  in  paths ]
510517            )
511518            if  zgroup_bytes  is  None :
512-                 raise  FileNotFoundError (store_path )
519+                 msg  =  (
520+                     "Zarr V2 group metadata was not found in " 
521+                     f"store { store_path .store !r} { store_path .path !r}  
522+                 )
523+                 raise  GroupNotFoundError (msg )
513524
514525            if  use_consolidated  or  use_consolidated  is  None :
515526                maybe_consolidated_metadata_bytes  =  rest [0 ]
@@ -520,7 +531,11 @@ async def open(
520531        elif  zarr_format  ==  3 :
521532            zarr_json_bytes  =  await  (store_path  /  ZARR_JSON ).get ()
522533            if  zarr_json_bytes  is  None :
523-                 raise  FileNotFoundError (store_path )
534+                 msg  =  (
535+                     "Zarr V3 group metadata was not found in " 
536+                     f"{ store_path .store !r} { store_path .path !r}  
537+                 )
538+                 raise  GroupNotFoundError (store_path .store , store_path .path )
524539        elif  zarr_format  is  None :
525540            (
526541                zarr_json_bytes ,
@@ -535,19 +550,27 @@ async def open(
535550            )
536551            if  zarr_json_bytes  is  not None  and  zgroup_bytes  is  not None :
537552                # warn and favor v3 
538-                 msg  =  f"Both zarr.json (Zarr format 3) and .zgroup (Zarr format 2) metadata objects exist at { store_path }  
553+                 msg  =  (
554+                     "Both zarr.json (Zarr format 3) and .zarray (Zarr format 2) metadata objects " 
555+                     f"exist in store { store_path .store !r} { store_path .path !r}  
556+                     "The Zarr V3 metadata will be used." 
557+                     "To open Zarr V2 groups, set zarr_format=2." 
558+                 )
539559                warnings .warn (msg , stacklevel = 1 )
540560            if  zarr_json_bytes  is  None  and  zgroup_bytes  is  None :
541-                 raise  FileNotFoundError (
542-                     f"could not find zarr.json or .zgroup objects in { store_path }  
561+                 msg  =  (
562+                     f"Neither Zarr V2 nor Zarr V3 Group metadata was not found in store " 
563+                     f"{ store_path .store !r} { store_path .path !r}  
543564                )
565+                 raise  GroupNotFoundError (msg )
544566            # set zarr_format based on which keys were found 
545567            if  zarr_json_bytes  is  not None :
546568                zarr_format  =  3 
547569            else :
548570                zarr_format  =  2 
549571        else :
550-             raise  MetadataValidationError ("zarr_format" , "2, 3, or None" , zarr_format )
572+             msg  =  f"Invalid value for zarr_format. Expected one of 2, 3 or None. Got { zarr_format }    # type: ignore[unreachable] 
573+             raise  MetadataValidationError (msg )
551574
552575        if  zarr_format  ==  2 :
553576            # this is checked above, asserting here for mypy 
@@ -569,7 +592,11 @@ async def open(
569592            # V3 groups are comprised of a zarr.json object 
570593            assert  zarr_json_bytes  is  not None 
571594            if  not  isinstance (use_consolidated , bool  |  None ):
572-                 raise  TypeError ("use_consolidated must be a bool or None for Zarr format 3." )
595+                 msg  =  (
596+                     "use_consolidated must be a bool or None for Zarr format 3. " 
597+                     f"Got { use_consolidated }  
598+                 )
599+                 raise  TypeError (msg )
573600
574601            return  cls ._from_bytes_v3 (
575602                store_path ,
@@ -628,7 +655,7 @@ def _from_bytes_v3(
628655    ) ->  AsyncGroup :
629656        group_metadata  =  json .loads (zarr_json_bytes .to_bytes ())
630657        if  use_consolidated  and  group_metadata .get ("consolidated_metadata" ) is  None :
631-             msg  =  f"Consolidated metadata requested with 'use_consolidated=True' but not found in '{ store_path .path }  
658+             msg  =  f"Consolidated metadata requested with 'use_consolidated=True' but not found in '{ store_path .path !r }  
632659            raise  ValueError (msg )
633660
634661        elif  use_consolidated  is  False :
@@ -691,7 +718,7 @@ async def getitem(
691718            return  await  get_node (
692719                store = store_path .store , path = store_path .path , zarr_format = self .metadata .zarr_format 
693720            )
694-         except  FileNotFoundError  as  e :
721+         except  ( ArrayNotFoundError ,  GroupNotFoundError )  as  e :
695722            raise  KeyError (key ) from  e 
696723
697724    def  _getitem_consolidated (
@@ -2981,7 +3008,7 @@ async def create_hierarchy(
29813008
29823009        for  key , value  in  zip (implicit_group_keys , maybe_extant_groups , strict = True ):
29833010            if  isinstance (value , BaseException ):
2984-                 if  isinstance (value , FileNotFoundError ):
3011+                 if  isinstance (value , GroupNotFoundError ):
29853012                    # this is fine -- there was no group there, so we will create one 
29863013                    pass 
29873014                else :
@@ -3025,8 +3052,9 @@ async def create_hierarchy(
30253052            for  key , extant_node  in  extant_node_query .items ():
30263053                proposed_node  =  nodes_parsed [key ]
30273054                if  isinstance (extant_node , BaseException ):
3028-                     if  isinstance (extant_node , FileNotFoundError ):
3029-                         # ignore FileNotFoundError, because they represent nodes we can safely create 
3055+                     if  isinstance (extant_node , (ArrayNotFoundError , GroupNotFoundError )):
3056+                         # ignore ArrayNotFoundError / GroupNotFoundError. 
3057+                         # They represent nodes we can safely create. 
30303058                        pass 
30313059                    else :
30323060                        # Any other exception is a real error 
@@ -3209,7 +3237,8 @@ def _parse_hierarchy_dict(
32093237            else :
32103238                if  not  isinstance (out [subpath ], GroupMetadata  |  ImplicitGroupMarker ):
32113239                    msg  =  (
3212-                         f"The node at { subpath }  
3240+                         f"The node at path { subpath !r}  
3241+                         "but it is not a Zarr group. " 
32133242                        "This is invalid. Only Zarr groups can contain other nodes." 
32143243                    )
32153244                    raise  ValueError (msg )
@@ -3374,7 +3403,8 @@ async def _read_metadata_v3(store: Store, path: str) -> ArrayV3Metadata | GroupM
33743403        _join_paths ([path , ZARR_JSON ]), prototype = default_buffer_prototype ()
33753404    )
33763405    if  zarr_json_bytes  is  None :
3377-         raise  FileNotFoundError (path )
3406+         msg  =  f"Neither array nor group metadata were found in store { store !r} { path !r}  
3407+         raise  NodeNotFoundError (msg )
33783408    else :
33793409        zarr_json  =  json .loads (zarr_json_bytes .to_bytes ())
33803410        return  _build_metadata_v3 (zarr_json )
@@ -3383,8 +3413,8 @@ async def _read_metadata_v3(store: Store, path: str) -> ArrayV3Metadata | GroupM
33833413async  def  _read_metadata_v2 (store : Store , path : str ) ->  ArrayV2Metadata  |  GroupMetadata :
33843414    """ 
33853415    Given a store_path, return ArrayV2Metadata or GroupMetadata defined by the metadata 
3386-     document stored at store_path.path / (.zgroup | .zarray). If no such  document is found, 
3387-     raise a FileNotFoundError . 
3416+     document stored at store_path.path / (.zgroup | .zarray). If no metadata  document is found, 
3417+     this routine raises a ``NodeNotFoundError`` . 
33883418    """ 
33893419    # TODO: consider first fetching array metadata, and only fetching group metadata when we don't 
33903420    # find an array 
@@ -3406,8 +3436,12 @@ async def _read_metadata_v2(store: Store, path: str) -> ArrayV2Metadata | GroupM
34063436        zmeta  =  json .loads (zarray_bytes .to_bytes ())
34073437    else :
34083438        if  zgroup_bytes  is  None :
3409-             # neither .zarray or .zgroup were found results in KeyError 
3410-             raise  FileNotFoundError (path )
3439+             # neither .zarray or .zgroup were found results in NodeNotFoundError 
3440+             msg  =  (
3441+                 "Neither array nor group metadata were found in " 
3442+                 f"{ store !r} { path !r}  
3443+             )
3444+             raise  NodeNotFoundError (msg )
34113445        else :
34123446            zmeta  =  json .loads (zgroup_bytes .to_bytes ())
34133447
@@ -3416,21 +3450,39 @@ async def _read_metadata_v2(store: Store, path: str) -> ArrayV2Metadata | GroupM
34163450
34173451async  def  _read_group_metadata_v2 (store : Store , path : str ) ->  GroupMetadata :
34183452    """ 
3419-     Read group metadata or error  
3453+     Read Zarr V2 group metadata.  
34203454    """ 
3421-     meta  =  await  _read_metadata_v2 (store = store , path = path )
3455+     try :
3456+         meta  =  await  _read_metadata_v2 (store = store , path = path )
3457+     except  NodeNotFoundError  as  e :
3458+         # NodeNotFoundError is raised when neither array nor group metadata were found, 
3459+         # but since this function is concerned with group metadata, 
3460+         # it returns a more specific exception here. 
3461+         msg  =  f"A group metadata document was not found in store { store !r} { path !r}  
3462+         raise  GroupNotFoundError (msg ) from  e 
34223463    if  not  isinstance (meta , GroupMetadata ):
3423-         raise  FileNotFoundError (f"Group metadata was not found in { store } { path }  )
3464+         msg  =  (f"Group metadata was not found in store { store !r} { path !r}  ,)
3465+         "An array metadata document was found there instead." 
3466+         raise  GroupNotFoundError (msg )
34243467    return  meta 
34253468
34263469
34273470async  def  _read_group_metadata_v3 (store : Store , path : str ) ->  GroupMetadata :
34283471    """ 
3429-     Read group metadata or error  
3472+     Read Zarr V3 group metadata.  
34303473    """ 
3431-     meta  =  await  _read_metadata_v3 (store = store , path = path )
3474+     try :
3475+         meta  =  await  _read_metadata_v3 (store = store , path = path )
3476+     except  NodeNotFoundError  as  e :
3477+         # NodeNotFoundError is raised when neither array nor group metadata were found, 
3478+         # but since this function is concerned with group metadata, 
3479+         # it returns a more specific exception here. 
3480+         msg  =  f"A group metadata document was not found in store { store !r} { path !r}  
3481+         raise  GroupNotFoundError (msg ) from  e 
34323482    if  not  isinstance (meta , GroupMetadata ):
3433-         raise  FileNotFoundError (f"Group metadata was not found in { store } { path }  )
3483+         msg  =  (f"Group metadata was not found in store { store !r} { path !r}  ,)
3484+         "An array metadata document was found there instead." 
3485+         raise  GroupNotFoundError (msg )
34343486    return  meta 
34353487
34363488
0 commit comments