pvl/dhcp/config.py
author Tero Marttila <terom@paivola.fi>
Mon, 02 Mar 2015 00:19:39 +0200
changeset 675 f1335a4301d0
parent 673 0eda16e29613
child 679 31adba0f586d
permissions -rw-r--r--
pvl.dhcp.config: loosen up TOKEN even further to permit unquoted IP addresses and ethernet addresses
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
     1
import logging; log = logging.getLogger('pvl.dhcp.config')
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
     2
import shlex
673
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
     3
import string
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
     4
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
     5
# simplified model of lexer chars
675
f1335a4301d0 pvl.dhcp.config: loosen up TOKEN even further to permit unquoted IP addresses and ethernet addresses
Tero Marttila <terom@paivola.fi>
parents: 673
diff changeset
     6
TOKEN = string.ascii_letters + string.digits + '-_.:'
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     7
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
     8
class DHCPConfigError(Exception):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
     9
    def __init__ (self, parser, error, line=None):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    10
        self.parser = parser
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    11
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    12
        self.name = parser.name
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    13
        self.line = line
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    14
        self.error = error
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    15
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    16
    def __str__ (self):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    17
        return "{self.name}:{self.line}: {self.error}".format(self=self)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    18
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    19
def split (line) :
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    20
    """
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    21
        Split given line-data into raw tokens.
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    22
        
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    23
        >>> list(split('foo'))
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    24
        ['foo']
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    25
        >>> list(split('foo bar'))
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    26
        ['foo', 'bar']
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    27
        >>> list(split('foo;'))
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    28
        ['foo', ';']
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    29
        >>> list(split('"foo"'))
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    30
        ['foo']
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    31
        >>> list(split('foo "asdf quux" bar'))
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    32
        ['foo', 'asdf quux', 'bar']
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    33
        >>> list(split('foo "asdf quux"'))
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    34
        ['foo', 'asdf quux']
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    35
        >>> list(split('# nevermind'))
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    36
        []
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    37
        >>> list(split(''))
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    38
        []
673
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    39
        >>> list(split('next-server foo'))
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    40
        ['next-server', 'foo']
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    41
        >>> list(split('include "foo/bar.conf";'))
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    42
        ['include', 'foo/bar.conf', ';']
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    43
    """
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    44
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    45
    if line is None:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    46
        raise TypeError(line)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    47
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    48
    lexer = shlex.shlex(line, posix=True)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    49
    lexer.commenters = '#'
673
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    50
    lexer.wordchars = TOKEN
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    51
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    52
    while True:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    53
        item = lexer.get_token()
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    54
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    55
        if item is None:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    56
            break
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    57
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    58
        yield item
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    59
673
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    60
def quote (value):
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    61
    """
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    62
        Build a single field as part of a dhcp.conf line.
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    63
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    64
        >>> print quote('foo')
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    65
        foo
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    66
        >>> print quote('foo bar')
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    67
        "foo bar"
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    68
        >>> print quote('foo/bar.conf')
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    69
        "foo/bar.conf"
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    70
        >>> print quote(5)
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    71
        5
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    72
        >>> print quote('5')
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    73
        "5"
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    74
    """
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    75
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    76
    if isinstance(value, int):
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    77
        return str(value)
675
f1335a4301d0 pvl.dhcp.config: loosen up TOKEN even further to permit unquoted IP addresses and ethernet addresses
Tero Marttila <terom@paivola.fi>
parents: 673
diff changeset
    78
    elif all(c in TOKEN for c in value):
673
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    79
        return str(value)
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    80
    else:
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    81
        # quoted
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    82
        return '"{value}"'.format(value=value)
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
    83
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    84
class Block (object):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    85
    """
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    86
        A block in a dhcp conf includes parameters and sub-blocks.
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    87
    """
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    88
668
794f943c835d pvl.dhcp.config: Block(comment=...)
Tero Marttila <terom@paivola.fi>
parents: 666
diff changeset
    89
    def __init__ (self, key, items=None, blocks=None, comment=None):
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    90
        """
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    91
            key: tuple      - name of block
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    92
        """
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    93
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    94
        self.key = key
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    95
        self.items = items or [ ]
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    96
        self.blocks = blocks or [ ]
668
794f943c835d pvl.dhcp.config: Block(comment=...)
Tero Marttila <terom@paivola.fi>
parents: 666
diff changeset
    97
        self.comment = comment
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    98
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
    99
    def __str__ (self):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   100
        return ' '.join(self.key)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   101
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   102
    def __repr__ (self):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   103
        return "Block({self.key!r}, items={self.items!r}, blocks={self.blocks!r}".format(self=self)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   104
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   105
class DHCPConfigParser (object):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   106
    """
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   107
        Simple parser for ISC dhcpd conf files.
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   108
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   109
        Supports iterative parsing as required for following a dhcpd.leases file.
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   110
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   111
        Doesn't implement the full spec, but a useful approximation.
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   112
    """
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   113
256
63b285ceae41 pvl.dhcp.config: nested blocks
Tero Marttila <terom@paivola.fi>
parents: 255
diff changeset
   114
    @classmethod
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   115
    def load (cls, file, name=None):
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   116
        """
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   117
            Parse an complete file, returning the top-level Block.
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   118
673
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
   119
            >>> DHCPConfigParser.load(['foo;', 'bar {', '\tasdf "quux";', '}'], name='test')
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   120
            Block(None, items=[('foo', )], blocks=[Block(('bar', ), items=[('asdf', 'quux')], blocks=[])])
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   121
        """
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   122
        
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   123
        if name is None:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   124
            name = file.name
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   125
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   126
        parser = cls(name=name)
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   127
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   128
        for lineno, line in enumerate(file, 1):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   129
            try:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   130
                for item in parser.parse_line(line):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   131
                    log.debug("%s", item)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   132
            except DHCPConfigError as error:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   133
                error.line = lineno
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   134
                raise
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   135
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   136
        if parser.token:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   137
            raise DHCPConfError(parser, "Trailing data: {token}".format(token=token), line=lineno)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   138
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   139
        return parser.block 
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   140
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   141
    def __init__ (self, name=None):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   142
        self.name = name
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   143
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   144
        # lexer state
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   145
        self.token = []
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   146
        
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   147
        # parser state
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   148
        self.stack = []
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   149
        
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   150
        # top-level block
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   151
        self.block = Block(None)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   152
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   153
    def lex (self, line):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   154
        """
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   155
            Lex one line of input into basic expressions:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   156
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   157
                open:   [...] {
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   158
                item:       [..];
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   159
                close:  [] }
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   160
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   161
            Yields (event, (...)) tokens.
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   162
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   163
            Raises DHCPConfError.
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   164
        """
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   165
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   166
        log.debug("%s", line)
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   167
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   168
        for word in split(line):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   169
            if word == '{':
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   170
                yield 'open', tuple(self.token)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   171
            
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   172
            elif word == ';':
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   173
                yield 'item', tuple(self.token)
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   174
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   175
            elif word == '}':
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   176
                if self.token:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   177
                    raise DHCPConfError(self, "Leading data on close: {token}".format(token=self.token))
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   178
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   179
                yield 'close', None
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   180
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   181
            else:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   182
                self.token.append(word)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   183
                continue
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   184
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   185
            self.token = [ ]
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   186
       
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   187
    def parse (self, tokens):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   188
        """
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   189
            Parse given tokens, yielding any complete Blocks.
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   190
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   191
            Note that the Blocks yielded may be within some other Block which is still incomplete.
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   192
        """
256
63b285ceae41 pvl.dhcp.config: nested blocks
Tero Marttila <terom@paivola.fi>
parents: 255
diff changeset
   193
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   194
        for token, args in tokens:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   195
            if token == 'open':
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   196
                block = Block(args)
