Package SCons :: Package compat
[hide private]
[frames] | no frames]

Source Code for Package SCons.compat

  1  # 
  2  # Copyright (c) 2001 - 2019 The SCons 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  The rest of the things here will be in individual compatibility modules 
 39  that are either: 1) suitably modified copies of the future modules that 
 40  we want to use; or 2) backwards compatible re-implementations of the 
 41  specific portions of a future module's API that we want to use. 
 42   
 43  GENERAL WARNINGS:  Implementations of functions in the SCons.compat 
 44  modules are *NOT* guaranteed to be fully compliant with these functions in 
 45  later versions of Python.  We are only concerned with adding functionality 
 46  that we actually use in SCons, so be wary if you lift this code for 
 47  other uses.  (That said, making these more nearly the same as later, 
 48  official versions is still a desirable goal, we just don't need to be 
 49  obsessive about it.) 
 50   
 51  We name the compatibility modules with an initial '_scons_' (for example, 
 52  _scons_subprocess.py is our compatibility module for subprocess) so 
 53  that we can still try to import the real module name and fall back to 
 54  our compatibility module if we get an ImportError.  The import_as() 
 55  function defined below loads the module as the "real" name (without the 
 56  '_scons'), after which all of the "import {module}" statements in the 
 57  rest of our code will find our pre-loaded compatibility module. 
 58  """ 
 59   
 60  __revision__ = "src/engine/SCons/compat/__init__.py a56bbd8c09fb219ab8a9673330ffcd55279219d0 2019-03-26 23:16:31 bdeegan" 
 61   
 62  import os 
 63  import sys 
 64  import imp  # Use the "imp" module to protect imports from fixers. 
 65   
 66  PYPY = hasattr(sys, 'pypy_translation_info') 
 67   
 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
78 -def rename_module(new, old):
79 """ 80 Attempts to import the old module and load it under the new name. 81 Used for purely cosmetic name changes in Python 3.x. 82 """ 83 try: 84 sys.modules[new] = imp.load_module(old, *imp.find_module(old)) 85 return True 86 except ImportError: 87 return False
88 89 90 # TODO: FIXME 91 # In 3.x, 'pickle' automatically loads the fast version if available. 92 rename_module('pickle', 'cPickle') 93 94 # Default pickle protocol. Higher protocols are more efficient/featureful 95 # but incompatible with older Python versions. On Python 2.7 this is 2. 96 # Negative numbers choose the highest available protocol. 97 import pickle 98 99 # Was pickle.HIGHEST_PROTOCOL 100 # Changed to 2 so py3.5+'s pickle will be compatible with py2.7. 101 PICKLE_PROTOCOL = pickle.HIGHEST_PROTOCOL 102 103 # TODO: FIXME 104 # In 3.x, 'profile' automatically loads the fast version if available. 105 rename_module('profile', 'cProfile') 106 107 # TODO: FIXME 108 # Before Python 3.0, the 'queue' module was named 'Queue'. 109 rename_module('queue', 'Queue') 110 111 # TODO: FIXME 112 # Before Python 3.0, the 'winreg' module was named '_winreg' 113 rename_module('winreg', '_winreg') 114 115 # Python 3 moved builtin intern() to sys package 116 # To make porting easier, make intern always live 117 # in sys package (for python 2.7.x) 118 try: 119 sys.intern 120 except AttributeError: 121 # We must be using python 2.7.x so monkey patch 122 # intern into the sys package 123 sys.intern = intern 124 125 # Preparing for 3.x. UserDict, UserList, UserString are in 126 # collections for 3.x, but standalone in 2.7.x 127 import collections 128 129 try: 130 collections.UserDict 131 except AttributeError: 132 exec ('from UserDict import UserDict as _UserDict') 133 collections.UserDict = _UserDict 134 del _UserDict 135 136 try: 137 collections.UserList 138 except AttributeError: 139 exec ('from UserList import UserList as _UserList') 140 collections.UserList = _UserList 141 del _UserList 142 143 try: 144 collections.UserString 145 except AttributeError: 146 exec ('from UserString import UserString as _UserString') 147 collections.UserString = _UserString 148 del _UserString 149 150 151 import shutil 152 try: 153 shutil.SameFileError 154 except AttributeError:
155 - class SameFileError(Exception):
156 pass
157 158 shutil.SameFileError = SameFileError 159
160 -def with_metaclass(meta, *bases):
161 """ 162 Function from jinja2/_compat.py. License: BSD. 163 164 Use it like this:: 165 166 class BaseForm(object): 167 pass 168 169 class FormType(type): 170 pass 171 172 class Form(with_metaclass(FormType, BaseForm)): 173 pass 174 175 This requires a bit of explanation: the basic idea is to make a 176 dummy metaclass for one level of class instantiation that replaces 177 itself with the actual metaclass. Because of internal type checks 178 we also need to make sure that we downgrade the custom metaclass 179 for one level to something closer to type (that's why __call__ and 180 __init__ comes back from type etc.). 181 182 This has the advantage over six.with_metaclass of not introducing 183 dummy classes into the final MRO. 184 """ 185 186 class metaclass(meta): 187 __call__ = type.__call__ 188 __init__ = type.__init__ 189 190 def __new__(cls, name, this_bases, d): 191 if this_bases is None: 192 return type.__new__(cls, name, (), d) 193 return meta(name, bases, d)
194 195 return metaclass('temporary_class', None, {}) 196 197
198 -class NoSlotsPyPy(type):
199 """ 200 Workaround for PyPy not working well with __slots__ and __class__ assignment. 201 """ 202
203 - def __new__(meta, name, bases, dct):
204 if PYPY and '__slots__' in dct: 205 dct.pop('__slots__') 206 return super(NoSlotsPyPy, meta).__new__(meta, name, bases, dct)
207 208 # Local Variables: 209 # tab-width:4 210 # indent-tabs-mode:nil 211 # End: 212 # vim: set expandtab tabstop=4 shiftwidth=4: 213