# -*- coding: utf-8 -*-
-# Copyright (c) 2013, 2014 Jack Kaliko <kaliko@azylum.org>
+# Copyright (c) 2013, 2014, 2015, 2020, 2021 kaliko <kaliko@azylum.org>
#
# This file is part of sima
#
import logging
import sys
-from importlib import __import__
+from importlib import __import__ as sima_import
from os.path import isfile
+from os import rename
##
# third parties components
from . import core, info
from .lib.logger import set_logger
from .lib.simadb import SimaDB
+from .mpdclient import PlayerError
from .utils.config import ConfMan
from .utils.startopt import StartOpt
-from .utils.utils import exception_log, SigHup
- # core plugins
+from .utils.utils import exception_log, SigHup, MPDSimaException
+from .utils.blcli import BLCli
+# core plugins
from .plugins.core.history import History
from .plugins.core.mpdoptions import MpdOptions
+from .plugins.core.uniq import Uniq
##
"""Handles internal/external plugins
sima: sima.core.Sima instance
source: ['internal', 'contrib']
- """
- if not sima.config.get('sima', source ):
+ """# pylint: disable=logging-not-lazy,logging-format-interpolation
+ if not sima.config.get('sima', source):
return
logger = logging.getLogger('sima')
+ # TODO: Sanity check for "sima.config.get('sima', source)" ?
for plugin in sima.config.get('sima', source).split(','):
plugin = plugin.strip(' \n')
- module = 'sima.plugins.{0}.{1}'.format(source, plugin.lower())
+ module = f'sima.plugins.{source}.{plugin.lower()}'
try:
- mod_obj = __import__(module, fromlist=[plugin])
+ mod_obj = sima_import(module, fromlist=[plugin])
except ImportError as err:
- logger.error('Failed to load plugin\'s module: {0} ({1})'.format(module, err))
+ logger.error(f'Failed to load "{plugin}" plugin\'s module: ' +
+ f'{module} ({err})')
sima.shutdown()
sys.exit(1)
try:
plugin_obj = getattr(mod_obj, plugin)
except AttributeError as err:
- logger.error('Failed to load plugin {0} ({1})'.format(plugin, err))
+ logger.error('Failed to load plugin %s (%s)', plugin, err)
sima.shutdown()
sys.exit(1)
- logger.info('Loading {0} plugin: {name} ({doc})'.format(source, **plugin_obj.info()))
+ logger.info('Loading {0} plugin: {name} ({doc})'.format(
+ source, **plugin_obj.info()))
sima.register_plugin(plugin_obj)
def start(sopt, restart=False):
"""starts application
"""
+ # loads configuration
+ cfg_mgmt = ConfMan(sopt.options)
+ config = cfg_mgmt.config
# set logger
- verbosity = sopt.options.get('verbosity', 'warning')
- logfile = sopt.options.get('logfile', None)
- cli_loglevel = getattr(logging, verbosity.upper())
- set_logger(level=verbosity, logfile=logfile)
logger = logging.getLogger('sima')
- logger.setLevel(cli_loglevel)
- # loads configuration
- config = ConfMan(logger, sopt.options).config
- logger.setLevel(getattr(logging,
- config.get('log', 'verbosity').upper())) # pylint: disable=E1103
-
- logger.debug('Command line say: {0}'.format(sopt.options))
- # Create Database
+ logfile = config.get('log', 'logfile', fallback=None)
+ verbosity = config.get('log', 'verbosity')
+ if sopt.options.get('command'): # disable file logging
+ set_logger(verbosity)
+ else:
+ set_logger(verbosity, logfile)
+ logger.debug('Command line say: %s', sopt.options)
+
+ # Create database if not present
db_file = config.get('sima', 'db_file')
- if (sopt.options.get('create_db', None)
- or not isfile(db_file)):
- logger.info('Creating database in "{}"'.format(db_file))
- open(db_file, 'a').close()
+ if not isfile(db_file):
+ logger.debug('Creating database in "%s"', db_file)
SimaDB(db_path=db_file).create_db()
- if sopt.options.get('create_db', None):
+ # Migration from v0.17.0
+ dbinfo = SimaDB(db_path=db_file).get_info()
+ if not dbinfo: # v0.17.0 → v0.18+ migration
+ logger.warning('Backing up database!')
+ rename(db_file, db_file + '-old-version-backup')
+ logger.info('Creating an new database in "%s"', db_file)
+ SimaDB(db_path=db_file).create_db()
+
+ if sopt.options.get('command'):
+ cmd = sopt.options.get('command')
+ if cmd.startswith('bl-'):
+ BLCli(config, sopt.options)
+ sys.exit(0)
+ if cmd == "generate-config":
+ config.write(sys.stdout, space_around_delimiters=True)
+ sys.exit(0)
+ logger.info('Running "%s" and exit', cmd)
+ if cmd == "config-test":
+ logger.info('Config location: "%s"', cfg_mgmt.conf_file)
+ from .utils.configtest import config_test
+ config_test(config)
+ sys.exit(0)
+ if cmd == "create-db":
+ if not isfile(db_file):
+ logger.info('Creating database in "%s"', db_file)
+ SimaDB(db_path=db_file).create_db()
+ else:
+ logger.info('Database already there, not overwriting %s', db_file)
logger.info('Done, bye...')
sys.exit(0)
+ if cmd == "purge-history":
+ db_file = config.get('sima', 'db_file')
+ if not isfile(db_file):
+ logger.warning('No db found: %s', db_file)
+ sys.exit(1)
+ SimaDB(db_path=db_file).purge_history(duration=0)
+ sys.exit(0)
- logger.info('Starting...')
+ logger.info('Starting (%s)...', info.__version__)
sima = core.Sima(config)
# required core plugins
- sima.register_plugin(History)
- sima.register_plugin(MpdOptions)
+ core_plugins = [History, MpdOptions, Uniq]
+ if config.getboolean('sima', 'mopidy_compat'):
+ logger.warning('Running with mopidy compat. mode!')
+ core_plugins = [History, MpdOptions]
+ config['sima']['musicbrainzid'] = 'False'
+ for cplgn in core_plugins:
+ logger.debug('Register core %(name)s (%(doc)s)', cplgn.info())
+ sima.register_core_plugin(cplgn)
+ logger.debug('core loaded, prioriy: %s',
+ ' > '.join(map(str, sima.core_plugins)))
# Loading internal plugins
load_plugins(sima, 'internal')
-
# Loading contrib plugins
load_plugins(sima, 'contrib')
+ logger.info('plugins loaded, prioriy: %s', ' > '.join(map(str, sima.plugins)))
+
# Run as a daemon
if config.getboolean('daemon', 'daemon'):
if restart:
Catches Unhandled exception
"""
# pylint: disable=broad-except
+ logger = logging.getLogger('sima')
try:
start(sopt, restart)
- except SigHup as err: # SigHup inherit from Exception
+ except SigHup: # SigHup inherit from Exception
run(sopt, True)
+ except (MPDSimaException, PlayerError) as err:
+ logger.error(err)
+ sys.exit(2)
except Exception: # Unhandled exception
exception_log()
+
# Script starts here
def main():
+ """Entry point"""
nfo = dict({'version': info.__version__,
- 'prog': 'sima'})
+ 'prog': 'mpd-sima'})
# StartOpt gathers options from command line call (in StartOpt().options)
sopt = StartOpt(nfo)
run(sopt)