From b6ddc354b1101e12b31834a7c7d57ab958a33867 Mon Sep 17 00:00:00 2001 From: ivanmatveyev Date: Tue, 27 Aug 2019 11:38:04 +0300 Subject: [PATCH 1/5] a slightly better restore_yaml_comments --- confuse.py | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/confuse.py b/confuse.py index 63efa61..7092763 100644 --- a/confuse.py +++ b/confuse.py @@ -861,29 +861,33 @@ def restore_yaml_comments(data, default_data): Only works with comments that are on one or more own lines, i.e. not next to a yaml mapping. """ - comment_map = dict() - default_lines = iter(default_data.splitlines()) - for line in default_lines: + + def has_comment(line): if not line: - comment = "\n" - elif line.startswith("#"): - comment = "{0}\n".format(line) + return True + elif re.match("^\s*#.*$", line): + return True else: - continue - while True: - line = next(default_lines) - if line and not line.startswith("#"): - break - comment += "{0}\n".format(line) - key = line.split(':')[0].strip() - comment_map[key] = comment - out_lines = iter(data.splitlines()) + return False + + comment = "" out_data = "" - for line in out_lines: - key = line.split(':')[0].strip() - if key in comment_map: - out_data += comment_map[key] - out_data += "{0}\n".format(line) + default_lines = iter(default_data.splitlines()) + out_lines = iter(data.splitlines()) + + for line in default_lines: + if has_comment(line): + comment += "{0}\n".format(line) + else: + out_data += comment + comment = "" + key = line.split(':')[0].strip() + out_line = next(out_lines) + while key != out_line.split(':')[0].strip(): + out_data += "{0}\n".format(out_line) + out_line = next(out_lines) + out_data += "{0}\n".format(out_line) + out_data += comment return out_data From fbc119ce569b00ef1fe8fc3db9006ba2d3668d52 Mon Sep 17 00:00:00 2001 From: ivanmatveyev Date: Tue, 27 Aug 2019 11:59:33 +0300 Subject: [PATCH 2/5] fix for invalid escape sequence '\s' --- confuse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/confuse.py b/confuse.py index 7092763..13616d7 100644 --- a/confuse.py +++ b/confuse.py @@ -865,7 +865,7 @@ def restore_yaml_comments(data, default_data): def has_comment(line): if not line: return True - elif re.match("^\s*#.*$", line): + elif re.match(r'^\s*#.*$', line): return True else: return False From f7efb051eee24c6efea7770ef12799bbf759a711 Mon Sep 17 00:00:00 2001 From: ivanmatveyev Date: Thu, 29 Aug 2019 12:15:49 +0300 Subject: [PATCH 3/5] added test for restore_yaml_comments --- test/test_dump.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/test_dump.py b/test/test_dump.py index e40add7..3054e26 100644 --- a/test/test_dump.py +++ b/test/test_dump.py @@ -59,6 +59,32 @@ def test_dump_sans_defaults(self): yaml = config.dump(full=False).strip() self.assertEqual(yaml, "baz: qux") + def test_restore_yaml_comments(self): + odict = confuse.OrderedDict() + odict['foo'] = 'bar' + odict['bar'] = 'baz' + + config = confuse.Configuration('myapp', read=False) + config.add({'key1': odict}) + config.add({'key2': odict}) + data = config.dump() + default_data = textwrap.dedent(""" + # Comment 1 + key1: + # Comment 2 + foo: bar + bar: baz + + key2: + foo: bar + bar: baz + + # TODO: add more keys + """) + self.assertEqual( + default_data, + confuse.restore_yaml_comments(data, default_data) + ) class RedactTest(unittest.TestCase): def test_no_redaction(self): From 3f8e4eb5e94a4c18c19f03bfbc074a2994ce192b Mon Sep 17 00:00:00 2001 From: ivanmatveyev Date: Thu, 29 Aug 2019 12:20:19 +0300 Subject: [PATCH 4/5] space and blank line for tests --- test/test_dump.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_dump.py b/test/test_dump.py index 3054e26..4cd4362 100644 --- a/test/test_dump.py +++ b/test/test_dump.py @@ -82,10 +82,11 @@ def test_restore_yaml_comments(self): # TODO: add more keys """) self.assertEqual( - default_data, + default_data, confuse.restore_yaml_comments(data, default_data) ) + class RedactTest(unittest.TestCase): def test_no_redaction(self): config = _root({'foo': 'bar'}) From 9eee173612e8ad5d1b93a8da390bfaf0e6ac913f Mon Sep 17 00:00:00 2001 From: ivanmatveyev Date: Thu, 29 Aug 2019 20:27:56 +0300 Subject: [PATCH 5/5] reworked restore_yaml_comments implementation to deal with reordered sections --- confuse.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/confuse.py b/confuse.py index 13616d7..976b79c 100644 --- a/confuse.py +++ b/confuse.py @@ -870,25 +870,25 @@ def has_comment(line): else: return False + comment_map = dict() comment = "" - out_data = "" default_lines = iter(default_data.splitlines()) - out_lines = iter(data.splitlines()) - for line in default_lines: if has_comment(line): comment += "{0}\n".format(line) else: - out_data += comment - comment = "" key = line.split(':')[0].strip() - out_line = next(out_lines) - while key != out_line.split(':')[0].strip(): - out_data += "{0}\n".format(out_line) - out_line = next(out_lines) - out_data += "{0}\n".format(out_line) - out_data += comment - return out_data + if comment != "": + comment_map[key] = comment + comment = "" + out_data = "" + out_lines = iter(data.splitlines()) + for line in out_lines: + key = line.split(':')[0].strip() + if key in comment_map: + out_data += comment_map.pop(key, None) + out_data += "{0}\n".format(line) + return out_data + comment # Main interface.