Package SCons :: Package Variables
[hide private]
[frames] | no frames]

Source Code for Package SCons.Variables

  1  """engine.SCons.Variables 
  2   
  3  This file defines the Variables class that is used to add user-friendly 
  4  customizable variables to an SCons build. 
  5  """ 
  6   
  7  # 
  8  # Copyright (c) 2001 - 2019 The SCons Foundation 
  9  # 
 10  # Permission is hereby granted, free of charge, to any person obtaining 
 11  # a copy of this software and associated documentation files (the 
 12  # "Software"), to deal in the Software without restriction, including 
 13  # without limitation the rights to use, copy, modify, merge, publish, 
 14  # distribute, sublicense, and/or sell copies of the Software, and to 
 15  # permit persons to whom the Software is furnished to do so, subject to 
 16  # the following conditions: 
 17  # 
 18  # The above copyright notice and this permission notice shall be included 
 19  # in all copies or substantial portions of the Software. 
 20  # 
 21  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
 22  # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 23  # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 24  # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
 25  # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
 26  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
 27  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 28   
 29  __revision__ = "src/engine/SCons/Variables/__init__.py 3a41ed6b288cee8d085373ad7fa02894e1903864 2019-01-23 17:30:35 bdeegan" 
 30   
 31  import os.path 
 32  import sys 
 33  from functools import cmp_to_key 
 34   
 35  import SCons.Environment 
 36  import SCons.Errors 
 37  import SCons.Util 
 38  import SCons.Warnings 
 39   
 40  from .BoolVariable import BoolVariable  # okay 
 41  from .EnumVariable import EnumVariable  # okay 
 42  from .ListVariable import ListVariable  # naja 
 43  from .PackageVariable import PackageVariable # naja 
 44  from .PathVariable import PathVariable # okay 
 45   
 46   
