From 2d1bebd6f093bef2bae4d89d2063724a4ca3e102 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 1 Jan 2021 15:32:58 -0700 Subject: Fix awkward consvar code from ancient Python The Append* and Prepend* environment methods which add to existing construction variables had some deeply nested try blocks because according to the comments, Python 1.5.2 would not allow a continue statement inside a try block. This has now been aligned to more modern usage for better readability. Signed-off-by: Mats Wichmann --- CHANGES.txt | 3 +- SCons/Environment.py | 248 ++++++++++++++++++++++++--------------------------- 2 files changed, 121 insertions(+), 130 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 611023e..0604514 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -99,7 +99,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fix cut-n-paste error in msvc debug printout and make some debug output in msvs and msvsTests.py be off until needed (uncomment to use) - Fix Issue #3014 - Empty file and missing file have same csig - + - Refactor env.Append/Prepend to remove Py 1.5 era need to nest + try blocks, can now "continue" at the appropriate places. diff --git a/SCons/Environment.py b/SCons/Environment.py index 4ebd515..2b9b294 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -407,9 +407,8 @@ class SubstitutionEnvironment: # key and we don't need to check. If we do check, using a # global, pre-compiled regular expression directly is more # efficient than calling another function or a method. - if key not in self._dict \ - and not _is_valid_var.match(key): - raise UserError("Illegal construction variable `%s'" % key) + if key not in self._dict and not _is_valid_var.match(key): + raise UserError("Illegal construction variable `%s'" % key) self._dict[key] = value def get(self, key, default=None): @@ -635,7 +634,7 @@ class SubstitutionEnvironment: Parse ``flags`` and return a dict with the flags distributed into the appropriate construction variable names. The flags are treated as a typical set of command-line flags for a GNU-like toolchain, - such as might have been generated by one of the \*-config scripts, + such as might have been generated by one of the {foo}-config scripts, and used to populate the entries based on knowledge embedded in this method - the choices are not expected to be portable to other toolchains. @@ -1173,92 +1172,85 @@ class Base(SubstitutionEnvironment): ####################################################################### def Append(self, **kw): - """Append values to existing construction variables in an Environment.""" + """Append values to construction variables in an Environment. + + The variable is created if it is not already present. + """ + kw = copy_non_reserved_keywords(kw) for key, val in kw.items(): - # It would be easier on the eyes to write this using - # "continue" statements whenever we finish processing an item, - # but Python 1.5.2 apparently doesn't let you use "continue" - # within try:-except: blocks, so we have to nest our code. try: if key == 'CPPDEFINES' and is_String(self._dict[key]): self._dict[key] = [self._dict[key]] orig = self._dict[key] except KeyError: - # No existing variable in the environment, so just set - # it to the new value. + # No existing var in the environment, so set to the new value. if key == 'CPPDEFINES' and is_String(val): self._dict[key] = [val] else: self._dict[key] = val - else: + continue + + try: + # Check if the original looks like a dict: has .update? + update_dict = orig.update + except AttributeError: try: - # Check if the original looks like a dictionary. - # If it is, we can't just try adding the value because - # dictionaries don't have __add__() methods, and - # things like UserList will incorrectly coerce the - # original dict to a list (which we don't want). - update_dict = orig.update - except AttributeError: + # Just try to add them together. This will work + # in most cases, when the original and new values + # are compatible types. + self._dict[key] = orig + val + except (KeyError, TypeError): try: - # Most straightforward: just try to add them - # together. This will work in most cases, when the - # original and new values are of compatible types. - self._dict[key] = orig + val - except (KeyError, TypeError): - try: - # Check if the original is a list. - add_to_orig = orig.append - except AttributeError: - # The original isn't a list, but the new - # value is (by process of elimination), - # so insert the original in the new value - # (if there's one to insert) and replace - # the variable with it. - if orig: - val.insert(0, orig) - self._dict[key] = val + # Check if the original is a list: has .append? + add_to_orig = orig.append + except AttributeError: + # The original isn't a list, but the new + # value is (by process of elimination), + # so insert the original in the new value + # (if there's one to insert) and replace + # the variable with it. + if orig: + val.insert(0, orig) + self._dict[key] = val + else: + # The original is a list, so append the new + # value to it (if there's a value to append). + if val: + add_to_orig(val) + continue + + # The original looks like a dictionary, so update it + # based on what we think the value looks like. + # We can't just try adding the value because + # dictionaries don't have __add__() methods, and + # things like UserList will incorrectly coerce the + # original dict to a list (which we don't want). + if is_List(val): + if key == 'CPPDEFINES': + tmp = [] + for (k, v) in orig.items(): + if v is not None: + tmp.append((k, v)) else: - # The original is a list, so append the new - # value to it (if there's a value to append). - if val: - add_to_orig(val) + tmp.append((k,)) + orig = tmp + orig += val + self._dict[key] = orig else: - # The original looks like a dictionary, so update it - # based on what we think the value looks like. - if is_List(val): - if key == 'CPPDEFINES': - tmp = [] - for (k, v) in orig.items(): - if v is not None: - tmp.append((k, v)) - else: - tmp.append((k,)) - orig = tmp - orig += val - self._dict[key] = orig - else: - for v in val: - orig[v] = None + for v in val: + orig[v] = None + else: + try: + update_dict(val) + except (AttributeError, TypeError, ValueError): + if is_Dict(val): + for k, v in val.items(): + orig[k] = v else: - try: - update_dict(val) - except (AttributeError, TypeError, ValueError): - if is_Dict(val): - for k, v in val.items(): - orig[k] = v - else: - orig[val] = None - self.scanner_map_delete(kw) + orig[val] = None - # allow Dirs and strings beginning with # for top-relative - # Note this uses the current env's fs (in self). - def _canonicalize(self, path): - if not is_String(path): # typically a Dir - path = str(path) - if path and path[0] == '#': - path = str(self.fs.Dir(path)) - return path + self.scanner_map_delete(kw) def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep, delete_existing=0): @@ -1295,8 +1287,7 @@ class Base(SubstitutionEnvironment): val = _delete_duplicates(val, delete_existing) if key not in self._dict or self._dict[key] in ('', None): self._dict[key] = val - elif is_Dict(self._dict[key]) and \ - is_Dict(val): + elif is_Dict(self._dict[key]) and is_Dict(val): self._dict[key].update(val) elif is_List(val): dk = self._dict[key] @@ -1682,68 +1673,68 @@ class Base(SubstitutionEnvironment): return SCons.Platform.Platform(platform)(self) def Prepend(self, **kw): - """Prepend values to existing construction variables - in an Environment. + """Prepend values to construction variables in an Environment. + + The variable is created if it is not already present. """ + kw = copy_non_reserved_keywords(kw) for key, val in kw.items(): - # It would be easier on the eyes to write this using - # "continue" statements whenever we finish processing an item, - # but Python 1.5.2 apparently doesn't let you use "continue" - # within try:-except: blocks, so we have to nest our code. try: orig = self._dict[key] except KeyError: - # No existing variable in the environment, so just set - # it to the new value. + # No existing var in the environment so set to the new value. self._dict[key] = val - else: + continue + + try: + # Check if the original looks like a dict: has .update? + update_dict = orig.update + except AttributeError: try: - # Check if the original looks like a dictionary. - # If it is, we can't just try adding the value because - # dictionaries don't have __add__() methods, and - # things like UserList will incorrectly coerce the - # original dict to a list (which we don't want). - update_dict = orig.update - except AttributeError: + # Just try to add them together. This will work + # in most cases, when the original and new values + # are compatible types. + self._dict[key] = val + orig + except (KeyError, TypeError): try: - # Most straightforward: just try to add them - # together. This will work in most cases, when the - # original and new values are of compatible types. - self._dict[key] = val + orig - except (KeyError, TypeError): - try: - # Check if the added value is a list. - add_to_val = val.append - except AttributeError: - # The added value isn't a list, but the - # original is (by process of elimination), - # so insert the the new value in the original - # (if there's one to insert). - if val: - orig.insert(0, val) - else: - # The added value is a list, so append - # the original to it (if there's a value - # to append). - if orig: - add_to_val(orig) - self._dict[key] = val - else: - # The original looks like a dictionary, so update it - # based on what we think the value looks like. - if is_List(val): - for v in val: - orig[v] = None + # Check if the added value is a list: has .append? + add_to_val = val.append + except AttributeError: + # The added value isn't a list, but the + # original is (by process of elimination), + # so insert the the new value in the original + # (if there's one to insert). + if val: + orig.insert(0, val) else: - try: - update_dict(val) - except (AttributeError, TypeError, ValueError): - if is_Dict(val): - for k, v in val.items(): - orig[k] = v - else: - orig[val] = None + # The added value is a list, so append + # the original to it (if there's a value + # to append) and replace the original. + if orig: + add_to_val(orig) + self._dict[key] = val + continue + + # The original looks like a dictionary, so update it + # based on what we think the value looks like. + # We can't just try adding the value because + # dictionaries don't have __add__() methods, and + # things like UserList will incorrectly coerce the + # original dict to a list (which we don't want). + if is_List(val): + for v in val: + orig[v] = None + else: + try: + update_dict(val) + except (AttributeError, TypeError, ValueError): + if is_Dict(val): + for k, v in val.items(): + orig[k] = v + else: + orig[val] = None + self.scanner_map_delete(kw) def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep, @@ -1782,8 +1773,7 @@ class Base(SubstitutionEnvironment): val = _delete_duplicates(val, not delete_existing) if key not in self._dict or self._dict[key] in ('', None): self._dict[key] = val - elif is_Dict(self._dict[key]) and \ - is_Dict(val): + elif is_Dict(self._dict[key]) and is_Dict(val): self._dict[key].update(val) elif is_List(val): dk = self._dict[key] -- cgit v0.12