# HG changeset patch # User Tero Marttila # Date 1238695861 -10800 # Node ID ff98fa9b84ce30e14bf13746f8fb5511690a71b4 # Parent e66102ab7048c3548d8322bc525da9dff23602f6 implement comments properly diff -r e66102ab7048 -r ff98fa9b84ce conf.py --- a/conf.py Thu Apr 02 20:54:37 2009 +0300 +++ b/conf.py Thu Apr 02 21:11:01 2009 +0300 @@ -9,6 +9,22 @@ An object that can be written to a ConfFile, as multiple lines of text. """ + def __init__ (self, comments=None) : + """ + Initialize with the given list of comments. Comments that are None should be ignore. + """ + + # init the comments list + self.comments = comments or [] + + def add_comment (self, comment) : + """ + Add a comment to be rendered in the output. + """ + + # add it + self.comments.append(comment) + def fmt_lines (self) : """ Yield a series of lines to be output in the file diff -r e66102ab7048 -r ff98fa9b84ce dhcp_conf.py --- a/dhcp_conf.py Thu Apr 02 20:54:37 2009 +0300 +++ b/dhcp_conf.py Thu Apr 02 21:11:01 2009 +0300 @@ -6,12 +6,24 @@ import itertools -class Comment (conf.ConfObject) : +class Object (conf.ConfObject) : + """ + Our version of ConfObject + """ + + def _fmt_comments (self) : + """ + Format our comment lines + """ + + for comment in self.comments : + if comment is not None : + yield "# %s" % (comment, ) + + +class Comment (Object) : """ A comment, is, well, a comment :) - - Currently, comments are only one line, and look like the following: - "#" """ def __init__ (self, comment) : @@ -19,18 +31,18 @@ @param comment the comment string """ - self.comment = comment + Object.__init__(self, [comment]) def fmt_lines (self) : """ Yield a single line with the comment """ - yield "# %s" % (self.comment, ) + return self._fmt_comments() -class Section (conf.ConfObject) : +class _Section (Object) : """ - A section holds a list of params and a list of decls + Base implementation of Section, but doesn't format comments in output (inheriting class can define how that happens) """ def __init__ (self, params=None, decls=None, comment=None) : @@ -39,10 +51,11 @@ If a comment is given, then it will be formatted before the section's stuff """ + + Object.__init__(self, [comment]) self.params = params or [] self.decls = decls or [] - self.comment = comment def add_param (self, param) : """ @@ -66,23 +79,11 @@ 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 @@ -92,6 +93,24 @@ for line in stmt.fmt_lines() : yield line +class Section (_Section) : + """ + A section holds a list of params and a list of decls, plus some comments at the beginning of the section + """ + + def fmt_lines (self) : + """ + Format all of our comments, and then super + """ + + # comments + for line in self._fmt_comments() : + yield line + + # section stuff + for line in _Section.fmt_lines(self) : + yield line + class ConfFile (Section, conf.File) : DEFAULT_NAME = "dhcpd.conf" DEFAULT_PATH = "/etc/dhcp3/dhcpd.conf" @@ -104,16 +123,22 @@ conf.File.__init__(self, name, path) Section.__init__(self, params, decls) -class Statement (conf.ConfObject) : +class Statement (Object) : """ A statement is a single line in the config file """ - def __init__ (self, name, *args) : + def __init__ (self, name, *args, **kwargs) : """ Arguments given as None will be ignored. + + A comment can be given as a keyword argument """ + if kwargs : assert len(kwargs) == 1 and 'comment' in kwargs + + Object.__init__(self, [kwargs.get('comment')]) + self.name = name self.args = [arg for arg in args if arg is not None] @@ -186,10 +211,15 @@ """ Yields a single ;-terminated line """ - + + # comments + for line in self._fmt_comments() : + yield line + + # the line yield "%s;" % self._fmt_data() -class Declaration (Section, Statement) : +class Declaration (_Section, Statement) : """ A declaration begins like a statement (with name and args), but then contains a curly-braces-delimited block that acts like a Section. @@ -200,26 +230,30 @@ """ - def __init__ (self, name, args=[], params=None, decls=None) : + def __init__ (self, name, args=[], params=None, decls=None, comment=None) : """ The name/args will be formatted as in Statement, but params should be an iterable of Parameters, and decls an iterable of Declarations. """ # init the statement bit - Section.__init__(self, params, decls) - Statement.__init__(self, name, *args) + _Section.__init__(self, params, decls) + Statement.__init__(self, name, *args, **dict(comment=comment)) def fmt_lines (self) : """ Yields a header line, a series of indented body lines, and the footer line """ + # comments + for line in self._fmt_comments() : + yield line + # the header to open the block yield "%s {" % self._fmt_data() # then output the section stuff, indented - for line in Section.fmt_lines(self) : + for line in _Section.fmt_lines(self) : yield "\t%s" % line # and then close the block diff -r e66102ab7048 -r ff98fa9b84ce test_dhcp.py --- a/test_dhcp.py Thu Apr 02 20:54:37 2009 +0300 +++ b/test_dhcp.py Thu Apr 02 21:11:01 2009 +0300 @@ -53,6 +53,7 @@ def test_parameter (self) : self.assert_obj(dhcpc.Parameter("param0", "this", 13, "that"), [ "param0 this 13 that;" ]) + self.assert_obj(dhcpc.Parameter("param1", comment="testing"), [ "# testing", "param1;" ]) def test_declaration (self) : self.assert_obj(dhcpc.Declaration("decl0", ["arg0", "arg1"], [ @@ -62,8 +63,8 @@ dhcpc.Declaration("decl0.0", params=[ dhcpc.Parameter("param0.0.1", "value") ]) - ]), [ - + ], comment="foo"), [ + "# foo", "decl0 arg0 arg1 {", "\tparam0;", "\tdecl0.0 {",