@@ -91,89 +91,88 @@ def __init__(self, *args, **kwargs):
9191 self .cfg = self .cfg .copy ()
9292
9393 # disable templating to avoid premature resolving of template values
94- self .cfg .enable_templating = False
95-
96- # list of checksums for patches (must be included after checksums for sources)
97- checksums_patches = []
98-
99- if self .cfg ['sanity_check_components' ] and self .cfg ['sanity_check_all_components' ]:
100- raise EasyBuildError ("sanity_check_components and sanity_check_all_components cannot be enabled together" )
101-
102- # backup and reset general sanity checks from main body of ec, if component-specific sanity checks are enabled
103- # necessary to avoid:
104- # - duplicating the general sanity check across all components running sanity checks
105- # - general sanity checks taking precedence over those defined in a component's easyblock
106- self .backup_sanity_paths = self .cfg ['sanity_check_paths' ]
107- self .backup_sanity_cmds = self .cfg ['sanity_check_commands' ]
108- if self .cfg ['sanity_check_components' ] or self .cfg ['sanity_check_all_components' ]:
109- # reset general sanity checks, to be restored later
110- self .cfg ['sanity_check_paths' ] = {}
111- self .cfg ['sanity_check_commands' ] = {}
112-
113- for comp in self .cfg ['components' ]:
114- comp_name , comp_version , comp_specs = comp [0 ], comp [1 ], {}
115- if len (comp ) == 3 :
116- comp_specs = comp [2 ]
117-
118- comp_cfg = self .cfg .copy ()
119-
120- comp_cfg ['name' ] = comp_name
121- comp_cfg ['version' ] = comp_version
122-
123- # determine easyblock to use for this component
124- # - if an easyblock is specified explicitely, that will be used
125- # - if not, a software-specific easyblock will be considered by get_easyblock_class
126- # - if no easyblock was found, default_easyblock is considered
127- comp_easyblock = comp_specs .get ('easyblock' )
128- easyblock_class = get_easyblock_class (comp_easyblock , name = comp_name , error_on_missing_easyblock = False )
129- if easyblock_class is None :
130- if self .cfg ['default_easyblock' ]:
131- easyblock = self .cfg ['default_easyblock' ]
132- easyblock_class = get_easyblock_class (easyblock )
133-
94+ # Note that self.cfg.update also resolves templates!
95+ with self .cfg .disable_templating ():
96+ # list of checksums for patches (must be included after checksums for sources)
97+ checksums_patches = []
98+
99+ if self .cfg ['sanity_check_components' ] and self .cfg ['sanity_check_all_components' ]:
100+ raise EasyBuildError ("sanity_check_components and sanity_check_all_components"
101+ "cannot be enabled together" )
102+
103+ # backup and reset general sanity checks from main body of ec,
104+ # if component-specific sanity checks are enabled necessary to avoid:
105+ # - duplicating the general sanity check across all components running sanity checks
106+ # - general sanity checks taking precedence over those defined in a component's easyblock
107+ self .backup_sanity_paths = self .cfg ['sanity_check_paths' ]
108+ self .backup_sanity_cmds = self .cfg ['sanity_check_commands' ]
109+ if self .cfg ['sanity_check_components' ] or self .cfg ['sanity_check_all_components' ]:
110+ # reset general sanity checks, to be restored later
111+ self .cfg ['sanity_check_paths' ] = {}
112+ self .cfg ['sanity_check_commands' ] = {}
113+ components = self .cfg ['components' ]
114+
115+ for comp in components :
116+ comp_name , comp_version , comp_specs = comp [0 ], comp [1 ], {}
117+ if len (comp ) == 3 :
118+ comp_specs = comp [2 ]
119+
120+ comp_cfg = self .cfg .copy ()
121+
122+ comp_cfg ['name' ] = comp_name
123+ comp_cfg ['version' ] = comp_version
124+
125+ # determine easyblock to use for this component
126+ # - if an easyblock is specified explicitely, that will be used
127+ # - if not, a software-specific easyblock will be considered by get_easyblock_class
128+ # - if no easyblock was found, default_easyblock is considered
129+ comp_easyblock = comp_specs .get ('easyblock' )
130+ easyblock_class = get_easyblock_class (comp_easyblock , name = comp_name , error_on_missing_easyblock = False )
134131 if easyblock_class is None :
135- raise EasyBuildError ("No easyblock found for component %s v%s" , comp_name , comp_version )
136- else :
137- self .log .info ("Using default easyblock %s for component %s" , easyblock , comp_name )
138- else :
139- easyblock = easyblock_class .__name__
140- self .log .info ("Using easyblock %s for component %s" , easyblock , comp_name )
132+ if self .cfg ['default_easyblock' ]:
133+ easyblock = self .cfg ['default_easyblock' ]
134+ easyblock_class = get_easyblock_class (easyblock )
141135
142- if easyblock == 'Bundle' :
143- raise EasyBuildError ("The Bundle easyblock can not be used to install components in a bundle" )
136+ if easyblock_class is None :
137+ raise EasyBuildError ("No easyblock found for component %s v%s" , comp_name , comp_version )
138+ self .log .info ("Using default easyblock %s for component %s" , easyblock , comp_name )
139+ else :
140+ easyblock = easyblock_class .__name__
141+ self .log .info ("Using easyblock %s for component %s" , easyblock , comp_name )
144142
145- comp_cfg .easyblock = easyblock_class
143+ if easyblock == 'Bundle' :
144+ raise EasyBuildError ("The Bundle easyblock can not be used to install components in a bundle" )
146145
147- # make sure that extra easyconfig parameters are known, so they can be set
148- extra_opts = comp_cfg .easyblock .extra_options ()
149- comp_cfg .extend_params (copy .deepcopy (extra_opts ))
146+ comp_cfg .easyblock = easyblock_class
150147
151- comp_cfg .generate_template_values ()
148+ # make sure that extra easyconfig parameters are known, so they can be set
149+ extra_opts = comp_cfg .easyblock .extra_options ()
150+ comp_cfg .extend_params (copy .deepcopy (extra_opts ))
152151
153- # do not inherit easyblock to use from parent (since that would result in an infinite loop in install_step)
154- comp_cfg ['easyblock' ] = None
152+ comp_cfg .generate_template_values ()
155153
156- # reset list of sources/source_urls/checksums
157- comp_cfg ['sources' ] = comp_cfg ['source_urls' ] = comp_cfg ['checksums' ] = comp_cfg ['patches' ] = []
154+ # do not inherit easyblock to use from parent
155+ # (since that would result in an infinite loop in install_step)
156+ comp_cfg ['easyblock' ] = None
158157
159- for key in self . cfg [ 'default_component_specs' ]:
160- comp_cfg [key ] = self . cfg [ 'default_component_specs' ][ key ]
158+ # reset list of sources/source_urls/checksums
159+ comp_cfg ['sources' ] = comp_cfg [ 'source_urls' ] = comp_cfg [ 'checksums' ] = comp_cfg [ 'patches' ] = [ ]
161160
162- for key in comp_specs :
163- comp_cfg [key ] = comp_specs [key ]
161+ for key in self . cfg [ 'default_component_specs' ] :
162+ comp_cfg [key ] = self . cfg [ 'default_component_specs' ] [key ]
164163
165- # enable resolving of templates for component-specific EasyConfig instance,
166- # but don't require that all template values can be resolved at this point;
167- # this is important to ensure that template values like %(name)s and %(version)s
168- # are correctly resolved with the component name/version before values are copied over to self.cfg
169- comp_cfg .enable_templating = True
170- comp_cfg .expect_resolved_template_values = False
164+ for key in comp_specs :
165+ comp_cfg [key ] = comp_specs [key ]
171166
172- # 'sources' is strictly required
173- comp_sources = comp_cfg ['sources' ]
174- if comp_sources :
167+ # Don't require that all template values can be resolved at this point but still resolve them.
168+ # This is important to ensure that template values like %(name)s and %(version)s
169+ # are correctly resolved with the component name/version before values are copied over to self.cfg
170+ with comp_cfg .allow_unresolved_templates ():
171+ comp_sources = comp_cfg ['sources' ]
172+ comp_source_urls = comp_cfg ['source_urls' ]
173+ if not comp_sources :
174+ raise EasyBuildError ("No sources specification for component %s v%s" , comp_name , comp_version )
175175 # If per-component source URLs are provided, attach them directly to the relevant sources
176- comp_source_urls = comp_cfg ['source_urls' ]
177176 if comp_source_urls :
178177 for source in comp_sources :
179178 if isinstance (source , str ):
@@ -190,36 +189,31 @@ def __init__(self, *args, **kwargs):
190189 else :
191190 # add component sources to list of sources
192191 self .cfg .update ('sources' , comp_sources )
193- else :
194- raise EasyBuildError ("No sources specification for component %s v%s" , comp_name , comp_version )
195-
196- comp_checksums = comp_cfg ['checksums' ]
197- if comp_checksums :
198- src_cnt = len (comp_sources )
199192
200- # add per-component checksums for sources to list of checksums
201- self .cfg .update ('checksums' , comp_checksums [:src_cnt ])
193+ comp_checksums = comp_cfg ['checksums' ]
194+ if comp_checksums :
195+ src_cnt = len (comp_sources )
202196
203- # add per-component checksums for patches to list of checksums for patches
204- checksums_patches . extend ( comp_checksums [src_cnt : ])
197+ # add per-component checksums for sources to list of checksums
198+ self . cfg . update ( 'checksums' , comp_checksums [: src_cnt ])
205199
206- comp_patches = comp_cfg ['patches' ]
207- if comp_patches :
208- self .cfg .update ('patches' , comp_patches )
200+ # add per-component checksums for patches to list of checksums for patches
201+ checksums_patches .extend (comp_checksums [src_cnt :])
209202
210- comp_cfg .expect_resolved_template_values = True
203+ with comp_cfg .allow_unresolved_templates ():
204+ comp_patches = comp_cfg ['patches' ]
205+ if comp_patches :
206+ self .cfg .update ('patches' , comp_patches )
211207
212- self .comp_instances .append ((comp_cfg , comp_cfg .easyblock (comp_cfg , logfile = self .logfile )))
208+ self .comp_instances .append ((comp_cfg , comp_cfg .easyblock (comp_cfg , logfile = self .logfile )))
213209
214- self .cfg .update ('checksums' , checksums_patches )
210+ self .cfg .update ('checksums' , checksums_patches )
215211
216212 # restore general sanity checks if using component-specific sanity checks
217213 if self .cfg ['sanity_check_components' ] or self .cfg ['sanity_check_all_components' ]:
218214 self .cfg ['sanity_check_paths' ] = self .backup_sanity_paths
219215 self .cfg ['sanity_check_commands' ] = self .backup_sanity_cmds
220216
221- self .cfg .enable_templating = True
222-
223217 def check_checksums (self ):
224218 """
225219 Check whether a SHA256 checksum is available for all sources & patches (incl. extensions).
@@ -279,9 +273,10 @@ def install_step(self):
279273
280274 comp .src = []
281275
282- # find match entries in self.src for this component
283- comp .cfg .expect_resolved_template_values = False
284- for source in comp .cfg ['sources' ]:
276+ # find matching entries in self.src for this component
277+ with comp .cfg .allow_unresolved_templates ():
278+ comp_sources = comp .cfg ['sources' ]
279+ for source in comp_sources :
285280 if isinstance (source , str ):
286281 comp_src_fn = source
287282 elif isinstance (source , dict ):
@@ -304,7 +299,6 @@ def install_step(self):
304299
305300 # location of first unpacked source is used to determine where to apply patch(es)
306301 comp .src [- 1 ]['finalpath' ] = comp .cfg ['start_dir' ]
307- comp .cfg .expect_resolved_template_values = True
308302
309303 # check if sanity checks are enabled for the component
310304 if self .cfg ['sanity_check_all_components' ] or comp .cfg ['name' ] in self .cfg ['sanity_check_components' ]:
0 commit comments