| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- import string
- from pyparsing import (
- Literal, White, Word, alphanums, CharsNotIn, Forward, Group, SkipTo,
- Optional, OneOrMore, ZeroOrMore, pythonStyleComment)
- class NginxParser(object):
- """
- A class that parses nginx configuration with pyparsing
- """
- # constants
- left_bracket = Literal("{").suppress()
- right_bracket = Literal("}").suppress()
- semicolon = Literal(";").suppress()
- space = White().suppress()
- key = Word(alphanums + "_/")
- value = CharsNotIn("{};")
- value2 = CharsNotIn(";")
- location = CharsNotIn("{};," + string.whitespace)
- ifword = Literal("if")
- setword = Literal("set")
- # modifier for location uri [ = | ~ | ~* | ^~ ]
- modifier = Literal("=") | Literal("~*") | Literal("~") | Literal("^~")
- # rules
- assignment = (key + Optional(space + value) + semicolon)
- setblock = (setword + OneOrMore(space + value2) + semicolon)
- block = Forward()
- ifblock = Forward()
- subblock = Forward()
- ifblock << (
- Group(ifword + Optional(space) + Optional(value) + SkipTo('{'))
- + left_bracket
- + Group(subblock)
- + right_bracket)
- subblock << ZeroOrMore(
- Group(assignment) | block | Group(ifblock) | setblock
- )
- block << Group(
- Group(key + Optional(space + modifier) + Optional(space + location))
- + left_bracket
- + Group(subblock)
- + right_bracket
- )
- script = OneOrMore(Group(assignment) | block).ignore(pythonStyleComment)
- def __init__(self, source):
- self.source = source
- def parse(self):
- """
- Returns the parsed tree.
- """
- return self.script.parseString(self.source)
- def as_list(self):
- """
- Returns the list of tree.
- """
- return self.parse().asList()
- class NginxDumper(object):
- """
- A class that dumps nginx configuration from the provided tree.
- """
- def __init__(self, blocks, indentation=4):
- self.blocks = blocks
- self.indentation = indentation
- def __iter__(self, blocks=None, current_indent=0, spacer=' '):
- """
- Iterates the dumped nginx content.
- """
- blocks = blocks or self.blocks
- for key, values in blocks:
- if current_indent:
- yield spacer
- indentation = spacer * current_indent
- if isinstance(key, list):
- yield indentation + spacer.join(key) + ' {'
- for parameter in values:
- if isinstance(parameter[0], list):
- dumped = self.__iter__(
- [parameter],
- current_indent + self.indentation)
- for line in dumped:
- yield line
- else:
- dumped = spacer.join(parameter) + ';'
- yield spacer * (
- current_indent + self.indentation) + dumped
- yield indentation + '}'
- else:
- yield spacer * current_indent + key + spacer + values + ';'
- def as_string(self):
- return '\n'.join(self)
- def to_file(self, out):
- for line in self:
- out.write(line+"\n")
- out.close()
- return out
- # Shortcut functions to respect Python's serialization interface
- # (like pyyaml, picker or json)
- def loads(source):
- return NginxParser(source).as_list()
- def load(_file):
- return loads(_file.read())
- def dumps(blocks, indentation=4):
- return NginxDumper(blocks, indentation).as_string()
- def dump(blocks, _file, indentation=4):
- return NginxDumper(blocks, indentation).to_file(_file)
|