changeset 484:0259bd521729

Avoid repeaded string concatenations in .expand_variable(): use a list of string parts and proper indexes into the source string
author Franz Glasner <f.glasner@feldmann-mg.com>
date Fri, 17 Dec 2021 15:55:51 +0100
parents 38e4be1882e3
children 008b35666a43
files configmix/config.py
diffstat 1 files changed, 21 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/configmix/config.py	Fri Dec 17 14:14:36 2021 +0100
+++ b/configmix/config.py	Fri Dec 17 15:55:51 2021 +0100
@@ -223,7 +223,8 @@
     """
 
     # Speed
-    _TEXTTYPE = type(u(""))
+    _EMPTY_STR = u("")
+    _TEXTTYPE = type(_EMPTY_STR)
     _STARTTOK = u(b"{{")
     _ENDTOK = u(b"}}")
     _HIER_SEPARATOR = u(b'.')
@@ -659,10 +660,17 @@
     def expand_variable(self, s):
         """Expand variables in the single string `s`"""
         start = s.find(self._STARTTOK, 0)
+        if start < 0:
+            return s
+        res = []
+        res_append = res.append
+        rest = 0
         while start != -1:
+            res_append(s[rest:start])
             end = s.find(self._ENDTOK, start)
             if end < 0:
-                return s
+                rest = start
+                break
             varname, filters = self._split_filters(s[start+2:end])
             try:
                 if NONE_FILTER in filters:
@@ -670,7 +678,8 @@
                         filters, self.getvar_s(varname, default=None))
                 elif EMPTY_FILTER in filters:
                     varvalue = self._apply_filters(
-                        filters, self.getvar_s(varname, default=u("")))
+                        filters, self.getvar_s(varname,
+                                               default=self._EMPTY_STR))
                 else:
                     varvalue = self._apply_filters(
                         filters, self.getvar_s(varname))
@@ -686,13 +695,16 @@
             #
             if (start == 0) and (end + 2 == len(s)):
                 return varvalue
-            if varvalue is None:
-                varvalue = u("")
-            replaced = s[:start] + u(str(varvalue))
-            s = replaced + s[end+2:]
+            if not varvalue:
+                # None and/or empty str are handled equally here
+                pass
+            else:
+                res_append(u(str(varvalue)))
             # don't re-evaluate because `self.getvar_s()` expands already
-            start = s.find(self._STARTTOK, len(replaced))
-        return s
+            rest = end + 2
+            start = s.find(self._STARTTOK, rest)
+        res_append(s[rest:])
+        return self._EMPTY_STR.join(res)
 
     def _apply_filters(self, filters, value):
         for name in filters: