summaryrefslogtreecommitdiff
path: root/engine/SCons/Action.py
diff options
context:
space:
mode:
Diffstat (limited to 'engine/SCons/Action.py')
-rw-r--r--engine/SCons/Action.py60
1 files changed, 36 insertions, 24 deletions
diff --git a/engine/SCons/Action.py b/engine/SCons/Action.py
index ce5471d..be4a5ff 100644
--- a/engine/SCons/Action.py
+++ b/engine/SCons/Action.py
@@ -77,7 +77,7 @@ way for wrapping up the functions.
"""
-# Copyright (c) 2001 - 2017 The SCons Foundation
+# Copyright (c) 2001 - 2019 The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -98,7 +98,7 @@ way for wrapping up the functions.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "src/engine/SCons/Action.py 74b2c53bc42290e911b334a6b44f187da698a668 2017/11/14 13:16:53 bdbaddog"
+__revision__ = "src/engine/SCons/Action.py 72ae09dc35ac2626f8ff711d8c4b30b6138e08e3 2019-08-08 14:50:06 bdeegan"
import os
import pickle
@@ -107,6 +107,7 @@ import sys
import subprocess
import itertools
import inspect
+from collections import OrderedDict
import SCons.Debug
from SCons.Debug import logInstanceCreation
@@ -115,8 +116,7 @@ import SCons.Util
import SCons.Subst
# we use these a lot, so try to optimize them
-is_String = SCons.Util.is_String
-is_List = SCons.Util.is_List
+from SCons.Util import is_String, is_List
class _null(object):
pass
@@ -211,7 +211,7 @@ def _object_contents(obj):
def _code_contents(code, docstring=None):
- """Return the signature contents of a code object.
+ r"""Return the signature contents of a code object.
By providing direct access to the code object of the
function, Python makes this extremely easy. Hooray!
@@ -258,8 +258,7 @@ def _code_contents(code, docstring=None):
# function. Note that we have to call _object_contents on each
# constants because the code object of nested functions can
# show-up among the constants.
-
- z = [_object_contents(cc) for cc in code.co_consts[1:]]
+ z = [_object_contents(cc) for cc in code.co_consts if cc != docstring]
contents.extend(b',(')
contents.extend(bytearray(',', 'utf-8').join(z))
contents.extend(b')')
@@ -535,7 +534,7 @@ class ActionBase(object):
result = self.get_presig(target, source, env)
if not isinstance(result,(bytes, bytearray)):
- result = bytearray("",'utf-8').join([ SCons.Util.to_bytes(r) for r in result ])
+ result = bytearray(result, 'utf-8')
else:
# Make a copy and put in bytearray, without this the contents returned by get_presig
# can be changed by the logic below, appending with each call and causing very
@@ -768,16 +767,22 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw):
it'll have to be tweaked to get the full desired functionality.
one special arg (so far?), 'error', to tell what to do with exceptions.
"""
- # allow std{in,out,err} to be "'devnull'"
- io = kw.get('stdin')
- if is_String(io) and io == 'devnull':
- kw['stdin'] = open(os.devnull)
- io = kw.get('stdout')
- if is_String(io) and io == 'devnull':
- kw['stdout'] = open(os.devnull, 'w')
- io = kw.get('stderr')
- if is_String(io) and io == 'devnull':
- kw['stderr'] = open(os.devnull, 'w')
+ # allow std{in,out,err} to be "'devnull'". This is like
+ # subprocess.DEVNULL, which does not exist for Py2. Use the
+ # subprocess one if possible.
+ # Clean this up when Py2 support is dropped
+ try:
+ from subprocess import DEVNULL
+ except ImportError:
+ DEVNULL = None
+
+ for stream in 'stdin', 'stdout', 'stderr':
+ io = kw.get(stream)
+ if is_String(io) and io == 'devnull':
+ if DEVNULL:
+ kw[stream] = DEVNULL
+ else:
+ kw[stream] = open(os.devnull, "r+")
# Figure out what shell environment to use
ENV = kw.get('env', None)
@@ -803,7 +808,7 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw):
kw['env'] = new_env
try:
- return subprocess.Popen(cmd, **kw)
+ pobj = subprocess.Popen(cmd, **kw)
except EnvironmentError as e:
if error == 'raise': raise
# return a dummy Popen instance that only returns error
@@ -817,7 +822,14 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw):
def readline(self): return ''
def __iter__(self): return iter(())
stdout = stderr = f()
- return dummyPopen(e)
+ pobj = dummyPopen(e)
+ finally:
+ # clean up open file handles stored in parent's kw
+ for k, v in kw.items():
+ if inspect.ismethod(getattr(v, 'close', None)):
+ v.close()
+
+ return pobj
class CommandAction(_ActionAction):
@@ -837,8 +849,8 @@ class CommandAction(_ActionAction):
_ActionAction.__init__(self, **kw)
if is_List(cmd):
if [c for c in cmd if is_List(c)]:
- raise TypeError("CommandAction should be given only " \
- "a single command")
+ raise TypeError("CommandAction should be given only "
+ "a single command")
self.cmd_list = cmd
def __str__(self):
@@ -1086,7 +1098,7 @@ class LazyAction(CommandGeneratorAction, CommandAction):
def get_parent_class(self, env):
c = env.get(self.var)
- if is_String(c) and not '\n' in c:
+ if is_String(c) and '\n' not in c:
return CommandAction
return CommandGeneratorAction
@@ -1289,7 +1301,7 @@ class ListAction(ActionBase):
return result
def get_varlist(self, target, source, env, executor=None):
- result = SCons.Util.OrderedDict()
+ result = OrderedDict()
for act in self.list:
for var in act.get_varlist(target, source, env, executor):
result[var] = True