ansible-later/env_27/lib/python2.7/site-packages/anyconfig/backend/shellvars.py
2019-04-11 13:00:36 +02:00

138 lines
3.8 KiB
Python

#
# Copyright (C) 2016 - 2017 Satoru SATOH <ssato @ redhat.com>
# License: MIT
#
r"""Simple Shell vars' definitions backend:
- Format to support: Simple shell variables' definitions w/o any shell variable
expansions nor complex shell statements such as conditionals, etc.
- Requirements: None (built-in)
- Development Status :: 3 - Alpha
- Limitations: Currently, it only supports a varialbe defined in a line.
- Special options: None
Changelog:
.. versionadded:: 0.7.0
- Added an experimental parser for simple shelll vars' definitions w/o shell
variable expansions nor complex shell statements like conditionals.
"""
from __future__ import absolute_import
import logging
import itertools
import os
import re
import anyconfig.backend.base
LOGGER = logging.getLogger(__name__)
def _parseline(line):
"""
Parse a line contains shell variable definition.
:param line: A string to parse, must not start with '#' (comment)
:return: A tuple of (key, value), both key and value may be None
>>> _parseline("aaa=")
('aaa', '')
>>> _parseline("aaa=bbb")
('aaa', 'bbb')
>>> _parseline("aaa='bb b'")
('aaa', 'bb b')
>>> _parseline('aaa="bb#b"')
('aaa', 'bb#b')
>>> _parseline('aaa="bb\\"b"')
('aaa', 'bb"b')
>>> _parseline("aaa=bbb # ccc")
('aaa', 'bbb')
"""
match = re.match(r"^\s*(export)?\s*(\S+)=(?:(?:"
r"(?:\"(.*[^\\])\")|(?:'(.*[^\\])')|"
r"(?:([^\"'#\s]+)))?)\s*#*", line)
if not match:
LOGGER.warning("Invalid line found: %s", line)
return (None, None)
tpl = match.groups()
vals = list(itertools.dropwhile(lambda x: x is None, tpl[2:]))
return (tpl[1], vals[0] if vals else '')
def load(stream, container=dict):
"""
Load and parse a file or file-like object `stream` provides simple shell
variables' definitions.
:param stream: A file or file like object
:param container:
Factory function to create a dict-like object to store properties
:return: Dict-like object holding shell variables' definitions
>>> from anyconfig.compat import StringIO as to_strm
>>> load(to_strm(''))
{}
>>> load(to_strm("# "))
{}
>>> load(to_strm("aaa="))
{'aaa': ''}
>>> load(to_strm("aaa=bbb"))
{'aaa': 'bbb'}
>>> load(to_strm("aaa=bbb # ..."))
{'aaa': 'bbb'}
"""
ret = container()
for line in stream.readlines():
line = line.rstrip()
if line is None or not line:
continue
(key, val) = _parseline(line)
if key is None:
LOGGER.warning("Empty val in the line: %s", line)
continue
ret[key] = val
return ret
class Parser(anyconfig.backend.base.StreamParser):
"""
Parser for Shell variable definition files.
"""
_type = "shellvars"
_ordered = True
_dict_opts = ["ac_dict"]
def load_from_stream(self, stream, container, **kwargs):
"""
Load config from given file like object `stream`.
:param stream:
A file or file like object of shell scripts define shell variables
:param container: callble to make a container object
:param kwargs: optional keyword parameters (ignored)
:return: Dict-like object holding config parameters
"""
return load(stream, container=container)
def dump_to_stream(self, cnf, stream, **kwargs):
"""
Dump config `cnf` to a file or file-like object `stream`.
:param cnf: Shell variables data to dump
:param stream: Shell script file or file like object
:param kwargs: backend-specific optional keyword parameters :: dict
"""
for key, val in anyconfig.compat.iteritems(cnf):
stream.write("%s='%s'%s" % (key, val, os.linesep))
# vim:sw=4:ts=4:et: