From 99099d67eaef472dbdf17202e691b750b0e05182 Mon Sep 17 00:00:00 2001 From: rip Date: Thu, 4 Jun 2015 23:54:28 +0200 Subject: [PATCH] Feature: Usage of config file. --- MANIFEST.in | 1 - cfg/config.yml | 4 -- ethunder/__init__.py | 7 ++- ethunder/app.py | 33 +++++-------- ethunder/config.py | 109 +++++++++++++++++++++++++++++++++++++++++++ setup.py | 8 +--- 6 files changed, 128 insertions(+), 34 deletions(-) delete mode 100644 cfg/config.yml create mode 100644 ethunder/config.py diff --git a/MANIFEST.in b/MANIFEST.in index 442ae59..19374f1 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,4 @@ include README.md include LICENSE -include cfg/config.yml include bin/ethunder recursive-include ethunder/test *.py diff --git a/cfg/config.yml b/cfg/config.yml deleted file mode 100644 index 3ef96a4..0000000 --- a/cfg/config.yml +++ /dev/null @@ -1,4 +0,0 @@ -# The config file for Enlighted Thunder -value1: 123456789 -path_to_rainbow: c:\temp\rainbow.txt -is_awesome: True diff --git a/ethunder/__init__.py b/ethunder/__init__.py index c37d456..1d45739 100644 --- a/ethunder/__init__.py +++ b/ethunder/__init__.py @@ -2,9 +2,9 @@ """ EnlightedThunder ~~~~~~~ - + A project to explore the possibilites of GitHub and Python deployment. - + This is a personal discovery and not considered usefull for other. It's probabliy best if you just ignore it. @@ -13,3 +13,6 @@ """ __version__ = "0.1.0" + +class EThunderError(Exception): + pass diff --git a/ethunder/app.py b/ethunder/app.py index ade7646..f1b582e 100644 --- a/ethunder/app.py +++ b/ethunder/app.py @@ -14,14 +14,16 @@ import os.path import sys -import yaml import docopt -import appdirs import ethunder +from ethunder.config import configurate __author__ = "Richard Pfeifer" -configpath = appdirs.user_config_dir("ethunder", appauthor=None) + +class EThunderError(Exception): + pass + def parse_commandline(argv): """ @@ -37,29 +39,18 @@ def parse_commandline(argv): return arguments -def parse_config(): - """ - Read the YAML config-file. - """ - with open(os.path.join(configpath, "config.yml"), 'r') as configfile: - cfg = yaml.load(configfile) - ethunder.value1 = cfg['value1'] - ethunder.path_to_rainbow = cfg['path_to_rainbow'] - ethunder.is_awesome = cfg['is_awesome'] - - def print_message(): awesome_negation = "not " - if ethunder.is_awesome: + if ethunder.config["is_awesome"]: awesome_negation = "" msg = ( "Hello world. This is ethunder and it is {0}awesome!\n" "\tRainbow can be found at: {1}\n" - "\tvalue1 = {2}" + "\tvalue1 = {2}" ).format( - awesome_negation, - os.path.normpath(ethunder.path_to_rainbow), - ethunder.value1 + awesome_negation, + os.path.normpath(ethunder.config["path_to_rainbow"]), + ethunder.config["value1"] ) print(msg) @@ -68,8 +59,8 @@ def Main(): parse_commandline(sys.argv[1:]) try: - parse_config() - print_message() + configurate() + print_message() except KeyboardInterrupt: print("Shutdown requested...exiting") sys.exit(0) diff --git a/ethunder/config.py b/ethunder/config.py new file mode 100644 index 0000000..2af0ad9 --- /dev/null +++ b/ethunder/config.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +""" +Provide tools to load configuration parameters from text-file using YAML. +""" + +from __future__ import print_function +from __future__ import unicode_literals + +import yaml +import os.path +import appdirs +import shutil +import datetime +import ethunder +from ethunder import EThunderError + +__author__ = "Richard Pfeifer" + + +config_dir = appdirs.user_config_dir("ethunder", appauthor=None) +config_filename = "config.yml" + +default_config = { + "path_to_rainbow": "ick schwörs µus", + "value1": 0, + "is_awesome": True, +} + + +class NoValidConfigfileError(EThunderError): + pass + + +def construct_yaml_str(self, node): + """ + Override the default string handling function to always return unicode + objects. + """ + return self.construct_scalar(node) +yaml.Loader.add_constructor("tag:yaml.org,2002:str", construct_yaml_str) +yaml.SafeLoader.add_constructor("tag:yaml.org,2002:str", construct_yaml_str) + + +def create_default_configfile(): + """ + Create a configfile with default config-values at the configpath. + """ + config_path = os.path.join(config_dir, config_filename) + if os.path.isfile(config_path): + backup_filename = "config_backup_{0}.yml".format( + datetime.datetime.now().isoformat()) + backup_filename = backup_filename.replace(":", "-") + backup_filepath = os.path.join(config_dir, backup_filename) + shutil.move(config_path, backup_filepath) + with open(config_path, 'w') as config_out_file: + d = yaml.safe_dump( + ethunder.config, + default_flow_style=False, + encoding=('utf-8'), + allow_unicode=True) + print(d) + config_out_file.write(d) + +def set_config(): + """ + Set configuration either from YAML config-file or from defaults. + """ + configpath = os.path.join(config_dir, config_filename) + ethunder.config = {} + ethunder.config.update(default_config) + try: + try: + print("try open") + with open(configpath, 'r') as configfile: + print("opened") + try: + cfg = yaml.safe_load(configfile) + except Exception as e: + print("error while loading: {0}".format(e)) + raise NoValidConfigfileError(e) + else: + print("should have cfg") + except IOError: + print("create empty cfg") + cfg = {} + raise NoValidConfigfileError( + "config.yml not found at {0}".format(configpath)) + else: + if not isinstance(cfg, dict): + raise NoValidConfigfileError( + "Invalid configfile at {0}".format(configpath)) + except NoValidConfigfileError: + raise + else: + ethunder.config.update(cfg) + print("Following config was read: {0}".format(ethunder.config)) + + +def configurate(): + """ + Make sure we have the needed configuration values. + """ + try: + set_config() + except NoValidConfigfileError: + create_default_configfile() + +if __name__ == "__main__": + configurate() diff --git a/setup.py b/setup.py index d8b54ec..8aeea64 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,7 @@ from setuptools import setup -import appdirs import ethunder -config_dir = appdirs.user_config_dir("ethunder", appauthor=None) - config = { 'name': 'EThunder', 'description': 'A test project.', @@ -25,10 +22,9 @@ 'install_requires': ['docopt==0.6.1', 'appdirs==1.4.0', 'nose==1.3.4', - 'pyYaml==3.11', - ], + 'pyYaml==3.11', + ], 'packages': ['ethunder', 'ethunder.test'], - 'data_files': [(config_dir, ['cfg/config.yml'])], 'include_package_data': True, 'entry_points': {'console_scripts': ['ethunder = ethunder.app:Main',