summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Util.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/SCons/Util.py')
-rw-r--r--src/engine/SCons/Util.py150
1 files changed, 112 insertions, 38 deletions
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py
index 311c6a8..af09786 100644
--- a/src/engine/SCons/Util.py
+++ b/src/engine/SCons/Util.py
@@ -109,41 +109,6 @@ def updrive(path):
path = string.upper(drive) + rest
return path
-#
-# Generic convert-to-string functions that abstract away whether or
-# not the Python we're executing has Unicode support. The wrapper
-# to_String_for_signature() will use a for_signature() method if the
-# specified object has one.
-#
-if hasattr(types, 'UnicodeType'):
- UnicodeType = types.UnicodeType
- def to_String(s):
- if isinstance(s, UserString):
- t = type(s.data)
- else:
- t = type(s)
- if t is UnicodeType:
- return unicode(s)
- else:
- return str(s)
-else:
- to_String = str
-
-def to_String_for_signature(obj):
- try:
- f = obj.for_signature
- except AttributeError:
- return to_String_for_subst(obj)
- else:
- return f()
-
-def to_String_for_subst(s):
- if is_Sequence( s ):
- return string.join( map(to_String_for_subst, s) )
-
- return to_String( s )
-
-
class CallableComposite(UserList):
"""A simple composite callable class that, when called, will invoke all
of its contained callables with the same arguments."""
@@ -213,7 +178,17 @@ class DisplayEngine:
def print_it(self, text, append_newline=1):
if append_newline: text = text + '\n'
- sys.stdout.write(text)
+ try:
+ sys.stdout.write(text)
+ except IOError:
+ # Stdout might be connected to a pipe that has been closed
+ # by now. The most likely reason for the pipe being closed
+ # is that the user has press ctrl-c. It this is the case,
+ # then SCons is currently shutdown. We therefore ignore
+ # IOError's here so that SCons can continue and shutdown
+ # properly so that the .sconsign is correctly written
+ # before SCons exits.
+ pass
def dont_print(self, text, append_newline=1):
pass
@@ -437,6 +412,41 @@ except TypeError:
else:
flatten_sequence(item, result)
return result
+
+ #
+ # Generic convert-to-string functions that abstract away whether or
+ # not the Python we're executing has Unicode support. The wrapper
+ # to_String_for_signature() will use a for_signature() method if the
+ # specified object has one.
+ #
+ if hasattr(types, 'UnicodeType'):
+ UnicodeType = types.UnicodeType
+ def to_String(s):
+ if isinstance(s, UserString):
+ t = type(s.data)
+ else:
+ t = type(s)
+ if t is UnicodeType:
+ return unicode(s)
+ else:
+ return str(s)
+ else:
+ to_String = str
+
+ def to_String_for_signature(obj):
+ try:
+ f = obj.for_signature
+ except AttributeError:
+ return to_String_for_subst(obj)
+ else:
+ return f()
+
+ def to_String_for_subst(s):
+ if is_Sequence( s ):
+ return string.join( map(to_String_for_subst, s) )
+
+ return to_String( s )
+
else:
# A modern Python version with new-style classes, so we can just use
# isinstance().
@@ -459,6 +469,10 @@ else:
# with basestring. (at least on Python 2.5.1)
StringTypes = (str, unicode, UserString)
+ # Empirically, it is faster to check explicitely for str and
+ # unicode than for basestring.
+ BaseStringTypes = (str, unicode)
+
def is_Dict(obj, isinstance=isinstance, DictTypes=DictTypes):
return isinstance(obj, DictTypes)
@@ -526,6 +540,56 @@ else:
return result
+ #
+ # Generic convert-to-string functions that abstract away whether or
+ # not the Python we're executing has Unicode support. The wrapper
+ # to_String_for_signature() will use a for_signature() method if the
+ # specified object has one.
+ #
+ def to_String(s,
+ isinstance=isinstance, str=str,
+ UserString=UserString, BaseStringTypes=BaseStringTypes):
+ if isinstance(s,BaseStringTypes):
+ # Early out when already a string!
+ return s
+ elif isinstance(s, UserString):
+ # s.data can only be either a unicode or a regular
+ # string. Please see the UserString initializer.
+ return s.data
+ else:
+ return str(s)
+
+ def to_String_for_subst(s,
+ isinstance=isinstance, join=string.join, str=str, to_String=to_String,
+ BaseStringTypes=BaseStringTypes, SequenceTypes=SequenceTypes,
+ UserString=UserString):
+
+ # Note that the test cases are sorted by order of probability.
+ if isinstance(s, BaseStringTypes):
+ return s
+ elif isinstance(s, SequenceTypes):
+ l = []
+ for e in s:
+ l.append(to_String_for_subst(e))
+ return join( s )
+ elif isinstance(s, UserString):
+ # s.data can only be either a unicode or a regular
+ # string. Please see the UserString initializer.
+ return s.data
+ else:
+ return str(s)
+
+ def to_String_for_signature(obj, to_String_for_subst=to_String_for_subst,
+ AttributeError=AttributeError):
+ try:
+ f = obj.for_signature
+ except AttributeError:
+ return to_String_for_subst(obj)
+ else:
+ return f()
+
+
+
# The SCons "semi-deep" copy.
#
# This makes separate copies of lists (including UserList objects)
@@ -1267,8 +1331,18 @@ class Unbuffered:
def __init__(self, file):
self.file = file
def write(self, arg):
- self.file.write(arg)
- self.file.flush()
+ try:
+ self.file.write(arg)
+ self.file.flush()
+ except IOError:
+ # Stdout might be connected to a pipe that has been closed
+ # by now. The most likely reason for the pipe being closed
+ # is that the user has press ctrl-c. It this is the case,
+ # then SCons is currently shutdown. We therefore ignore
+ # IOError's here so that SCons can continue and shutdown
+ # properly so that the .sconsign is correctly written
+ # before SCons exits.
+ pass
def __getattr__(self, attr):
return getattr(self.file, attr)