1 """SCons.Util
2
3 Various utility functions go here.
4
5 """
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 __revision__ = "src/engine/SCons/Util.py 4720 2010/03/24 03:14:11 jars"
31
32 import copy
33 import os
34 import os.path
35 import re
36 import string
37 import sys
38 import types
39
40 from UserDict import UserDict
41 from UserList import UserList
42 from UserString import UserString
43
44
45
46 DictType = types.DictType
47 InstanceType = types.InstanceType
48 ListType = types.ListType
49 StringType = types.StringType
50 TupleType = types.TupleType
51
52 -def dictify(keys, values, result={}):
56
57 _altsep = os.altsep
58 if _altsep is None and sys.platform == 'win32':
59
60 _altsep = '/'
61 if _altsep:
65 else:
66 rightmost_separator = string.rfind
67
68
69
71 """Check whether sequence str contains ANY of the items in set."""
72 for c in set:
73 if c in str: return 1
74 return 0
75
77 """Check whether sequence str contains ALL of the items in set."""
78 for c in set:
79 if c not in str: return 0
80 return 1
81
83 """Check whether sequence str contains ONLY items in set."""
84 for c in str:
85 if c not in set: return 0
86 return 1
87
89 "Same as os.path.splitext() but faster."
90 sep = rightmost_separator(path, os.sep)
91 dot = string.rfind(path, '.')
92
93 if dot > sep and not containsOnly(path[dot:], "0123456789."):
94 return path[:dot],path[dot:]
95 else:
96 return path,""
97
99 """
100 Make the drive letter (if any) upper case.
101 This is useful because Windows is inconsitent on the case
102 of the drive letter, which can cause inconsistencies when
103 calculating command signatures.
104 """
105 drive, rest = os.path.splitdrive(path)
106 if drive:
107 path = string.upper(drive) + rest
108 return path
109
111 """This class is almost exactly like a regular list of Nodes
112 (actually it can hold any object), with one important difference.
113 If you try to get an attribute from this list, it will return that
114 attribute from every item in the list. For example:
115
116 >>> someList = NodeList([ ' foo ', ' bar ' ])
117 >>> someList.strip()
118 [ 'foo', 'bar' ]
119 """
121 return len(self.data) != 0
122
124 return string.join(map(str, self.data))
125
127 return iter(self.data)
128
130 result = map(lambda x, args=args, kwargs=kwargs: apply(x,
131 args,
132 kwargs),
133 self.data)
134 return self.__class__(result)
135
137 result = map(lambda x, n=name: getattr(x, n), self.data)
138 return self.__class__(result)
139
140
141 _get_env_var = re.compile(r'^\$([_a-zA-Z]\w*|{[_a-zA-Z]\w*})$')
142
144 """Given a string, first determine if it looks like a reference
145 to a single environment variable, like "$FOO" or "${FOO}".
146 If so, return that variable with no decorations ("FOO").
147 If not, return None."""
148 mo=_get_env_var.match(to_String(varstr))
149 if mo:
150 var = mo.group(1)
151 if var[0] == '{':
152 return var[1:-1]
153 else:
154 return var
155 else:
156 return None
157
161
162 - def print_it(self, text, append_newline=1):
163 if append_newline: text = text + '\n'
164 try:
165 sys.stdout.write(text)
166 except IOError:
167
168
169
170
171
172
173
174 pass
175
178
184
185 -def render_tree(root, child_func, prune=0, margin=[0], visited={}):
186 """
187 Render a tree of nodes into an ASCII tree view.
188 root - the root node of the tree
189 child_func - the function called to get the children of a node
190 prune - don't visit the same node twice
191 margin - the format of the left margin to use for children of root.
192 1 results in a pipe, and 0 results in no pipe.
193 visited - a dictionary of visited nodes in the current branch if not prune,
194 or in the whole tree if prune.
195 """
196
197 rname = str(root)
198
199 children = child_func(root)
200 retval = ""
201 for pipe in margin[:-1]:
202 if pipe:
203 retval = retval + "| "
204 else:
205 retval = retval + " "
206
207 if visited.has_key(rname):
208 return retval + "+-[" + rname + "]\n"
209
210 retval = retval + "+-" + rname + "\n"
211 if not prune:
212 visited = copy.copy(visited)
213 visited[rname] = 1
214
215 for i in range(len(children)):
216 margin.append(i<len(children)-1)
217 retval = retval + render_tree(children[i], child_func, prune, margin, visited
218 )
219 margin.pop()
220
221 return retval
222
223 IDX = lambda N: N and 1 or 0
224
225 -def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}):
226 """
227 Print a tree of nodes. This is like render_tree, except it prints
228 lines directly instead of creating a string representation in memory,
229 so that huge trees can be printed.
230
231 root - the root node of the tree
232 child_func - the function called to get the children of a node
233 prune - don't visit the same node twice
234 showtags - print status information to the left of each node line
235 margin - the format of the left margin to use for children of root.
236 1 results in a pipe, and 0 results in no pipe.
237 visited - a dictionary of visited nodes in the current branch if not prune,
238 or in the whole tree if prune.
239 """
240
241 rname = str(root)
242
243 if showtags:
244
245 if showtags == 2:
246 print ' E = exists'
247 print ' R = exists in repository only'
248 print ' b = implicit builder'
249 print ' B = explicit builder'
250 print ' S = side effect'
251 print ' P = precious'
252 print ' A = always build'
253 print ' C = current'
254 print ' N = no clean'
255 print ' H = no cache'
256 print ''
257
258 tags = ['[']
259 tags.append(' E'[IDX(root.exists())])
260 tags.append(' R'[IDX(root.rexists() and not root.exists())])
261 tags.append(' BbB'[[0,1][IDX(root.has_explicit_builder())] +
262 [0,2][IDX(root.has_builder())]])
263 tags.append(' S'[IDX(root.side_effect)])
264 tags.append(' P'[IDX(root.precious)])
265 tags.append(' A'[IDX(root.always_build)])
266 tags.append(' C'[IDX(root.is_up_to_date())])
267 tags.append(' N'[IDX(root.noclean)])
268 tags.append(' H'[IDX(root.nocache)])
269 tags.append(']')
270
271 else:
272 tags = []
273
274 def MMM(m):
275 return [" ","| "][m]
276 margins = map(MMM, margin[:-1])
277
278 children = child_func(root)
279
280 if prune and visited.has_key(rname) and children:
281 print string.join(tags + margins + ['+-[', rname, ']'], '')
282 return
283
284 print string.join(tags + margins + ['+-', rname], '')
285
286 visited[rname] = 1
287
288 if children:
289 margin.append(1)
290 idx = IDX(showtags)
291 for C in children[:-1]:
292 print_tree(C, child_func, prune, idx, margin, visited)
293 margin[-1] = 0
294 print_tree(children[-1], child_func, prune, idx, margin, visited)
295 margin.pop()
296
297
298
299
300
301
302
303
304
305
306
307 try:
310 except TypeError:
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
331 t = type(obj)
332 return t is DictType or \
333 (t is InstanceType and isinstance(obj, UserDict))
334
336 t = type(obj)
337 return t is ListType \
338 or (t is InstanceType and isinstance(obj, UserList))
339
341 t = type(obj)
342 return t is ListType \
343 or t is TupleType \
344 or (t is InstanceType and isinstance(obj, UserList))
345
347 t = type(obj)
348 return t is TupleType
349
350 if hasattr(types, 'UnicodeType'):
352 t = type(obj)
353 return t is StringType \
354 or t is UnicodeType \
355 or (t is InstanceType and isinstance(obj, UserString))
356 else:
358 t = type(obj)
359 return t is StringType \
360 or (t is InstanceType and isinstance(obj, UserString))
361
363 return is_String(obj) or not is_Sequence(obj)
364
366 """Flatten a sequence to a non-nested list.
367
368 Flatten() converts either a single scalar or a nested sequence
369 to a non-nested list. Note that flatten() considers strings
370 to be scalars instead of sequences like Python would.
371 """
372 if is_Scalar(obj):
373 return [obj]
374 if result is None:
375 result = []
376 for item in obj:
377 if is_Scalar(item):
378 result.append(item)
379 else:
380 flatten_sequence(item, result)
381 return result
382
384 """Flatten a sequence to a non-nested list.
385
386 Same as flatten(), but it does not handle the single scalar
387 case. This is slightly more efficient when one knows that
388 the sequence to flatten can not be a scalar.
389 """
390 if result is None:
391 result = []
392 for item in sequence:
393 if is_Scalar(item):
394 result.append(item)
395 else:
396 flatten_sequence(item, result)
397 return result
398
399
400
401
402
403
404
405 if hasattr(types, 'UnicodeType'):
406 UnicodeType = types.UnicodeType
408 if isinstance(s, UserString):
409 t = type(s.data)
410 else:
411 t = type(s)
412 if t is UnicodeType:
413 return unicode(s)
414 else:
415 return str(s)
416 else:
417 to_String = str
418
420 try:
421 f = obj.for_signature
422 except AttributeError:
423 return to_String_for_subst(obj)
424 else:
425 return f()
426
428 if is_Sequence( s ):
429 return string.join( map(to_String_for_subst, s) )
430
431 return to_String( s )
432
433 else:
434
435
436
437
438
439
440
441
442
443 DictTypes = (dict, UserDict)
444 ListTypes = (list, UserList)
445 SequenceTypes = (list, tuple, UserList)
446
447
448
449
450
451
452
453 StringTypes = (str, unicode, UserString)
454
455
456
457 BaseStringTypes = (str, unicode)
458
461
464
467
468 - def is_Tuple(obj, isinstance=isinstance, tuple=tuple):
469 return isinstance(obj, tuple)
470
473
482
490
493 """Flatten a sequence to a non-nested list.
494
495 Flatten() converts either a single scalar or a nested sequence
496 to a non-nested list. Note that flatten() considers strings
497 to be scalars instead of sequences like Python would.
498 """
499 if isinstance(obj, StringTypes) or not isinstance(obj, SequenceTypes):
500 return [obj]
501 result = []
502 for item in obj:
503 if isinstance(item, StringTypes) or not isinstance(item, SequenceTypes):
504 result.append(item)
505 else:
506 do_flatten(item, result)
507 return result
508
511 """Flatten a sequence to a non-nested list.
512
513 Same as flatten(), but it does not handle the single scalar
514 case. This is slightly more efficient when one knows that
515 the sequence to flatten can not be a scalar.
516 """
517 result = []
518 for item in sequence:
519 if isinstance(item, StringTypes) or not isinstance(item, SequenceTypes):
520 result.append(item)
521 else:
522 do_flatten(item, result)
523 return result
524
525
526
527
528
529
530
531
535 if isinstance(s,BaseStringTypes):
536
537 return s
538 elif isinstance(s, UserString):
539
540
541 return s.data
542 else:
543 return str(s)
544
549
550
551 if isinstance(s, BaseStringTypes):
552 return s
553 elif isinstance(s, SequenceTypes):
554 l = []
555 for e in s:
556 l.append(to_String_for_subst(e))
557 return join( s )
558 elif isinstance(s, UserString):
559
560
561 return s.data
562 else:
563 return str(s)
564
567 try:
568 f = obj.for_signature
569 except AttributeError:
570 return to_String_for_subst(obj)
571 else:
572 return f()
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589 _semi_deepcopy_dispatch = d = {}
590
592 copy = {}
593 for key, val in x.items():
594
595
596
597
598
599
600 copy[key] = semi_deepcopy(val)
601 return copy
602 d[types.DictionaryType] = _semi_deepcopy_dict
603
605 return map(semi_deepcopy, x)
606 d[types.ListType] = _semi_deepcopy_list
607
609 return tuple(map(semi_deepcopy, x))
610 d[types.TupleType] = _semi_deepcopy_tuple
611
613 if hasattr(x, '__semi_deepcopy__'):
614 return x.__semi_deepcopy__()
615 elif isinstance(x, UserDict):
616 return x.__class__(_semi_deepcopy_dict(x))
617 elif isinstance(x, UserList):
618 return x.__class__(_semi_deepcopy_list(x))
619 else:
620 return x
621 d[types.InstanceType] = _semi_deepcopy_inst
622
629
630
631
633 """A simple generic Proxy class, forwarding all calls to
634 subject. So, for the benefit of the python newbie, what does
635 this really mean? Well, it means that you can take an object, let's
636 call it 'objA', and wrap it in this Proxy class, with a statement
637 like this
638
639 proxyObj = Proxy(objA),
640
641 Then, if in the future, you do something like this
642
643 x = proxyObj.var1,
644
645 since Proxy does not have a 'var1' attribute (but presumably objA does),
646 the request actually is equivalent to saying
647
648 x = objA.var1
649
650 Inherit from this class to create a Proxy."""
651
653 """Wrap an object as a Proxy object"""
654 self.__subject = subject
655
657 """Retrieve an attribute from the wrapped object. If the named
658 attribute doesn't exist, AttributeError is raised"""
659 return getattr(self.__subject, name)
660
662 """Retrieve the entire wrapped object"""
663 return self.__subject
664
666 if issubclass(other.__class__, self.__subject.__class__):
667 return cmp(self.__subject, other)
668 return cmp(self.__dict__, other.__dict__)
669
670
671 can_read_reg = 0
672 try:
673 import _winreg
674
675 can_read_reg = 1
676 hkey_mod = _winreg
677
678 RegOpenKeyEx = _winreg.OpenKeyEx
679 RegEnumKey = _winreg.EnumKey
680 RegEnumValue = _winreg.EnumValue
681 RegQueryValueEx = _winreg.QueryValueEx
682 RegError = _winreg.error
683
684 except ImportError:
685 try:
686 import win32api
687 import win32con
688 can_read_reg = 1
689 hkey_mod = win32con
690
691 RegOpenKeyEx = win32api.RegOpenKeyEx
692 RegEnumKey = win32api.RegEnumKey
693 RegEnumValue = win32api.RegEnumValue
694 RegQueryValueEx = win32api.RegQueryValueEx
695 RegError = win32api.error
696
697 except ImportError:
700 RegError = _NoError
701
702 if can_read_reg:
703 HKEY_CLASSES_ROOT = hkey_mod.HKEY_CLASSES_ROOT
704 HKEY_LOCAL_MACHINE = hkey_mod.HKEY_LOCAL_MACHINE
705 HKEY_CURRENT_USER = hkey_mod.HKEY_CURRENT_USER
706 HKEY_USERS = hkey_mod.HKEY_USERS
707
709 """This utility function returns a value in the registry
710 without having to open the key first. Only available on
711 Windows platforms with a version of Python that can read the
712 registry. Returns the same thing as
713 SCons.Util.RegQueryValueEx, except you just specify the entire
714 path to the value, and don't have to bother opening the key
715 first. So:
716
717 Instead of:
718 k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
719 r'SOFTWARE\Microsoft\Windows\CurrentVersion')
720 out = SCons.Util.RegQueryValueEx(k,
721 'ProgramFilesDir')
722
723 You can write:
724 out = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE,
725 r'SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir')
726 """
727
728
729 p = key.rfind('\\') + 1
730 keyp = key[:p-1]
731 val = key[p:]
732 k = RegOpenKeyEx(root, keyp)
733 return RegQueryValueEx(k,val)
734 else:
735 try:
736 e = WindowsError
737 except NameError:
738
739
740
741
744 import __builtin__
745 __builtin__.WindowsError = WindowsError
746 else:
747 del e
748
749 HKEY_CLASSES_ROOT = None
750 HKEY_LOCAL_MACHINE = None
751 HKEY_CURRENT_USER = None
752 HKEY_USERS = None
753
756
759
760 if sys.platform == 'win32':
761
762 - def WhereIs(file, path=None, pathext=None, reject=[]):
763 if path is None:
764 try:
765 path = os.environ['PATH']
766 except KeyError:
767 return None
768 if is_String(path):
769 path = string.split(path, os.pathsep)
770 if pathext is None:
771 try:
772 pathext = os.environ['PATHEXT']
773 except KeyError:
774 pathext = '.COM;.EXE;.BAT;.CMD'
775 if is_String(pathext):
776 pathext = string.split(pathext, os.pathsep)
777 for ext in pathext:
778 if string.lower(ext) == string.lower(file[-len(ext):]):
779 pathext = ['']
780 break
781 if not is_List(reject) and not is_Tuple(reject):
782 reject = [reject]
783 for dir in path:
784 f = os.path.join(dir, file)
785 for ext in pathext:
786 fext = f + ext
787 if os.path.isfile(fext):
788 try:
789 reject.index(fext)
790 except ValueError:
791 return os.path.normpath(fext)
792 continue
793 return None
794
795 elif os.name == 'os2':
796
797 - def WhereIs(file, path=None, pathext=None, reject=[]):
798 if path is None:
799 try:
800 path = os.environ['PATH']
801 except KeyError:
802 return None
803 if is_String(path):
804 path = string.split(path, os.pathsep)
805 if pathext is None:
806 pathext = ['.exe', '.cmd']
807 for ext in pathext:
808 if string.lower(ext) == string.lower(file[-len(ext):]):
809 pathext = ['']
810 break
811 if not is_List(reject) and not is_Tuple(reject):
812 reject = [reject]
813 for dir in path:
814 f = os.path.join(dir, file)
815 for ext in pathext:
816 fext = f + ext
817 if os.path.isfile(fext):
818 try:
819 reject.index(fext)
820 except ValueError:
821 return os.path.normpath(fext)
822 continue
823 return None
824
825 else:
826
827 - def WhereIs(file, path=None, pathext=None, reject=[]):
856
859 """This prepends newpath elements to the given oldpath. Will only
860 add any particular path once (leaving the first one it encounters
861 and ignoring the rest, to preserve path order), and will
862 os.path.normpath and os.path.normcase all paths to help assure
863 this. This can also handle the case where the given old path
864 variable is a list instead of a string, in which case a list will
865 be returned instead of a string.
866
867 Example:
868 Old Path: "/foo/bar:/foo"
869 New Path: "/biz/boom:/foo"
870 Result: "/biz/boom:/foo:/foo/bar"
871
872 If delete_existing is 0, then adding a path that exists will
873 not move it to the beginning; it will stay where it is in the
874 list.
875
876 If canonicalize is not None, it is applied to each element of
877 newpath before use.
878 """
879
880 orig = oldpath
881 is_list = 1
882 paths = orig
883 if not is_List(orig) and not is_Tuple(orig):
884 paths = string.split(paths, sep)
885 is_list = 0
886
887 if is_String(newpath):
888 newpaths = string.split(newpath, sep)
889 elif not is_List(newpath) and not is_Tuple(newpath):
890 newpaths = [ newpath ]
891 else:
892 newpaths = newpath
893
894 if canonicalize:
895 newpaths=map(canonicalize, newpaths)
896
897 if not delete_existing:
898
899
900
901
902
903 result = []
904 normpaths = []
905 for path in paths:
906 if not path:
907 continue
908 normpath = os.path.normpath(os.path.normcase(path))
909 if normpath not in normpaths:
910 result.append(path)
911 normpaths.append(normpath)
912 newpaths.reverse()
913 for path in newpaths:
914 if not path:
915 continue
916 normpath = os.path.normpath(os.path.normcase(path))
917 if normpath not in normpaths:
918 result.insert(0, path)
919 normpaths.append(normpath)
920 paths = result
921
922 else:
923 newpaths = newpaths + paths
924
925 normpaths = []
926 paths = []
927
928 for path in newpaths:
929 normpath = os.path.normpath(os.path.normcase(path))
930 if path and not normpath in normpaths:
931 paths.append(path)
932 normpaths.append(normpath)
933
934 if is_list:
935 return paths
936 else:
937 return string.join(paths, sep)
938
941 """This appends new path elements to the given old path. Will
942 only add any particular path once (leaving the last one it
943 encounters and ignoring the rest, to preserve path order), and
944 will os.path.normpath and os.path.normcase all paths to help
945 assure this. This can also handle the case where the given old
946 path variable is a list instead of a string, in which case a list
947 will be returned instead of a string.
948
949 Example:
950 Old Path: "/foo/bar:/foo"
951 New Path: "/biz/boom:/foo"
952 Result: "/foo/bar:/biz/boom:/foo"
953
954 If delete_existing is 0, then adding a path that exists
955 will not move it to the end; it will stay where it is in the list.
956
957 If canonicalize is not None, it is applied to each element of
958 newpath before use.
959 """
960
961 orig = oldpath
962 is_list = 1
963 paths = orig
964 if not is_List(orig) and not is_Tuple(orig):
965 paths = string.split(paths, sep)
966 is_list = 0
967
968 if is_String(newpath):
969 newpaths = string.split(newpath, sep)
970 elif not is_List(newpath) and not is_Tuple(newpath):
971 newpaths = [ newpath ]
972 else:
973 newpaths = newpath
974
975 if canonicalize:
976 newpaths=map(canonicalize, newpaths)
977
978 if not delete_existing:
979
980
981
982
983
984 result = []
985 normpaths = []
986 for path in paths:
987 if not path:
988 continue
989 result.append(path)
990 normpaths.append(os.path.normpath(os.path.normcase(path)))
991 for path in newpaths:
992 if not path:
993 continue
994 normpath = os.path.normpath(os.path.normcase(path))
995 if normpath not in normpaths:
996 result.append(path)
997 normpaths.append(normpath)
998 paths = result
999 else:
1000
1001
1002 newpaths = paths + newpaths
1003 newpaths.reverse()
1004
1005 normpaths = []
1006 paths = []
1007
1008 for path in newpaths:
1009 normpath = os.path.normpath(os.path.normcase(path))
1010 if path and not normpath in normpaths:
1011 paths.append(path)
1012 normpaths.append(normpath)
1013 paths.reverse()
1014
1015 if is_list:
1016 return paths
1017 else:
1018 return string.join(paths, sep)
1019
1020 if sys.platform == 'cygwin':
1022 """Transforms an absolute path into a native path for the system. In
1023 Cygwin, this converts from a Cygwin path to a Windows one."""
1024 return string.replace(os.popen('cygpath -w ' + path).read(), '\n', '')
1025 else:
1027 """Transforms an absolute path into a native path for the system.
1028 Non-Cygwin version, just leave the path alone."""
1029 return path
1030
1031 display = DisplayEngine()
1032
1034 if is_List(arg) or is_Tuple(arg):
1035 return arg
1036 elif is_String(arg):
1037 return string.split(arg)
1038 else:
1039 return [arg]
1040
1042 """A class for command-line construction variables.
1043
1044 This is a list that uses Split() to split an initial string along
1045 white-space arguments, and similarly to split any strings that get
1046 added. This allows us to Do the Right Thing with Append() and
1047 Prepend() (as well as straight Python foo = env['VAR'] + 'arg1
1048 arg2') regardless of whether a user adds a list or a string to a
1049 command-line construction variable.
1050 """
1058 return (self, CLVar(other))
1060 return string.join(self.data)
1061
1062
1063
1064
1065
1070
1074
1076 UserDict.__setitem__(self, key, item)
1077 if key not in self._keys: self._keys.append(key)
1078
1080 UserDict.clear(self)
1081 self._keys = []
1082
1087
1090
1092 return self._keys[:]
1093
1095 try:
1096 key = self._keys[-1]
1097 except IndexError:
1098 raise KeyError('dictionary is empty')
1099
1100 val = self[key]
1101 del self[key]
1102
1103 return (key, val)
1104
1106 UserDict.setdefault(self, key, failobj)
1107 if key not in self._keys: self._keys.append(key)
1108
1112
1114 return map(self.get, self._keys)
1115
1117 """A callable ordered dictionary that maps file suffixes to
1118 dictionary values. We preserve the order in which items are added
1119 so that get_suffix() calls always return the first suffix added."""
1120 - def __call__(self, env, source, ext=None):
1121 if ext is None:
1122 try:
1123 ext = source[0].suffix
1124 except IndexError:
1125 ext = ""
1126 try:
1127 return self[ext]
1128 except KeyError:
1129
1130
1131 s_dict = {}
1132 for (k,v) in self.items():
1133 if k is not None:
1134 s_k = env.subst(k)
1135 if s_dict.has_key(s_k):
1136
1137
1138
1139
1140 raise KeyError, (s_dict[s_k][0], k, s_k)
1141 s_dict[s_k] = (k,v)
1142 try:
1143 return s_dict[ext][1]
1144 except KeyError:
1145 try:
1146 return self[None]
1147 except KeyError:
1148 return None
1149
1150
1151 if sys.platform == 'cygwin':
1152
1153
1156 else:
1159
1161 if pre:
1162 path, fn = os.path.split(os.path.normpath(fname))
1163 if fn[:len(pre)] != pre:
1164 fname = os.path.join(path, pre + fn)
1165
1166
1167
1168 if suf and fname[-len(suf):] != suf and \
1169 (ensure_suffix or not splitext(fname)[1]):
1170 fname = fname + suf
1171 return fname
1172
1173
1174
1175
1176
1177
1178
1179
1181 """Return a list of the elements in s, but without duplicates.
1182
1183 For example, unique([1,2,3,1,2,3]) is some permutation of [1,2,3],
1184 unique("abcabc") some permutation of ["a", "b", "c"], and
1185 unique(([1, 2], [2, 3], [1, 2])) some permutation of
1186 [[2, 3], [1, 2]].
1187
1188 For best speed, all sequence elements should be hashable. Then
1189 unique() will usually work in linear time.
1190
1191 If not possible, the sequence elements should enjoy a total
1192 ordering, and if list(s).sort() doesn't raise TypeError it's
1193 assumed that they do enjoy a total ordering. Then unique() will
1194 usually work in O(N*log2(N)) time.
1195
1196 If that's not possible either, the sequence elements must support
1197 equality-testing. Then unique() will usually work in quadratic
1198 time.
1199 """
1200
1201 n = len(s)
1202 if n == 0:
1203 return []
1204
1205
1206
1207
1208
1209 u = {}
1210 try:
1211 for x in s:
1212 u[x] = 1
1213 except TypeError:
1214 pass
1215 else:
1216 return u.keys()
1217 del u
1218
1219
1220
1221
1222
1223
1224
1225
1226 try:
1227 t = list(s)
1228 t.sort()
1229 except TypeError:
1230 pass
1231 else:
1232 assert n > 0
1233 last = t[0]
1234 lasti = i = 1
1235 while i < n:
1236 if t[i] != last:
1237 t[lasti] = last = t[i]
1238 lasti = lasti + 1
1239 i = i + 1
1240 return t[:lasti]
1241 del t
1242
1243
1244 u = []
1245 for x in s:
1246 if x not in u:
1247 u.append(x)
1248 return u
1249
1250
1251
1252
1253
1254
1255
1256
1257
1259 if idfun is None:
1260 def idfun(x): return x
1261 seen = {}
1262 result = []
1263 for item in seq:
1264 marker = idfun(item)
1265
1266
1267
1268 if marker in seen: continue
1269 seen[marker] = 1
1270 result.append(item)
1271 return result
1272
1273
1274
1275
1276
1286
1287
1288
1289
1290
1292
1294 self.fileobj = fileobj
1295
1308
1317
1318
1319
1325 if not self.unique:
1326 self.data = uniquer_hashables(self.data)
1327 self.unique = True
1403 - def sort(self, *args, **kwds):
1410
1411
1412
1414 """
1415 A proxy class that wraps a file object, flushing after every write,
1416 and delegating everything else to the wrapped object.
1417 """
1421 try:
1422 self.file.write(arg)
1423 self.file.flush()
1424 except IOError:
1425
1426
1427
1428
1429
1430
1431
1432 pass
1434 return getattr(self.file, attr)
1435
1437 """ makes an absolute path name to a relative pathname.
1438 """
1439 if os.path.isabs(path):
1440 drive_s,path = os.path.splitdrive(path)
1441
1442 import re
1443 if not drive_s:
1444 path=re.compile("/*(.*)").findall(path)[0]
1445 else:
1446 path=path[1:]
1447
1448 assert( not os.path.isabs( path ) ), path
1449 return path
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477 -def AddMethod(object, function, name = None):
1478 """
1479 Adds either a bound method to an instance or an unbound method to
1480 a class. If name is ommited the name of the specified function
1481 is used by default.
1482 Example:
1483 a = A()
1484 def f(self, x, y):
1485 self.z = x + y
1486 AddMethod(f, A, "add")
1487 a.add(2, 4)
1488 print a.z
1489 AddMethod(lambda self, i: self.l[i], a, "listIndex")
1490 print a.listIndex(5)
1491 """
1492 import new
1493
1494 if name is None:
1495 name = function.func_name
1496 else:
1497 function = RenameFunction(function, name)
1498
1499 try:
1500 klass = object.__class__
1501 except AttributeError:
1502
1503 object.__dict__[name] = new.instancemethod(function, None, object)
1504 else:
1505
1506 object.__dict__[name] = new.instancemethod(function, object, klass)
1507
1509 """
1510 Returns a function identical to the specified function, but with
1511 the specified name.
1512 """
1513 import new
1514
1515
1516
1517
1518 func_defaults = function.func_defaults
1519 if func_defaults is None:
1520 func_defaults = ()
1521
1522 return new.function(function.func_code,
1523 function.func_globals,
1524 name,
1525 func_defaults)
1526
1527
1528 md5 = False
1531
1537
1538 try:
1539 import hashlib
1540 except ImportError:
1541 pass
1542 else:
1543 if hasattr(hashlib, 'md5'):
1544 md5 = True
1549
1551 m = hashlib.md5()
1552 f = open(fname, "rb")
1553 while 1:
1554 blck = f.read(chunksize)
1555 if not blck:
1556 break
1557 m.update(str(blck))
1558 f.close()
1559 return m.hexdigest()
1560
1562 """
1563 Collects a list of signatures into an aggregate signature.
1564
1565 signatures - a list of signatures
1566 returns - the aggregate signature
1567 """
1568 if len(signatures) == 1:
1569 return signatures[0]
1570 else:
1571 return MD5signature(string.join(signatures, ', '))
1572
1573
1574
1575
1576
1577
1578 try:
1579 intern
1580 except NameError:
1581 from sys import intern
1582
1584 """
1585 Perform intern() on the passed argument and return the result.
1586 If the input is ineligible (e.g. a unicode string) the original argument is
1587 returned and no exception is thrown.
1588 """
1589 try:
1590 return intern(x)
1591 except TypeError:
1592 return x
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1605 """ Null objects always and reliably "do nothing." """
1606 - def __new__(cls, *args, **kwargs):
1607 if not '_inst' in vars(cls):
1608
1609 cls._inst = apply(type.__new__, (cls,) + args, kwargs)
1610 return cls._inst
1616 return "Null(0x%08X)" % id(self)
1625
1637
1638
1639 del __revision__
1640
1641
1642
1643
1644
1645
1646