Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(188)

Side by Side Diff: third_party/scons/scons-local/SCons/Util.py

Issue 20025: Update SCons to latest checkpoint release, 1.2.0.d20090113.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 """SCons.Util 1 """SCons.Util
2 2
3 Various utility functions go here. 3 Various utility functions go here.
4 4
5 """ 5 """
6 6
7 # 7 #
8 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundat ion 8 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons F oundation
9 # 9 #
10 # Permission is hereby granted, free of charge, to any person obtaining 10 # Permission is hereby granted, free of charge, to any person obtaining
11 # a copy of this software and associated documentation files (the 11 # a copy of this software and associated documentation files (the
12 # "Software"), to deal in the Software without restriction, including 12 # "Software"), to deal in the Software without restriction, including
13 # without limitation the rights to use, copy, modify, merge, publish, 13 # without limitation the rights to use, copy, modify, merge, publish,
14 # distribute, sublicense, and/or sell copies of the Software, and to 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 15 # permit persons to whom the Software is furnished to do so, subject to
16 # the following conditions: 16 # the following conditions:
17 # 17 #
18 # The above copyright notice and this permission notice shall be included 18 # The above copyright notice and this permission notice shall be included
19 # in all copies or substantial portions of the Software. 19 # in all copies or substantial portions of the Software.
20 # 20 #
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 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 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 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. 27 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 # 28 #
29 29
30 __revision__ = "src/engine/SCons/Util.py 3842 2008/12/20 22:59:52 scons" 30 __revision__ = "src/engine/SCons/Util.py 3897 2009/01/13 06:45:54 scons"
31 31
32 import copy 32 import copy
33 import os 33 import os
34 import os.path 34 import os.path
35 import re 35 import re
36 import string 36 import string
37 import sys 37 import sys
38 import types 38 import types
39 39
40 from UserDict import UserDict 40 from UserDict import UserDict
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 Make the drive letter (if any) upper case. 100 Make the drive letter (if any) upper case.
101 This is useful because Windows is inconsitent on the case 101 This is useful because Windows is inconsitent on the case
102 of the drive letter, which can cause inconsistencies when 102 of the drive letter, which can cause inconsistencies when
103 calculating command signatures. 103 calculating command signatures.
104 """ 104 """
105 drive, rest = os.path.splitdrive(path) 105 drive, rest = os.path.splitdrive(path)
106 if drive: 106 if drive:
107 path = string.upper(drive) + rest 107 path = string.upper(drive) + rest
108 return path 108 return path
109 109
110 class CallableComposite(UserList):
111 """A simple composite callable class that, when called, will invoke all
112 of its contained callables with the same arguments."""
113 def __call__(self, *args, **kwargs):
114 retvals = map(lambda x, args=args, kwargs=kwargs: apply(x,
115 args,
116 kwargs),
117 self.data)
118 if self.data and (len(self.data) == len(filter(callable, retvals))):
119 return self.__class__(retvals)
120 return NodeList(retvals)
121
122 class NodeList(UserList): 110 class NodeList(UserList):
123 """This class is almost exactly like a regular list of Nodes 111 """This class is almost exactly like a regular list of Nodes
124 (actually it can hold any object), with one important difference. 112 (actually it can hold any object), with one important difference.
125 If you try to get an attribute from this list, it will return that 113 If you try to get an attribute from this list, it will return that
126 attribute from every item in the list. For example: 114 attribute from every item in the list. For example:
127 115
128 >>> someList = NodeList([ ' foo ', ' bar ' ]) 116 >>> someList = NodeList([ ' foo ', ' bar ' ])
129 >>> someList.strip() 117 >>> someList.strip()
130 [ 'foo', 'bar' ] 118 [ 'foo', 'bar' ]
131 """ 119 """
132 def __nonzero__(self): 120 def __nonzero__(self):
133 return len(self.data) != 0 121 return len(self.data) != 0
134 122
135 def __str__(self): 123 def __str__(self):
136 return string.join(map(str, self.data)) 124 return string.join(map(str, self.data))
137 125
126 def __iter__(self):
127 return iter(self.data)
128
129 def __call__(self, *args, **kwargs):
130 result = map(lambda x, args=args, kwargs=kwargs: apply(x,
131 args,
132 kwargs),
133 self.data)
134 return self.__class__(result)
135
138 def __getattr__(self, name): 136 def __getattr__(self, name):
139 if not self.data: 137 result = map(lambda x, n=name: getattr(x, n), self.data)
140 # If there is nothing in the list, then we have no attributes to 138 return self.__class__(result)
141 # pass through, so raise AttributeError for everything.
142 raise AttributeError, "NodeList has no attribute: %s" % name
143 139
144 # Return a list of the attribute, gotten from every element
145 # in the list
146 attrList = map(lambda x, n=name: getattr(x, n), self.data)
147
148 # Special case. If the attribute is callable, we do not want
149 # to return a list of callables. Rather, we want to return a
150 # single callable that, when called, will invoke the function on
151 # all elements of this list.
152 if self.data and (len(self.data) == len(filter(callable, attrList))):
153 return CallableComposite(attrList)
154 return self.__class__(attrList)
155 140
156 _get_env_var = re.compile(r'^\$([_a-zA-Z]\w*|{[_a-zA-Z]\w*})$') 141 _get_env_var = re.compile(r'^\$([_a-zA-Z]\w*|{[_a-zA-Z]\w*})$')
157 142
158 def get_environment_var(varstr): 143 def get_environment_var(varstr):
159 """Given a string, first determine if it looks like a reference 144 """Given a string, first determine if it looks like a reference
160 to a single environment variable, like "$FOO" or "${FOO}". 145 to a single environment variable, like "$FOO" or "${FOO}".
161 If so, return that variable with no decorations ("FOO"). 146 If so, return that variable with no decorations ("FOO").
162 If not, return None.""" 147 If not, return None."""
163 mo=_get_env_var.match(to_String(varstr)) 148 mo=_get_env_var.match(to_String(varstr))
164 if mo: 149 if mo:
(...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 # network issues. 822 # network issues.
838 continue 823 continue
839 if stat.S_IMODE(st[stat.ST_MODE]) & 0111: 824 if stat.S_IMODE(st[stat.ST_MODE]) & 0111:
840 try: 825 try:
841 reject.index(f) 826 reject.index(f)
842 except ValueError: 827 except ValueError:
843 return os.path.normpath(f) 828 return os.path.normpath(f)
844 continue 829 continue
845 return None 830 return None
846 831
847 def PrependPath(oldpath, newpath, sep = os.pathsep, delete_existing=1): 832 def PrependPath(oldpath, newpath, sep = os.pathsep,
833 delete_existing=1, canonicalize=None):
848 """This prepends newpath elements to the given oldpath. Will only 834 """This prepends newpath elements to the given oldpath. Will only
849 add any particular path once (leaving the first one it encounters 835 add any particular path once (leaving the first one it encounters
850 and ignoring the rest, to preserve path order), and will 836 and ignoring the rest, to preserve path order), and will
851 os.path.normpath and os.path.normcase all paths to help assure 837 os.path.normpath and os.path.normcase all paths to help assure
852 this. This can also handle the case where the given old path 838 this. This can also handle the case where the given old path
853 variable is a list instead of a string, in which case a list will 839 variable is a list instead of a string, in which case a list will
854 be returned instead of a string. 840 be returned instead of a string.
855 841
856 Example: 842 Example:
857 Old Path: "/foo/bar:/foo" 843 Old Path: "/foo/bar:/foo"
858 New Path: "/biz/boom:/foo" 844 New Path: "/biz/boom:/foo"
859 Result: "/biz/boom:/foo:/foo/bar" 845 Result: "/biz/boom:/foo:/foo/bar"
860 846
861 If delete_existing is 0, then adding a path that exists will 847 If delete_existing is 0, then adding a path that exists will
862 not move it to the beginning; it will stay where it is in the 848 not move it to the beginning; it will stay where it is in the
863 list. 849 list.
850
851 If canonicalize is not None, it is applied to each element of
852 newpath before use.
864 """ 853 """
865 854
866 orig = oldpath 855 orig = oldpath
867 is_list = 1 856 is_list = 1
868 paths = orig 857 paths = orig
869 if not is_List(orig) and not is_Tuple(orig): 858 if not is_List(orig) and not is_Tuple(orig):
870 paths = string.split(paths, sep) 859 paths = string.split(paths, sep)
871 is_list = 0 860 is_list = 0
872 861
873 if is_List(newpath) or is_Tuple(newpath): 862 if is_String(newpath):
863 newpaths = string.split(newpath, sep)
864 elif not is_List(newpath) and not is_Tuple(newpath):
865 newpaths = [ newpath ] # might be a Dir
866 else:
874 newpaths = newpath 867 newpaths = newpath
875 else: 868
876 newpaths = string.split(newpath, sep) 869 if canonicalize:
870 newpaths=map(canonicalize, newpaths)
877 871
878 if not delete_existing: 872 if not delete_existing:
879 # First uniquify the old paths, making sure to 873 # First uniquify the old paths, making sure to
880 # preserve the first instance (in Unix/Linux, 874 # preserve the first instance (in Unix/Linux,
881 # the first one wins), and remembering them in normpaths. 875 # the first one wins), and remembering them in normpaths.
882 # Then insert the new paths at the head of the list 876 # Then insert the new paths at the head of the list
883 # if they're not already in the normpaths list. 877 # if they're not already in the normpaths list.
884 result = [] 878 result = []
885 normpaths = [] 879 normpaths = []
886 for path in paths: 880 for path in paths:
(...skipping 23 matching lines...) Expand all
910 normpath = os.path.normpath(os.path.normcase(path)) 904 normpath = os.path.normpath(os.path.normcase(path))
911 if path and not normpath in normpaths: 905 if path and not normpath in normpaths:
912 paths.append(path) 906 paths.append(path)
913 normpaths.append(normpath) 907 normpaths.append(normpath)
914 908
915 if is_list: 909 if is_list:
916 return paths 910 return paths
917 else: 911 else:
918 return string.join(paths, sep) 912 return string.join(paths, sep)
919 913
920 def AppendPath(oldpath, newpath, sep = os.pathsep, delete_existing=1): 914 def AppendPath(oldpath, newpath, sep = os.pathsep,
915 delete_existing=1, canonicalize=None):
921 """This appends new path elements to the given old path. Will 916 """This appends new path elements to the given old path. Will
922 only add any particular path once (leaving the last one it 917 only add any particular path once (leaving the last one it
923 encounters and ignoring the rest, to preserve path order), and 918 encounters and ignoring the rest, to preserve path order), and
924 will os.path.normpath and os.path.normcase all paths to help 919 will os.path.normpath and os.path.normcase all paths to help
925 assure this. This can also handle the case where the given old 920 assure this. This can also handle the case where the given old
926 path variable is a list instead of a string, in which case a list 921 path variable is a list instead of a string, in which case a list
927 will be returned instead of a string. 922 will be returned instead of a string.
928 923
929 Example: 924 Example:
930 Old Path: "/foo/bar:/foo" 925 Old Path: "/foo/bar:/foo"
931 New Path: "/biz/boom:/foo" 926 New Path: "/biz/boom:/foo"
932 Result: "/foo/bar:/biz/boom:/foo" 927 Result: "/foo/bar:/biz/boom:/foo"
933 928
934 If delete_existing is 0, then adding a path that exists 929 If delete_existing is 0, then adding a path that exists
935 will not move it to the end; it will stay where it is in the list. 930 will not move it to the end; it will stay where it is in the list.
931
932 If canonicalize is not None, it is applied to each element of
933 newpath before use.
936 """ 934 """
937 935
938 orig = oldpath 936 orig = oldpath
939 is_list = 1 937 is_list = 1
940 paths = orig 938 paths = orig
941 if not is_List(orig) and not is_Tuple(orig): 939 if not is_List(orig) and not is_Tuple(orig):
942 paths = string.split(paths, sep) 940 paths = string.split(paths, sep)
943 is_list = 0 941 is_list = 0
944 942
945 if is_List(newpath) or is_Tuple(newpath): 943 if is_String(newpath):
944 newpaths = string.split(newpath, sep)
945 elif not is_List(newpath) and not is_Tuple(newpath):
946 newpaths = [ newpath ] # might be a Dir
947 else:
946 newpaths = newpath 948 newpaths = newpath
947 else: 949
948 newpaths = string.split(newpath, sep) 950 if canonicalize:
951 newpaths=map(canonicalize, newpaths)
949 952
950 if not delete_existing: 953 if not delete_existing:
951 # add old paths to result, then 954 # add old paths to result, then
952 # add new paths if not already present 955 # add new paths if not already present
953 # (I thought about using a dict for normpaths for speed, 956 # (I thought about using a dict for normpaths for speed,
954 # but it's not clear hashing the strings would be faster 957 # but it's not clear hashing the strings would be faster
955 # than linear searching these typically short lists.) 958 # than linear searching these typically short lists.)
956 result = [] 959 result = []
957 normpaths = [] 960 normpaths = []
958 for path in paths: 961 for path in paths:
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1082 for (key, val) in dict.items(): 1085 for (key, val) in dict.items():
1083 self.__setitem__(key, val) 1086 self.__setitem__(key, val)
1084 1087
1085 def values(self): 1088 def values(self):
1086 return map(self.get, self._keys) 1089 return map(self.get, self._keys)
1087 1090
1088 class Selector(OrderedDict): 1091 class Selector(OrderedDict):
1089 """A callable ordered dictionary that maps file suffixes to 1092 """A callable ordered dictionary that maps file suffixes to
1090 dictionary values. We preserve the order in which items are added 1093 dictionary values. We preserve the order in which items are added
1091 so that get_suffix() calls always return the first suffix added.""" 1094 so that get_suffix() calls always return the first suffix added."""
1092 def __call__(self, env, source): 1095 def __call__(self, env, source, ext=None):
1093 try: 1096 if ext is None:
1094 ext = source[0].suffix 1097 try:
1095 except IndexError: 1098 ext = source[0].suffix
1096 ext = "" 1099 except IndexError:
1100 ext = ""
1097 try: 1101 try:
1098 return self[ext] 1102 return self[ext]
1099 except KeyError: 1103 except KeyError:
1100 # Try to perform Environment substitution on the keys of 1104 # Try to perform Environment substitution on the keys of
1101 # the dictionary before giving up. 1105 # the dictionary before giving up.
1102 s_dict = {} 1106 s_dict = {}
1103 for (k,v) in self.items(): 1107 for (k,v) in self.items():
1104 if not k is None: 1108 if not k is None:
1105 s_k = env.subst(k) 1109 s_k = env.subst(k)
1106 if s_dict.has_key(s_k): 1110 if s_dict.has_key(s_k):
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
1542 return MD5signature(string.join(signatures, ', ')) 1546 return MD5signature(string.join(signatures, ', '))
1543 1547
1544 1548
1545 1549
1546 # From Dinu C. Gherman, 1550 # From Dinu C. Gherman,
1547 # Python Cookbook, second edition, recipe 6.17, p. 277. 1551 # Python Cookbook, second edition, recipe 6.17, p. 277.
1548 # Also: 1552 # Also:
1549 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205 1553 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205
1550 # ASPN: Python Cookbook: Null Object Design Pattern 1554 # ASPN: Python Cookbook: Null Object Design Pattern
1551 1555
1556 # TODO(1.5):
1557 #class Null(object):
1552 class Null: 1558 class Null:
1553 """ Null objects always and reliably "do nothging." """ 1559 """ Null objects always and reliably "do nothing." """
1554
1555 def __new__(cls, *args, **kwargs): 1560 def __new__(cls, *args, **kwargs):
1556 if not '_inst' in vars(cls): 1561 if not '_inst' in vars(cls):
1557 #cls._inst = type.__new__(cls, *args, **kwargs) 1562 #cls._inst = type.__new__(cls, *args, **kwargs)
1558 cls._inst = apply(type.__new__, (cls,) + args, kwargs) 1563 cls._inst = apply(type.__new__, (cls,) + args, kwargs)
1559 return cls._inst 1564 return cls._inst
1560 def __init__(self, *args, **kwargs): 1565 def __init__(self, *args, **kwargs):
1561 pass 1566 pass
1562 def __call__(self, *args, **kwargs): 1567 def __call__(self, *args, **kwargs):
1563 return self 1568 return self
1564 def __repr__(self): 1569 def __repr__(self):
1565 return "Null()" 1570 return "Null(0x%08X)" % id(self)
1566 def __nonzero__(self): 1571 def __nonzero__(self):
1567 return False 1572 return False
1568 def __getattr__(self, mname): 1573 def __getattr__(self, name):
1569 return self 1574 return self
1570 def __setattr__(self, name, value): 1575 def __setattr__(self, name, value):
1571 return self 1576 return self
1572 def __delattr__(self, name): 1577 def __delattr__(self, name):
1573 return self 1578 return self
1574 1579
1580 class NullSeq(Null):
1581 def __len__(self):
1582 return 0
1583 def __iter__(self):
1584 return iter(())
1585 def __getitem__(self, i):
1586 return self
1587 def __delitem__(self, i):
1588 return self
1589 def __setitem__(self, i, v):
1590 return self
1575 1591
1576 1592
1577 del __revision__ 1593 del __revision__
OLDNEW
« no previous file with comments | « third_party/scons/scons-local/SCons/Tool/zip.py ('k') | third_party/scons/scons-local/SCons/Variables/BoolVariable.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698