summaryrefslogtreecommitdiff
path: root/engine/SCons/compat/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'engine/SCons/compat/__init__.py')
-rw-r--r--engine/SCons/compat/__init__.py271
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: