diff options
Diffstat (limited to 'engine/SCons/compat/__init__.py')
-rw-r--r-- | engine/SCons/compat/__init__.py | 271 |
1 files changed, 103 insertions, 168 deletions
diff --git a/engine/SCons/compat/__init__.py b/engine/SCons/compat/__init__.py index 165dddf..cba69ef 100644 --- a/engine/SCons/compat/__init__.py +++ b/engine/SCons/compat/__init__.py @@ -31,12 +31,12 @@ we still support. Other code will not generally reference things in this package through the SCons.compat namespace. The modules included here add things to -the __builtin__ namespace or the global module list so that the rest +the builtins namespace or the global module list so that the rest of our code can use the objects and names imported here regardless of Python version. -Simply enough, things that go in the __builtin__ name space come from -our builtins module. +Simply enough, things that go in the builtins name space come from +our _scons_builtins module. The rest of the things here will be in individual compatibility modules that are either: 1) suitably modified copies of the future modules that @@ -60,20 +60,35 @@ function defined below loads the module as the "real" name (without the rest of our code will find our pre-loaded compatibility module. """ -__revision__ = "src/engine/SCons/compat/__init__.py 4720 2010/03/24 03:14:11 jars" +__revision__ = "src/engine/SCons/compat/__init__.py 5023 2010/06/14 22:05:46 scons" + +import os +import sys +import imp # Use the "imp" module to protect imports from fixers. def import_as(module, name): """ Imports the specified module (from our local directory) as the - specified name. + specified name, returning the loaded module object. """ - import imp - import os.path dir = os.path.split(__file__)[0] - file, filename, suffix_mode_type = imp.find_module(module, [dir]) - imp.load_module(name, file, filename, suffix_mode_type) + return imp.load_module(name, *imp.find_module(module, [dir])) + +def rename_module(new, old): + """ + Attempts to import the old module and load it under the new name. + Used for purely cosmetic name changes in Python 3.x. + """ + try: + sys.modules[new] = imp.load_module(old, *imp.find_module(old)) + return True + except ImportError: + return False + + +rename_module('builtins', '__builtin__') +import _scons_builtins -import builtins try: import hashlib @@ -92,75 +107,48 @@ try: set except NameError: # Pre-2.4 Python has no native set type - try: - # Python 2.2 and 2.3 can use the copy of the 2.[45] sets module - # that we grabbed. - import_as('_scons_sets', 'sets') - except (ImportError, SyntaxError): - # Python 1.5 (ImportError, no __future_ module) and 2.1 - # (SyntaxError, no generators in __future__) will blow up - # trying to import the 2.[45] sets module, so back off to a - # custom sets module that can be discarded easily when we - # stop supporting those versions. - import_as('_scons_sets15', 'sets') - import __builtin__ - import sets - __builtin__.set = sets.Set - -import fnmatch -try: - fnmatch.filter -except AttributeError: - # Pre-2.2 Python has no fnmatch.filter() function. - def filter(names, pat): - """Return the subset of the list NAMES that match PAT""" - import os,posixpath - result=[] - pat = os.path.normcase(pat) - if not fnmatch._cache.has_key(pat): - import re - res = fnmatch.translate(pat) - fnmatch._cache[pat] = re.compile(res) - match = fnmatch._cache[pat].match - if os.path is posixpath: - # normcase on posix is NOP. Optimize it away from the loop. - for name in names: - if match(name): - result.append(name) - else: - for name in names: - if match(os.path.normcase(name)): - result.append(name) - return result - fnmatch.filter = filter - del filter + import_as('_scons_sets', 'sets') + import builtins, sets + builtins.set = sets.Set -try: - import itertools -except ImportError: - # Pre-2.3 Python has no itertools module. - import_as('_scons_itertools', 'itertools') -# If we need the compatibility version of textwrap, it must be imported -# before optparse, which uses it. try: - import textwrap + import collections except ImportError: - # Pre-2.3 Python has no textwrap module. - import_as('_scons_textwrap', 'textwrap') + # Pre-2.4 Python has no collections module. + import_as('_scons_collections', 'collections') +else: + try: + collections.UserDict + except AttributeError: + exec('from UserDict import UserDict as _UserDict') + collections.UserDict = _UserDict + del _UserDict + try: + collections.UserList + except AttributeError: + exec('from UserList import UserList as _UserList') + collections.UserList = _UserList + del _UserList + try: + collections.UserString + except AttributeError: + exec('from UserString import UserString as _UserString') + collections.UserString = _UserString + del _UserString + try: - import optparse + import io except ImportError: - # Pre-2.3 Python has no optparse module. - import_as('_scons_optparse', 'optparse') + # Pre-2.6 Python has no io module. + import_as('_scons_io', 'io') + -import os try: os.devnull except AttributeError: # Pre-2.4 Python has no os.devnull attribute - import sys _names = sys.builtin_module_names if 'posix' in _names: os.devnull = '/dev/null' @@ -176,64 +164,25 @@ except AttributeError: os.path.lexists = lexists -try: - import platform -except ImportError: - # Pre-2.3 Python has no platform module. - import_as('_scons_platform', 'platform') +# When we're using the '-3' option during regression tests, importing +# cPickle gives a warning no matter how it's done, so always use the +# real profile module, whether it's fast or not. +if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is None: + # Not a regression test with '-3', so try to use faster version. + # In 3.x, 'pickle' automatically loads the fast version if available. + rename_module('pickle', 'cPickle') -import shlex -try: - shlex.split -except AttributeError: - # Pre-2.3 Python has no shlex.split() function. - # - # The full white-space splitting semantics of shlex.split() are - # complicated to reproduce by hand, so just use a compatibility - # version of the shlex module cribbed from Python 2.5 with some - # minor modifications for older Python versions. - del shlex - import_as('_scons_shlex', 'shlex') +# In 3.x, 'profile' automatically loads the fast version if available. +rename_module('profile', 'cProfile') -import shutil -try: - shutil.move -except AttributeError: - # Pre-2.3 Python has no shutil.move() function. - # - # Cribbed from Python 2.5. - import os - - def move(src, dst): - """Recursively move a file or directory to another location. - - If the destination is on our current filesystem, then simply use - rename. Otherwise, copy src to the dst and then remove src. - A lot more could be done here... A look at a mv.c shows a lot of - the issues this implementation glosses over. - - """ - try: - os.rename(src, dst) - except OSError: - if os.path.isdir(src): - if shutil.destinsrc(src, dst): - raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst) - shutil.copytree(src, dst, symlinks=True) - shutil.rmtree(src) - else: - shutil.copy2(src,dst) - os.unlink(src) - shutil.move = move - del move - - def destinsrc(src, dst): - src = os.path.abspath(src) - return os.path.abspath(dst)[:len(src)] == src - shutil.destinsrc = destinsrc - del destinsrc +# Before Python 3.0, the 'queue' module was named 'Queue'. +rename_module('queue', 'Queue') + + +# Before Python 3.0, the 'winreg' module was named '_winreg' +rename_module('winreg', '_winreg') try: @@ -242,57 +191,43 @@ except ImportError: # Pre-2.4 Python has no subprocess module. import_as('_scons_subprocess', 'subprocess') -import sys try: - sys.version_info + sys.intern except AttributeError: - # Pre-1.6 Python has no sys.version_info - import string - version_string = string.split(sys.version)[0] - version_ints = map(int, string.split(version_string, '.')) - sys.version_info = tuple(version_ints + ['final', 0]) - -try: - import UserString -except ImportError: - # Pre-1.6 Python has no UserString module. - import_as('_scons_UserString', 'UserString') - -import tempfile + # Pre-2.6 Python has no sys.intern() function. + import builtins + try: + sys.intern = builtins.intern + except AttributeError: + # Pre-2.x Python has no builtin intern() function. + def intern(x): + return x + sys.intern = intern + del intern try: - tempfile.mkstemp + sys.maxsize except AttributeError: - # Pre-2.3 Python has no tempfile.mkstemp function, so try to simulate it. - # adapted from the mkstemp implementation in python 3. - import os - import errno - def mkstemp(*args, **kw): - text = False - # TODO (1.5) - #if 'text' in kw : - if 'text' in kw.keys() : - text = kw['text'] - del kw['text'] - elif len( args ) == 4 : - text = args[3] - args = args[:3] - flags = os.O_RDWR | os.O_CREAT | os.O_EXCL - if not text and hasattr( os, 'O_BINARY' ) : - flags = flags | os.O_BINARY - while True: - try : - name = apply(tempfile.mktemp, args, kw) - fd = os.open( name, flags, 0600 ) - return (fd, os.path.abspath(name)) - except OSError, e: - if e.errno == errno.EEXIST: - continue - raise - - tempfile.mkstemp = mkstemp - del mkstemp - - + # Pre-2.6 Python has no sys.maxsize attribute + # Wrapping sys in () is silly, but protects it from 2to3 renames fixer + sys.maxsize = (sys).maxint + + +if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is not None: + # We can't apply the 'callable' fixer until the floor is 2.6, but the + # '-3' option to Python 2.6 and 2.7 generates almost ten thousand + # warnings. This hack allows us to run regression tests with the '-3' + # option by replacing the callable() built-in function with a hack + # that performs the same function but doesn't generate the warning. + # Note that this hack is ONLY intended to be used for regression + # testing, and should NEVER be used for real runs. + from types import ClassType + def callable(obj): + if hasattr(obj, '__call__'): return True + if isinstance(obj, (ClassType, type)): return True + return False + import builtins + builtins.callable = callable + del callable # Local Variables: |