From 57cd999f7081d94fb1c623665e016576725b5353 Mon Sep 17 00:00:00 2001 From: mathieui Date: Sun, 11 Apr 2021 18:38:22 +0200 Subject: [PATCH] refactor: move argument parsing away from config.py global state-- --- poezio/args.py | 45 +++++++++++++++++++++++++---- poezio/config.py | 63 +++++++++-------------------------------- poezio/connection.py | 6 ++-- poezio/core/commands.py | 4 +-- poezio/core/core.py | 9 ++++-- poezio/poezio.py | 11 ++++--- 6 files changed, 69 insertions(+), 69 deletions(-) diff --git a/poezio/args.py b/poezio/args.py index e1ebe5e0..3907fc88 100644 --- a/poezio/args.py +++ b/poezio/args.py @@ -1,12 +1,16 @@ """ Module related to the argument parsing - -There is a fallback to the deprecated optparse if argparse is not found """ +import pkg_resources +import stat +import sys +from argparse import ArgumentParser, SUPPRESS, Namespace from pathlib import Path -from argparse import ArgumentParser, SUPPRESS +from shutil import copy2 +from typing import Tuple from poezio.version import __version__ +from poezio import xdg def parse_args(CONFIG_PATH: Path): @@ -47,5 +51,36 @@ def parse_args(CONFIG_PATH: Path): metavar="VERSION", default=__version__ ) - options = parser.parse_args() - return options + return parser.parse_args() + + +def run_cmdline_args() -> Tuple[Namespace, bool]: + "Parse the command line arguments" + options = parse_args(xdg.CONFIG_HOME) + firstrun = False + + # Copy a default file if none exists + if not options.filename.is_file(): + try: + options.filename.parent.mkdir(parents=True, exist_ok=True) + except OSError as e: + sys.stderr.write( + 'Poezio was unable to create the config directory: %s\n' % e) + sys.exit(1) + default = Path(__file__).parent / '..' / 'data' / 'default_config.cfg' + other = Path( + pkg_resources.resource_filename('poezio', 'default_config.cfg')) + if default.is_file(): + copy2(str(default), str(options.filename)) + elif other.is_file(): + copy2(str(other), str(options.filename)) + + # Inside the nixstore and possibly other distributions, the reference + # file is readonly, so is the copy. + # Make it writable by the user who just created it. + if options.filename.exists(): + options.filename.chmod(options.filename.stat().st_mode + | stat.S_IWUSR) + firstrun = True + + return (options, firstrun) diff --git a/poezio/config.py b/poezio/config.py index 1eda2e86..102c5dd0 100644 --- a/poezio/config.py +++ b/poezio/config.py @@ -12,16 +12,12 @@ to remove our ugly custom I/O methods. import logging.config import os -import stat import sys -import pkg_resources from configparser import RawConfigParser, NoOptionError, NoSectionError from pathlib import Path -from shutil import copy2 from typing import Callable, Dict, List, Optional, Union, Tuple, cast, Any -from poezio.args import parse_args from poezio import xdg @@ -617,43 +613,11 @@ def check_config(): print(' \033[31m%s\033[0m' % option) -def run_cmdline_args(): - "Parse the command line arguments" - global options - options = parse_args(xdg.CONFIG_HOME) - - # Copy a default file if none exists - if not options.filename.is_file(): - try: - options.filename.parent.mkdir(parents=True, exist_ok=True) - except OSError as e: - sys.stderr.write( - 'Poezio was unable to create the config directory: %s\n' % e) - sys.exit(1) - default = Path(__file__).parent / '..' / 'data' / 'default_config.cfg' - other = Path( - pkg_resources.resource_filename('poezio', 'default_config.cfg')) - if default.is_file(): - copy2(str(default), str(options.filename)) - elif other.is_file(): - copy2(str(other), str(options.filename)) - - # Inside the nixstore and possibly other distributions, the reference - # file is readonly, so is the copy. - # Make it writable by the user who just created it. - if options.filename.exists(): - options.filename.chmod(options.filename.stat().st_mode - | stat.S_IWUSR) - - global firstrun - firstrun = True - - -def create_global_config(): +def create_global_config(filename): "Create the global config object, or crash" try: global config - config = Config(options.filename, DEFAULT_CONFIG) + config = Config(filename, DEFAULT_CONFIG) except: import traceback sys.stderr.write('Poezio was unable to read or' @@ -662,11 +626,13 @@ def create_global_config(): sys.exit(1) -def setup_logging(): +def setup_logging(debug_file=''): "Change the logging config according to the cmdline options and config" global LOG_DIR LOG_DIR = config.get('log_dir') LOG_DIR = Path(LOG_DIR).expanduser() if LOG_DIR else xdg.DATA_HOME / 'logs' + from copy import deepcopy + logging_config = deepcopy(LOGGING_CONFIG) if config.get('log_errors'): try: LOG_DIR.mkdir(parents=True, exist_ok=True) @@ -674,8 +640,8 @@ def setup_logging(): # We can’t really log any error here, because logging isn’t setup yet. pass else: - LOGGING_CONFIG['root']['handlers'].append('error') - LOGGING_CONFIG['handlers']['error'] = { + logging_config['root']['handlers'].append('error') + logging_config['handlers']['error'] = { 'level': 'ERROR', 'class': 'logging.FileHandler', 'filename': str(LOG_DIR / 'errors.log'), @@ -683,18 +649,18 @@ def setup_logging(): } logging.disable(logging.WARNING) - if options.debug: - LOGGING_CONFIG['root']['handlers'].append('debug') - LOGGING_CONFIG['handlers']['debug'] = { + if debug_file: + logging_config['root']['handlers'].append('debug') + logging_config['handlers']['debug'] = { 'level': 'DEBUG', 'class': 'logging.FileHandler', - 'filename': options.debug, + 'filename': debug_file, 'formatter': 'simple', } logging.disable(logging.NOTSET) - if LOGGING_CONFIG['root']['handlers']: - logging.config.dictConfig(LOGGING_CONFIG) + if logging_config['root']['handlers']: + logging.config.dictConfig(logging_config) else: logging.disable(logging.ERROR) logging.basicConfig(level=logging.CRITICAL) @@ -737,9 +703,6 @@ config = Config(Path('/dev/null')) # The logger object for this module log = logging.getLogger(__name__) # type: logging.Logger -# The command-line options -options = None - # delayed import from common.py safeJID = None # type: Optional[Callable] diff --git a/poezio/connection.py b/poezio/connection.py index e474ca94..06715b6b 100644 --- a/poezio/connection.py +++ b/poezio/connection.py @@ -27,7 +27,7 @@ from slixmpp.util import FileSystemCache from poezio import common from poezio import fixes from poezio import xdg -from poezio.config import config, options +from poezio.config import config class Connection(slixmpp.ClientXMPP): @@ -37,7 +37,7 @@ class Connection(slixmpp.ClientXMPP): """ __init = False - def __init__(self): + def __init__(self, custom_version=''): keyfile = config.getstr('keyfile') certfile = config.getstr('certfile') @@ -169,7 +169,7 @@ class Connection(slixmpp.ClientXMPP): self.register_plugin('xep_0172') if config.getbool('send_poezio_info'): - info = {'name': 'poezio', 'version': options.custom_version} + info = {'name': 'poezio', 'version': custom_version} if config.getbool('send_os_info'): info['os'] = common.get_os_info() self.plugin['xep_0030'].set_identities(identities={('client', diff --git a/poezio/core/commands.py b/poezio/core/commands.py index 3cd65207..75f90279 100644 --- a/poezio/core/commands.py +++ b/poezio/core/commands.py @@ -18,7 +18,7 @@ from poezio import common from poezio import tabs from poezio import multiuserchat as muc from poezio.bookmarks import Bookmark -from poezio.config import config, DEFAULT_CONFIG, options as config_opts +from poezio.config import config, DEFAULT_CONFIG from poezio.contact import Contact, Resource from poezio.decorators import deny_anonymous from poezio.plugin import PluginConfig @@ -1346,7 +1346,7 @@ class CommandCore: info = ('Your JID is %s\nYour current status is "%s" (%s)' '\nYour default nickname is %s\nYou are running poezio %s' % (jid, message if message else '', show - if show else 'available', nick, config_opts.custom_version)) + if show else 'available', nick, self.core.custom_version)) self.core.information(info, 'Info') @command_args_parser.ignored diff --git a/poezio/core/core.py b/poezio/core/core.py index 5ea8978f..66af7a28 100644 --- a/poezio/core/core.py +++ b/poezio/core/core.py @@ -73,7 +73,6 @@ from poezio.core.structs import ( from poezio.ui.types import ( Message, - InfoMessage, PersistentInfoMessage, ) @@ -81,12 +80,15 @@ log = logging.getLogger(__name__) T = TypeVar('T', bound=tabs.Tab) + class Core: """ “Main” class of poezion """ - def __init__(self): + custom_version: str + + def __init__(self, custom_version: str): self.completion = CompletionCore(self) self.command = CommandCore(self) self.handler = HandlerCore(self) @@ -100,7 +102,8 @@ class Core: status = POSSIBLE_SHOW.get(status, None) self.status = Status(show=status, message=config.getstr('status_message')) self.running = True - self.xmpp = connection.Connection() + self.custom_version = custom_version + self.xmpp = connection.Connection(custom_version) self.xmpp.core = self self.keyboard = keyboard.Keyboard() roster.set_node(self.xmpp.client_roster) diff --git a/poezio/poezio.py b/poezio/poezio.py index 1954acd9..28e80496 100644 --- a/poezio/poezio.py +++ b/poezio/poezio.py @@ -79,17 +79,16 @@ def main(): sys.stdout.write("\x1b]0;poezio\x07") sys.stdout.flush() + from poezio.args import run_cmdline_args + options, firstrun = run_cmdline_args() from poezio import config - config.run_cmdline_args() - config.create_global_config() - config.setup_logging() + config.create_global_config(options.filename) + config.setup_logging(options.debug) config.post_logging_setup() import logging logging.raiseExceptions = False - from poezio.config import options - if options.check_config: config.check_config() sys.exit(0) @@ -109,7 +108,7 @@ def main(): from poezio.core.core import Core signal.signal(signal.SIGINT, signal.SIG_IGN) # ignore ctrl-c - cocore = Core() + cocore = Core(options.custom_version) signal.signal(signal.SIGUSR1, cocore.sigusr_handler) # reload the config signal.signal(signal.SIGHUP, cocore.exit_from_signal) signal.signal(signal.SIGTERM, cocore.exit_from_signal)