5858from easybuild .tools .build_log import EasyBuildError , print_error , print_msg , print_warning
5959from easybuild .tools .config import build_option
6060from easybuild .tools .environment import restore_env
61- from easybuild .tools .filetools import find_easyconfigs , is_patch_file , locate_files
61+ from easybuild .tools .filetools import EASYBLOCK_CLASS_PREFIX , find_easyconfigs , is_patch_file , locate_files
6262from easybuild .tools .filetools import read_file , resolve_path , which , write_file
6363from easybuild .tools .github import GITHUB_EASYCONFIGS_REPO
6464from easybuild .tools .github import det_pr_labels , det_pr_title , download_repo , fetch_easyconfigs_from_commit
@@ -758,7 +758,7 @@ def avail_easyblocks():
758758 """Return a list of all available easyblocks."""
759759
760760 module_regexp = re .compile (r"^([^_].*)\.py$" )
761- class_regex = re .compile (r"^class ([^(]*)\(" , re .M )
761+ class_regex = re .compile (r"^class ([^(: ]*)\(" , re .M )
762762
763763 # finish initialisation of the toolchain module (ie set the TC_CONSTANT constants)
764764 search_toolchain ('' )
@@ -768,33 +768,43 @@ def avail_easyblocks():
768768 __import__ (pkg )
769769
770770 # determine paths for this package
771- paths = sys .modules [pkg ].__path__
771+ paths = [ path for path in sys .modules [pkg ].__path__ if os . path . exists ( path )]
772772
773773 # import all modules in these paths
774774 for path in paths :
775- if os .path . exists (path ):
776- for fn in os . listdir ( path ):
777- res = module_regexp . match ( fn )
778- if res :
779- easyblock_mod_name = '%s.%s' % ( pkg , res .group (1 ) )
780-
781- if easyblock_mod_name not in easyblocks :
782- __import__ ( easyblock_mod_name )
783- easyblock_loc = os . path . join ( path , fn )
784-
785- class_names = class_regex . findall ( read_file ( easyblock_loc ))
786- if len ( class_names ) == 1 :
787- easyblock_class = class_names [ 0 ]
788- elif class_names :
789- raise EasyBuildError ( "Found multiple class names for easyblock %s: %s" ,
790- easyblock_loc , class_names )
791- else :
792- raise EasyBuildError ( "Failed to determine easyblock class name for %s" , easyblock_loc )
793-
794- easyblocks [ easyblock_mod_name ] = { 'class' : easyblock_class , 'loc' : easyblock_loc }
775+ for fn in os .listdir (path ):
776+ res = module_regexp . match ( fn )
777+ if not res :
778+ continue
779+ easyblock_mod_name = res .group (1 )
780+ easyblock_full_mod_name = '%s.%s' % ( pkg , easyblock_mod_name )
781+
782+ if easyblock_full_mod_name in easyblocks :
783+ _log . debug ( "%s already imported from %s, ignoring %s" ,
784+ easyblock_full_mod_name , easyblocks [ easyblock_full_mod_name ][ 'loc' ], path )
785+ else :
786+ __import__ ( easyblock_full_mod_name )
787+ easyblock_loc = os . path . join ( path , fn )
788+
789+ class_names = class_regex . findall ( read_file ( easyblock_loc ))
790+ if len ( class_names ) > 1 :
791+ if pkg . endswith ( '.generic' ) :
792+ # In generic easyblocks we have e.g. ConfigureMake in configuremake.py
793+ sw_specific_class_names = [ name for name in class_names
794+ if name . lower () == easyblock_mod_name . lower ()]
795795 else :
796- _log .debug ("%s already imported from %s, ignoring %s" ,
797- easyblock_mod_name , easyblocks [easyblock_mod_name ]['loc' ], path )
796+ # If there is exactly one software specific easyblock we use that
797+ sw_specific_class_names = [name for name in class_names
798+ if name .startswith (EASYBLOCK_CLASS_PREFIX )]
799+ if len (sw_specific_class_names ) == 1 :
800+ class_names = sw_specific_class_names
801+ if len (class_names ) == 1 :
802+ easyblocks [easyblock_full_mod_name ] = {'class' : class_names [0 ], 'loc' : easyblock_loc }
803+ elif class_names :
804+ raise EasyBuildError ("Found multiple class names for easyblock %s: %s" ,
805+ easyblock_loc , class_names )
806+ else :
807+ raise EasyBuildError ("Failed to determine easyblock class name for %s" , easyblock_loc )
798808
799809 return easyblocks
800810
0 commit comments