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 e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" 
 61   
 62  import os 
 63  import sys 
 64  import importlib 
 65   
 66  PYPY = hasattr(sys, 'pypy_translation_info') 
 67   
 68   
69 -def rename_module(new, old):
70 """ 71 Attempt to import the old module and load it under the new name. 72 Used for purely cosmetic name changes in Python 3.x. 73 """ 74 try: 75 sys.modules[new] = importlib.import_module(old) 76 return True 77 except ImportError: 78 return False
79 80 81 # TODO: FIXME 82 # In 3.x, 'pickle' automatically loads the fast version if available. 83 rename_module('pickle', 'cPickle') 84 85 # Default pickle protocol. Higher protocols are more efficient/featureful 86 # but incompatible with older Python versions. On Python 2.7 this is 2. 87 # Negative numbers choose the highest available protocol. 88 import pickle 89 90 # Was pickle.HIGHEST_PROTOCOL 91 # Changed to 2 so py3.5+'s pickle will be compatible with py2.7. 92 PICKLE_PROTOCOL = pickle.HIGHEST_PROTOCOL 93 94 # TODO: FIXME 95 # In 3.x, 'profile' automatically loads the fast version if available. 96 rename_module('profile', 'cProfile') 97 98 # TODO: FIXME 99 # Before Python 3.0, the 'queue' module was named 'Queue'. 100 rename_module('queue', 'Queue') 101 102 # TODO: FIXME 103 # Before Python 3.0, the 'winreg' module was named '_winreg' 104 rename_module('winreg', '_winreg') 105 106 # Python 3 moved builtin intern() to sys package 107 # To make porting easier, make intern always live 108 # in sys package (for python 2.7.x) 109 try: 110 sys.intern 111 except AttributeError: 112 # We must be using python 2.7.x so monkey patch 113 # intern into the sys package 114 sys.intern = intern 115 116 # UserDict, UserList, UserString are in # collections for 3.x, 117 # but standalone in 2.7.x. Monkey-patch into collections for 2.7. 118 import collections 119 120 try: 121 collections.UserDict 122 except AttributeError: 123 from UserDict import UserDict as _UserDict 124 collections.UserDict = _UserDict 125 del _UserDict 126 127 try: 128 collections.UserList 129 except AttributeError: 130 from UserList import UserList as _UserList 131 collections.UserList = _UserList 132 del _UserList 133 134 try: 135 collections.UserString 136 except AttributeError: 137 from UserString import UserString as _UserString 138 collections.UserString = _UserString 139 del _UserString 140 141 142 import shutil 143 try: 144 shutil.SameFileError 145 except AttributeError:
146 - class SameFileError(Exception):
147 pass
148 149 shutil.SameFileError = SameFileError 150
151 -def with_metaclass(meta, *bases):
152 """ 153 Function from jinja2/_compat.py. License: BSD. 154 155 Use it like this:: 156 157 class BaseForm(object): 158 pass 159 160 class FormType(type): 161 pass 162 163 class Form(with_metaclass(FormType, BaseForm)): 164 pass 165 166 This requires a bit of explanation: the basic idea is to make a 167 dummy metaclass for one level of class instantiation that replaces 168 itself with the actual metaclass. Because of internal type checks 169 we also need to make sure that we downgrade the custom metaclass 170 for one level to something closer to type (that's why __call__ and 171 __init__ comes back from type etc.). 172 173 This has the advantage over six.with_metaclass of not introducing 174 dummy classes into the final MRO. 175 """ 176 177 class metaclass(meta): 178 __call__ = type.__call__ 179 __init__ = type.__init__ 180 181 def __new__(cls, name, this_bases, d): 182 if this_bases is None: 183 return type.__new__(cls, name, (), d) 184 return meta(name, bases, d)
185 186 return metaclass('temporary_class', None, {}) 187 188
189 -class NoSlotsPyPy(type):
190 """ 191 Workaround for PyPy not working well with __slots__ and __class__ assignment. 192 """ 193
194 - def __new__(meta, name, bases, dct):
195 if PYPY and '__slots__' in dct: 196 dct.pop('__slots__') 197 return super(NoSlotsPyPy, meta).__new__(meta, name, bases, dct)
198 199 # Local Variables: 200 # tab-width:4 201 # indent-tabs-mode:nil 202 # End: 203 # vim: set expandtab tabstop=4 shiftwidth=4: 204