256
63b285ceae41 pvl.dhcp.config: nested blocks
Tero Marttila <terom@paivola.fi>
parents: 255
diff changeset
   197
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   198
                log.debug("open block: %s > %s", self.block, block)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   199
                
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   200
                self.block.blocks.append(block)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   201
                self.block = block
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   202
                self.stack.append(block)
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   203
            
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   204
            # must be within block!
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   205
            elif token == 'item' :
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   206
                log.debug("block %s item: %s", self.block, args)
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   207
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   208
                self.block.items.append(args)
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   209
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   210
            elif token == 'close' :
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   211
                log.debug("close block: %s", self.block)
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   212
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   213
                block = self.block
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   214
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   215
                if self.stack:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   216
                    self.block = self.stack.pop()
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   217
                else:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   218
                    raise DHCPConfigError(self, "Mismatched block close: {block}".format(block=block))
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   219
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   220
                yield block
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   221
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   222
            else:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   223
                raise ValueError(token, args)
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   224
    
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   225
    def parse_line (self, line):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   226
        """
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   227
            Lex and parse line tokens.
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   228
        """
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   229
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   230
        for block in self.parse(self.lex(line)):
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   231
            yield block
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   232
255
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   233
    def parse_lines (self, lines) :
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   234
        """
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   235
            Trivial wrapper around parse to parse multiple lines.
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   236
        """
d14eda12d966 split pvl.dhcp.config.DHCPConfigParser
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   237
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   238
        for line in lines:
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   239
            for block in self.parse_line(line) :
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   240
                yield block
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   241
    
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   242
def build_line (item, end, indent=0):
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   243
    """
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   244
        Build a structured line.
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   245
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   246
        >>> print build_line(['foo'], ';')
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   247
        foo;
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   248
        >>> print build_line(['host', 'foo'], ' {')
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   249
        host foo {
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   250
        >>> print build_line(['foo', 'bar quux'], ';', indent=1)
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   251
            foo "bar quux";
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   252
    """
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   253
673
0eda16e29613 pvl.dhcp.config: stricter quoting of e.g. include file paths
Tero Marttila <terom@paivola.fi>
parents: 668
diff changeset
   254
    return '    '*indent + ' '.join(quote(field) for field in item) + end
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   255
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   256
def build_item (item, **opts):
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   257
    """
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   258
        Build a single parameter line.
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   259
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   260
        >>> print build_item(['foo'])
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   261
        foo;
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   262
    """
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   263
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   264
    return build_line(item, end=';', **opts)
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   265
668
794f943c835d pvl.dhcp.config: Block(comment=...)
Tero Marttila <terom@paivola.fi>
parents: 666
diff changeset
   266
def build_block (block, indent=0):
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   267
    """
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   268
        Build a complete Block, recursively, yielding output lines.
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   269
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   270
        >>> for line in build_block(Block(('host', 'foo'), [('hardware', 'ethernet', '00:11:22:33:44:55')]), comment="Testing"): print line
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   271
        # Testing
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   272
        host foo {
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   273
            hardware ethernet 00:11:22:33:44:55;
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   274
        }
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   275
        >>> for line in build_block(Block(('group', ), [('next-server', 'booter')], [ \
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   276
                    (('host', 'foo'), [('hardware', 'ethernet', '00:11:22:33:44:55')], ()) \
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   277
                ])): print line
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   278
        group {
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   279
            next-server booter;
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   280
        <BLANKLINE>
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   281
            host foo {
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   282
                hardware ethernet 00:11:22:33:44:55;
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   283
            }
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   284
        }
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   285
    """
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   286
668
794f943c835d pvl.dhcp.config: Block(comment=...)
Tero Marttila <terom@paivola.fi>
parents: 666
diff changeset
   287
    if block.comment:
794f943c835d pvl.dhcp.config: Block(comment=...)
Tero Marttila <terom@paivola.fi>
parents: 666
diff changeset
   288
        yield build_line((), end="# {comment}".format(comment=block.comment), indent=indent)
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   289
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   290
    yield build_line(block.key, end=' {', indent=indent)
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   291
    
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   292
    for item in block.items:
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   293
        yield build_item(item, indent=indent+1)
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   294
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   295
    for subblock in block.blocks:
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   296
        yield ''
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   297
666
a8ddcbe894ff pvl.dhcp.config: refactor DHCPConfigParser to use shlex and yield Block objects, change build_block() to use Block; tests
Tero Marttila <terom@paivola.fi>
parents: 478
diff changeset
   298
        for line in build_block(subblock, indent=indent+1):
476
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   299
            yield line
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   300
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   301
    yield build_line((), end='}', indent=indent)
4b792c44cf05 pvl.dhcp.config: build configs
Tero Marttila <tero.marttila@aalto.fi>
parents: 256
diff changeset
   302