47 -class Variables(object):
48 instance=None 49 50 """ 51 Holds all the options, updates the environment with the variables, 52 and renders the help text. 53 """
54 - def __init__(self, files=None, args=None, is_global=1):
55 """ 56 files - [optional] List of option configuration files to load 57 (backward compatibility) If a single string is passed it is 58 automatically placed in a file list 59 """ 60 # initialize arguments 61 if files is None: 62 files = [] 63 if args is None: 64 args = {} 65 self.options = [] 66 self.args = args 67 if not SCons.Util.is_List(files): 68 if files: 69 files = [ files ] 70 else: 71 files = [] 72 self.files = files 73 self.unknown = {} 74 75 # create the singleton instance 76 if is_global: 77 self=Variables.instance 78 79 if not Variables.instance: 80 Variables.instance=self
81
82 - def _do_add(self, key, help="", default=None, validator=None, converter=None):
83 class Variable(object): 84 pass
85 86 option = Variable() 87 88 # if we get a list or a tuple, we take the first element as the 89 # option key and store the remaining in aliases. 90 if SCons.Util.is_List(key) or SCons.Util.is_Tuple(key): 91 option.key = key[0] 92 option.aliases = key[1:] 93 else: 94 option.key = key 95 option.aliases = [ key ] 96 option.help = help 97 option.default = default 98 option.validator = validator 99 option.converter = converter 100 101 self.options.append(option) 102 103 # options might be added after the 'unknown' dict has been set up, 104 # so we remove the key and all its aliases from that dict 105 for alias in list(option.aliases) + [ option.key ]: 106 if alias in self.unknown: 107 del self.unknown[alias]
108
109 - def keys(self):
110 """ 111 Returns the keywords for the options 112 """ 113 return [o.key for o in self.options]
114
115 - def Add(self, key, help="", default=None, validator=None, converter=None, **kw):
116 """ 117 Add an option. 118 119 120 @param key: the name of the variable, or a list or tuple of arguments 121 @param help: optional help text for the options 122 @param default: optional default value 123 @param validator: optional function that is called to validate the option's value 124 @type validator: Called with (key, value, environment) 125 @param converter: optional function that is called to convert the option's value before putting it in the environment. 126 """ 127 128 if SCons.Util.is_List(key) or isinstance(key, tuple): 129 self._do_add(*key) 130 return 131 132 if not SCons.Util.is_String(key) or \ 133 not SCons.Environment.is_valid_construction_var(key): 134 raise SCons.Errors.UserError("Illegal Variables.Add() key `%s'" % str(key)) 135 136 self._do_add(key, help, default, validator, converter)
137
138 - def AddVariables(self, *optlist):
139 """ 140 Add a list of options. 141 142 Each list element is a tuple/list of arguments to be passed on 143 to the underlying method for adding options. 144 145 Example:: 146 147 opt.AddVariables( 148 ('debug', '', 0), 149 ('CC', 'The C compiler'), 150 ('VALIDATE', 'An option for testing validation', 'notset', 151 validator, None), 152 ) 153 154 """ 155 156 for o in optlist: 157 self._do_add(*o)
158 159
160 - def Update(self, env, args=None):
161 """ 162 Update an environment with the option variables. 163 164 env - the environment to update. 165 """ 166 167 values = {} 168 169 # first set the defaults: 170 for option in self.options: 171 if not option.default is None: 172 values[option.key] = option.default 173 174 # next set the value specified in the options file 175 for filename in self.files: 176 if os.path.exists(filename): 177 dir = os.path.split(os.path.abspath(filename))[0] 178 if dir: 179 sys.path.insert(0, dir) 180 try: 181 values['__name__'] = filename 182 with open(filename, 'r') as f: 183 contents = f.read() 184 exec(contents, {}, values) 185 finally: 186 if dir: 187 del sys.path[0] 188 del values['__name__'] 189 190 # set the values specified on the command line 191 if args is None: 192 args = self.args 193 194 for arg, value in args.items(): 195 added = False 196 for option in self.options: 197 if arg in list(option.aliases) + [ option.key ]: 198 values[option.key] = value 199 added = True 200 if not added: 201 self.unknown[arg] = value 202 203 # put the variables in the environment: 204 # (don't copy over variables that are not declared as options) 205 for option in self.options: 206 try: 207 env[option.key] = values[option.key] 208 except KeyError: 209 pass 210 211 # Call the convert functions: 212 for option in self.options: 213 if option.converter and option.key in values: 214 value = env.subst('${%s}'%option.key) 215 try: 216 try: 217 env[option.key] = option.converter(value) 218 except TypeError: 219 env[option.key] = option.converter(value, env) 220 except ValueError as x: 221 raise SCons.Errors.UserError('Error converting option: %s\n%s'%(option.key, x)) 222 223 224 # Finally validate the values: 225 for option in self.options: 226 if option.validator and option.key in values: 227 option.validator(option.key, env.subst('${%s}'%option.key), env)
228
229 - def UnknownVariables(self):
230 """ 231 Returns any options in the specified arguments lists that 232 were not known, declared options in this object. 233 """ 234 return self.unknown
235
236 - def Save(self, filename, env):
237 """ 238 Saves all the options in the given file. This file can 239 then be used to load the options next run. This can be used 240 to create an option cache file. 241 242 filename - Name of the file to save into 243 env - the environment get the option values from 244 """ 245 246 # Create the file and write out the header 247 try: 248 fh = open(filename, 'w') 249 250 try: 251 # Make an assignment in the file for each option 252 # within the environment that was assigned a value 253 # other than the default. 254 for option in self.options: 255 try: 256 value = env[option.key] 257 try: 258 prepare = value.prepare_to_store 259 except AttributeError: 260 try: 261 eval(repr(value)) 262 except KeyboardInterrupt: 263 raise 264 except: 265 # Convert stuff that has a repr() that 266 # cannot be evaluated into a string 267 value = SCons.Util.to_String(value) 268 else: 269 value = prepare() 270 271 defaultVal = env.subst(SCons.Util.to_String(option.default)) 272 if option.converter: 273 defaultVal = option.converter(defaultVal) 274 275 if str(env.subst('${%s}' % option.key)) != str(defaultVal): 276 fh.write('%s = %s\n' % (option.key, repr(value))) 277 except KeyError: 278 pass 279 finally: 280 fh.close() 281 282 except IOError as x: 283 raise SCons.Errors.UserError('Error writing options to file: %s\n%s' % (filename, x))
284
285 - def GenerateHelpText(self, env, sort=None):
286 """ 287 Generate the help text for the options. 288 289 env - an environment that is used to get the current values 290 of the options. 291 cmp - Either a function as follows: The specific sort function should take two arguments and return -1, 0 or 1 292 or a boolean to indicate if it should be sorted. 293 """ 294 295 if callable(sort): 296 options = sorted(self.options, key=cmp_to_key(lambda x,y: sort(x.key,y.key))) 297 elif sort is True: 298 options = sorted(self.options, key=lambda x: x.key) 299 else: 300 options = self.options 301 302 def format(opt, self=self, env=env): 303 if opt.key in env: 304 actual = env.subst('${%s}' % opt.key) 305 else: 306 actual = None 307 return self.FormatVariableHelpText(env, opt.key, opt.help, opt.default, actual, opt.aliases)
308 lines = [_f for _f in map(format, options) if _f] 309 310 return ''.join(lines) 311 312 format = '\n%s: %s\n default: %s\n actual: %s\n' 313 format_ = '\n%s: %s\n default: %s\n actual: %s\n aliases: %s\n' 314
315 - def FormatVariableHelpText(self, env, key, help, default, actual, aliases=[]):
316 # Don't display the key name itself as an alias. 317 aliases = [a for a in aliases if a != key] 318 if len(aliases)==0: 319 return self.format % (key, help, default, actual) 320 else: 321 return self.format_ % (key, help, default, actual, aliases)
322 323 # Local Variables: 324 # tab-width:4 325 # indent-tabs-mode:nil 326 # End: 327 # vim: set expandtab tabstop=4 shiftwidth=4: 328