add inifile add/remove code

This commit is contained in:
Sean Dague 2017-01-16 09:37:39 -05:00
parent 7955f99443
commit 0c14c58913
4 changed files with 259 additions and 1 deletions

70
devstack/dsconf.py Normal file
View File

@ -0,0 +1,70 @@
# 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 re
import shutil
import tempfile
class IniFile(object):
"""Class for manipulating ini files in place."""
def __init__(self, fname):
self.fname = fname
def add(self, section, name, value):
"""add a key / value to an ini file in a section.
The new key value will be added at the beginning of the
section, if no section is found a new section and key value
will be added to the end of the file.
"""
temp = tempfile.NamedTemporaryFile(mode='r')
shutil.copyfile(self.fname, temp.name)
found = False
with open(temp.name) as reader:
with open(self.fname, "w") as writer:
for line in reader.readlines():
writer.write(line)
m = re.match("\[([^\[\]]+)\]", line)
if m and m.group(1) == section:
found = True
writer.write("%s = %s\n" % (name, value))
if not found:
writer.write("[%s]\n" % section)
writer.write("%s = %s\n" % (name, value))
def remove(self, section, name):
"""remove a key / value from an ini file in a section."""
temp = tempfile.NamedTemporaryFile(mode='r')
shutil.copyfile(self.fname, temp.name)
current_section = ""
with open(temp.name) as reader:
with open(self.fname, "w") as writer:
for line in reader.readlines():
m = re.match("\[([^\[\]]+)\]", line)
if m:
current_section = m.group(1)
if current_section == section:
if re.match("%s\s*\=" % name, line):
continue
else:
writer.write(line)
else:
writer.write(line)

View File

@ -0,0 +1,90 @@
# 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
[second]
e = f
g = h
"""
RESULT1 = """[default]
s = t
a = b
c = d
[second]
e = f
g = h
"""
RESULT2 = """[default]
a = b
c = d
[second]
s = t
e = f
g = h
"""
RESULT3 = """[default]
a = b
c = d
[second]
e = f
g = h
[new]
s = t
"""
class TestIniAdd(testtools.TestCase):
def setUp(self):
super(TestIniAdd, 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_add_ini_default(self):
conf = dsconf.IniFile(self._path)
conf.add("default", "s", "t")
with open(self._path) as f:
content = f.read()
self.assertEqual(content, RESULT1)
def test_add_ini_second(self):
conf = dsconf.IniFile(self._path)
conf.add("second", "s", "t")
with open(self._path) as f:
content = f.read()
self.assertEqual(content, RESULT2)
def test_add_ini_new(self):
conf = dsconf.IniFile(self._path)
conf.add("new", "s", "t")
with open(self._path) as f:
content = f.read()
self.assertEqual(content, RESULT3)

View File

@ -0,0 +1,98 @@
# 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
[second]
e = f
g = h
[new]
s = t
"""
RESULT1 = """[default]
c = d
[second]
e = f
g = h
[new]
s = t
"""
RESULT2 = """[default]
a = b
c = d
[second]
e = f
[new]
s = t
"""
RESULT3 = """[default]
a = b
c = d
[second]
e = f
g = h
[new]
"""
class TestIniRemove(testtools.TestCase):
def setUp(self):
super(TestIniRemove, 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_remove_ini_default(self):
conf = dsconf.IniFile(self._path)
conf.remove("default", "a")
with open(self._path) as f:
content = f.read()
self.assertEqual(content, RESULT1)
def test_remove_ini_second(self):
conf = dsconf.IniFile(self._path)
conf.remove("second", "g")
with open(self._path) as f:
content = f.read()
self.assertEqual(content, RESULT2)
def test_remove_ini_new(self):
conf = dsconf.IniFile(self._path)
conf.remove("new", "s")
with open(self._path) as f:
content = f.read()
self.assertEqual(content, RESULT3)
def test_remove_ini_none(self):
conf = dsconf.IniFile(self._path)
conf.remove("default", "s")
with open(self._path) as f:
content = f.read()
self.assertEqual(content, BASIC)

View File

@ -7,10 +7,10 @@ hacking>=0.12.0,<0.13 # Apache-2.0
coverage>=4.0 # Apache-2.0
python-subunit>=0.0.18 # Apache-2.0/BSD
sphinx>=1.2.1,!=1.3b1,<1.4 # BSD
fixtures
oslosphinx>=4.7.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
testrepository>=0.0.18 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD
testtools>=1.4.0 # MIT
# releasenotes