2019-04-10 12:50:48 +00:00
|
|
|
"""Global utils collection."""
|
|
|
|
|
2018-12-19 10:19:07 +00:00
|
|
|
from __future__ import print_function
|
|
|
|
|
2019-03-28 00:20:43 +00:00
|
|
|
import contextlib
|
2018-12-19 10:19:07 +00:00
|
|
|
import os
|
|
|
|
import re
|
2019-04-04 13:35:47 +00:00
|
|
|
import sys
|
|
|
|
from distutils.version import LooseVersion
|
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
|
|
|
|
|
|
|
|
for i, e in enumerate(c_string):
|
|
|
|
if not e.isspace():
|
|
|
|
break
|
|
|
|
leading_spaces += 1
|
|
|
|
|
|
|
|
for i, e in reversed(list(enumerate(c_string))):
|
|
|
|
if not e.isspace():
|
|
|
|
break
|
|
|
|
trailing_spaces += 1
|
|
|
|
|
2020-04-05 12:33:43 +00:00
|
|
|
return ((leading_spaces, trailing_spaces))
|
2019-01-25 11:32:28 +00:00
|
|
|
|
|
|
|
|
2018-12-19 10:19:07 +00:00
|
|
|
def get_property(prop):
|
|
|
|
currentdir = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
parentdir = os.path.dirname(currentdir)
|
|
|
|
result = re.search(
|
|
|
|
r'{}\s*=\s*[\'"]([^\'"]*)[\'"]'.format(prop),
|
2020-04-05 12:33:43 +00:00
|
|
|
open(os.path.join(parentdir, "__init__.py")).read()
|
|
|
|
)
|
2018-12-19 10:19:07 +00:00
|
|
|
return result.group(1)
|
|
|
|
|
|
|
|
|
|
|
|
def standards_latest(standards):
|
|
|
|
return max([standard.version for standard in standards if standard.version] or ["0.1"],
|
|
|
|
key=LooseVersion)
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
"""
|
|
|
|
try:
|
|
|
|
return yaml.safe_load(string) or {}
|
|
|
|
except yaml.scanner.ScannerError as e:
|
|
|
|
print(str(e))
|
|
|
|
|
|
|
|
|
|
|
|
@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]
|
|
|
|
tree[key] = value \
|
|
|
|
if len(vector) == 1 \
|
|
|
|
else add_dict_branch(tree[key] if key in tree else {},
|
|
|
|
vector[1:],
|
|
|
|
value)
|
|
|
|
return tree
|
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:
|
|
|
|
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
|
|
|
return cls._instances[cls]
|