Skip to content
Permalink
Browse files

Preserve the comments in config files

Use the comment keyword to store the comments in the file configuration,
and restore them on config dump.
  • Loading branch information...
cvaroqui committed Jul 10, 2019
1 parent fc1713d commit af40e7dd0417650b5be14242e968fcec4bdcf8a4
Showing with 63 additions and 8 deletions.
  1. +29 −8 lib/extconfig.py
  2. +34 −0 lib/rcUtilities.py
@@ -10,7 +10,7 @@
import rcExceptions as ex
from converters import *
from rcUtilities import is_string, try_decode, read_cf, eval_expr, unset_lazy, \
lazy, makedirs, factory
lazy, makedirs, factory, read_cf_comments
from rcGlobalEnv import rcEnv

SECRETS = []
@@ -1312,6 +1312,24 @@ def parse_config_file(self, cf=None):
if config.has_option(section, option):
tmpsection[option] = config.get(section, option)
data[section] = tmpsection

comments = read_cf_comments(cf)
for section, comments in comments.items():
if section in data:
if "comment" not in data[section]:
data[section]["comment"] = ""
else:
data[section]["comment"] += "\n"
data[section]["comment"] += "\n".join(comments)
else:
if "DEFAULT" not in data:
data["DEFAULT"] = {}
if "comment" not in data["DEFAULT"]:
data["DEFAULT"]["comment"] = ""
else:
data["DEFAULT"]["comment"] += "\n"
data["DEFAULT"]["comment"] += "\n".join(comments)

return data

def dump_config_data(self, cd=None, cf=None, validation=True):
@@ -1344,24 +1362,27 @@ def dump_config_data(self, cd=None, cf=None, validation=True):
raise ex.excError

makedirs(os.path.dirname(cf))
import rcConfigParser
config = rcConfigParser.RawConfigParser()
lines = []

for section_name, section in cd.items():
if section_name != "DEFAULT":
config.add_section(section_name)
lines.append("[%s]" % section_name)
for key, value in section.items():
config.set(section_name, key, value)
if key != "comment":
lines.append("%s = %s" % (key, value))
else:
lines += map(lambda x: "# "+x if x else "", value.split("\n"))
lines.append("")

try:
buff = "\n".join(lines)
if six.PY2:
with codecs.open(cf, "w", "utf-8") as ofile:
os.chmod(cf, 0o0600)
config.write(ofile)
ofile.write(buff)
else:
with open(cf, "w") as ofile:
os.chmod(cf, 0o0600)
config.write(ofile)
ofile.write(buff)
except Exception as exc:
raise ex.excError("failed to write %s: %s" % (cf, exc))
self.unset_all_lazy()
@@ -998,6 +998,40 @@ def read_cf(fpaths, defaults=None):
raise
return config

def read_cf_comments(fpath):
data = {}
if isinstance(fpath, list):
return data
if not os.path.exists(fpath):
return data
section = ".header"
current = []

import codecs
with codecs.open(fpath, "r", "utf8") as ofile:
buff = ofile.read()

for line in buff.splitlines():
line = line.strip()
if not line:
continue
if re.match("\[.+\]", line):
if current:
data[section] = current
current = []
section = line[1:-1]
continue
if line[0] in (";", "#"):
stripped = line.lstrip("#;").strip()
if re.match("\[.+\]", stripped):
# add an empty line before a commented section
current.append("")
current.append(stripped)
if current:
data[section] = current
current = []
return data

def has_option(option, cmd):
"""
Return True if <option> is set in the <cmd> shlex list.

0 comments on commit af40e7d

Please sign in to comment.
You can’t perform that action at this time.