summaryrefslogtreecommitdiff
path: root/src/engine/SCons
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2010-04-07 13:16:57 +0000
committerSteven Knight <knight@baldmt.com>2010-04-07 13:16:57 +0000
commite484c24f3ea5168bb420a715913da1bca156a0a2 (patch)
tree4d16f888d6f0de67d3dba1341b768df17d852b44 /src/engine/SCons
parent52b2b87b8666da930b061c37efafe6a90c106627 (diff)
downloadscons-e484c24f3ea5168bb420a715913da1bca156a0a2.tar.gz
Issue 2332: Convert from using StringIO.StringIO class to using the
forward-compatible io.StringIO class, with the addition of an "io" compatibility module for Python versions before 2.6.
Diffstat (limited to 'src/engine/SCons')
-rw-r--r--src/engine/SCons/Action.py4
-rw-r--r--src/engine/SCons/ActionTests.py38
-rw-r--r--src/engine/SCons/BuilderTests.py4
-rw-r--r--src/engine/SCons/Environment.py2
-rw-r--r--src/engine/SCons/EnvironmentTests.py10
-rw-r--r--src/engine/SCons/Node/FS.py3
-rw-r--r--src/engine/SCons/Node/FSTests.py10
-rw-r--r--src/engine/SCons/SConf.py6
-rw-r--r--src/engine/SCons/SConfTests.py6
-rw-r--r--src/engine/SCons/Taskmaster.py26
-rw-r--r--src/engine/SCons/TaskmasterTests.py6
-rw-r--r--src/engine/SCons/Util.py29
-rw-r--r--src/engine/SCons/UtilTests.py14
-rw-r--r--src/engine/SCons/compat/__init__.py6
-rw-r--r--src/engine/SCons/compat/_scons_io.py40
15 files changed, 131 insertions, 73 deletions
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py
index 9d497526..da68b7de 100644
--- a/src/engine/SCons/Action.py
+++ b/src/engine/SCons/Action.py
@@ -497,7 +497,7 @@ class _ActionAction(ActionBase):
SCons.Util.AddMethod(self, batch_key, 'batch_key')
def print_cmd_line(self, s, target, source, env):
- sys.stdout.write(s + "\n")
+ sys.stdout.write(s + u"\n")
def __call__(self, target, source, env,
exitstatfunc=_null,
@@ -536,7 +536,7 @@ class _ActionAction(ActionBase):
source = executor.get_all_sources()
t = ' and '.join(map(str, target))
l = '\n '.join(self.presub_lines(env))
- out = "Building %s with action:\n %s\n" % (t, l)
+ out = u"Building %s with action:\n %s\n" % (t, l)
sys.stdout.write(out)
cmd = None
if show and self.strfunction:
diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py
index 3f78812e..6b8b465d 100644
--- a/src/engine/SCons/ActionTests.py
+++ b/src/engine/SCons/ActionTests.py
@@ -23,6 +23,8 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import SCons.compat
+
# Define a null function and a null class for use as builder actions.
# Where these are defined in the file seems to affect their byte-code
# contents, so try to minimize changes by defining them here, before we
@@ -34,9 +36,9 @@ class GlobalActFunc:
def __call__(self):
pass
+import io
import os
import re
-import StringIO
import sys
import types
import unittest
@@ -97,7 +99,7 @@ scons_env = SCons.Environment.Environment()
# Capture all the stuff the Actions will print,
# so it doesn't clutter the output.
-sys.stdout = StringIO.StringIO()
+sys.stdout = io.StringIO()
class CmdStringHolder:
def __init__(self, cmd, literal=None):
@@ -514,7 +516,7 @@ class _ActionActionTestCase(unittest.TestCase):
pass
a = SCons.Action.Action(execfunc)
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
a.print_cmd_line("foo bar", None, None, None)
s = sio.getvalue()
@@ -556,7 +558,7 @@ class _ActionActionTestCase(unittest.TestCase):
return 9
b = SCons.Action.Action([firstfunc, execfunc, lastfunc])
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a("out", "in", env)
assert result.status == 7, result
@@ -566,14 +568,14 @@ class _ActionActionTestCase(unittest.TestCase):
a.chdir = 'xyz'
expect = "os.chdir(%s)\nexecfunc(['out'], ['in'])\nos.chdir(%s)\n"
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a("out", "in", env)
assert result.status == 7, result.status
s = sio.getvalue()
assert s == expect % (repr('xyz'), repr(test.workpath())), s
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a("out", "in", env, chdir='sub')
assert result.status == 7, result.status
@@ -582,7 +584,7 @@ class _ActionActionTestCase(unittest.TestCase):
a.chdir = None
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = b("out", "in", env)
assert result.status == 7, result.status
@@ -591,14 +593,14 @@ class _ActionActionTestCase(unittest.TestCase):
SCons.Action.execute_actions = 0
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a("out", "in", env)
assert result == 0, result
s = sio.getvalue()
assert s == "execfunc(['out'], ['in'])\n", s
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = b("out", "in", env)
assert result == 0, result
@@ -608,35 +610,35 @@ class _ActionActionTestCase(unittest.TestCase):
SCons.Action.print_actions_presub = 1
SCons.Action.execute_actions = 1
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a("out", "in", env)
assert result.status == 7, result.status
s = sio.getvalue()
assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a("out", "in", env, presub=0)
assert result.status == 7, result.status
s = sio.getvalue()
assert s == "execfunc(['out'], ['in'])\n", s
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a("out", "in", env, presub=1)
assert result.status == 7, result.status
s = sio.getvalue()
assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = b(["out"], "in", env, presub=1)
assert result.status == 7, result.status
s = sio.getvalue()
assert s == "Building out with action:\n firstfunc(target, source, env)\nfirstfunc(['out'], ['in'])\nBuilding out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = b(["out", "list"], "in", env, presub=1)
assert result.status == 7, result.status
@@ -645,14 +647,14 @@ class _ActionActionTestCase(unittest.TestCase):
a2 = SCons.Action.Action(execfunc)
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a2("out", "in", env)
assert result.status == 7, result.status
s = sio.getvalue()
assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a2("out", "in", env, presub=0)
assert result.status == 7, result.status
@@ -661,14 +663,14 @@ class _ActionActionTestCase(unittest.TestCase):
SCons.Action.execute_actions = 0
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a2("out", "in", env, presub=0)
assert result == 0, result
s = sio.getvalue()
assert s == "execfunc(['out'], ['in'])\n", s
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
result = a("out", "in", env, presub=0, execute=1, show=0)
assert result.status == 7, result.status
diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py
index e4ddaec5..de6d2be9 100644
--- a/src/engine/SCons/BuilderTests.py
+++ b/src/engine/SCons/BuilderTests.py
@@ -32,10 +32,10 @@ import SCons.compat
def Func():
pass
+import io
import os.path
import re
import sys
-import StringIO
import unittest
import UserList
@@ -48,7 +48,7 @@ import SCons.Errors
import SCons.Subst
import SCons.Util
-sys.stdout = StringIO.StringIO()
+sys.stdout = io.StringIO()
# Initial setup of the common environment for all tests,
# a temporary working directory containing a
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 267b73dc..1fd763d3 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -591,7 +591,7 @@ class SubstitutionEnvironment:
out,err = p.communicate()
status = p.wait()
if err:
- sys.stderr.write(err)
+ sys.stderr.write(unicode(err))
if status:
raise OSError("'%s' exited %d" % (command, status))
return out
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index 25404082..3a2cd8a9 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -26,8 +26,8 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
import copy
+import io
import os
-import StringIO
import sys
import TestCmd
import unittest
@@ -645,21 +645,21 @@ sys.exit(0)
python = '"' + sys.executable + '"'
try:
- sys.stderr = StringIO.StringIO()
+ sys.stderr = io.StringIO()
cmd = '%s %s' % (python, test.workpath('stdout.py'))
output = env.backtick(cmd)
errout = sys.stderr.getvalue()
assert output == 'this came from stdout.py\n', output
assert errout == '', errout
- sys.stderr = StringIO.StringIO()
+ sys.stderr = io.StringIO()
cmd = '%s %s' % (python, test.workpath('stderr.py'))
output = env.backtick(cmd)
errout = sys.stderr.getvalue()
assert output == '', output
assert errout == 'this came from stderr.py\n', errout
- sys.stderr = StringIO.StringIO()
+ sys.stderr = io.StringIO()
cmd = '%s %s' % (python, test.workpath('fail.py'))
try:
env.backtick(cmd)
@@ -668,7 +668,7 @@ sys.exit(0)
else:
self.fail("did not catch expected OSError")
- sys.stderr = StringIO.StringIO()
+ sys.stderr = io.StringIO()
cmd = '%s %s' % (python, test.workpath('echo.py'))
env['ENV'] = os.environ.copy()
env['ENV']['ECHO'] = 'this came from ECHO'
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 4e455da3..acba76ea 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -37,7 +37,6 @@ from __future__ import generators ### KEEP FOR COMPATIBILITY FIXERS
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
from itertools import izip
-import cStringIO
import fnmatch
import os
import os.path
@@ -3111,7 +3110,7 @@ class FileFinder:
if verbose and not callable(verbose):
if not SCons.Util.is_String(verbose):
verbose = "find_file"
- _verbose = ' %s: ' % verbose
+ _verbose = u' %s: ' % verbose
verbose = lambda s: sys.stdout.write(_verbose + s)
filedir, filename = os.path.split(filename)
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index e68b389a..8e581f12 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -23,6 +23,8 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import SCons.compat
+
import os
import os.path
import sys
@@ -2891,11 +2893,11 @@ class find_fileTestCase(unittest.TestCase):
# 'bar/baz' as a Dir.
SCons.Node.FS.find_file('baz/no_file_here', paths)
- import StringIO
+ import io
save_sys_stdout = sys.stdout
try:
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
SCons.Node.FS.find_file('foo2', paths, verbose="xyz")
expect = " xyz: looking for 'foo2' in '.' ...\n" + \
@@ -2903,7 +2905,7 @@ class find_fileTestCase(unittest.TestCase):
c = sio.getvalue()
assert c == expect, c
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
SCons.Node.FS.find_file('baz2', paths, verbose=1)
expect = " find_file: looking for 'baz2' in '.' ...\n" + \
@@ -2912,7 +2914,7 @@ class find_fileTestCase(unittest.TestCase):
c = sio.getvalue()
assert c == expect, c
- sio = StringIO.StringIO()
+ sio = io.StringIO()
sys.stdout = sio
SCons.Node.FS.find_file('on_disk', paths, verbose=1)
expect = " find_file: looking for 'on_disk' in '.' ...\n" + \
diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py
index e8b6c0eb..ac019ad3 100644
--- a/src/engine/SCons/SConf.py
+++ b/src/engine/SCons/SConf.py
@@ -28,9 +28,11 @@ Autoconf-like configuration support.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import SCons.compat
+
+import io
import os
import re
-import StringIO
import sys
import traceback
@@ -176,7 +178,7 @@ class Streamer:
"""
def __init__(self, orig):
self.orig = orig
- self.s = StringIO.StringIO()
+ self.s = io.StringIO()
def write(self, str):
if self.orig:
diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py
index 26f21f39..7e48862e 100644
--- a/src/engine/SCons/SConfTests.py
+++ b/src/engine/SCons/SConfTests.py
@@ -23,16 +23,18 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import SCons.compat
+
+import io
import os
import re
-import StringIO
import sys
from types import *
import unittest
import TestCmd
-sys.stdout = StringIO.StringIO()
+sys.stdout = io.StringIO()
if sys.platform == 'win32':
existing_lib = "msvcrt"
diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py
index b2c4204e..1b42bcb2 100644
--- a/src/engine/SCons/Taskmaster.py
+++ b/src/engine/SCons/Taskmaster.py
@@ -165,7 +165,7 @@ class Task:
the Action is actually called to build the targets.
"""
T = self.tm.trace
- if T: T.write(self.trace_message('Task.prepare()', self.node))
+ if T: T.write(self.trace_message(u'Task.prepare()', self.node))
# Now that it's the appropriate time, give the TaskMaster a
# chance to raise any exceptions it encountered while preparing
@@ -218,7 +218,7 @@ class Task:
prepare(), executed() or failed().
"""
T = self.tm.trace
- if T: T.write(self.trace_message('Task.execute()', self.node))
+ if T: T.write(self.trace_message(u'Task.execute()', self.node))
try:
everything_was_cached = 1
@@ -370,7 +370,7 @@ class Task:
This is the default behavior for building only what's necessary.
"""
T = self.tm.trace
- if T: T.write(self.trace_message('Task.make_ready_current()',
+ if T: T.write(self.trace_message(u'Task.make_ready_current()',
self.node))
self.out_of_date = []
@@ -415,7 +415,7 @@ class Task:
that can be put back on the candidates list.
"""
T = self.tm.trace
- if T: T.write(self.trace_message('Task.postprocess()', self.node))
+ if T: T.write(self.trace_message(u'Task.postprocess()', self.node))
# We may have built multiple targets, some of which may have
# common parents waiting for this build. Count up how many
@@ -432,7 +432,7 @@ class Task:
# A node can only be in the pending_children set if it has
# some waiting_parents.
if t.waiting_parents:
- if T: T.write(self.trace_message('Task.postprocess()',
+ if T: T.write(self.trace_message(u'Task.postprocess()',
t,
'removing'))
pending_children.discard(t)
@@ -451,7 +451,7 @@ class Task:
for p, subtract in parents.items():
p.ref_count = p.ref_count - subtract
- if T: T.write(self.trace_message('Task.postprocess()',
+ if T: T.write(self.trace_message(u'Task.postprocess()',
p,
'adjusted parent ref count'))
if p.ref_count == 0:
@@ -735,12 +735,12 @@ class Taskmaster:
self.ready_exc = None
T = self.trace
- if T: T.write('\n' + self.trace_message('Looking for a node to evaluate'))
+ if T: T.write(u'\n' + self.trace_message('Looking for a node to evaluate'))
while True:
node = self.next_candidate()
if node is None:
- if T: T.write(self.trace_message('No candidate anymore.') + '\n')
+ if T: T.write(self.trace_message('No candidate anymore.') + u'\n')
return None
node = node.disambiguate()
@@ -763,7 +763,7 @@ class Taskmaster:
else:
S = None
- if T: T.write(self.trace_message(' Considering node %s and its children:' % self.trace_node(node)))
+ if T: T.write(self.trace_message(u' Considering node %s and its children:' % self.trace_node(node)))
if state == NODE_NO_STATE:
# Mark this node as being on the execution stack:
@@ -771,7 +771,7 @@ class Taskmaster:
elif state > NODE_PENDING:
# Skip this node if it has already been evaluated:
if S: S.already_handled = S.already_handled + 1
- if T: T.write(self.trace_message(' already handled (executed)'))
+ if T: T.write(self.trace_message(u' already handled (executed)'))
continue
executor = node.get_executor()
@@ -802,7 +802,7 @@ class Taskmaster:
for child in chain(executor.get_all_prerequisites(), children):
childstate = child.get_state()
- if T: T.write(self.trace_message(' ' + self.trace_node(child)))
+ if T: T.write(self.trace_message(u' ' + self.trace_node(child)))
if childstate == NODE_NO_STATE:
children_not_visited.append(child)
@@ -861,7 +861,7 @@ class Taskmaster:
# count so we can be put back on the list for
# re-evaluation when they've all finished.
node.ref_count = node.ref_count + child.add_to_waiting_parents(node)
- if T: T.write(self.trace_message(' adjusted ref count: %s, child %s' %
+ if T: T.write(self.trace_message(u' adjusted ref count: %s, child %s' %
(self.trace_node(node), repr(str(child)))))
if T:
@@ -887,7 +887,7 @@ class Taskmaster:
# The default when we've gotten through all of the checks above:
# this node is ready to be built.
if S: S.build = S.build + 1
- if T: T.write(self.trace_message('Evaluating %s\n' %
+ if T: T.write(self.trace_message(u'Evaluating %s\n' %
self.trace_node(node)))
# For debugging only:
diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py
index 65d10b59..917bb622 100644
--- a/src/engine/SCons/TaskmasterTests.py
+++ b/src/engine/SCons/TaskmasterTests.py
@@ -23,6 +23,8 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import SCons.compat
+
import copy
import sys
import unittest
@@ -1054,9 +1056,9 @@ class TaskmasterTestCase(unittest.TestCase):
def test_trace(self):
"""Test Taskmaster tracing
"""
- import StringIO
+ import io
- trace = StringIO.StringIO()
+ trace = io.StringIO()
n1 = Node("n1")
n2 = Node("n2")
n3 = Node("n3", [n1, n2])
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py
index 8aa5f238..4ada2736 100644
--- a/src/engine/SCons/Util.py
+++ b/src/engine/SCons/Util.py
@@ -161,7 +161,7 @@ class DisplayEngine:
def print_it(self, text, append_newline=1):
if append_newline: text = text + '\n'
try:
- sys.stdout.write(text)
+ sys.stdout.write(unicode(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
@@ -242,17 +242,18 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}):
if showtags:
if showtags == 2:
- print ' E = exists'
- print ' R = exists in repository only'
- print ' b = implicit builder'
- print ' B = explicit builder'
- print ' S = side effect'
- print ' P = precious'
- print ' A = always build'
- print ' C = current'
- print ' N = no clean'
- print ' H = no cache'
- print ''
+ legend = (' E = exists\n' +
+ ' R = exists in repository only\n' +
+ ' b = implicit builder\n' +
+ ' B = explicit builder\n' +
+ ' S = side effect\n' +
+ ' P = precious\n' +
+ ' A = always build\n' +
+ ' C = current\n' +
+ ' N = no clean\n' +
+ ' H = no cache\n' +
+ '\n')
+ sys.stdout.write(unicode(legend))
tags = ['[']
tags.append(' E'[IDX(root.exists())])
@@ -277,10 +278,10 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}):
children = child_func(root)
if prune and rname in visited and children:
- print ''.join(tags + margins + ['+-[', rname, ']'])
+ sys.stdout.write(''.join(tags + margins + ['+-[', rname, ']']) + u'\n')
return
- print ''.join(tags + margins + ['+-', rname])
+ sys.stdout.write(''.join(tags + margins + ['+-', rname]) + u'\n')
visited[rname] = 1
diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py
index ad271278..fd7862c7 100644
--- a/src/engine/SCons/UtilTests.py
+++ b/src/engine/SCons/UtilTests.py
@@ -23,9 +23,11 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import SCons.compat
+
+import io
import os
import os.path
-import StringIO
import sys
import unittest
@@ -171,24 +173,24 @@ class UtilTestCase(unittest.TestCase):
try:
node, expect, withtags = self.tree_case_1()
- sys.stdout = StringIO.StringIO()
+ sys.stdout = io.StringIO()
print_tree(node, get_children)
actual = sys.stdout.getvalue()
assert expect == actual, (expect, actual)
- sys.stdout = StringIO.StringIO()
+ sys.stdout = io.StringIO()
print_tree(node, get_children, showtags=1)
actual = sys.stdout.getvalue()
assert withtags == actual, (withtags, actual)
node, expect, withtags = self.tree_case_2(prune=0)
- sys.stdout = StringIO.StringIO()
+ sys.stdout = io.StringIO()
print_tree(node, get_children, 1)
actual = sys.stdout.getvalue()
assert expect == actual, (expect, actual)
- sys.stdout = StringIO.StringIO()
+ sys.stdout = io.StringIO()
# The following call should work here:
# print_tree(node, get_children, 1, showtags=1)
# For some reason I don't understand, though, *this*
@@ -678,7 +680,7 @@ class UtilTestCase(unittest.TestCase):
def test_LogicalLines(self):
"""Test the LogicalLines class"""
- fobj = StringIO.StringIO(r"""
+ fobj = io.StringIO(r"""
foo \
bar \
baz
diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py
index 792b77a0..0b70c5d1 100644
--- a/src/engine/SCons/compat/__init__.py
+++ b/src/engine/SCons/compat/__init__.py
@@ -125,6 +125,12 @@ except AttributeError:
del filter
try:
+ import io
+except ImportError:
+ # Pre-2.6 Python has no io module.
+ import_as('_scons_io', 'io')
+
+try:
import itertools
except ImportError:
# Pre-2.3 Python has no itertools module.
diff --git a/src/engine/SCons/compat/_scons_io.py b/src/engine/SCons/compat/_scons_io.py
new file mode 100644
index 00000000..784021dc
--- /dev/null
+++ b/src/engine/SCons/compat/_scons_io.py
@@ -0,0 +1,40 @@
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__doc__ = """
+io compatibility module for older (pre-2.6) Python versions
+
+This does not not NOT (repeat, *NOT*) provide complete io
+functionality. It only wraps the portions of io functionality used
+by SCons, in an interface that looks enough like io for our purposes.
+"""
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+from cStringIO import StringIO
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4: