1
0
Fork 0
scripts/sysadmin/nginx/config/api/blocks.py

121 lines
3.7 KiB
Python

import six
from .base import Base
from .options import AttrDict, AttrList, KeyOption, KeyValueOption, KeyMultiValueOption
class Block(Base):
""" A block represent a named section of an Nginx config, such as 'http', 'server' or 'location'
Using this object is as simple as providing a name and any sections or options,
which can be other Block objects or option objects.
Example::
>>> from nginx.config.api import Block
>>> http = Block('http', option='value')
>>> print(http)
http {
option value;
}
"""
def __init__(self, name, *sections, **options):
""" Creates a block.
Sections should be config objects such as Block or EmptyBlock,
Options can be any key/value pair (such as worker_connections=512, etc)
:param name str: The name of the block.
"""
self.name = name
self.sections = AttrList(self)
self.options = AttrDict(self)
self._set_directives(*sections, **options)
@property
def _directives(self):
dirs = self._dump_options() + list(self.sections)
return [directive for directive in dirs if directive is not self]
def _set_directives(self, *sections, **options):
for section in sections:
self.sections.append(section)
for key, value in six.iteritems(options):
setattr(self.options, key, value)
def _build_options(self, key, value):
if isinstance(value, Block):
option = value
elif isinstance(value, list):
option = KeyMultiValueOption(key, value=value)
elif value is None or value == '':
option = KeyOption(key)
else:
if isinstance(value, str) and ' ' in value:
option = KeyMultiValueOption(key, value=value.split())
else:
option = KeyValueOption(key, value=value)
return option
def _dump_options(self):
return [self._build_options(key, value) for key, value in six.iteritems(self.options)]
def __repr__(self):
directives = self._directives
for directive in directives:
if directive is not self:
directive._indent_level = self._indent_level + 1
return '\n{indent}{name}{{{directives}\n{indent}}}'.format(
name='{0} '.format(self.name),
directives=''.join([repr(e) for e in directives]),
indent=self._get_indent(),
)
class EmptyBlock(Block):
""" An unnamed block of options and/or sections.
Empty blocks are useful for representing groups of options.
For example, you can use them to represent options with non-unique keys:
Example::
>>> from nginx.config.helpers import duplicate_options
>>> dupes = duplicate_options('key', ['value', 'other_value', 'third_value'])
>>> type(dupes)
nginx.config.api.blocks.EmptyBlock
>>> print(dupes)
key third_value;
key value;
key other_value;
"""
def __init__(self, *sections, **options):
""" Create an EmptyBlock. """
self.sections = AttrList(self)
self.options = AttrDict(self)
self._set_directives(*sections, **options)
def __repr__(self):
directives = self._directives
for directive in directives:
directive._indent_level = self._indent_level
return ''.join([repr(o) for o in directives])
class Location(Block):
""" A Location is just a named block with "location" prefixed """
def __init__(self, location, *args, **kwargs):
super(Location, self).__init__('location {0}'.format(location), *args, **kwargs)