From 027d7d1543c2575c92698fe3afa6724ac078290b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?GOLDERWEB=20=E2=80=93=20Jonathan=20Golder?= Date: Thu, 25 Feb 2016 13:24:13 +0100 Subject: [PATCH 1/4] Use configparser to read configuration --- __init__.py | 2 +- config.py | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 config.py diff --git a/__init__.py b/__init__.py index f27313c..29f7e86 100644 --- a/__init__.py +++ b/__init__.py @@ -26,4 +26,4 @@ Scripts for our redundances bot """ # noqa needed to prevent pyflakes from warning about unused imports from jogobot.jogobot import ( output, sendmail, is_active ) # noqa -import jogobot.config as config # noqa +from jogobot.config import config # noqa diff --git a/config.py b/config.py new file mode 100644 index 0000000..58fbc9e --- /dev/null +++ b/config.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# config.py +# +# Copyright 2016 GOLDERWEB – Jonathan Golder +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# +""" +This module will read config for jogobot from config file (ini-style) using +python standard library module configparser +""" + +import configparser + +import pywikibot + +config = configparser.ConfigParser() +config.read(pywikibot.config.get_base_dir() + "/jogobot.conf") + +# Make jogobot entrys available in root level (without sections) +config = dict( config ) +for key, value in dict(config["jogobot"]).items(): + config[key] = value From b0c844b2de2503eb77a172e57a288f947a978530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?GOLDERWEB=20=E2=80=93=20Jonathan=20Golder?= Date: Thu, 25 Feb 2016 13:48:38 +0100 Subject: [PATCH 2/4] Use config in jogobot.py Set configparser.interpolation to none to prevent parsing timestamps --- config.py | 2 +- jogobot.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/config.py b/config.py index 58fbc9e..a30a27b 100644 --- a/config.py +++ b/config.py @@ -30,7 +30,7 @@ import configparser import pywikibot -config = configparser.ConfigParser() +config = configparser.ConfigParser(interpolation=None) config.read(pywikibot.config.get_base_dir() + "/jogobot.conf") # Make jogobot entrys available in root level (without sections) diff --git a/jogobot.py b/jogobot.py index 437f75a..aa8692d 100644 --- a/jogobot.py +++ b/jogobot.py @@ -23,6 +23,7 @@ # import os +import shlex from datetime import datetime from email.mime.text import MIMEText from subprocess import Popen, PIPE, TimeoutExpired @@ -32,7 +33,7 @@ import pywikibot from pywikibot.bot import( DEBUG, INFO, WARNING, ERROR, CRITICAL, STDOUT, VERBOSE, logoutput ) -import jogobot.config as config +from jogobot.config import config def output( text, level="INFO", decoder=None, newline=True, @@ -41,7 +42,7 @@ def output( text, level="INFO", decoder=None, newline=True, Wrapper for pywikibot output functions """ - text = datetime.utcnow().strftime( "%Y-%m-%d %H:%M:%S (UTC) " ) + text + text = datetime.utcnow().strftime( config["log_timestamp"] ) + " " + text if ( level.upper() == "STDOUT" ): _level = STDOUT @@ -102,7 +103,7 @@ pywikibot.output = pywikibot_output def sendmail( Subject, Body, To=None, CC=None, BCC=None, - From="JogoBot " ): + From=config["mail_from"] ): """ Provides a simple wrapper for exim (MTA) on tool labs Params should be formated according related fields in RFC 5322 @@ -143,7 +144,7 @@ def sendmail( Subject, Body, To=None, CC=None, BCC=None, # We have no local MTA so we need to catch errors and write to file instead try: # Send the message via exim - with Popen( config.mail_cmd, stdin=PIPE, + with Popen( shlex.split(config['mail_cmd']), stdin=PIPE, universal_newlines=True ) as MTA: MTA.communicate(msg.as_string()) @@ -164,9 +165,9 @@ def sendmail( Subject, Body, To=None, CC=None, BCC=None, except FileNotFoundError: # Local fallback - with open( config.bot_dir + "/Mail.txt", "a" ) as mail: + with open( config["dir"] + "/Mail.txt", "a" ) as mail: mail.write( "\n\n" ) - mail.write( datetime.utcnow().strftime( "%Y-%m-%d %H:%M:%S (UTC)")) + mail.write( datetime.utcnow().strftime( config["log_timestamp"])) mail.write( "\n" + msg.as_string() ) @@ -218,8 +219,7 @@ class StatusAPI: self.site = pywikibot.Site() # We need the shell working directory - self.cwd = "/home/joni/GOLDERWEB/Daten/Projekte/" +\ - "05_Wikimedia/62_BOT/bot" + self.cwd = config["dir"] def is_disabled_on_wiki( self, task_slug=None ): """ From dac01a224b8b190ed8c5bf8c0183dc879e775f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?GOLDERWEB=20=E2=80=93=20Jonathan=20Golder?= Date: Mon, 29 Feb 2016 11:09:50 +0100 Subject: [PATCH 3/4] Parse config entrys with ast.literal_eval to get python datatypes (like Tuples, Lists ...) --- config.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/config.py b/config.py index a30a27b..e4f742e 100644 --- a/config.py +++ b/config.py @@ -27,13 +27,25 @@ python standard library module configparser """ import configparser +import ast import pywikibot -config = configparser.ConfigParser(interpolation=None) -config.read(pywikibot.config.get_base_dir() + "/jogobot.conf") +__config = configparser.ConfigParser(interpolation=None) +__config.read(pywikibot.config.get_base_dir() + "/jogobot.conf") + +# Convert to dict as configparser could contain only strings +config = dict( __config ) + +# Parse all sections +for section in __config.sections(): + # Convert to dict as configparser could contain only strings + config[section] = dict( __config[section] ) + + # Parse config with ast.literal_eval to get python datatypes + for key, value in config[section].items(): + config[section][key] = ast.literal_eval( value ) # Make jogobot entrys available in root level (without sections) -config = dict( config ) -for key, value in dict(config["jogobot"]).items(): +for key, value in config["jogobot"].items(): config[key] = value From 7212b8eee44bae25378a40486ec2ee17101d4a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?GOLDERWEB=20=E2=80=93=20Jonathan=20Golder?= Date: Fri, 11 Mar 2016 14:39:17 +0100 Subject: [PATCH 4/4] Re-Structure config module --- config.py | 69 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/config.py b/config.py index e4f742e..ba5f8c2 100644 --- a/config.py +++ b/config.py @@ -31,21 +31,66 @@ import ast import pywikibot -__config = configparser.ConfigParser(interpolation=None) -__config.read(pywikibot.config.get_base_dir() + "/jogobot.conf") -# Convert to dict as configparser could contain only strings -config = dict( __config ) +def load_config(): + """ + Reads raw configuration from file and provides it as attribute -# Parse all sections -for section in __config.sections(): + @param Config-Object + @r-type configparser.ConfigParser + """ + # Load configparser + config = configparser.ConfigParser(interpolation=None) + # Load config file + config.read(pywikibot.config.get_base_dir() + "/jogobot.conf") + + return config + + +def parse_config( raw_config ): + """ + Converts config to normal dictionary + Parses each entry with ast.literal_eval + + @param config Config-Object to parse + @type config configparser.ConfigParser + + @return Parsed configuration + @rtype dict + """ # Convert to dict as configparser could contain only strings - config[section] = dict( __config[section] ) + config = dict( raw_config ) + + # Parse all sections + for section in raw_config.sections(): + # Convert to dict as configparser could contain only strings + config[section] = dict( raw_config[section] ) - # Parse config with ast.literal_eval to get python datatypes + # Parse config with ast.literal_eval to get python datatypes + for key, value in config[section].items(): + config[section][key] = ast.literal_eval( value ) + + return config + + +def root_section( config, section="jogobot" ): + """ + Make 'section' entrys available in root level (without sections) + + @param config Config-Object to parse + @type config dict + + @return Parsed configuration + @rtype dict + """ for key, value in config[section].items(): - config[section][key] = ast.literal_eval( value ) + config[key] = value + + return config -# Make jogobot entrys available in root level (without sections) -for key, value in config["jogobot"].items(): - config[key] = value +# Load config +config = load_config() +# Parse config to get python datatypes +config = parse_config( config ) +# Make jogobot section available as root +config = root_section( config )