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__.py92
1 files changed, 82 insertions, 10 deletions
diff --git a/engine/SCons/compat/__init__.py b/engine/SCons/compat/__init__.py
index d3d4fe6..7973732 100644
--- a/engine/SCons/compat/__init__.py
+++ b/engine/SCons/compat/__init__.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2001 - 2016 The SCons Foundation
+# Copyright (c) 2001 - 2017 The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -57,11 +57,14 @@ 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 rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog"
+__revision__ = "src/engine/SCons/compat/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"
import os
import sys
-import imp # Use the "imp" module to protect imports from fixers.
+import imp # Use the "imp" module to protect imports from fixers.
+
+PYPY = hasattr(sys, 'pypy_translation_info')
+
def import_as(module, name):
"""
@@ -71,6 +74,7 @@ def import_as(module, name):
dir = os.path.split(__file__)[0]
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.
@@ -82,21 +86,32 @@ def rename_module(new, old):
except ImportError:
return False
+
+# TODO: FIXME
# In 3.x, 'pickle' automatically loads the fast version if available.
rename_module('pickle', 'cPickle')
+# Default pickle protocol. Higher protocols are more efficient/featureful
+# but incompatible with older Python versions. On Python 2.7 this is 2.
+# Negative numbers choose the highest available protocol.
+import pickle
+
+# Was pickle.HIGHEST_PROTOCOL
+# Changed to 2 so py3.5+'s pickle will be compatible with py2.7.
+PICKLE_PROTOCOL = 2
+
+# TODO: FIXME
# In 3.x, 'profile' automatically loads the fast version if available.
rename_module('profile', 'cProfile')
-
+# TODO: FIXME
# Before Python 3.0, the 'queue' module was named 'Queue'.
rename_module('queue', 'Queue')
-
+# TODO: FIXME
# Before Python 3.0, the 'winreg' module was named '_winreg'
rename_module('winreg', '_winreg')
-
# Python 3 moved builtin intern() to sys package
# To make porting easier, make intern always live
# in sys package (for python 2.7.x)
@@ -107,32 +122,89 @@ except AttributeError:
# intern into the sys package
sys.intern = intern
-
# Preparing for 3.x. UserDict, UserList, UserString are in
# collections for 3.x, but standalone in 2.7.x
import collections
+
try:
collections.UserDict
except AttributeError:
- exec('from UserDict import UserDict as _UserDict')
+ exec ('from UserDict import UserDict as _UserDict')
collections.UserDict = _UserDict
del _UserDict
try:
collections.UserList
except AttributeError:
- exec('from UserList import UserList as _UserList')
+ exec ('from UserList import UserList as _UserList')
collections.UserList = _UserList
del _UserList
try:
collections.UserString
except AttributeError:
- exec('from UserString import UserString as _UserString')
+ exec ('from UserString import UserString as _UserString')
collections.UserString = _UserString
del _UserString
+import shutil
+try:
+ shutil.SameFileError
+except AttributeError:
+ class SameFileError(Exception):
+ pass
+
+ shutil.SameFileError = SameFileError
+
+def with_metaclass(meta, *bases):
+ """
+ Function from jinja2/_compat.py. License: BSD.
+
+ Use it like this::
+
+ class BaseForm(object):
+ pass
+
+ class FormType(type):
+ pass
+
+ class Form(with_metaclass(FormType, BaseForm)):
+ pass
+
+ This requires a bit of explanation: the basic idea is to make a
+ dummy metaclass for one level of class instantiation that replaces
+ itself with the actual metaclass. Because of internal type checks
+ we also need to make sure that we downgrade the custom metaclass
+ for one level to something closer to type (that's why __call__ and
+ __init__ comes back from type etc.).
+
+ This has the advantage over six.with_metaclass of not introducing
+ dummy classes into the final MRO.
+ """
+
+ class metaclass(meta):
+ __call__ = type.__call__
+ __init__ = type.__init__
+
+ def __new__(cls, name, this_bases, d):
+ if this_bases is None:
+ return type.__new__(cls, name, (), d)
+ return meta(name, bases, d)
+
+ return metaclass('temporary_class', None, {})
+
+
+class NoSlotsPyPy(type):
+ """
+ Workaround for PyPy not working well with __slots__ and __class__ assignment.
+ """
+
+ def __new__(meta, name, bases, dct):
+ if PYPY and '__slots__' in dct:
+ dct.pop('__slots__')
+ return super(NoSlotsPyPy, meta).__new__(meta, name, bases, dct)
+
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil