pvl.dns.zone: add ZoneDirective type
authorTero Marttila <terom@paivola.fi>
Thu, 19 Dec 2013 19:30:23 +0200
changeset 323 9b3cbd8687eb
parent 322 0c3bb9d2f13b
child 324 9b9c662f36b2
pvl.dns.zone: add ZoneDirective type
pvl/dns/zone.py
--- a/pvl/dns/zone.py	Thu Dec 19 18:58:15 2013 +0200
+++ b/pvl/dns/zone.py	Thu Dec 19 19:30:23 2013 +0200
@@ -42,37 +42,39 @@
 
             elif line.line.startswith('$') :
                 # control record
-                args = list(line.parts)
-                directive = args.pop(0)[1:]
+                directive = ZoneDirective.parse(line,
+                        origin      = origin,
+                        comment     = line.comment,
+                )
 
-                if directive == 'ORIGIN' :
+                if directive.directive == 'ORIGIN' :
                     # update
-                    origin, = args
+                    origin, = directive.arguments
                     
                     log.info("%s: origin: %s", line, origin)
                     
                     yield line, None
 
-                elif directive == 'TTL' :
-                    ttl, = args
+                elif directive.directive == 'TTL' :
+                    ttl, = directive.arguments
                     
                     log.info("%s: ttl: %s", line, ttl)
                     
                     yield line, None
                 
-                elif directive == 'GENERATE' :
+                elif directive.directive == 'GENERATE' :
                     if expand_generate :
                         # process...
-                        log.info("%s: generate: %s", line, args)
+                        log.info("%s: generate: %s", line, directive.arguments)
 
-                        for record in process_generate(line, origin, args) :
+                        for record in process_generate(line, origin, directive.arguments) :
                             yield line, record
                     else :
                         yield line, None
 
-                elif directive == 'INCLUDE' :
+                elif directive.directive == 'INCLUDE' :
                     if expand_include :
-                        include, = args
+                        include, = directive.arguments
 
                         path = os.path.join(os.path.dirname(file.name), include)
                         
@@ -84,7 +86,7 @@
                         yield line, None
 
                 else :
-                    log.warn("%s: skip unknown control record: %s", line, line.line)
+                    log.warn("%s: skip unknown control record: %r", line, directive)
                     yield line, None
                 
             else :
@@ -234,6 +236,65 @@
     def __repr__ (self) :
         return "{file}:{lineno}".format(file=self.file, lineno=self.lineno)
 
+class ZoneDirective (object) :
+    """
+        An $DIRECTIVE in a zonefile.
+    """
+    
+    # context
+    line    = None
+    origin  = None
+
+    # fields
+    directive   = None
+    arguments   = None
+    
+    @classmethod
+    def parse (cls, line, **opts) :
+        # control record
+        args = list(line.parts)
+        directive = args[0][1:]
+        arguments = args[1:]
+
+        return cls.build(line, directive, *arguments, **opts)
+
+    @classmethod
+    def build (cls, line, directive, *arguments, **opts) :
+        return cls(directive, arguments,
+                line        = line,
+                **opts
+        )
+
+    def __init__ (self, directive, arguments, line=None, origin=None, comment=None) :
+        self.directive  = directive
+        self.arguments  = arguments
+
+        self.line = line
+        self.origin = origin
+        self.comment = comment
+
+    def __unicode__ (self) :
+        """
+            Construct a zonefile-format line...
+        """
+
+        if self.comment :
+            comment = '\t; ' + self.comment
+        else :
+            comment = ''
+            
+        return u"${directive}\t{arguments}{comment}".format(
+                directive   = self.directive,
+                arguments   = '\t'.join(self.arguments),
+                comment     = comment,
+        )
+
+    def __repr__ (self) :
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(repr(arg) for arg in (
+            (self.directive) + tuple(self.arguments)
+        )))
+
+
 class ZoneRecord (object) :
     """
         A record from a zonefile.
@@ -549,6 +610,8 @@
         directive into a series of ZoneResource's.
     """
 
+    parts = list(parts)
+
     range = parse_generate_range(parts.pop(0))
 
     lhs_func = parse_generate_field(parts.pop(0), line=line)