OLD | NEW |
(Empty) | |
| 1 # |
| 2 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The S
Cons Foundation |
| 3 # |
| 4 # Permission is hereby granted, free of charge, to any person obtaining |
| 5 # a copy of this software and associated documentation files (the |
| 6 # "Software"), to deal in the Software without restriction, including |
| 7 # without limitation the rights to use, copy, modify, merge, publish, |
| 8 # distribute, sublicense, and/or sell copies of the Software, and to |
| 9 # permit persons to whom the Software is furnished to do so, subject to |
| 10 # the following conditions: |
| 11 # |
| 12 # The above copyright notice and this permission notice shall be included |
| 13 # in all copies or substantial portions of the Software. |
| 14 # |
| 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
| 16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
| 17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 22 # |
| 23 |
| 24 __doc__ = """ |
| 25 SCons compatibility package for old Python versions |
| 26 |
| 27 This subpackage holds modules that provide backwards-compatible |
| 28 implementations of various things that we'd like to use in SCons but which |
| 29 only show up in later versions of Python than the early, old version(s) |
| 30 we still support. |
| 31 |
| 32 Other code will not generally reference things in this package through |
| 33 the SCons.compat namespace. The modules included here add things to |
| 34 the builtins namespace or the global module list so that the rest |
| 35 of our code can use the objects and names imported here regardless of |
| 36 Python version. |
| 37 |
| 38 Simply enough, things that go in the builtins name space come from |
| 39 our _scons_builtins module. |
| 40 |
| 41 The rest of the things here will be in individual compatibility modules |
| 42 that are either: 1) suitably modified copies of the future modules that |
| 43 we want to use; or 2) backwards compatible re-implementations of the |
| 44 specific portions of a future module's API that we want to use. |
| 45 |
| 46 GENERAL WARNINGS: Implementations of functions in the SCons.compat |
| 47 modules are *NOT* guaranteed to be fully compliant with these functions in |
| 48 later versions of Python. We are only concerned with adding functionality |
| 49 that we actually use in SCons, so be wary if you lift this code for |
| 50 other uses. (That said, making these more nearly the same as later, |
| 51 official versions is still a desirable goal, we just don't need to be |
| 52 obsessive about it.) |
| 53 |
| 54 We name the compatibility modules with an initial '_scons_' (for example, |
| 55 _scons_subprocess.py is our compatibility module for subprocess) so |
| 56 that we can still try to import the real module name and fall back to |
| 57 our compatibility module if we get an ImportError. The import_as() |
| 58 function defined below loads the module as the "real" name (without the |
| 59 '_scons'), after which all of the "import {module}" statements in the |
| 60 rest of our code will find our pre-loaded compatibility module. |
| 61 """ |
| 62 |
| 63 __revision__ = "src/engine/SCons/compat/__init__.py 5134 2010/08/16 23:02:40 bde
egan" |
| 64 |
| 65 import os |
| 66 import sys |
| 67 import imp # Use the "imp" module to protect imports from fixers. |
| 68 |
| 69 def import_as(module, name): |
| 70 """ |
| 71 Imports the specified module (from our local directory) as the |
| 72 specified name, returning the loaded module object. |
| 73 """ |
| 74 dir = os.path.split(__file__)[0] |
| 75 return imp.load_module(name, *imp.find_module(module, [dir])) |
| 76 |
| 77 def rename_module(new, old): |
| 78 """ |
| 79 Attempts to import the old module and load it under the new name. |
| 80 Used for purely cosmetic name changes in Python 3.x. |
| 81 """ |
| 82 try: |
| 83 sys.modules[new] = imp.load_module(old, *imp.find_module(old)) |
| 84 return True |
| 85 except ImportError: |
| 86 return False |
| 87 |
| 88 |
| 89 rename_module('builtins', '__builtin__') |
| 90 import _scons_builtins |
| 91 |
| 92 |
| 93 try: |
| 94 import hashlib |
| 95 except ImportError: |
| 96 # Pre-2.5 Python has no hashlib module. |
| 97 try: |
| 98 import_as('_scons_hashlib', 'hashlib') |
| 99 except ImportError: |
| 100 # If we failed importing our compatibility module, it probably |
| 101 # means this version of Python has no md5 module. Don't do |
| 102 # anything and let the higher layer discover this fact, so it |
| 103 # can fall back to using timestamp. |
| 104 pass |
| 105 |
| 106 try: |
| 107 set |
| 108 except NameError: |
| 109 # Pre-2.4 Python has no native set type |
| 110 import_as('_scons_sets', 'sets') |
| 111 import builtins, sets |
| 112 builtins.set = sets.Set |
| 113 |
| 114 |
| 115 try: |
| 116 import collections |
| 117 except ImportError: |
| 118 # Pre-2.4 Python has no collections module. |
| 119 import_as('_scons_collections', 'collections') |
| 120 else: |
| 121 try: |
| 122 collections.UserDict |
| 123 except AttributeError: |
| 124 exec('from UserDict import UserDict as _UserDict') |
| 125 collections.UserDict = _UserDict |
| 126 del _UserDict |
| 127 try: |
| 128 collections.UserList |
| 129 except AttributeError: |
| 130 exec('from UserList import UserList as _UserList') |
| 131 collections.UserList = _UserList |
| 132 del _UserList |
| 133 try: |
| 134 collections.UserString |
| 135 except AttributeError: |
| 136 exec('from UserString import UserString as _UserString') |
| 137 collections.UserString = _UserString |
| 138 del _UserString |
| 139 |
| 140 |
| 141 try: |
| 142 import io |
| 143 except ImportError: |
| 144 # Pre-2.6 Python has no io module. |
| 145 import_as('_scons_io', 'io') |
| 146 |
| 147 |
| 148 try: |
| 149 os.devnull |
| 150 except AttributeError: |
| 151 # Pre-2.4 Python has no os.devnull attribute |
| 152 _names = sys.builtin_module_names |
| 153 if 'posix' in _names: |
| 154 os.devnull = '/dev/null' |
| 155 elif 'nt' in _names: |
| 156 os.devnull = 'nul' |
| 157 os.path.devnull = os.devnull |
| 158 try: |
| 159 os.path.lexists |
| 160 except AttributeError: |
| 161 # Pre-2.4 Python has no os.path.lexists function |
| 162 def lexists(path): |
| 163 return os.path.exists(path) or os.path.islink(path) |
| 164 os.path.lexists = lexists |
| 165 |
| 166 |
| 167 # When we're using the '-3' option during regression tests, importing |
| 168 # cPickle gives a warning no matter how it's done, so always use the |
| 169 # real profile module, whether it's fast or not. |
| 170 if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is None: |
| 171 # Not a regression test with '-3', so try to use faster version. |
| 172 # In 3.x, 'pickle' automatically loads the fast version if available. |
| 173 rename_module('pickle', 'cPickle') |
| 174 |
| 175 |
| 176 # In 3.x, 'profile' automatically loads the fast version if available. |
| 177 rename_module('profile', 'cProfile') |
| 178 |
| 179 |
| 180 # Before Python 3.0, the 'queue' module was named 'Queue'. |
| 181 rename_module('queue', 'Queue') |
| 182 |
| 183 |
| 184 # Before Python 3.0, the 'winreg' module was named '_winreg' |
| 185 rename_module('winreg', '_winreg') |
| 186 |
| 187 |
| 188 try: |
| 189 import subprocess |
| 190 except ImportError: |
| 191 # Pre-2.4 Python has no subprocess module. |
| 192 import_as('_scons_subprocess', 'subprocess') |
| 193 |
| 194 try: |
| 195 sys.intern |
| 196 except AttributeError: |
| 197 # Pre-2.6 Python has no sys.intern() function. |
| 198 import builtins |
| 199 try: |
| 200 sys.intern = builtins.intern |
| 201 except AttributeError: |
| 202 # Pre-2.x Python has no builtin intern() function. |
| 203 def intern(x): |
| 204 return x |
| 205 sys.intern = intern |
| 206 del intern |
| 207 try: |
| 208 sys.maxsize |
| 209 except AttributeError: |
| 210 # Pre-2.6 Python has no sys.maxsize attribute |
| 211 # Wrapping sys in () is silly, but protects it from 2to3 renames fixer |
| 212 sys.maxsize = (sys).maxint |
| 213 |
| 214 |
| 215 if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is not None: |
| 216 # We can't apply the 'callable' fixer until the floor is 2.6, but the |
| 217 # '-3' option to Python 2.6 and 2.7 generates almost ten thousand |
| 218 # warnings. This hack allows us to run regression tests with the '-3' |
| 219 # option by replacing the callable() built-in function with a hack |
| 220 # that performs the same function but doesn't generate the warning. |
| 221 # Note that this hack is ONLY intended to be used for regression |
| 222 # testing, and should NEVER be used for real runs. |
| 223 from types import ClassType |
| 224 def callable(obj): |
| 225 if hasattr(obj, '__call__'): return True |
| 226 if isinstance(obj, (ClassType, type)): return True |
| 227 return False |
| 228 import builtins |
| 229 builtins.callable = callable |
| 230 del callable |
| 231 |
| 232 |
| 233 # Local Variables: |
| 234 # tab-width:4 |
| 235 # indent-tabs-mode:nil |
| 236 # End: |
| 237 # vim: set expandtab tabstop=4 shiftwidth=4: |
OLD | NEW |