From f92c77f5b8cf6afb380ef21fde31d8a482ea83ed Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Thu, 28 Mar 2019 01:20:43 +0100 Subject: [PATCH] basic setup for new settings object --- ansiblelater/__init__.py | 12 +++++-- ansiblelater/__main__.py | 25 ++++++++------ ansiblelater/settings.py | 62 +++++++++++++++++++++++++++------- ansiblelater/utils/__init__.py | 25 ++++++++++++++ setup.py | 3 +- 5 files changed, 100 insertions(+), 27 deletions(-) diff --git a/ansiblelater/__init__.py b/ansiblelater/__init__.py index f2db8c8..bdbfdcb 100644 --- a/ansiblelater/__init__.py +++ b/ansiblelater/__init__.py @@ -14,11 +14,13 @@ import re from distutils.version import LooseVersion import ansible +from appdirs import AppDirs from ansiblelater.utils import (abort, error, get_property, info, is_line_in_ranges, lines_ranges, read_standards, standards_latest, warn) -from .settings import Settings + + try: # Ansible 2.4 import of module loader @@ -29,8 +31,13 @@ except ImportError: except ImportError: from ansible.utils import module_finder as module_loader +try: + import ConfigParser as configparser +except ImportError: + import configparser + + -config = Settings() class Standard(object): @@ -333,4 +340,3 @@ def find_version(filename, version_regex=r"^# Standards:\s*([\d.]+)"): if match: return match.group(1) return None - diff --git a/ansiblelater/__main__.py b/ansiblelater/__main__.py index 9dc60a4..45738ed 100755 --- a/ansiblelater/__main__.py +++ b/ansiblelater/__main__.py @@ -4,33 +4,38 @@ import logging import optparse import os import sys + from appdirs import AppDirs from pkg_resources import resource_filename -from ansiblelater import classify -from ansiblelater import config -from ansiblelater.utils import info, warn, get_property + +from ansiblelater import classify, settings +from ansiblelater.utils import get_property, info, warn + +from .settings import Settings def main(): config_dir = AppDirs("ansible-later").user_config_dir - default_config_file = os.path.join(config_dir, "config.ini") + default_config_file = os.path.join(config_dir, "config.yml") parser = optparse.OptionParser("%prog playbook_file|role_file|inventory_file", version="%prog " + get_property("__version__")) - parser.add_option('-c', dest='configfile', default=default_config_file, + parser.add_option('-c', dest='config_file', default=default_config_file, help="Location of configuration file: [%s]" % default_config_file) - parser.add_option('-d', dest='rulesdir', + parser.add_option('-d', dest='rules_dir', help="Location of standards rules") - parser.add_option('-q', dest='log_level', action="store_const", default=logging.WARN, + parser.add_option('-q', dest='log_level', action="store_const", const=logging.ERROR, help="Only output errors") parser.add_option('-s', dest='standards_filter', action='append', help="limit standards to specific names") - parser.add_option('-v', dest='log_level', action="store_const", default=logging.WARN, - const=logging.INFO, help="Show more verbose output") + parser.add_option('-v', '--verbose', dest='log_level', action="count", + help="Show more verbose output") options, args = parser.parse_args(sys.argv[1:]) - print(config.rulesdir) + settings = Settings(options) + + # print(settings.rulesdir) # settings = read_config(options.configfile) # # Merge CLI options with config options. CLI options override config options. diff --git a/ansiblelater/settings.py b/ansiblelater/settings.py index d630a43..cdf0411 100644 --- a/ansiblelater/settings.py +++ b/ansiblelater/settings.py @@ -1,3 +1,12 @@ +import json +import logging +import os + +import anyconfig +from pkg_resources import resource_filename + +from ansiblelater import utils + try: import ConfigParser as configparser except ImportError: @@ -5,16 +14,43 @@ except ImportError: class Settings(object): - def __init__(self, config=configparser.ConfigParser(), config_file="asas"): - self.rulesdir = "ahjhsjahsjas" - self.custom_modules = [] - self.log_level = None - self.standards_filter = None - - if config.has_section('rules'): - self.rulesdir = config.get('rules', 'standards') - if config.has_section('ansible'): - modules = config.get('ansible', 'custom_modules') - self.custom_modules = [x.strip() for x in modules.split(',')] - - self.configfile = config_file + def __init__(self, args={}): + self.args = self._get_args(args) + self.config = self._get_config() + + def _get_args(self, args): + # Override correct log level from argparse + levels = [logging.WARNING, logging.INFO, logging.DEBUG] + if args.log_level: + args.log_level = levels[min(len(levels) - 1, args.log_level - 1)] + + args_dict = dict(filter(lambda item: item[1] is not None, args.__dict__.items())) + return args_dict + + def _get_config(self): + defaults = self._get_defaults() + config_file = self.args.get('config_file') + + if config_file and os.path.exists(config_file): + with utils.open_file(config_file) as stream: + s = stream.read() + anyconfig.merge(defaults, utils.safe_load(s), ac_merge=anyconfig.MS_DICTS) + + print(json.dumps(defaults, indent=4, sort_keys=True)) + return defaults + + def _get_defaults(self): + rules_dir = os.path.join(resource_filename('ansiblelater', 'examples')) + + return { + 'rules': { + 'standards': self.args.get('rules_dir', rules_dir), + 'standards_filter': [], + }, + 'logging': { + 'level': self.args.get('log_level', logging.WARN), + }, + 'ansible': { + 'custom_modules': [], + } + } diff --git a/ansiblelater/utils/__init__.py b/ansiblelater/utils/__init__.py index 805dff7..aeed4a2 100644 --- a/ansiblelater/utils/__init__.py +++ b/ansiblelater/utils/__init__.py @@ -1,5 +1,6 @@ from __future__ import print_function +import contextlib import importlib import logging import os @@ -7,6 +8,7 @@ import sys import re import colorama +import yaml from distutils.version import LooseVersion from ansible.module_utils.parsing.convert_bool import boolean as to_bool @@ -112,3 +114,26 @@ def read_config(config_file): return Settings(config, config_file) + +def safe_load(string): + """ + Parse the provided string returns a dict. + :param string: A string to be parsed. + :return: dict + """ + try: + return yaml.safe_load(string) or {} + except yaml.scanner.ScannerError as e: + print(str(e)) + + +@contextlib.contextmanager +def open_file(filename, mode='r'): + """ + Open the provide file safely and returns a file type. + :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. + :return: file type + """ + with open(filename, mode) as stream: + yield stream diff --git a/setup.py b/setup.py index 4a8fa84..b59b112 100644 --- a/setup.py +++ b/setup.py @@ -66,7 +66,8 @@ setup( "flake8", "yamllint", "nested-lookup", - "colorama" + "colorama", + "anyconfig", ], entry_points={ 'console_scripts': [