summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Dague <sean@dague.net>2017-01-16 09:37:39 -0500
committerSean Dague <sean@dague.net>2017-01-16 09:37:39 -0500
commit0c14c589133db28f041c641eea08bd2f25fb610b (patch)
tree289455de7126b73cb579a9790881f3fa6d3cf6f4
parent7955f99443e1a22950bfc4a59f22795062ec616e (diff)
add inifile add/remove code
-rw-r--r--devstack/dsconf.py70
-rw-r--r--devstack/tests/test_ini_add.py90
-rw-r--r--devstack/tests/test_ini_remove.py98
-rw-r--r--test-requirements.txt2
4 files changed, 259 insertions, 1 deletions
diff --git a/devstack/dsconf.py b/devstack/dsconf.py
new file mode 100644
index 0000000..b31e221
--- /dev/null
+++ b/devstack/dsconf.py
@@ -0,0 +1,70 @@
1# Copyright 2017 IBM
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15# Implementation of ini add / remove for devstack. We don't use the
16# python ConfigFile parser because that ends up rewriting the entire
17# file and doesn't ensure comments remain.
18
19import re
20import shutil
21import tempfile
22
23
24class IniFile(object):
25 """Class for manipulating ini files in place."""
26
27 def __init__(self, fname):
28 self.fname = fname
29
30 def add(self, section, name, value):
31 """add a key / value to an ini file in a section.
32
33 The new key value will be added at the beginning of the
34 section, if no section is found a new section and key value
35 will be added to the end of the file.
36 """
37 temp = tempfile.NamedTemporaryFile(mode='r')
38 shutil.copyfile(self.fname, temp.name)
39 found = False
40 with open(temp.name) as reader:
41 with open(self.fname, "w") as writer:
42 for line in reader.readlines():
43 writer.write(line)
44 m = re.match("\[([^\[\]]+)\]", line)
45 if m and m.group(1) == section:
46 found = True
47 writer.write("%s = %s\n" % (name, value))
48 if not found:
49 writer.write("[%s]\n" % section)
50 writer.write("%s = %s\n" % (name, value))
51
52 def remove(self, section, name):
53 """remove a key / value from an ini file in a section."""
54
55 temp = tempfile.NamedTemporaryFile(mode='r')
56 shutil.copyfile(self.fname, temp.name)
57 current_section = ""
58 with open(temp.name) as reader:
59 with open(self.fname, "w") as writer:
60 for line in reader.readlines():
61 m = re.match("\[([^\[\]]+)\]", line)
62 if m:
63 current_section = m.group(1)
64 if current_section == section:
65 if re.match("%s\s*\=" % name, line):
66 continue
67 else:
68 writer.write(line)
69 else:
70 writer.write(line)
diff --git a/devstack/tests/test_ini_add.py b/devstack/tests/test_ini_add.py
new file mode 100644
index 0000000..2654e3e
--- /dev/null
+++ b/devstack/tests/test_ini_add.py
@@ -0,0 +1,90 @@
1# Copyright 2017 IBM
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15# Implementation of ini add / remove for devstack. We don't use the
16# python ConfigFile parser because that ends up rewriting the entire
17# file and doesn't ensure comments remain.
18
19import fixtures
20import testtools
21
22from devstack import dsconf
23
24
25BASIC = """[default]
26a = b
27c = d
28[second]
29e = f
30g = h
31"""
32
33RESULT1 = """[default]
34s = t
35a = b
36c = d
37[second]
38e = f
39g = h
40"""
41
42RESULT2 = """[default]
43a = b
44c = d
45[second]
46s = t
47e = f
48g = h
49"""
50
51RESULT3 = """[default]
52a = b
53c = d
54[second]
55e = f
56g = h
57[new]
58s = t
59"""
60
61
62class TestIniAdd(testtools.TestCase):
63
64 def setUp(self):
65 super(TestIniAdd, self).setUp()
66 self._path = self.useFixture(fixtures.TempDir()).path
67 self._path += "/test.ini"
68 with open(self._path, "w") as f:
69 f.write(BASIC)
70
71 def test_add_ini_default(self):
72 conf = dsconf.IniFile(self._path)
73 conf.add("default", "s", "t")
74 with open(self._path) as f:
75 content = f.read()
76 self.assertEqual(content, RESULT1)
77
78 def test_add_ini_second(self):
79 conf = dsconf.IniFile(self._path)
80 conf.add("second", "s", "t")
81 with open(self._path) as f:
82 content = f.read()
83 self.assertEqual(content, RESULT2)
84
85 def test_add_ini_new(self):
86 conf = dsconf.IniFile(self._path)
87 conf.add("new", "s", "t")
88 with open(self._path) as f:
89 content = f.read()
90 self.assertEqual(content, RESULT3)
diff --git a/devstack/tests/test_ini_remove.py b/devstack/tests/test_ini_remove.py
new file mode 100644
index 0000000..9472270
--- /dev/null
+++ b/devstack/tests/test_ini_remove.py
@@ -0,0 +1,98 @@
1# Copyright 2017 IBM
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15# Implementation of ini add / remove for devstack. We don't use the
16# python ConfigFile parser because that ends up rewriting the entire
17# file and doesn't ensure comments remain.
18
19import fixtures
20import testtools
21
22from devstack import dsconf
23
24
25BASIC = """[default]
26a = b
27c = d
28[second]
29e = f
30g = h
31[new]
32s = t
33"""
34
35RESULT1 = """[default]
36c = d
37[second]
38e = f
39g = h
40[new]
41s = t
42"""
43
44RESULT2 = """[default]
45a = b
46c = d
47[second]
48e = f
49[new]
50s = t
51"""
52
53RESULT3 = """[default]
54a = b
55c = d
56[second]
57e = f
58g = h
59[new]
60"""
61
62
63class TestIniRemove(testtools.TestCase):
64
65 def setUp(self):
66 super(TestIniRemove, self).setUp()
67 self._path = self.useFixture(fixtures.TempDir()).path
68 self._path += "/test.ini"
69 with open(self._path, "w") as f:
70 f.write(BASIC)
71
72 def test_remove_ini_default(self):
73 conf = dsconf.IniFile(self._path)
74 conf.remove("default", "a")
75 with open(self._path) as f:
76 content = f.read()
77 self.assertEqual(content, RESULT1)
78
79 def test_remove_ini_second(self):
80 conf = dsconf.IniFile(self._path)
81 conf.remove("second", "g")
82 with open(self._path) as f:
83 content = f.read()
84 self.assertEqual(content, RESULT2)
85
86 def test_remove_ini_new(self):
87 conf = dsconf.IniFile(self._path)
88 conf.remove("new", "s")
89 with open(self._path) as f:
90 content = f.read()
91 self.assertEqual(content, RESULT3)
92
93 def test_remove_ini_none(self):
94 conf = dsconf.IniFile(self._path)
95 conf.remove("default", "s")
96 with open(self._path) as f:
97 content = f.read()
98 self.assertEqual(content, BASIC)
diff --git a/test-requirements.txt b/test-requirements.txt
index 4a7d204..794a973 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -7,10 +7,10 @@ hacking>=0.12.0,<0.13 # Apache-2.0
7coverage>=4.0 # Apache-2.0 7coverage>=4.0 # Apache-2.0
8python-subunit>=0.0.18 # Apache-2.0/BSD 8python-subunit>=0.0.18 # Apache-2.0/BSD
9sphinx>=1.2.1,!=1.3b1,<1.4 # BSD 9sphinx>=1.2.1,!=1.3b1,<1.4 # BSD
10fixtures
10oslosphinx>=4.7.0 # Apache-2.0 11oslosphinx>=4.7.0 # Apache-2.0
11oslotest>=1.10.0 # Apache-2.0 12oslotest>=1.10.0 # Apache-2.0
12testrepository>=0.0.18 # Apache-2.0/BSD 13testrepository>=0.0.18 # Apache-2.0/BSD
13testscenarios>=0.4 # Apache-2.0/BSD
14testtools>=1.4.0 # MIT 14testtools>=1.4.0 # MIT
15 15
16# releasenotes 16# releasenotes