diff options
Diffstat (limited to 'engine/SCons/Tool/textfile.py')
-rw-r--r-- | engine/SCons/Tool/textfile.py | 115 |
1 files changed, 74 insertions, 41 deletions
diff --git a/engine/SCons/Tool/textfile.py b/engine/SCons/Tool/textfile.py index 3cea7eb..7303e06 100644 --- a/engine/SCons/Tool/textfile.py +++ b/engine/SCons/Tool/textfile.py @@ -1,6 +1,6 @@ # -*- python -*- # -# 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 @@ -44,7 +44,7 @@ Textfile/Substfile builder for SCons. is unpredictable whether the expansion will occur. """ -__revision__ = "src/engine/SCons/Tool/textfile.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/textfile.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons @@ -53,7 +53,15 @@ import re from SCons.Node import Node from SCons.Node.Python import Value -from SCons.Util import is_String, is_Sequence, is_Dict +from SCons.Util import is_String, is_Sequence, is_Dict, to_bytes, PY3 + + +if PY3: + TEXTFILE_FILE_WRITE_MODE = 'w' +else: + TEXTFILE_FILE_WRITE_MODE = 'wb' + +LINESEP = '\n' def _do_subst(node, subs): """ @@ -64,62 +72,82 @@ def _do_subst(node, subs): 1.2345 and so forth. """ contents = node.get_text_contents() - if not subs: return contents - for (k,v) in subs: - contents = re.sub(k, v, contents) + if subs: + for (k, val) in subs: + contents = re.sub(k, val, contents) + + if 'b' in TEXTFILE_FILE_WRITE_MODE: + try: + contents = bytearray(contents, 'utf-8') + except UnicodeDecodeError: + # contents is already utf-8 encoded python 2 str i.e. a byte array + contents = bytearray(contents) + return contents + def _action(target, source, env): + # prepare the line separator linesep = env['LINESEPARATOR'] if linesep is None: - linesep = os.linesep + linesep = LINESEP # os.linesep elif is_String(linesep): pass elif isinstance(linesep, Value): linesep = linesep.get_text_contents() else: - raise SCons.Errors.UserError( - 'unexpected type/class for LINESEPARATOR: %s' - % repr(linesep), None) + raise SCons.Errors.UserError('unexpected type/class for LINESEPARATOR: %s' + % repr(linesep), None) + + if 'b' in TEXTFILE_FILE_WRITE_MODE: + linesep = to_bytes(linesep) # create a dictionary to use for the substitutions if 'SUBST_DICT' not in env: subs = None # no substitutions else: - d = env['SUBST_DICT'] - if is_Dict(d): - d = list(d.items()) - elif is_Sequence(d): + subst_dict = env['SUBST_DICT'] + if is_Dict(subst_dict): + subst_dict = list(subst_dict.items()) + elif is_Sequence(subst_dict): pass else: raise SCons.Errors.UserError('SUBST_DICT must be dict or sequence') subs = [] - for (k,v) in d: - if callable(v): - v = v() - if is_String(v): - v = env.subst(v) + for (k, value) in subst_dict: + if callable(value): + value = value() + if is_String(value): + value = env.subst(value) else: - v = str(v) - subs.append((k,v)) + value = str(value) + subs.append((k, value)) # write the file try: - fd = open(target[0].get_path(), "wb") - except (OSError,IOError), e: + if SCons.Util.PY3: + target_file = open(target[0].get_path(), TEXTFILE_FILE_WRITE_MODE, newline='') + else: + target_file = open(target[0].get_path(), TEXTFILE_FILE_WRITE_MODE) + except (OSError, IOError): raise SCons.Errors.UserError("Can't write target file %s" % target[0]) + # separate lines by 'linesep' only if linesep is not empty lsep = None - for s in source: - if lsep: fd.write(lsep) - fd.write(_do_subst(s, subs)) + for line in source: + if lsep: + target_file.write(lsep) + + target_file.write(_do_subst(line, subs)) lsep = linesep - fd.close() + target_file.close() + def _strfunc(target, source, env): return "Creating '%s'" % target[0] + def _convert_list_R(newlist, sources): for elem in sources: if is_Sequence(elem): @@ -128,6 +156,8 @@ def _convert_list_R(newlist, sources): newlist.append(elem) else: newlist.append(Value(elem)) + + def _convert_list(target, source, env): if len(target) != 1: raise SCons.Errors.UserError("Only one target file allowed") @@ -135,29 +165,31 @@ def _convert_list(target, source, env): _convert_list_R(newlist, source) return target, newlist + _common_varlist = ['SUBST_DICT', 'LINESEPARATOR'] _text_varlist = _common_varlist + ['TEXTFILEPREFIX', 'TEXTFILESUFFIX'] _text_builder = SCons.Builder.Builder( - action = SCons.Action.Action(_action, _strfunc, varlist = _text_varlist), - source_factory = Value, - emitter = _convert_list, - prefix = '$TEXTFILEPREFIX', - suffix = '$TEXTFILESUFFIX', - ) + action=SCons.Action.Action(_action, _strfunc, varlist=_text_varlist), + source_factory=Value, + emitter=_convert_list, + prefix='$TEXTFILEPREFIX', + suffix='$TEXTFILESUFFIX', +) _subst_varlist = _common_varlist + ['SUBSTFILEPREFIX', 'TEXTFILESUFFIX'] _subst_builder = SCons.Builder.Builder( - action = SCons.Action.Action(_action, _strfunc, varlist = _subst_varlist), - source_factory = SCons.Node.FS.File, - emitter = _convert_list, - prefix = '$SUBSTFILEPREFIX', - suffix = '$SUBSTFILESUFFIX', - src_suffix = ['.in'], - ) + action=SCons.Action.Action(_action, _strfunc, varlist=_subst_varlist), + source_factory=SCons.Node.FS.File, + emitter=_convert_list, + prefix='$SUBSTFILEPREFIX', + suffix='$SUBSTFILESUFFIX', + src_suffix=['.in'], +) + def generate(env): - env['LINESEPARATOR'] = os.linesep + env['LINESEPARATOR'] = LINESEP # os.linesep env['BUILDERS']['Textfile'] = _text_builder env['TEXTFILEPREFIX'] = '' env['TEXTFILESUFFIX'] = '.txt' @@ -165,6 +197,7 @@ def generate(env): env['SUBSTFILEPREFIX'] = '' env['SUBSTFILESUFFIX'] = '' + def exists(env): return 1 |