2019-04-10 12:50:48 +00:00
|
|
|
"""Global utils collection."""
|
|
|
|
|
2019-03-28 00:20:43 +00:00
|
|
|
import contextlib
|
2023-04-26 06:58:34 +00:00
|
|
|
import re
|
2019-04-04 13:35:47 +00:00
|
|
|
import sys
|
2023-02-10 07:51:17 +00:00
|
|
|
from contextlib import suppress
|
2018-12-19 10:19:07 +00:00
|
|
|
|
2019-03-28 00:20:43 +00:00
|
|
|
import yaml
|
2019-04-04 13:35:47 +00:00
|
|
|
|
2019-04-02 14:34:03 +00:00
|
|
|
from ansiblelater import logger
|
2018-12-19 10:19:07 +00:00
|
|
|
|
|
|
|
try:
|
2020-04-05 12:33:43 +00:00
|
|
|
import ConfigParser as configparser # noqa
|
2018-12-19 10:19:07 +00:00
|
|
|
except ImportError:
|
2020-04-05 12:33:43 +00:00
|
|
|
import configparser # noqa
|
2019-04-02 14:34:03 +00:00
|
|
|
|
|
|
|
LOG = logger.get_logger(__name__)
|
|
|
|
|
|
|
|
|
2019-01-25 11:32:28 +00:00
|
|
|
def count_spaces(c_string):
|
|
|
|
leading_spaces = 0
|
|
|
|
trailing_spaces = 0
|
|
|
|
|
2023-02-10 07:51:17 +00:00
|
|
|
for _i, e in enumerate(c_string):
|
2019-01-25 11:32:28 +00:00
|
|
|
if not e.isspace():
|
|
|
|
break
|
|
|
|
leading_spaces += 1
|
|
|
|
|
2023-02-10 07:51:17 +00:00
|
|
|
for _i, e in reversed(list(enumerate(c_string))):
|
2019-01-25 11:32:28 +00:00
|
|
|
if not e.isspace():
|
|
|
|
break
|
|
|
|
trailing_spaces += 1
|
|
|
|
|
2023-11-10 13:50:48 +00:00
|
|
|
return (leading_spaces, trailing_spaces)
|
2019-01-25 11:32:28 +00:00
|
|
|
|
|
|
|
|
2018-12-19 10:19:07 +00:00
|
|
|
def lines_ranges(lines_spec):
|
|
|
|
if not lines_spec:
|
|
|
|
return None
|
|
|
|
result = []
|
|
|
|
for interval in lines_spec.split(","):
|
|
|
|
(start, end) = interval.split("-")
|
|
|
|
result.append(range(int(start), int(end) + 1))
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
def is_line_in_ranges(line, ranges):
|
2021-02-12 15:48:45 +00:00
|
|
|
return not ranges or any(line in r for r in ranges)
|
2018-12-19 10:19:07 +00:00
|
|
|
|
|
|
|
|
2019-03-28 00:20:43 +00:00
|
|
|
def safe_load(string):
|
|
|
|
"""
|
|
|
|
Parse the provided string returns a dict.
|
2019-04-04 13:35:47 +00:00
|
|
|
|
2019-03-28 00:20:43 +00:00
|
|
|
:param string: A string to be parsed.
|
2019-04-04 13:35:47 +00:00
|
|
|
:returns: dict
|
|
|
|
|
2019-03-28 00:20:43 +00:00
|
|
|
"""
|
2023-02-10 07:51:17 +00:00
|
|
|
with suppress(yaml.scanner.ScannerError):
|
2019-03-28 00:20:43 +00:00
|
|
|
return yaml.safe_load(string) or {}
|
|
|
|
|
|
|
|
|
|
|
|
@contextlib.contextmanager
|
2019-04-04 13:35:47 +00:00
|
|
|
def open_file(filename, mode="r"):
|
2019-03-28 00:20:43 +00:00
|
|
|
"""
|
|
|
|
Open the provide file safely and returns a file type.
|
2019-04-04 13:35:47 +00:00
|
|
|
|
2019-03-28 00:20:43 +00:00
|
|
|
:param filename: A string containing an absolute path to the file to open.
|
|
|
|
:param mode: A string describing the way in which the file will be used.
|
2019-04-04 13:35:47 +00:00
|
|
|
:returns: file type
|
|
|
|
|
2019-03-28 00:20:43 +00:00
|
|
|
"""
|
|
|
|
with open(filename, mode) as stream:
|
|
|
|
yield stream
|
2019-03-28 15:54:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
def add_dict_branch(tree, vector, value):
|
|
|
|
key = vector[0]
|
2023-11-10 13:50:48 +00:00
|
|
|
tree[key] = (
|
|
|
|
value
|
|
|
|
if len(vector) == 1
|
|
|
|
else add_dict_branch(tree[key] if key in tree else {}, vector[1:], value)
|
|
|
|
)
|
2019-03-28 15:54:45 +00:00
|
|
|
return tree
|
2019-04-02 14:34:03 +00:00
|
|
|
|
|
|
|
|
2023-04-26 06:58:34 +00:00
|
|
|
def has_jinja(value):
|
|
|
|
"""Return true if a string seems to contain jinja templating."""
|
|
|
|
re_has_jinja = re.compile(r"{[{%#].*[%#}]}", re.DOTALL)
|
|
|
|
return bool(isinstance(value, str) and re_has_jinja.search(value))
|
|
|
|
|
|
|
|
|
|
|
|
def has_glob(value):
|
|
|
|
"""Return true if a string looks like having a glob pattern."""
|
|
|
|
re_has_glob = re.compile("[][*?]")
|
|
|
|
return bool(isinstance(value, str) and re_has_glob.search(value))
|
|
|
|
|
|
|
|
|
2019-04-02 14:34:03 +00:00
|
|
|
def sysexit(code=1):
|
|
|
|
sys.exit(code)
|
|
|
|
|
|
|
|
|
|
|
|
def sysexit_with_message(msg, code=1):
|
|
|
|
LOG.critical(msg)
|
|
|
|
sysexit(code)
|
2021-01-30 15:52:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Singleton(type):
|
|
|
|
"""Meta singleton class."""
|
|
|
|
|
|
|
|
_instances = {}
|
|
|
|
|
|
|
|
def __call__(cls, *args, **kwargs):
|
|
|
|
if cls not in cls._instances:
|
2023-02-10 07:51:17 +00:00
|
|
|
cls._instances[cls] = super().__call__(*args, **kwargs)
|
2021-01-30 15:52:48 +00:00
|
|
|
return cls._instances[cls]
|