fix up data.load_py, and make conf.File be a ConfObject itself - implement this for dhcp_conf
--- a/data.py Thu Apr 02 20:19:18 2009 +0300
+++ b/data.py Thu Apr 02 20:54:37 2009 +0300
@@ -4,20 +4,13 @@
import imp
-def load_py (path) :
+def load_py (name, path) :
"""
- Load a python file from the given filesystem path, returning the module itself
+ Load a python file from the given filesystem path, returning the module itself.
+
+ The "name" of the module must be given, it should be something sane and unique...
"""
- # XXX: what name to use?
- name = "hosts"
+ # just load it and return
+ return imp.load_source(name, path)
- # find the module
- file, pathname, info = imp.find_module(name, [path])
-
- # load it
- module = imp.load_module(name, file, pathname, info)
-
- # ok
- return module
-
--- a/dhcp_conf.py Thu Apr 02 20:19:18 2009 +0300
+++ b/dhcp_conf.py Thu Apr 02 20:54:37 2009 +0300
@@ -6,18 +6,43 @@
import itertools
+class Comment (conf.ConfObject) :
+ """
+ A comment, is, well, a comment :)
+
+ Currently, comments are only one line, and look like the following:
+ "#" <comment>
+ """
+
+ def __init__ (self, comment) :
+ """
+ @param comment the comment string
+ """
+
+ self.comment = comment
+
+ def fmt_lines (self) :
+ """
+ Yield a single line with the comment
+ """
+
+ yield "# %s" % (self.comment, )
+
class Section (conf.ConfObject) :
"""
A section holds a list of params and a list of decls
"""
- def __init__ (self, params=None, decls=None) :
+ def __init__ (self, params=None, decls=None, comment=None) :
"""
If params/decls are given, those are the used as the initial contents of this section
+
+ If a comment is given, then it will be formatted before the section's stuff
"""
self.params = params or []
self.decls = decls or []
+ self.comment = comment
def add_param (self, param) :
"""
@@ -41,11 +66,23 @@
for decl in decls :
self.add_decl(decl)
+ def _fmt_comment (self) :
+ """
+ Format our comment line
+ """
+
+ return "# %s" % (self.comment, )
+
+
def fmt_lines (self) :
"""
Format all of our params and decls, in that order
"""
+ # comment?
+ if self.comment :
+ yield self._fmt_comment()
+
# then output each content line
for stmt in itertools.chain(self.params, self.decls) :
# skip Nones
@@ -74,14 +111,11 @@
def __init__ (self, name, *args) :
"""
- The statement will be formatted like this:
- <name> [ <arg> [ ... ] ] ";"
-
Arguments given as None will be ignored.
"""
self.name = name
- self.args = args
+ self.args = [arg for arg in args if arg is not None]
def _fmt_arg (self, arg) :
"""
@@ -121,7 +155,7 @@
Formats the statement name/params as a single line, ignoring None
"""
- return "%s%s" % (self.name, (' ' + ' '.join(self._fmt_arg(a) for a in self.args if a is not None)) if self.args else '')
+ return "%s%s" % (self.name, (' ' + ' '.join(self._fmt_arg(a) for a in self.args)) if self.args else '')
class Literal (Statement) :
"""
@@ -143,6 +177,9 @@
Parameters have a name, and optionally, a number of arguments, and are formatted as statements terminated with
a semicolon. For convenience, params/decls that are None are ignored.
+
+ The parameter will be formatted like this:
+ <name> [ <arg> [ ... ] ] ";"
"""
def fmt_lines (self) :
--- a/main.py Thu Apr 02 20:19:18 2009 +0300
+++ b/main.py Thu Apr 02 20:54:37 2009 +0300
@@ -51,7 +51,7 @@
options, (data_file, ) = parse_args(argv)
# load the data
- data_module = data.load_py(data_file)
+ data_module = data.load_py('pvl_hosts_data', data_file)
# write out the config files
write_dhcp(options, data_module)
--- a/test_dhcp.py Thu Apr 02 20:19:18 2009 +0300
+++ b/test_dhcp.py Thu Apr 02 20:54:37 2009 +0300
@@ -3,19 +3,42 @@
Test conf_dhcp
"""
-import dhcp_conf as dhcpc, conf, addr
+import dhcp_conf as dhcpc, dhcp, addr
import unittest
-from cStringIO import StringIO
-class TestConfDHCP (unittest.TestCase) :
+class _TestConfObj (unittest.TestCase) :
+ def assert_obj (self, obj, lines) :
+ """
+ Formats the given conf.Object and compares the output against the given lines
+ """
+
+ for obj_line, line in zip(obj.fmt_lines(), lines) :
+ self.assertEqual(obj_line, line)
+
+class TestDHCPConf (_TestConfObj) :
def assert_stmt (self, stmt, line) :
"""
- Formats the given Statement, and compares the output against the given line
+ Formats the given Statement, and compares the output against the given line.
+
+ Note that the dhcpc.Statement doesn't have a working fmt_lines implementation.
"""
self.assertEqual(stmt._fmt_data(), line)
+ def test_comment (self) :
+ self.assert_obj(dhcpc.Comment("foo bar"), [ "# foo bar" ])
+
+ def test_section (self) :
+ self.assert_obj(dhcpc.Section(comment="test"), [ "# test" ])
+
+ self.assert_obj(dhcpc.Section(params=[
+ dhcpc.Parameter("param0"), None
+ ], comment="foo"), [
+ "# foo",
+ "param0;",
+ ])
+
def test_statement (self) :
self.assert_stmt(dhcpc.Statement("stmt0"), "stmt0")
self.assert_stmt(dhcpc.Statement("stmt1", [ "this", "that" ]), "stmt1 this, that")
@@ -24,14 +47,7 @@
self.assert_stmt(dhcpc.Statement("stmt4", "bar"), "stmt4 bar")
self.assert_stmt(dhcpc.Statement("stmt5", 1), "stmt5 1")
self.assert_stmt(dhcpc.Statement("stmt6", 1, None, 2), "stmt6 1 2")
-
- def assert_obj (self, obj, lines) :
- """
- Formats the given conf.Object and compares the output against the given lines
- """
-
- self.assertEqual(list(obj.fmt_lines()), lines)
-
+
def test_literal (self) :
self.assert_obj(dhcpc.Literal("///"), [ "///" ])
@@ -101,6 +117,55 @@
"option foo example.com;",
])
+class TestDHCP (_TestConfObj) :
+ def test_host (self) :
+ self.assert_obj(dhcp.Host("testhost", addr.MAC("12:34:56:78:90:ab"), addr.IP("1.2.3.4")), [
+ "host testhost {",
+ "\thardware ethernet 12:34:56:78:90:ab;",
+ "\tfixed-address 1.2.3.4;",
+ "}"
+ ])
+
+ def test_subnet (self) :
+ self.assert_obj(dhcp.Subnet(addr.Network("1.2.3.0/24")), [
+ "subnet 1.2.3.0 netmask 255.255.255.0 {",
+ "\toption routers 1.2.3.1;",
+ "}"
+ ])
+
+ self.assert_obj(dhcp.Subnet(addr.Network("1.2.3.0/24"), router_idx=10, range=(20, 30), unknown_clients='allow'), [
+ "subnet 1.2.3.0 netmask 255.255.255.0 {",
+ "\toption routers 1.2.3.10;",
+ "\trange 1.2.3.20 1.2.3.30;",
+ "\tallow unknown-clients;",
+ "}"
+ ])
+
+ def test_config (self) :
+ self.assert_obj(dhcp.Config(
+ settings = { 'foo-setting': 'someval' },
+ options = { 'bar-opt': ['one', 'two'] },
+ shared_network = "FOO-NET",
+ subnets = [
+ dhcp.Subnet(addr.Network("1.2.3.0/24"))
+ ],
+ hosts = [
+ dhcp.Host("testhost", addr.MAC("12:34:56:78:90:ab"), addr.IP("1.2.3.4"))
+ ],
+ ), [
+ "foo-setting someval;",
+ "option bar-opt one, two;",
+ "shared-network FOO-NET {",
+ "\tsubnet 1.2.3.0 netmask 255.255.255.0 {",
+ "\t\toption routers 1.2.3.1;",
+ "\t}",
+ "}",
+ "host testhost {",
+ "\thardware ethernet 12:34:56:78:90:ab;",
+ "\tfixed-address 1.2.3.4;",
+ "}"
+ ])
+
if __name__ == '__main__' :
unittest.main()