From 32d7c315d62846ea8febadcbb2c60cf9e3382cbf Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Wed, 7 Apr 2010 13:16:57 +0000 Subject: 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. --- src/engine/MANIFEST.in | 1 + src/engine/SCons/Action.py | 4 ++-- src/engine/SCons/ActionTests.py | 38 ++++++++++++++++++---------------- src/engine/SCons/BuilderTests.py | 4 ++-- src/engine/SCons/Environment.py | 2 +- src/engine/SCons/EnvironmentTests.py | 10 ++++----- src/engine/SCons/Node/FS.py | 3 +-- src/engine/SCons/Node/FSTests.py | 10 +++++---- src/engine/SCons/SConf.py | 6 ++++-- src/engine/SCons/SConfTests.py | 6 ++++-- src/engine/SCons/Taskmaster.py | 26 +++++++++++------------ src/engine/SCons/TaskmasterTests.py | 6 ++++-- src/engine/SCons/Util.py | 29 +++++++++++++------------- src/engine/SCons/UtilTests.py | 14 +++++++------ src/engine/SCons/compat/__init__.py | 6 ++++++ src/engine/SCons/compat/_scons_io.py | 40 ++++++++++++++++++++++++++++++++++++ 16 files changed, 132 insertions(+), 73 deletions(-) create mode 100644 src/engine/SCons/compat/_scons_io.py diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index e180170..a14bc48 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -3,6 +3,7 @@ SCons/Action.py SCons/Builder.py SCons/compat/__init__.py SCons/compat/_scons_hashlib.py +SCons/compat/_scons_io.py SCons/compat/_scons_itertools.py SCons/compat/_scons_optparse.py SCons/compat/_scons_sets.py diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 9d49752..da68b7d 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 3f78812..6b8b465 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 e4ddaec..de6d2be 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 267b73d..1fd763d 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 2540408..3a2cd8a 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 4e455da..acba76e 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 e68b389..8e581f1 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 e8b6c0e..ac019ad 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 26f21f3..7e48862 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 b2c4204..1b42bcb 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 65d10b5..917bb62 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 8aa5f23..4ada273 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 ad27127..fd7862c 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 792b77a..0b70c5d 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 0000000..784021d --- /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: -- cgit v0.12