1 """SCons.Environment
2
3 Base class for construction Environments. These are
4 the primary objects used to communicate dependency and
5 construction information to the build engine.
6
7 Keyword arguments supplied when the construction Environment
8 is created are construction variables used to initialize the
9 Environment
10 """
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 __revision__ = "src/engine/SCons/Environment.py 3842 2008/12/20 22:59:52 scons"
36
37
38 import copy
39 import os
40 import sys
41 import re
42 import shlex
43 import string
44 from UserDict import UserDict
45
46 import SCons.Action
47 import SCons.Builder
48 from SCons.Debug import logInstanceCreation
49 import SCons.Defaults
50 import SCons.Errors
51 import SCons.Memoize
52 import SCons.Node
53 import SCons.Node.Alias
54 import SCons.Node.FS
55 import SCons.Node.Python
56 import SCons.Platform
57 import SCons.SConsign
58 import SCons.Subst
59 import SCons.Tool
60 import SCons.Util
61 import SCons.Warnings
62
65
66 _null = _Null
67
68 _warn_copy_deprecated = True
69 _warn_source_signatures_deprecated = True
70 _warn_target_signatures_deprecated = True
71
72 CleanTargets = {}
73 CalculatorArgs = {}
74
75 semi_deepcopy = SCons.Util.semi_deepcopy
76
77
78
79
80 UserError = SCons.Errors.UserError
81
84
85 AliasBuilder = SCons.Builder.Builder(action = alias_builder,
86 target_factory = SCons.Node.Alias.default_ans.Alias,
87 source_factory = SCons.Node.FS.Entry,
88 multi = 1,
89 is_explicit = None,
90 name='AliasBuilder')
91
107
108
109
110
111 reserved_construction_var_names = [
112 'SOURCE',
113 'SOURCES',
114 'TARGET',
115 'TARGETS',
116 ]
117
118 future_reserved_construction_var_names = [
119 'CHANGED_SOURCES',
120 'CHANGED_TARGETS',
121 'UNCHANGED_SOURCES',
122 'UNCHANGED_TARGETS',
123 ]
124
133
137
142
144 try:
145 bd = env._dict[key]
146 for k in bd.keys():
147 del bd[k]
148 except KeyError:
149 bd = BuilderDict(kwbd, env)
150 env._dict[key] = bd
151 bd.update(value)
152
156
160
162 """Delete duplicates from a sequence, keeping the first or last."""
163 seen={}
164 result=[]
165 if keep_last:
166 l.reverse()
167 for i in l:
168 try:
169 if not seen.has_key(i):
170 result.append(i)
171 seen[i]=1
172 except TypeError:
173
174 result.append(i)
175 if keep_last:
176 result.reverse()
177 return result
178
179
180
181
182
183
184
185
186
187
188
189
190
191
193 """
194 A generic Wrapper class that associates a method (which can
195 actually be any callable) with an object. As part of creating this
196 MethodWrapper object an attribute with the specified (by default,
197 the name of the supplied method) is added to the underlying object.
198 When that new "method" is called, our __call__() method adds the
199 object as the first argument, simulating the Python behavior of
200 supplying "self" on method calls.
201
202 We hang on to the name by which the method was added to the underlying
203 base class so that we can provide a method to "clone" ourselves onto
204 a new underlying object being copied (without which we wouldn't need
205 to save that info).
206 """
207 - def __init__(self, object, method, name=None):
214
216 nargs = (self.object,) + args
217 return apply(self.method, nargs, kwargs)
218
219 - def clone(self, new_object):
220 """
221 Returns an object that re-binds the underlying "method" to
222 the specified new object.
223 """
224 return self.__class__(new_object, self.method, self.name)
225
227 """
228 A MethodWrapper subclass that that associates an environment with
229 a Builder.
230
231 This mainly exists to wrap the __call__() function so that all calls
232 to Builders can have their argument lists massaged in the same way
233 (treat a lone argument as the source, treat two arguments as target
234 then source, make sure both target and source are lists) without
235 having to have cut-and-paste code to do it.
236
237 As a bit of obsessive backwards compatibility, we also intercept
238 attempts to get or set the "env" or "builder" attributes, which were
239 the names we used before we put the common functionality into the
240 MethodWrapper base class. We'll keep this around for a while in case
241 people shipped Tool modules that reached into the wrapper (like the
242 Tool/qt.py module does, or did). There shouldn't be a lot attribute
243 fetching or setting on these, so a little extra work shouldn't hurt.
244 """
246 if source is _null:
247 source = target
248 target = None
249 if not target is None and not SCons.Util.is_List(target):
250 target = [target]
251 if not source is None and not SCons.Util.is_List(source):
252 source = [source]
253 return apply(MethodWrapper.__call__, (self, target, source) + args, kw)
254
256 return '<BuilderWrapper %s>' % repr(self.name)
257
260
262 if name == 'env':
263 return self.object
264 elif name == 'builder':
265 return self.method
266 else:
267 raise AttributeError, name
268
270 if name == 'env':
271 self.object = value
272 elif name == 'builder':
273 self.method = value
274 else:
275 self.__dict__[name] = value
276
277
278
279
280
281
282
283
284
285
286
287
289 """This is a dictionary-like class used by an Environment to hold
290 the Builders. We need to do this because every time someone changes
291 the Builders in the Environment's BUILDERS dictionary, we must
292 update the Environment's attributes."""
294
295
296
297 self.env = env
298 UserDict.__init__(self, dict)
299
301 return self.__class__(self.data, self.env)
302
304 try:
305 method = getattr(self.env, item).method
306 except AttributeError:
307 pass
308 else:
309 self.env.RemoveMethod(method)
310 UserDict.__setitem__(self, item, val)
311 BuilderWrapper(self.env, val, item)
312
314 UserDict.__delitem__(self, item)
315 delattr(self.env, item)
316
320
321
322
323 _is_valid_var = re.compile(r'[_a-zA-Z]\w*$')
324
326 """Return if the specified string is a legitimate construction
327 variable.
328 """
329 return _is_valid_var.match(varstr)
330
331
332
334 """Base class for different flavors of construction environments.
335
336 This class contains a minimal set of methods that handle contruction
337 variable expansion and conversion of strings to Nodes, which may or
338 may not be actually useful as a stand-alone class. Which methods
339 ended up in this class is pretty arbitrary right now. They're
340 basically the ones which we've empirically determined are common to
341 the different construction environment subclasses, and most of the
342 others that use or touch the underlying dictionary of construction
343 variables.
344
345 Eventually, this class should contain all the methods that we
346 determine are necessary for a "minimal" interface to the build engine.
347 A full "native Python" SCons environment has gotten pretty heavyweight
348 with all of the methods and Tools and construction variables we've
349 jammed in there, so it would be nice to have a lighter weight
350 alternative for interfaces that don't need all of the bells and
351 whistles. (At some point, we'll also probably rename this class
352 "Base," since that more reflects what we want this class to become,
353 but because we've released comments that tell people to subclass
354 Environment.Base to create their own flavors of construction
355 environment, we'll save that for a future refactoring when this
356 class actually becomes useful.)
357 """
358
359 if SCons.Memoize.use_memoizer:
360 __metaclass__ = SCons.Memoize.Memoized_Metaclass
361
372
373
392
394 return cmp(self._dict, other._dict)
395
397 special = self._special_del.get(key)
398 if special:
399 special(self, key)
400 else:
401 del self._dict[key]
402
404 return self._dict[key]
405
407
408
409
410
411
412
413
414
415
416
417
418
419 if key in self._special_set_keys:
420 self._special_set[key](self, key, value)
421 else:
422
423
424
425
426 if not self._dict.has_key(key) \
427 and not _is_valid_var.match(key):
428 raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
429 self._dict[key] = value
430
431 - def get(self, key, default=None):
432 "Emulates the get() method of dictionaries."""
433 return self._dict.get(key, default)
434
437
440
442 return self._dict.items()
443
445 if node_factory is _null:
446 node_factory = self.fs.File
447 if lookup_list is _null:
448 lookup_list = self.lookup_list
449
450 if not args:
451 return []
452
453 args = SCons.Util.flatten(args)
454
455 nodes = []
456 for v in args:
457 if SCons.Util.is_String(v):
458 n = None
459 for l in lookup_list:
460 n = l(v)
461 if not n is None:
462 break
463 if not n is None:
464 if SCons.Util.is_String(n):
465
466 kw['raw'] = 1
467 n = apply(self.subst, (n,), kw)
468 if node_factory:
469 n = node_factory(n)
470 if SCons.Util.is_List(n):
471 nodes.extend(n)
472 else:
473 nodes.append(n)
474 elif node_factory:
475
476 kw['raw'] = 1
477 v = node_factory(apply(self.subst, (v,), kw))
478 if SCons.Util.is_List(v):
479 nodes.extend(v)
480 else:
481 nodes.append(v)
482 else:
483 nodes.append(v)
484
485 return nodes
486
489
492
493 - def subst(self, string, raw=0, target=None, source=None, conv=None):
494 """Recursively interpolates construction variables from the
495 Environment into the specified string, returning the expanded
496 result. Construction variables are specified by a $ prefix
497 in the string and begin with an initial underscore or
498 alphabetic character followed by any number of underscores
499 or alphanumeric characters. The construction variable names
500 may be surrounded by curly braces to separate the name from
501 trailing characters.
502 """
503 gvars = self.gvars()
504 lvars = self.lvars()
505 lvars['__env__'] = self
506 return SCons.Subst.scons_subst(string, self, raw, target, source, gvars, lvars, conv)
507
508 - def subst_kw(self, kw, raw=0, target=None, source=None):
509 nkw = {}
510 for k, v in kw.items():
511 k = self.subst(k, raw, target, source)
512 if SCons.Util.is_String(v):
513 v = self.subst(v, raw, target, source)
514 nkw[k] = v
515 return nkw
516
517 - def subst_list(self, string, raw=0, target=None, source=None, conv=None):
518 """Calls through to SCons.Subst.scons_subst_list(). See
519 the documentation for that function."""
520 gvars = self.gvars()
521 lvars = self.lvars()
522 lvars['__env__'] = self
523 return SCons.Subst.scons_subst_list(string, self, raw, target, source, gvars, lvars, conv)
524
525 - def subst_path(self, path, target=None, source=None):
526 """Substitute a path list, turning EntryProxies into Nodes
527 and leaving Nodes (and other objects) as-is."""
528
529 if not SCons.Util.is_List(path):
530 path = [path]
531
532 def s(obj):
533 """This is the "string conversion" routine that we have our
534 substitutions use to return Nodes, not strings. This relies
535 on the fact that an EntryProxy object has a get() method that
536 returns the underlying Node that it wraps, which is a bit of
537 architectural dependence that we might need to break or modify
538 in the future in response to additional requirements."""
539 try:
540 get = obj.get
541 except AttributeError:
542 obj = SCons.Util.to_String_for_subst(obj)
543 else:
544 obj = get()
545 return obj
546
547 r = []
548 for p in path:
549 if SCons.Util.is_String(p):
550 p = self.subst(p, target=target, source=source, conv=s)
551 if SCons.Util.is_List(p):
552 if len(p) == 1:
553 p = p[0]
554 else:
555
556
557
558 p = string.join(map(SCons.Util.to_String_for_subst, p), '')
559 else:
560 p = s(p)
561 r.append(p)
562 return r
563
564 subst_target_source = subst
565
567 import subprocess
568
569 kw = { 'stdin' : 'devnull',
570 'stdout' : subprocess.PIPE,
571 'stderr' : subprocess.PIPE,
572 'universal_newlines' : True,
573 }
574
575
576 if not SCons.Util.is_List(command): kw['shell'] = True
577
578
579 p = apply(SCons.Action._subproc, (self, command), kw)
580 out,err = p.communicate()
581 status = p.wait()
582 if err:
583 sys.stderr.write(err)
584 if status:
585 raise OSError("'%s' exited %d" % (command, status))
586 return out
587
589 """
590 Adds the specified function as a method of this construction
591 environment with the specified name. If the name is omitted,
592 the default name is the name of the function itself.
593 """
594 method = MethodWrapper(self, function, name)
595 self.added_methods.append(method)
596
598 """
599 Removes the specified function's MethodWrapper from the
600 added_methods list, so we don't re-bind it when making a clone.
601 """
602 is_not_func = lambda dm, f=function: not dm.method is f
603 self.added_methods = filter(is_not_func, self.added_methods)
604
606 """
607 Produce a modified environment whose variables are overriden by
608 the overrides dictionaries. "overrides" is a dictionary that
609 will override the variables of this environment.
610
611 This function is much more efficient than Clone() or creating
612 a new Environment because it doesn't copy the construction
613 environment dictionary, it just wraps the underlying construction
614 environment, and doesn't even create a wrapper object if there
615 are no overrides.
616 """
617 if not overrides: return self
618 o = copy_non_reserved_keywords(overrides)
619 if not o: return self
620 overrides = {}
621 merges = None
622 for key, value in o.items():
623 if key == 'parse_flags':
624 merges = value
625 else:
626 overrides[key] = SCons.Subst.scons_subst_once(value, self, key)
627 env = OverrideEnvironment(self, overrides)
628 if merges: env.MergeFlags(merges)
629 return env
630
632 """
633 Parse the set of flags and return a dict with the flags placed
634 in the appropriate entry. The flags are treated as a typical
635 set of command-line flags for a GNU-like toolchain and used to
636 populate the entries in the dict immediately below. If one of
637 the flag strings begins with a bang (exclamation mark), it is
638 assumed to be a command and the rest of the string is executed;
639 the result of that evaluation is then added to the dict.
640 """
641 dict = {
642 'ASFLAGS' : SCons.Util.CLVar(''),
643 'CFLAGS' : SCons.Util.CLVar(''),
644 'CCFLAGS' : SCons.Util.CLVar(''),
645 'CPPDEFINES' : [],
646 'CPPFLAGS' : SCons.Util.CLVar(''),
647 'CPPPATH' : [],
648 'FRAMEWORKPATH' : SCons.Util.CLVar(''),
649 'FRAMEWORKS' : SCons.Util.CLVar(''),
650 'LIBPATH' : [],
651 'LIBS' : [],
652 'LINKFLAGS' : SCons.Util.CLVar(''),
653 'RPATH' : [],
654 }
655
656
657
658 def do_parse(arg, me, self = self, dict = dict):
659
660 if not arg:
661 return
662
663 if not SCons.Util.is_String(arg):
664 for t in arg: me(t, me)
665 return
666
667
668 if arg[0] == '!':
669 arg = self.backtick(arg[1:])
670
671
672 def append_define(name, dict = dict):
673 t = string.split(name, '=')
674 if len(t) == 1:
675 dict['CPPDEFINES'].append(name)
676 else:
677 dict['CPPDEFINES'].append([t[0], string.join(t[1:], '=')])
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699 params = shlex.split(arg)
700 append_next_arg_to = None
701 for arg in params:
702 if append_next_arg_to:
703 if append_next_arg_to == 'CPPDEFINES':
704 append_define(arg)
705 elif append_next_arg_to == '-include':
706 t = ('-include', self.fs.File(arg))
707 dict['CCFLAGS'].append(t)
708 elif append_next_arg_to == '-isysroot':
709 t = ('-isysroot', arg)
710 dict['CCFLAGS'].append(t)
711 dict['LINKFLAGS'].append(t)
712 elif append_next_arg_to == '-arch':
713 t = ('-arch', arg)
714 dict['CCFLAGS'].append(t)
715 dict['LINKFLAGS'].append(t)
716 else:
717 dict[append_next_arg_to].append(arg)
718 append_next_arg_to = None
719 elif not arg[0] in ['-', '+']:
720 dict['LIBS'].append(self.fs.File(arg))
721 elif arg[:2] == '-L':
722 if arg[2:]:
723 dict['LIBPATH'].append(arg[2:])
724 else:
725 append_next_arg_to = 'LIBPATH'
726 elif arg[:2] == '-l':
727 if arg[2:]:
728 dict['LIBS'].append(arg[2:])
729 else:
730 append_next_arg_to = 'LIBS'
731 elif arg[:2] == '-I':
732 if arg[2:]:
733 dict['CPPPATH'].append(arg[2:])
734 else:
735 append_next_arg_to = 'CPPPATH'
736 elif arg[:4] == '-Wa,':
737 dict['ASFLAGS'].append(arg[4:])
738 dict['CCFLAGS'].append(arg)
739 elif arg[:4] == '-Wl,':
740 if arg[:11] == '-Wl,-rpath=':
741 dict['RPATH'].append(arg[11:])
742 elif arg[:7] == '-Wl,-R,':
743 dict['RPATH'].append(arg[7:])
744 elif arg[:6] == '-Wl,-R':
745 dict['RPATH'].append(arg[6:])
746 else:
747 dict['LINKFLAGS'].append(arg)
748 elif arg[:4] == '-Wp,':
749 dict['CPPFLAGS'].append(arg)
750 elif arg[:2] == '-D':
751 if arg[2:]:
752 append_define(arg[2:])
753 else:
754 append_next_arg_to = 'CPPDEFINES'
755 elif arg == '-framework':
756 append_next_arg_to = 'FRAMEWORKS'
757 elif arg[:14] == '-frameworkdir=':
758 dict['FRAMEWORKPATH'].append(arg[14:])
759 elif arg[:2] == '-F':
760 if arg[2:]:
761 dict['FRAMEWORKPATH'].append(arg[2:])
762 else:
763 append_next_arg_to = 'FRAMEWORKPATH'
764 elif arg == '-mno-cygwin':
765 dict['CCFLAGS'].append(arg)
766 dict['LINKFLAGS'].append(arg)
767 elif arg == '-mwindows':
768 dict['LINKFLAGS'].append(arg)
769 elif arg == '-pthread':
770 dict['CCFLAGS'].append(arg)
771 dict['LINKFLAGS'].append(arg)
772 elif arg[:5] == '-std=':
773 dict['CFLAGS'].append(arg)
774 elif arg[0] == '+':
775 dict['CCFLAGS'].append(arg)
776 dict['LINKFLAGS'].append(arg)
777 elif arg in ['-include', '-isysroot', '-arch']:
778 append_next_arg_to = arg
779 else:
780 dict['CCFLAGS'].append(arg)
781
782 for arg in flags:
783 do_parse(arg, do_parse)
784 return dict
785
787 """
788 Merge the dict in args into the construction variables of this
789 env, or the passed-in dict. If args is not a dict, it is
790 converted into a dict using ParseFlags. If unique is not set,
791 the flags are appended rather than merged.
792 """
793
794 if dict is None:
795 dict = self
796 if not SCons.Util.is_Dict(args):
797 args = self.ParseFlags(args)
798 if not unique:
799 apply(self.Append, (), args)
800 return self
801 for key, value in args.items():
802 if not value:
803 continue
804 try:
805 orig = self[key]
806 except KeyError:
807 orig = value
808 else:
809 if not orig:
810 orig = value
811 elif value:
812
813
814
815
816
817
818 try:
819 orig = orig + value
820 except (KeyError, TypeError):
821 try:
822 add_to_orig = orig.append
823 except AttributeError:
824 value.insert(0, orig)
825 orig = value
826 else:
827 add_to_orig(value)
828 t = []
829 if key[-4:] == 'PATH':
830
831 for v in orig:
832 if v not in t:
833 t.append(v)
834 else:
835
836 orig.reverse()
837 for v in orig:
838 if v not in t:
839 t.insert(0, v)
840 self[key] = t
841 return self
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
873
877
881
883 f = SCons.Defaults.DefaultEnvironment().copy_from_cache
884 return f(src, dst)
885
886 -class Base(SubstitutionEnvironment):
887 """Base class for "real" construction Environments. These are the
888 primary objects used to communicate dependency and construction
889 information to the build engine.
890
891 Keyword arguments supplied when the construction Environment
892 is created are construction variables used to initialize the
893 Environment.
894 """
895
896 if SCons.Memoize.use_memoizer:
897 __metaclass__ = SCons.Memoize.Memoized_Metaclass
898
899 memoizer_counters = []
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915 - def __init__(self,
916 platform=None,
917 tools=None,
918 toolpath=None,
919 variables=None,
920 parse_flags = None,
921 **kw):
922 """
923 Initialization of a basic SCons construction environment,
924 including setting up special construction variables like BUILDER,
925 PLATFORM, etc., and searching for and applying available Tools.
926
927 Note that we do *not* call the underlying base class
928 (SubsitutionEnvironment) initialization, because we need to
929 initialize things in a very specific order that doesn't work
930 with the much simpler base class initialization.
931 """
932 if __debug__: logInstanceCreation(self, 'Environment.Base')
933 self._memo = {}
934 self.fs = SCons.Node.FS.get_default_fs()
935 self.ans = SCons.Node.Alias.default_ans
936 self.lookup_list = SCons.Node.arg2nodes_lookups
937 self._dict = semi_deepcopy(SCons.Defaults.ConstructionEnvironment)
938 self._init_special()
939 self.added_methods = []
940
941
942
943
944
945
946
947 self.decide_target = default_decide_target
948 self.decide_source = default_decide_source
949
950 self.copy_from_cache = default_copy_from_cache
951
952 self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self)
953
954 if platform is None:
955 platform = self._dict.get('PLATFORM', None)
956 if platform is None:
957 platform = SCons.Platform.Platform()
958 if SCons.Util.is_String(platform):
959 platform = SCons.Platform.Platform(platform)
960 self._dict['PLATFORM'] = str(platform)
961 platform(self)
962
963
964
965
966 if kw.has_key('options'):
967
968
969 variables = kw['options']
970 del kw['options']
971 apply(self.Replace, (), kw)
972 keys = kw.keys()
973 if variables:
974 keys = keys + variables.keys()
975 variables.Update(self)
976
977 save = {}
978 for k in keys:
979 try:
980 save[k] = self._dict[k]
981 except KeyError:
982
983
984 pass
985
986 SCons.Tool.Initializers(self)
987
988 if tools is None:
989 tools = self._dict.get('TOOLS', None)
990 if tools is None:
991 tools = ['default']
992 apply_tools(self, tools, toolpath)
993
994
995
996
997 for key, val in save.items():
998 self._dict[key] = val
999
1000
1001 if parse_flags: self.MergeFlags(parse_flags)
1002
1003
1004
1005
1006
1007
1009 """Fetch the builder with the specified name from the environment.
1010 """
1011 try:
1012 return self._dict['BUILDERS'][name]
1013 except KeyError:
1014 return None
1015
1017 try:
1018 path = self._CacheDir_path
1019 except AttributeError:
1020 path = SCons.Defaults.DefaultEnvironment()._CacheDir_path
1021 try:
1022 if path == self._last_CacheDir_path:
1023 return self._last_CacheDir
1024 except AttributeError:
1025 pass
1026 cd = SCons.CacheDir.CacheDir(path)
1027 self._last_CacheDir_path = path
1028 self._last_CacheDir = cd
1029 return cd
1030
1032 """Return a factory function for creating Nodes for this
1033 construction environment.
1034 """
1035 name = default
1036 try:
1037 is_node = issubclass(factory, SCons.Node.Node)
1038 except TypeError:
1039
1040
1041 pass
1042 else:
1043 if is_node:
1044
1045
1046
1047
1048 try: name = factory.__name__
1049 except AttributeError: pass
1050 else: factory = None
1051 if not factory:
1052
1053
1054
1055
1056
1057 factory = getattr(self.fs, name)
1058 return factory
1059
1060 memoizer_counters.append(SCons.Memoize.CountValue('_gsm'))
1061
1063 try:
1064 return self._memo['_gsm']
1065 except KeyError:
1066 pass
1067
1068 result = {}
1069
1070 try:
1071 scanners = self._dict['SCANNERS']
1072 except KeyError:
1073 pass
1074 else:
1075
1076
1077
1078
1079 if not SCons.Util.is_List(scanners):
1080 scanners = [scanners]
1081 else:
1082 scanners = scanners[:]
1083 scanners.reverse()
1084 for scanner in scanners:
1085 for k in scanner.get_skeys(self):
1086 result[k] = scanner
1087
1088 self._memo['_gsm'] = result
1089
1090 return result
1091
1093 """Find the appropriate scanner given a key (usually a file suffix).
1094 """
1095 return self._gsm().get(skey)
1096
1098 """Delete the cached scanner map (if we need to).
1099 """
1100 try:
1101 del self._memo['_gsm']
1102 except KeyError:
1103 pass
1104
1106 """Update an environment's values directly, bypassing the normal
1107 checks that occur when users try to set items.
1108 """
1109 self._dict.update(dict)
1110
1112 try:
1113 return self.src_sig_type
1114 except AttributeError:
1115 t = SCons.Defaults.DefaultEnvironment().src_sig_type
1116 self.src_sig_type = t
1117 return t
1118
1120 try:
1121 return self.tgt_sig_type
1122 except AttributeError:
1123 t = SCons.Defaults.DefaultEnvironment().tgt_sig_type
1124 self.tgt_sig_type = t
1125 return t
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1137 """Append values to existing construction variables
1138 in an Environment.
1139 """
1140 kw = copy_non_reserved_keywords(kw)
1141 for key, val in kw.items():
1142
1143
1144
1145
1146 try:
1147 orig = self._dict[key]
1148 except KeyError:
1149
1150
1151 self._dict[key] = val
1152 else:
1153 try:
1154
1155
1156
1157
1158
1159 update_dict = orig.update
1160 except AttributeError:
1161 try:
1162
1163
1164
1165 self._dict[key] = orig + val
1166 except (KeyError, TypeError):
1167 try:
1168
1169 add_to_orig = orig.append
1170 except AttributeError:
1171
1172
1173
1174
1175
1176 if orig:
1177 val.insert(0, orig)
1178 self._dict[key] = val
1179 else:
1180
1181
1182 if val:
1183 add_to_orig(val)
1184 else:
1185
1186
1187 if SCons.Util.is_List(val):
1188 for v in val:
1189 orig[v] = None
1190 else:
1191 try:
1192 update_dict(val)
1193 except (AttributeError, TypeError, ValueError):
1194 if SCons.Util.is_Dict(val):
1195 for k, v in val.items():
1196 orig[k] = v
1197 else:
1198 orig[val] = None
1199 self.scanner_map_delete(kw)
1200
1203 """Append path elements to the path 'name' in the 'ENV'
1204 dictionary for this environment. Will only add any particular
1205 path once, and will normpath and normcase all paths to help
1206 assure this. This can also handle the case where the env
1207 variable is a list instead of a string.
1208
1209 If delete_existing is 0, a newpath which is already in the path
1210 will not be moved to the end (it will be left where it is).
1211 """
1212
1213 orig = ''
1214 if self._dict.has_key(envname) and self._dict[envname].has_key(name):
1215 orig = self._dict[envname][name]
1216
1217 nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing)
1218
1219 if not self._dict.has_key(envname):
1220 self._dict[envname] = {}
1221
1222 self._dict[envname][name] = nv
1223
1225 """Append values to existing construction variables
1226 in an Environment, if they're not already there.
1227 If delete_existing is 1, removes existing values first, so
1228 values move to end.
1229 """
1230 kw = copy_non_reserved_keywords(kw)
1231 for key, val in kw.items():
1232 if SCons.Util.is_List(val):
1233 val = _delete_duplicates(val, delete_existing)
1234 if not self._dict.has_key(key) or self._dict[key] in ('', None):
1235 self._dict[key] = val
1236 elif SCons.Util.is_Dict(self._dict[key]) and \
1237 SCons.Util.is_Dict(val):
1238 self._dict[key].update(val)
1239 elif SCons.Util.is_List(val):
1240 dk = self._dict[key]
1241 if not SCons.Util.is_List(dk):
1242 dk = [dk]
1243 if delete_existing:
1244 dk = filter(lambda x, val=val: x not in val, dk)
1245 else:
1246 val = filter(lambda x, dk=dk: x not in dk, val)
1247 self._dict[key] = dk + val
1248 else:
1249 dk = self._dict[key]
1250 if SCons.Util.is_List(dk):
1251
1252
1253 if delete_existing:
1254 dk = filter(lambda x, val=val: x not in val, dk)
1255 self._dict[key] = dk + [val]
1256 else:
1257 if not val in dk:
1258 self._dict[key] = dk + [val]
1259 else:
1260 if delete_existing:
1261 dk = filter(lambda x, val=val: x not in val, dk)
1262 self._dict[key] = dk + val
1263 self.scanner_map_delete(kw)
1264
1265 - def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw):
1266 """Return a copy of a construction Environment. The
1267 copy is like a Python "deep copy"--that is, independent
1268 copies are made recursively of each objects--except that
1269 a reference is copied when an object is not deep-copyable
1270 (like a function). There are no references to any mutable
1271 objects in the original Environment.
1272 """
1273 clone = copy.copy(self)
1274 clone._dict = semi_deepcopy(self._dict)
1275
1276 try:
1277 cbd = clone._dict['BUILDERS']
1278 except KeyError:
1279 pass
1280 else:
1281 clone._dict['BUILDERS'] = BuilderDict(cbd, clone)
1282
1283
1284
1285
1286
1287 clone.added_methods = []
1288 for mw in self.added_methods:
1289 if mw == getattr(self, mw.name):
1290 clone.added_methods.append(mw.clone(clone))
1291
1292 clone._memo = {}
1293
1294
1295
1296 kw = copy_non_reserved_keywords(kw)
1297 new = {}
1298 for key, value in kw.items():
1299 new[key] = SCons.Subst.scons_subst_once(value, self, key)
1300 apply(clone.Replace, (), new)
1301
1302 apply_tools(clone, tools, toolpath)
1303
1304
1305 apply(clone.Replace, (), new)
1306
1307
1308 if parse_flags: clone.MergeFlags(parse_flags)
1309
1310 if __debug__: logInstanceCreation(self, 'Environment.EnvironmentClone')
1311 return clone
1312
1313 - def Copy(self, *args, **kw):
1320
1325
1326 - def _changed_content(self, dependency, target, prev_ni):
1327 return dependency.changed_content(target, prev_ni)
1328
1336
1337 - def _changed_timestamp_then_content(self, dependency, target, prev_ni):
1338 return dependency.changed_timestamp_then_content(target, prev_ni)
1339
1342
1345
1347 return self.fs.copy(src, dst)
1348
1350 return self.fs.copy2(src, dst)
1351
1375
1377 """Return the first available program in progs.
1378 """
1379 if not SCons.Util.is_List(progs):
1380 progs = [ progs ]
1381 for prog in progs:
1382 path = self.WhereIs(prog)
1383 if path: return prog
1384 return None
1385
1387 if not args:
1388 return self._dict
1389 dlist = map(lambda x, s=self: s._dict[x], args)
1390 if len(dlist) == 1:
1391 dlist = dlist[0]
1392 return dlist
1393
1394 - def Dump(self, key = None):
1395 """
1396 Using the standard Python pretty printer, dump the contents of the
1397 scons build environment to stdout.
1398
1399 If the key passed in is anything other than None, then that will
1400 be used as an index into the build environment dictionary and
1401 whatever is found there will be fed into the pretty printer. Note
1402 that this key is case sensitive.
1403 """
1404 import pprint
1405 pp = pprint.PrettyPrinter(indent=2)
1406 if key:
1407 dict = self.Dictionary(key)
1408 else:
1409 dict = self.Dictionary()
1410 return pp.pformat(dict)
1411
1412 - def FindIxes(self, paths, prefix, suffix):
1413 """
1414 Search a list of paths for something that matches the prefix and suffix.
1415
1416 paths - the list of paths or nodes.
1417 prefix - construction variable for the prefix.
1418 suffix - construction variable for the suffix.
1419 """
1420
1421 suffix = self.subst('$'+suffix)
1422 prefix = self.subst('$'+prefix)
1423
1424 for path in paths:
1425 dir,name = os.path.split(str(path))
1426 if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
1427 return path
1428
1429 - def ParseConfig(self, command, function=None, unique=1):
1430 """
1431 Use the specified function to parse the output of the command
1432 in order to modify the current environment. The 'command' can
1433 be a string or a list of strings representing a command and
1434 its arguments. 'Function' is an optional argument that takes
1435 the environment, the output of the command, and the unique flag.
1436 If no function is specified, MergeFlags, which treats the output
1437 as the result of a typical 'X-config' command (i.e. gtk-config),
1438 will merge the output into the appropriate variables.
1439 """
1440 if function is None:
1441 def parse_conf(env, cmd, unique=unique):
1442 return env.MergeFlags(cmd, unique)
1443 function = parse_conf
1444 if SCons.Util.is_List(command):
1445 command = string.join(command)
1446 command = self.subst(command)
1447 return function(self, self.backtick(command))
1448
1449 - def ParseDepends(self, filename, must_exist=None, only_one=0):
1450 """
1451 Parse a mkdep-style file for explicit dependencies. This is
1452 completely abusable, and should be unnecessary in the "normal"
1453 case of proper SCons configuration, but it may help make
1454 the transition from a Make hierarchy easier for some people
1455 to swallow. It can also be genuinely useful when using a tool
1456 that can write a .d file, but for which writing a scanner would
1457 be too complicated.
1458 """
1459 filename = self.subst(filename)
1460 try:
1461 fp = open(filename, 'r')
1462 except IOError:
1463 if must_exist:
1464 raise
1465 return
1466 lines = SCons.Util.LogicalLines(fp).readlines()
1467 lines = filter(lambda l: l[0] != '#', lines)
1468 tdlist = []
1469 for line in lines:
1470 try:
1471 target, depends = string.split(line, ':', 1)
1472 except (AttributeError, TypeError, ValueError):
1473
1474
1475
1476
1477 pass
1478 else:
1479 tdlist.append((string.split(target), string.split(depends)))
1480 if only_one:
1481 targets = reduce(lambda x, y: x+y, map(lambda p: p[0], tdlist))
1482 if len(targets) > 1:
1483 raise SCons.Errors.UserError, "More than one dependency target found in `%s': %s" % (filename, targets)
1484 for target, depends in tdlist:
1485 self.Depends(target, depends)
1486
1490
1492 """Prepend values to existing construction variables
1493 in an Environment.
1494 """
1495 kw = copy_non_reserved_keywords(kw)
1496 for key, val in kw.items():
1497
1498
1499
1500
1501 try:
1502 orig = self._dict[key]
1503 except KeyError:
1504
1505
1506 self._dict[key] = val
1507 else:
1508 try:
1509
1510
1511
1512
1513
1514 update_dict = orig.update
1515 except AttributeError:
1516 try:
1517
1518
1519
1520 self._dict[key] = val + orig
1521 except (KeyError, TypeError):
1522 try:
1523
1524 add_to_val = val.append
1525 except AttributeError:
1526
1527
1528
1529
1530 if val:
1531 orig.insert(0, val)
1532 else:
1533
1534
1535
1536 if orig:
1537 add_to_val(orig)
1538 self._dict[key] = val
1539 else:
1540
1541
1542 if SCons.Util.is_List(val):
1543 for v in val:
1544 orig[v] = None
1545 else:
1546 try:
1547 update_dict(val)
1548 except (AttributeError, TypeError, ValueError):
1549 if SCons.Util.is_Dict(val):
1550 for k, v in val.items():
1551 orig[k] = v
1552 else:
1553 orig[val] = None
1554 self.scanner_map_delete(kw)
1555
1558 """Prepend path elements to the path 'name' in the 'ENV'
1559 dictionary for this environment. Will only add any particular
1560 path once, and will normpath and normcase all paths to help
1561 assure this. This can also handle the case where the env
1562 variable is a list instead of a string.
1563
1564 If delete_existing is 0, a newpath which is already in the path
1565 will not be moved to the front (it will be left where it is).
1566 """
1567
1568 orig = ''
1569 if self._dict.has_key(envname) and self._dict[envname].has_key(name):
1570 orig = self._dict[envname][name]
1571
1572 nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing)
1573
1574 if not self._dict.has_key(envname):
1575 self._dict[envname] = {}
1576
1577 self._dict[envname][name] = nv
1578
1580 """Prepend values to existing construction variables
1581 in an Environment, if they're not already there.
1582 If delete_existing is 1, removes existing values first, so
1583 values move to front.
1584 """
1585 kw = copy_non_reserved_keywords(kw)
1586 for key, val in kw.items():
1587 if SCons.Util.is_List(val):
1588 val = _delete_duplicates(val, not delete_existing)
1589 if not self._dict.has_key(key) or self._dict[key] in ('', None):
1590 self._dict[key] = val
1591 elif SCons.Util.is_Dict(self._dict[key]) and \
1592 SCons.Util.is_Dict(val):
1593 self._dict[key].update(val)
1594 elif SCons.Util.is_List(val):
1595 dk = self._dict[key]
1596 if not SCons.Util.is_List(dk):
1597 dk = [dk]
1598 if delete_existing:
1599 dk = filter(lambda x, val=val: x not in val, dk)
1600 else:
1601 val = filter(lambda x, dk=dk: x not in dk, val)
1602 self._dict[key] = val + dk
1603 else:
1604 dk = self._dict[key]
1605 if SCons.Util.is_List(dk):
1606
1607
1608 if delete_existing:
1609 dk = filter(lambda x, val=val: x not in val, dk)
1610 self._dict[key] = [val] + dk
1611 else:
1612 if not val in dk:
1613 self._dict[key] = [val] + dk
1614 else:
1615 if delete_existing:
1616 dk = filter(lambda x, val=val: x not in val, dk)
1617 self._dict[key] = val + dk
1618 self.scanner_map_delete(kw)
1619
1621 """Replace existing construction variables in an Environment
1622 with new construction variables and/or values.
1623 """
1624 try:
1625 kwbd = kw['BUILDERS']
1626 except KeyError:
1627 pass
1628 else:
1629 kwbd = semi_deepcopy(kwbd)
1630 del kw['BUILDERS']
1631 self.__setitem__('BUILDERS', kwbd)
1632 kw = copy_non_reserved_keywords(kw)
1633 self._update(semi_deepcopy(kw))
1634 self.scanner_map_delete(kw)
1635
1636 - def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
1637 """
1638 Replace old_prefix with new_prefix and old_suffix with new_suffix.
1639
1640 env - Environment used to interpolate variables.
1641 path - the path that will be modified.
1642 old_prefix - construction variable for the old prefix.
1643 old_suffix - construction variable for the old suffix.
1644 new_prefix - construction variable for the new prefix.
1645 new_suffix - construction variable for the new suffix.
1646 """
1647 old_prefix = self.subst('$'+old_prefix)
1648 old_suffix = self.subst('$'+old_suffix)
1649
1650 new_prefix = self.subst('$'+new_prefix)
1651 new_suffix = self.subst('$'+new_suffix)
1652
1653 dir,name = os.path.split(str(path))
1654 if name[:len(old_prefix)] == old_prefix:
1655 name = name[len(old_prefix):]
1656 if name[-len(old_suffix):] == old_suffix:
1657 name = name[:-len(old_suffix)]
1658 return os.path.join(dir, new_prefix+name+new_suffix)
1659
1661 for k in kw.keys():
1662 if self._dict.has_key(k):
1663 del kw[k]
1664 apply(self.Replace, (), kw)
1665
1668
1677
1678 - def WhereIs(self, prog, path=None, pathext=None, reject=[]):
1679 """Find prog in the path.
1680 """
1681 if path is None:
1682 try:
1683 path = self['ENV']['PATH']
1684 except KeyError:
1685 pass
1686 elif SCons.Util.is_String(path):
1687 path = self.subst(path)
1688 if pathext is None:
1689 try:
1690 pathext = self['ENV']['PATHEXT']
1691 except KeyError:
1692 pass
1693 elif SCons.Util.is_String(pathext):
1694 pathext = self.subst(pathext)
1695 prog = self.subst(prog)
1696 path = SCons.Util.WhereIs(prog, path, pathext, reject)
1697 if path: return path
1698 return None
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708 - def Action(self, *args, **kw):
1713 nargs = map(subst_string, args)
1714 nkw = self.subst_kw(kw)
1715 return apply(SCons.Action.Action, nargs, nkw)
1716
1726
1727 - def AddPostAction(self, files, action):
1728 nodes = self.arg2nodes(files, self.fs.Entry)
1729 action = SCons.Action.Action(action)
1730 uniq = {}
1731 for executor in map(lambda n: n.get_executor(), nodes):
1732 uniq[executor] = 1
1733 for executor in uniq.keys():
1734 executor.add_post_action(action)
1735 return nodes
1736
1737 - def Alias(self, target, source=[], action=None, **kw):
1738 tlist = self.arg2nodes(target, self.ans.Alias)
1739 if not SCons.Util.is_List(source):
1740 source = [source]
1741 source = filter(None, source)
1742
1743 if not action:
1744 if not source:
1745
1746
1747
1748
1749
1750
1751 return tlist
1752
1753
1754
1755 result = []
1756 for t in tlist:
1757 bld = t.get_builder(AliasBuilder)
1758 result.extend(bld(self, t, source))
1759 return result
1760
1761 nkw = self.subst_kw(kw)
1762 nkw.update({
1763 'action' : SCons.Action.Action(action),
1764 'source_factory' : self.fs.Entry,
1765 'multi' : 1,
1766 'is_explicit' : None,
1767 })
1768 bld = apply(SCons.Builder.Builder, (), nkw)
1769
1770
1771
1772
1773
1774 result = []
1775 for t in tlist:
1776
1777
1778
1779
1780 b = t.get_builder()
1781 if b is None or b is AliasBuilder:
1782 b = bld
1783 else:
1784 nkw['action'] = b.action + action
1785 b = apply(SCons.Builder.Builder, (), nkw)
1786 t.convert()
1787 result.extend(b(self, t, t.sources + source))
1788 return result
1789
1797
1799 if kw.has_key('build_dir'):
1800 kw['variant_dir'] = kw['build_dir']
1801 del kw['build_dir']
1802 return apply(self.VariantDir, args, kw)
1803
1807
1813
1814 - def Clean(self, targets, files):
1823
1835
1836 - def Command(self, target, source, action, **kw):
1837 """Builds the supplied target files from the supplied
1838 source files using the supplied action. Action may
1839 be any type that the Builder constructor will accept
1840 for an action."""
1841 bkw = {
1842 'action' : action,
1843 'target_factory' : self.fs.Entry,
1844 'source_factory' : self.fs.Entry,
1845 }
1846 try: bkw['source_scanner'] = kw['source_scanner']
1847 except KeyError: pass
1848 else: del kw['source_scanner']
1849 bld = apply(SCons.Builder.Builder, (), bkw)
1850 return apply(bld, (self, target, source), kw)
1851
1852 - def Depends(self, target, dependency):
1853 """Explicity specify that 'target's depend on 'dependency'."""
1854 tlist = self.arg2nodes(target, self.fs.Entry)
1855 dlist = self.arg2nodes(dependency, self.fs.Entry)
1856 for t in tlist:
1857 t.add_dependency(dlist)
1858 return tlist
1859
1860 - def Dir(self, name, *args, **kw):
1870
1872 """Tags a target so that it will not be cleaned by -c"""
1873 tlist = []
1874 for t in targets:
1875 tlist.extend(self.arg2nodes(t, self.fs.Entry))
1876 for t in tlist:
1877 t.set_noclean()
1878 return tlist
1879
1881 """Tags a target so that it will not be cached"""
1882 tlist = []
1883 for t in targets:
1884 tlist.extend(self.arg2nodes(t, self.fs.Entry))
1885 for t in tlist:
1886 t.set_nocache()
1887 return tlist
1888
1889 - def Entry(self, name, *args, **kw):
1890 """
1891 """
1892 s = self.subst(name)
1893 if SCons.Util.is_Sequence(s):
1894 result=[]
1895 for e in s:
1896 result.append(apply(self.fs.Entry, (e,) + args, kw))
1897 return result
1898 return apply(self.fs.Entry, (s,) + args, kw)
1899
1902
1903 - def Execute(self, action, *args, **kw):
1904 """Directly execute an action through an Environment
1905 """
1906 action = apply(self.Action, (action,) + args, kw)
1907 result = action([], [], self)
1908 if isinstance(result, SCons.Errors.BuildError):
1909 errstr = result.errstr
1910 if result.filename:
1911 errstr = result.filename + ': ' + errstr
1912 sys.stderr.write("scons: *** %s\n" % errstr)
1913 return result.status
1914 else:
1915 return result
1916
1917 - def File(self, name, *args, **kw):
1927
1932
1935
1942
1945
1946 - def Ignore(self, target, dependency):
1953
1956
1957 - def Local(self, *targets):
1968
1976
1980
1981 - def Requires(self, target, prerequisite):
1982 """Specify that 'prerequisite' must be built before 'target',
1983 (but 'target' does not actually depend on 'prerequisite'
1984 and need not be rebuilt if it changes)."""
1985 tlist = self.arg2nodes(target, self.fs.Entry)
1986 plist = self.arg2nodes(prerequisite, self.fs.Entry)
1987 for t in tlist:
1988 t.add_prerequisite(plist)
1989 return tlist
1990
1999
2000 - def SConsignFile(self, name=".sconsign", dbm_module=None):
2011
2013 """Tell scons that side_effects are built as side
2014 effects of building targets."""
2015 side_effects = self.arg2nodes(side_effect, self.fs.Entry)
2016 targets = self.arg2nodes(target, self.fs.Entry)
2017
2018 for side_effect in side_effects:
2019 if side_effect.multiple_side_effect_has_builder():
2020 raise SCons.Errors.UserError, "Multiple ways to build the same target were specified for: %s" % str(side_effect)
2021 side_effect.add_source(targets)
2022 side_effect.side_effect = 1
2023 self.Precious(side_effect)
2024 for target in targets:
2025 target.side_effects.append(side_effect)
2026 return side_effects
2027
2029 """Arrange for a source code builder for (part of) a tree."""
2030 entries = self.arg2nodes(entry, self.fs.Entry)
2031 for entry in entries:
2032 entry.set_src_builder(builder)
2033 return entries
2034
2052
2054 """This function converts a string or list into a list of strings
2055 or Nodes. This makes things easier for users by allowing files to
2056 be specified as a white-space separated list to be split.
2057 The input rules are:
2058 - A single string containing names separated by spaces. These will be
2059 split apart at the spaces.
2060 - A single Node instance
2061 - A list containing either strings or Node instances. Any strings
2062 in the list are not split at spaces.
2063 In all cases, the function returns a list of Nodes and strings."""
2064 if SCons.Util.is_List(arg):
2065 return map(self.subst, arg)
2066 elif SCons.Util.is_String(arg):
2067 return string.split(self.subst(arg))
2068 else:
2069 return [self.subst(arg)]
2070
2092
2093 - def Value(self, value, built_value=None):
2097
2098 - def VariantDir(self, variant_dir, src_dir, duplicate=1):
2102
2128
2129
2130
2131 map( get_final_srcnode, sources )
2132
2133
2134 return list(set(sources))
2135
2137 """ returns the list of all targets of the Install and InstallAs Builder.
2138 """
2139 from SCons.Tool import install
2140 if install._UNIQUE_INSTALLED_FILES is None:
2141 install._UNIQUE_INSTALLED_FILES = SCons.Util.uniquer_hashables(install._INSTALLED_FILES)
2142 return install._UNIQUE_INSTALLED_FILES
2143
2145 """A proxy that overrides variables in a wrapped construction
2146 environment by returning values from an overrides dictionary in
2147 preference to values from the underlying subject environment.
2148
2149 This is a lightweight (I hope) proxy that passes through most use of
2150 attributes to the underlying Environment.Base class, but has just
2151 enough additional methods defined to act like a real construction
2152 environment with overridden values. It can wrap either a Base
2153 construction environment, or another OverrideEnvironment, which
2154 can in turn nest arbitrary OverrideEnvironments...
2155
2156 Note that we do *not* call the underlying base class
2157 (SubsitutionEnvironment) initialization, because we get most of those
2158 from proxying the attributes of the subject construction environment.
2159 But because we subclass SubstitutionEnvironment, this class also
2160 has inherited arg2nodes() and subst*() methods; those methods can't
2161 be proxied because they need *this* object's methods to fetch the
2162 values from the overrides dictionary.
2163 """
2164
2165 if SCons.Memoize.use_memoizer:
2166 __metaclass__ = SCons.Memoize.Memoized_Metaclass
2167
2168 - def __init__(self, subject, overrides={}):
2169 if __debug__: logInstanceCreation(self, 'Environment.OverrideEnvironment')
2170 self.__dict__['__subject'] = subject
2171 self.__dict__['overrides'] = overrides
2172
2173
2175 return getattr(self.__dict__['__subject'], name)
2177 setattr(self.__dict__['__subject'], name, value)
2178
2179
2181 try:
2182 return self.__dict__['overrides'][key]
2183 except KeyError:
2184 return self.__dict__['__subject'].__getitem__(key)
2190 try:
2191 del self.__dict__['overrides'][key]
2192 except KeyError:
2193 deleted = 0
2194 else:
2195 deleted = 1
2196 try:
2197 result = self.__dict__['__subject'].__delitem__(key)
2198 except KeyError:
2199 if not deleted:
2200 raise
2201 result = None
2202 return result
2203 - def get(self, key, default=None):
2204 """Emulates the get() method of dictionaries."""
2205 try:
2206 return self.__dict__['overrides'][key]
2207 except KeyError:
2208 return self.__dict__['__subject'].get(key, default)
2210 try:
2211 self.__dict__['overrides'][key]
2212 return 1
2213 except KeyError:
2214 return self.__dict__['__subject'].has_key(key)
2216 if self.__dict__['overrides'].__contains__(key):
2217 return 1
2218 return self.__dict__['__subject'].__contains__(key)
2220 """Emulates the items() method of dictionaries."""
2221 d = self.__dict__['__subject'].Dictionary().copy()
2222 d.update(self.__dict__['overrides'])
2223 return d
2225 """Emulates the items() method of dictionaries."""
2226 return self.Dictionary().items()
2227
2228
2230 """Update an environment's values directly, bypassing the normal
2231 checks that occur when users try to set items.
2232 """
2233 self.__dict__['overrides'].update(dict)
2234
2236 return self.__dict__['__subject'].gvars()
2237
2242
2243
2247
2248
2249
2250
2251
2252
2253
2254 Environment = Base
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2269 class _NoSubstitutionProxy(Environment):
2270 def __init__(self, subject):
2271 self.__dict__['__subject'] = subject
2272 def __getattr__(self, name):
2273 return getattr(self.__dict__['__subject'], name)
2274 def __setattr__(self, name, value):
2275 return setattr(self.__dict__['__subject'], name, value)
2276 def raw_to_mode(self, dict):
2277 try:
2278 raw = dict['raw']
2279 except KeyError:
2280 pass
2281 else:
2282 del dict['raw']
2283 dict['mode'] = raw
2284 def subst(self, string, *args, **kwargs):
2285 return string
2286 def subst_kw(self, kw, *args, **kwargs):
2287 return kw
2288 def subst_list(self, string, *args, **kwargs):
2289 nargs = (string, self,) + args
2290 nkw = kwargs.copy()
2291 nkw['gvars'] = {}
2292 self.raw_to_mode(nkw)
2293 return apply(SCons.Subst.scons_subst_list, nargs, nkw)
2294 def subst_target_source(self, string, *args, **kwargs):
2295 nargs = (string, self,) + args
2296 nkw = kwargs.copy()
2297 nkw['gvars'] = {}
2298 self.raw_to_mode(nkw)
2299 return apply(SCons.Subst.scons_subst, nargs, nkw)
2300 return _NoSubstitutionProxy(subject)
2301