Merge branch 'cnfvar-deprecations'
[pyi2ncommon] / src / sysmisc.py
index 3806b31..8f9e8df 100644 (file)
@@ -373,6 +373,43 @@ def cmd_block_till(cmd, timeout, cond, interval=1, *userdata, **kwuserdata):
     return RUN_RESULT_OK, None
 
 
+def replace_file_regex(edited_file, value, regex=None, ignore_fail=False):
+    """
+    Replace with value in a provided file using an optional regex or entirely.
+
+    :param str edited_file: file to use for the replacement
+    :param str value: value to replace the first matched group with
+    :param regex: more restrictive regular expression to use when replacing with value
+    :type regex: str or None
+    :param bool ignore_fail: whether to ignore regex mismatching
+    :raises: :py:class:`ValueError` if (also default) `regex` doesn't have a match
+
+    In order to ensure better matching capabilities you are supposed to
+    provide a regex pattern with at least one subgroup to match your value.
+    What this means is that the value you like to replace is not directly
+    searched into the config text but matched within a larger regex in
+    in order to avoid any mismatch.
+
+    Example:
+    provider.cnf, 'PROVIDER_LOCALIP,0: "(\d+)"', 127.0.0.1
+    """
+    pattern = regex.encode() if regex else "(.+)"
+
+    with open(edited_file, "rb") as file_handle:
+        text = file_handle.read()
+    match_line = re.search(pattern, text)
+
+    if match_line is None and not ignore_fail:
+        raise ValueError(f"Pattern {pattern} not found in {edited_file}")
+    elif match_line is not None:
+        old_line = match_line.group(0)
+        text = text[:match_line.start(1)] + value.encode() + text[match_line.end(1):]
+        line = re.search(pattern, text).group(0)
+        llog.debug(f"Updating {old_line} to {line} in {edited_file}")
+        with open(edited_file, "wb") as file_handle:
+            file_handle.write(text)
+
+
 ###############################################################################
 # LOGGING
 ###############################################################################