summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2016-08-12 14:13:03 (GMT)
committerWilliam Deegan <bill@baddogconsulting.com>2016-08-12 14:13:03 (GMT)
commit8bb44b6de01a456e4027f58af0bb7890b78142cb (patch)
tree4ed92c72ecc468c82978bec7d2496b33060416e0 /src/engine/SCons
parent0bc95a1575a1e48b0f27a27c4bc48070c838c484 (diff)
parent18ed9b715d052ad972940e90e9d83da53216c289 (diff)
downloadSCons-8bb44b6de01a456e4027f58af0bb7890b78142cb.zip
SCons-8bb44b6de01a456e4027f58af0bb7890b78142cb.tar.gz
SCons-8bb44b6de01a456e4027f58af0bb7890b78142cb.tar.bz2
merge from upstream
Diffstat (limited to 'src/engine/SCons')
-rw-r--r--src/engine/SCons/ActionTests.py30
-rw-r--r--src/engine/SCons/Executor.py6
-rw-r--r--src/engine/SCons/Node/FS.py4
-rw-r--r--src/engine/SCons/Node/__init__.py30
-rw-r--r--src/engine/SCons/Scanner/C.py5
-rw-r--r--src/engine/SCons/__main__.py4
-rw-r--r--src/engine/SCons/compat/__init__.py47
7 files changed, 94 insertions, 32 deletions
diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py
index 3eee4b6..9007183 100644
--- a/src/engine/SCons/ActionTests.py
+++ b/src/engine/SCons/ActionTests.py
@@ -231,7 +231,7 @@ def test_positional_args(pos_callback, cmd, **kw):
"""
act = SCons.Action.Action(cmd, **kw)
pos_callback(act)
- assert act.varlist is (), act.varlist
+ assert act.varlist == (), act.varlist
if not isinstance(act, SCons.Action._ActionAction):
# only valid cmdstrfunc is None
@@ -316,7 +316,7 @@ class ActionTestCase(unittest.TestCase):
"""
a1 = SCons.Action.Action(["x", "y", "z", [ "a", "b", "c"]])
assert isinstance(a1, SCons.Action.ListAction), a1
- assert a1.varlist is (), a1.varlist
+ assert a1.varlist == (), a1.varlist
assert isinstance(a1.list[0], SCons.Action.CommandAction), a1.list[0]
assert a1.list[0].cmd_list == "x", a1.list[0].cmd_list
assert isinstance(a1.list[1], SCons.Action.CommandAction), a1.list[1]
@@ -328,7 +328,7 @@ class ActionTestCase(unittest.TestCase):
a2 = SCons.Action.Action("x\ny\nz")
assert isinstance(a2, SCons.Action.ListAction), a2
- assert a2.varlist is (), a2.varlist
+ assert a2.varlist == (), a2.varlist
assert isinstance(a2.list[0], SCons.Action.CommandAction), a2.list[0]
assert a2.list[0].cmd_list == "x", a2.list[0].cmd_list
assert isinstance(a2.list[1], SCons.Action.CommandAction), a2.list[1]
@@ -341,7 +341,7 @@ class ActionTestCase(unittest.TestCase):
a3 = SCons.Action.Action(["x", foo, "z"])
assert isinstance(a3, SCons.Action.ListAction), a3
- assert a3.varlist is (), a3.varlist
+ assert a3.varlist == (), a3.varlist
assert isinstance(a3.list[0], SCons.Action.CommandAction), a3.list[0]
assert a3.list[0].cmd_list == "x", a3.list[0].cmd_list
assert isinstance(a3.list[1], SCons.Action.FunctionAction), a3.list[1]
@@ -351,7 +351,7 @@ class ActionTestCase(unittest.TestCase):
a4 = SCons.Action.Action(["x", "y"], strfunction=foo)
assert isinstance(a4, SCons.Action.ListAction), a4
- assert a4.varlist is (), a4.varlist
+ assert a4.varlist == (), a4.varlist
assert isinstance(a4.list[0], SCons.Action.CommandAction), a4.list[0]
assert a4.list[0].cmd_list == "x", a4.list[0].cmd_list
assert a4.list[0].strfunction == foo, a4.list[0].strfunction
@@ -361,7 +361,7 @@ class ActionTestCase(unittest.TestCase):
a5 = SCons.Action.Action("x\ny", strfunction=foo)
assert isinstance(a5, SCons.Action.ListAction), a5
- assert a5.varlist is (), a5.varlist
+ assert a5.varlist == (), a5.varlist
assert isinstance(a5.list[0], SCons.Action.CommandAction), a5.list[0]
assert a5.list[0].cmd_list == "x", a5.list[0].cmd_list
assert a5.list[0].strfunction == foo, a5.list[0].strfunction
@@ -1533,7 +1533,8 @@ class FunctionActionTestCase(unittest.TestCase):
global count
count = count + 1
for t in target:
- open(t, 'w').write("function1\n")
+ with open(t, 'w') as f:
+ f.write("function1\n")
return 1
act = SCons.Action.FunctionAction(function1, {})
@@ -1548,7 +1549,8 @@ class FunctionActionTestCase(unittest.TestCase):
class class1a(object):
def __init__(self, target, source, env):
- open(env['out'], 'w').write("class1a\n")
+ with open(env['out'], 'w') as f:
+ f.write("class1a\n")
act = SCons.Action.FunctionAction(class1a, {})
r = act([], [], Environment(out = outfile))
@@ -1558,7 +1560,8 @@ class FunctionActionTestCase(unittest.TestCase):
class class1b(object):
def __call__(self, target, source, env):
- open(env['out'], 'w').write("class1b\n")
+ with open(env['out'], 'w') as f:
+ f.write("class1b\n")
return 2
act = SCons.Action.FunctionAction(class1b(), {})
@@ -1710,17 +1713,20 @@ class ListActionTestCase(unittest.TestCase):
cmd2 = r'%s %s %s syzygy' % (_python_, act_py, outfile)
def function2(target, source, env):
- open(env['out'], 'a').write("function2\n")
+ with open(env['out'], 'a') as f:
+ f.write("function2\n")
return 0
class class2a(object):
def __call__(self, target, source, env):
- open(env['out'], 'a').write("class2a\n")
+ with open(env['out'], 'a') as f:
+ f.write("class2a\n")
return 0
class class2b(object):
def __init__(self, target, source, env):
- open(env['out'], 'a').write("class2b\n")
+ with open(env['out'], 'a') as f:
+ f.write("class2b\n")
act = SCons.Action.ListAction([cmd2, function2, class2a(), class2b])
r = act([], [], Environment(out = outfile))
assert isinstance(r.status, class2b), r.status
diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py
index 7107fde..dd5088d 100644
--- a/src/engine/SCons/Executor.py
+++ b/src/engine/SCons/Executor.py
@@ -35,7 +35,7 @@ import SCons.Debug
from SCons.Debug import logInstanceCreation
import SCons.Errors
import SCons.Memoize
-
+from SCons.compat import with_metaclass, NoSlotsPyPy
class Batch(object):
"""Remembers exact association between targets
@@ -154,7 +154,7 @@ _execute_str_map = {0 : execute_null_str,
1 : execute_actions_str}
-class Executor(object):
+class Executor(object, with_metaclass(NoSlotsPyPy)):
"""A class for controlling instances of executing an action.
This largely exists to hold a single association of an action,
@@ -580,7 +580,7 @@ def get_NullEnvironment():
nullenv = NullEnvironment()
return nullenv
-class Null(object):
+class Null(object, with_metaclass(NoSlotsPyPy)):
"""A null Executor, with a null build Environment, that does
nothing when the rest of the methods call it.
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index d19afa9..71511b5 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -1211,9 +1211,9 @@ class FS(LocalFS):
def getcwd(self):
if hasattr(self, "_cwd"):
- return self._cwd
+ return self._cwd
else:
- return "<no cwd>"
+ return "<no cwd>"
def chdir(self, dir, change_os_dir=0):
"""Change the current working directory for lookups.
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 1a76b60..00ddf2f 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -57,6 +57,8 @@ import SCons.Util
from SCons.Debug import Trace
+from SCons.compat import with_metaclass, NoSlotsPyPy
+
print_duplicate = 0
def classname(obj):
@@ -212,7 +214,8 @@ def get_contents_file(node):
return ''
fname = node.rfile().get_abspath()
try:
- contents = open(fname, "rb").read()
+ with open(fname, "rb") as fp:
+ contents = fp.read()
except EnvironmentError as e:
if not e.filename:
e.filename = fname
@@ -489,7 +492,8 @@ class BuildInfoBase(object):
if key not in ('__weakref__',):
setattr(self, key, value)
-class Node(object):
+
+class Node(object, with_metaclass(NoSlotsPyPy)):
"""The base Node class, for entities that we know how to
build, or use to build other Nodes.
"""
@@ -926,9 +930,9 @@ class Node(object):
scanner's recursive flag says that we should.
"""
nodes = [self]
- seen = {}
- seen[self] = 1
+ seen = set(nodes)
dependencies = []
+ path_memo = {}
root_node_scanner = self._get_scanner(env, initial_scanner, None, kw)
@@ -936,30 +940,32 @@ class Node(object):
node = nodes.pop(0)
scanner = node._get_scanner(env, initial_scanner, root_node_scanner, kw)
-
if not scanner:
continue
- path = path_func(scanner)
+ try:
+ path = path_memo[scanner]
+ except KeyError:
+ path = path_func(scanner)
+ path_memo[scanner] = path
included_deps = [x for x in node.get_found_includes(env, scanner, path) if x not in seen]
if included_deps:
dependencies.extend(included_deps)
- for dep in included_deps:
- seen[dep] = 1
+ seen.update(included_deps)
nodes.extend(scanner.recurse_nodes(included_deps))
return dependencies
def _get_scanner(self, env, initial_scanner, root_node_scanner, kw):
- if not initial_scanner:
+ if initial_scanner:
+ # handle explicit scanner case
+ scanner = initial_scanner.select(self)
+ else:
# handle implicit scanner case
scanner = self.get_env_scanner(env, kw)
if scanner:
scanner = scanner.select(self)
- else:
- # handle explicit scanner case
- scanner = initial_scanner.select(self)
if not scanner:
# no scanner could be found for the given node's scanner key;
diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py
index 3b34b88..c2e50a6 100644
--- a/src/engine/SCons/Scanner/C.py
+++ b/src/engine/SCons/Scanner/C.py
@@ -58,12 +58,11 @@ class SConsCPPScanner(SCons.cpp.PreProcessor):
return result
def read_file(self, file):
try:
- fp = open(str(file.rfile()))
+ with open(str(file.rfile())) as fp:
+ return fp.read()
except EnvironmentError as e:
self.missing.append((file, self.current_file))
return ''
- else:
- return fp.read()
def dictify_CPPDEFINES(env):
cppdefines = env.get('CPPDEFINES', {})
diff --git a/src/engine/SCons/__main__.py b/src/engine/SCons/__main__.py
new file mode 100644
index 0000000..0dfbb9d
--- /dev/null
+++ b/src/engine/SCons/__main__.py
@@ -0,0 +1,4 @@
+import SCons.Script
+# this does all the work, and calls sys.exit
+# with the proper exit status when done.
+SCons.Script.main()
diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py
index 0ddbdd5..6f20b73 100644
--- a/src/engine/SCons/compat/__init__.py
+++ b/src/engine/SCons/compat/__init__.py
@@ -63,6 +63,8 @@ import os
import sys
import imp # Use the "imp" module to protect imports from fixers.
+PYPY = hasattr(sys, 'pypy_translation_info')
+
def import_as(module, name):
"""
Imports the specified module (from our local directory) as the
@@ -135,6 +137,51 @@ except AttributeError:
del _UserString
+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