1515from sqlalchemy .sql .expression import cast
1616from bids_validator import BIDSValidator
1717
18- from ..utils import listify , natural_sort
18+ from ..utils import listify , natural_sort , hashablefy
1919from ..external import inflect
2020from ..exceptions import (
2121 BIDSEntityError ,
@@ -591,6 +591,10 @@ def get(self, return_type='object', target=None, scope='all',
591591 A list of BIDSFiles (default) or strings (see return_type).
592592 """
593593
594+ if return_type not in ("object" , "file" , "filename" , "id" , "dir" ):
595+ raise ValueError ("Invalid return_type specified (must be one "
596+ "of 'object', 'file', 'filename', 'id', or 'dir'." )
597+
594598 if absolute_paths is False :
595599 absolute_path_deprecation_warning ()
596600
@@ -637,6 +641,9 @@ def get(self, return_type='object', target=None, scope='all',
637641 message = "Valid targets are: {}" .format (potential )
638642 raise TargetError (("Unknown target '{}'. " + message )
639643 .format (target ))
644+ elif target is None and return_type in ['id' , 'dir' ]:
645+ raise TargetError ('If return_type is "id" or "dir", a valid '
646+ 'target entity must also be specified.' )
640647
641648 results = []
642649 for l in layouts :
@@ -663,49 +670,42 @@ def get(self, return_type='object', target=None, scope='all',
663670 results [i ] = fi
664671
665672 if return_type .startswith ('file' ):
666- results = natural_sort ([f .path for f in results ])
667-
668- elif return_type in ['id' , 'dir' ]:
669- if target is None :
670- raise TargetError ('If return_type is "id" or "dir", a valid '
671- 'target entity must also be specified.' )
672-
673- metadata = target not in self .get_entities (metadata = False )
674-
675- if return_type == 'id' :
676- ent_iter = (x .get_entities (metadata = metadata ) for x in results )
677- results = list ({
678- ents [target ] for ents in ent_iter if target in ents
679- })
680-
681- elif return_type == 'dir' :
682- template = entities [target ].directory
683- if template is None :
684- raise ValueError ('Return type set to directory, but no '
685- 'directory template is defined for the '
686- 'target entity (\" %s\" ).' % target )
687- # Construct regex search pattern from target directory template
688- # On Windows, the regex won't compile if, e.g., there is a folder starting with "U" on the path.
689- # Converting to a POSIX path with forward slashes solves this.
690- template = self ._root .as_posix () + template
691- to_rep = re .findall (r'{(.*?)\}' , template )
692- for ent in to_rep :
693- patt = entities [ent ].pattern
694- template = template .replace ('{%s}' % ent , patt )
695- # Avoid matching subfolders. We are working with POSIX paths here, so we explicitly use "/"
696- # as path separator.
697- template += r'[^/]*$'
698- matches = [
699- f .dirname if absolute_paths else str (f ._dirname .relative_to (self ._root )) # noqa: E501
700- for f in results
701- if re .search (template , f ._dirname .as_posix ())
702- ]
703-
704- results = natural_sort (list (set (matches )))
673+ return natural_sort ([f .path for f in results ])
705674
706- else :
707- raise ValueError ("Invalid return_type specified (must be one "
708- "of 'tuple', 'filename', 'id', or 'dir'." )
675+ metadata = target not in self .get_entities (metadata = False )
676+
677+ if return_type == 'id' :
678+ ent_iter = (
679+ hashablefy (x .get_entities (metadata = metadata ))
680+ for x in results
681+ )
682+ results = list ({
683+ ents [target ] for ents in ent_iter if target in ents
684+ })
685+ elif return_type == 'dir' :
686+ template = entities [target ].directory
687+ if template is None :
688+ raise ValueError ('Return type set to directory, but no '
689+ 'directory template is defined for the '
690+ 'target entity (\" %s\" ).' % target )
691+ # Construct regex search pattern from target directory template
692+ # On Windows, the regex won't compile if, e.g., there is a folder starting with "U" on the path.
693+ # Converting to a POSIX path with forward slashes solves this.
694+ template = self ._root .as_posix () + template
695+ to_rep = re .findall (r'{(.*?)\}' , template )
696+ for ent in to_rep :
697+ patt = entities [ent ].pattern
698+ template = template .replace ('{%s}' % ent , patt )
699+ # Avoid matching subfolders. We are working with POSIX paths here, so we explicitly use "/"
700+ # as path separator.
701+ template += r'[^/]*$'
702+ matches = [
703+ f .dirname if absolute_paths else str (f ._dirname .relative_to (self ._root )) # noqa: E501
704+ for f in results
705+ if re .search (template , f ._dirname .as_posix ())
706+ ]
707+
708+ results = natural_sort (list (set (matches )))
709709 else :
710710 results = natural_sort (results , 'path' )
711711
0 commit comments