00001 """
00002 List of helpful SCons builders to work with SLIMpy
00003 """
00004
00005 __copyright__ = """
00006 Copyright 2008 Sean Ross-Ross
00007 """
00008 __license__ = """
00009 This file is part of SLIMpy .
00010
00011 SLIMpy is free software: you can redistribute it and/or modify
00012 it under the terms of the GNU Lesser General Public License as published by
00013 the Free Software Foundation, either version 3 of the License, or
00014 (at your option) any later version.
00015
00016 SLIMpy is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019 GNU Lesser General Public License for more details.
00020
00021 You should have received a copy of the GNU Lesser General Public License
00022 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00023 """
00024
00025
00026 from slimpy_base import __version__ as slimpy_version
00027 from inspect import isroutine,getsource,getsourcefile,getsourcelines
00028 from itertools import chain
00029 from os import environ
00030 from os.path import isfile
00031 from re import compile
00032 from SCons.Script import Help
00033
00034
00035 def rsf_binary_emitter( target, source, env):
00036 'add binary file as a side effect and call Clean '
00037 rsf_headers = [ tgt for tgt in target if hasattr(tgt, "suffix") and tgt.suffix == '.rsf']
00038 in_eq = compile("^\W*in=(.*)$")
00039 for node in rsf_headers:
00040
00041 contents = None
00042 if contents:
00043 lines = contents.split('\n')
00044 lines.reverse()
00045 for line in lines:
00046 all = in_eq.findall( line )
00047 if all:
00048 data = all[0].replace("@","\@")
00049 break
00050 else:
00051 data_path = environ.get("DATAPATH", "")
00052 data = data_path +node.name + "@"
00053
00054 env.SideEffect( data, node )
00055 env.Clean( node, data )
00056
00057
00058 return target, source
00059
00060 def logfile_emitter(target,source,env):
00061 'append a log file target if logfile in env'
00062 logfile = env.get('logfile', None)
00063 if logfile is not None:
00064 target.append( logfile )
00065 if not env.has_key('verbose'):
00066 env['verbose'] = 0
00067
00068 return target, source
00069
00070
00071 DEFAULT_PROFILES = []
00072 def profile_emitter_wrapper(act):
00073 """
00074 profile 'act'
00075 Uses functional closure to return an emitter func
00076 that calls the profile builder
00077 """
00078 def profile_emitter(target, source, env):
00079 ''
00080 profiler = env.get( 'profile', None )
00081
00082 if profiler is not None:
00083 profiler.set_action(act)
00084 profiler.set_env(target,source,env)
00085 profiler.profile( )
00086
00087 return target, source
00088
00089 return profile_emitter
00090
00091 def dottest_emitter_wrapper(act):
00092 """
00093 profile 'act'
00094 Uses functional closure to return an emitter func
00095 that calls the profile builder
00096 """
00097 def dottest_emitter(target, source, env):
00098 ''
00099 dottester = env.get( 'dottest', None )
00100
00101 if dottester is not None:
00102 dottester.set_action(act)
00103 dottester.set_env(target,source,env)
00104 dottester.dot_test( )
00105
00106 return target, source
00107
00108 return dottest_emitter
00109
00110
00111 def slimpy_file(mod_file):
00112 """
00113 ??
00114 """
00115 if mod_file.endswith('.pyc') and isfile(mod_file[:-1]):
00116 mod_file = mod_file[:-1]
00117 def slimpy_file_emitter( target, source, env):
00118
00119 coutput = env.get('coutput',None)
00120
00121 val = env.Value( slimpy_version )
00122 source.append( val )
00123
00124 if coutput is not None:
00125 target.append(coutput)
00126
00127 source.append( mod_file )
00128
00129 if mod_file != __file__:
00130 source.append( __file__ )
00131
00132
00133 return target, source
00134 return slimpy_file_emitter
00135
00136
00137
00138 def slimpy_variable_emitter( target ,source, env):
00139 """
00140 add dependencies on SLIMpy global variables
00141 if a variable defined in slimvars and specified in
00142 env, then slimpy adds it as a Value source
00143 """
00144 from slimpy_base.Environment.InstanceManager import InstanceManager
00145 slimvars = InstanceManager()['slimvars']
00146
00147 for key in slimvars.keys():
00148 if env.has_key(key):
00149 par =env[key]
00150 val = env.Value( (key,par) )
00151 source.append( val )
00152
00153 return target ,source
00154
00155
00156 def additional_parameters( additional_pars ):
00157 """
00158 Add dependencies on functions as environment parameters
00159 """
00160
00161 def additional_parameter_emitter( target ,source, env):
00162 default_package = env.get( 'default_pack' ,{} )
00163 Get = lambda name : env.get( name, default_package.get(name) )
00164 has_key = lambda key: env.has_key(key) or default_package.has_key(key)
00165
00166 parameters = chain( additional_pars, default_package.get('additional_parameters',[]) )
00167 for key in parameters:
00168 Get(key)
00169 if has_key(key):
00170 par = Get(key)
00171 val = env.Value( (key,par) )
00172 source.append( val )
00173
00174 return target ,source
00175 return additional_parameter_emitter
00176
00177 def function_parameters( funcnames ):
00178 """
00179 Add dependencies on functions passed in to env
00180 """
00181 def additional_parameter_emitter( target ,source, env ):
00182 default_pack = env.get( 'problem', env.get('default_pack') )
00183 Get = lambda name : env.get( name, default_pack.get(name) )
00184 has_key = lambda key: env.has_key(key) or default_pack.has_key(key)
00185
00186 new_pars = set()
00187 for key in funcnames:
00188 if has_key(key):
00189 func =Get(key)
00190
00191 if isroutine(func):
00192 try:
00193 source_code = getsource(func)
00194 except IOError:
00195 source_code = None
00196
00197 if source_code is None:
00198 continue
00199
00200 sha = hash(source_code)
00201 rr ="<function %s hash=%s>" %(func.__name__,sha)
00202 val = env.Value( (key,rr) )
00203
00204 source.append( val )
00205
00206 pars = getattr( func, '__additional_dependancies__' , [] )
00207
00208 new_pars.update( pars )
00209
00210 if new_pars:
00211 additional_parameters(new_pars)(target,source,env)
00212
00213 return target ,source
00214 return additional_parameter_emitter
00215
00216 help_names = set()
00217 def help_emitter( target, source, env ):
00218 if env.has_key('default_pack') or env.has_key('problem'):
00219 default_pack = env.get( 'problem', env.get('default_pack') )
00220 help_name = default_pack['name']
00221 if help_name in help_names:
00222 return target,source
00223 else:
00224 help_names.add( help_name )
00225
00226 Help("Help for %(help_name)s\n" %vars())
00227 Help("eg.\n" %vars())
00228 Help("Solve( target, source, problem=%(help_name)s,\n" %vars() )
00229 Help(" ...params... ,\n" %vars() )
00230 Help(" )\n\n" %vars() )
00231
00232
00233 keys = default_pack.keys()
00234 keys.sort()
00235 for item in keys:
00236 val= default_pack[item]
00237 if item in ['doc','name']:
00238 continue
00239 doc = default_pack['doc'].get(item)
00240 if doc is None:
00241 if isroutine(val):
00242 doc = val.__doc__
00243 if doc is None:
00244 doc = "No doc for %(item)s" %vars()
00245 else:
00246 pars = getattr( val, '__additional_dependancies__' , [] )
00247 doc = "Depends on %s\n" %pars + doc
00248
00249 doc = doc.strip()
00250 doc = "\n\t".join([ line.strip() for line in doc.split('\n') ])
00251 if isroutine(val):
00252 name = (val.__name__)
00253 try:
00254 stuff = ( val.__name__,repr(getsourcefile(val)),getsourcelines(val)[-1])
00255 except IOError:
00256 val = "<function %s in ???>" %name
00257 else:
00258 val = "<function %s in %s at line %s>" %stuff
00259
00260 Help(" %(item)s: default=%(val)s" %vars() )
00261 Help("\n\n\t%(doc)s\n\n" %vars() )
00262
00263 return target ,source