From 79f8f551c3925933203b3079d85b6aca658c51be Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Mon, 16 Jan 2017 10:18:53 -0500 Subject: [PATCH] add uncomment function --- devstack/dsconf.py | 10 ++- devstack/tests/test_ini_uncomment.py | 113 +++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 devstack/tests/test_ini_uncomment.py diff --git a/devstack/dsconf.py b/devstack/dsconf.py index f9ba066..597fe9b 100644 --- a/devstack/dsconf.py +++ b/devstack/dsconf.py @@ -64,7 +64,7 @@ class IniFile(object): writer.write("[%s]\n" % section) writer.write("%s = %s\n" % (name, value)) - def _at_existing_key(self, section, name, func): + def _at_existing_key(self, section, name, func, match="%s\s*\="): temp = tempfile.NamedTemporaryFile(mode='r') shutil.copyfile(self.fname, temp.name) current_section = "" @@ -75,7 +75,7 @@ class IniFile(object): if m: current_section = m.group(1) if current_section == section: - if re.match("%s\s*\=" % name, line): + if re.match(match % name, line): # run function with writer and found line func(writer, line) else: @@ -98,6 +98,12 @@ class IniFile(object): self._at_existing_key(section, name, _do_comment) + def uncomment(self, section, name): + def _do_uncomment(writer, line): + writer.write(re.sub("^#\s*", "", line)) + + self._at_existing_key(section, name, _do_uncomment, match="#\s*%s\s*\=") + def set(self, section, name, value): def _do_set(writer, line): writer.write("%s = %s\n" % (name, value)) diff --git a/devstack/tests/test_ini_uncomment.py b/devstack/tests/test_ini_uncomment.py new file mode 100644 index 0000000..9064762 --- /dev/null +++ b/devstack/tests/test_ini_uncomment.py @@ -0,0 +1,113 @@ +# Copyright 2017 IBM +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +# Implementation of ini add / remove for devstack. We don't use the +# python ConfigFile parser because that ends up rewriting the entire +# file and doesn't ensure comments remain. + +import fixtures +import testtools + +from devstack import dsconf + + +BASIC = """[default] +a = b +c = d +# f = 1 +[second] +e = f +g = h +# h = 2 +[new] +s = t +# x = 3 +""" + +RESULT1 = """[default] +a = b +c = d +f = 1 +[second] +e = f +g = h +# h = 2 +[new] +s = t +# x = 3 +""" + +RESULT2 = """[default] +a = b +c = d +# f = 1 +[second] +e = f +g = h +h = 2 +[new] +s = t +# x = 3 +""" + +RESULT3 = """[default] +a = b +c = d +# f = 1 +[second] +e = f +g = h +# h = 2 +[new] +s = t +x = 3 +""" + + +class TestIniUncomment(testtools.TestCase): + + def setUp(self): + super(TestIniUncomment, self).setUp() + self._path = self.useFixture(fixtures.TempDir()).path + self._path += "/test.ini" + with open(self._path, "w") as f: + f.write(BASIC) + + def test_uncomment_ini_default(self): + conf = dsconf.IniFile(self._path) + conf.uncomment("default", "f") + with open(self._path) as f: + content = f.read() + self.assertEqual(content, RESULT1) + + def test_uncomment_ini_second(self): + conf = dsconf.IniFile(self._path) + conf.uncomment("second", "h") + with open(self._path) as f: + content = f.read() + self.assertEqual(content, RESULT2) + + def test_uncomment_ini_new(self): + conf = dsconf.IniFile(self._path) + conf.uncomment("new", "x") + with open(self._path) as f: + content = f.read() + self.assertEqual(content, RESULT3) + + def test_uncomment_ini_none(self): + conf = dsconf.IniFile(self._path) + conf.uncomment("default", "s") + with open(self._path) as f: + content = f.read() + self.assertEqual(content, BASIC)