[Zope-Checkins] CVS: Packages/ZConfig - BracesStyle.py:1.1.2.1

Fred L. Drake, Jr. fdrake@acm.org
Thu, 10 Oct 2002 11:27:38 -0400


Update of /cvs-repository/Packages/ZConfig
In directory cvs.zope.org:/tmp/cvs-serv7252

Added Files:
      Tag: zconfig-brace-syntax
	BracesStyle.py 
Log Message:
Add the example of an alternate syntax.

=== Added File Packages/ZConfig/BracesStyle.py ===
"""Alternate configuration parser.

This parser accepts curly braces instead of Apache-style section
markers, and requires an equal sign between keys and values.

This can be used instead of the default Apache-style parser by
subclassing the Context class:

class BracesContext(Context):
    def parse(self, file, section):
        from Standby.Config.BracesStyle import Parse
        Parse(file, self, section)

"""

import urlparse

from Common import *


def Parse(file, context, section, url):
    lineno = 0
    stack = []
    line = None
    while 1:
        if not line:
            line = file.readline()
            if not line:
                break
            lineno += 1
            line = line.strip()

            # blank line
            if not line:
                continue

        # end section
        while line[0] == "}":
            # section end
            if not stack:
                raise ConfigurationSyntaxError(
                    "unexpected section end", url, lineno)
            section = stack.pop()
            line = line[1:].lstrip()
            if not line:
                break

        # comment
        if line[:1] in ("#", ""):
            line = ''
            continue

        # key-value
        m = _keyvalue_rx.match(line)
        if m:
            key, value = m.group('key', 'value')
            try:
                section.addValue(key, value)
            except ConfigurationError, e:
                raise ConfigurationSyntaxError(e[0], url, lineno)
            line = ''
            continue

        # import / include
        m = _import_rx.match(line)
        if m:
            keyword, relurl = m.group('keyword', 'url')
            newurl = urlparse.urljoin(url, relurl)
            if keyword == "import":
                context.importConfiguration(section, newurl)
            else:
                context.includeConfiguration(section, newurl)
            line = ''
            continue

        # section start
        m = _section_start_rx.match(line)
        if m:
            type, name, delegatename = m.group('type', 'name', 'delegatename')
            type = type.lower()
            if type in ("import", "include"):
                raise ConfigurationSyntaxError(
                    "'import' is not a valid section type", url, lineno)
            # section start
            try:
                newsect = context.nestSection(section, type, name,
                                              delegatename)
            except ConfigurationError, e:
                raise ConfigurationSyntaxError(e[0], url, lineno)
            line = line[len(m.group(0)):].lstrip()
            if line[:1] == "{":
                stack.append(section)
                section = newsect
                line = line[1:].lstrip()
            elif line:
                raise ConfigurationSyntaxError(
                    "junk on line after section start: " + repr(line),
                    url, lineno)
            continue

        raise ConfigurationSyntaxError(
            "malformed configuration data: " + repr(line), url, lineno)
    if stack:
        raise ConfigurationSyntaxError(
            "unclosed sections no allowed", url, lineno + 1)


import re
# _name_re cannot allow "(" or ")" since we need to be able to tell if
# a section has a name or not: <section (name)> would be ambiguous if
# parentheses were allowed in names.
_name_re = r"[^\s(){}]+"
_import_rx = re.compile(r"(?P<keyword>(import|include))\s+"
                        r"(?P<url>[^\s]+)\s*$", re.I)
_keyvalue_rx = re.compile(r"(?P<key>%s)\s*=\s*(?P<value>.*)$"
                          % _name_re)
_section_start_rx = re.compile(r"(?P<type>%s)"
                               r"(?:\s+(?P<name>%s))?"
                               r"(?:\s*[(](?P<delegatename>%s)[)])?"
                               % (_name_re, _name_re, _name_re))
del re