♻️ (pypo) cleanup pypo/__main__.py

Clean up code and add python 3 support (with python 2 bc).
This commit is contained in:
Lucas Bickel 2018-12-23 11:01:25 +01:00
parent cb0daddaf5
commit 36891c18c8
2 changed files with 130 additions and 98 deletions

View File

@ -1,39 +1,36 @@
""" """
Python part of radio playout (pypo) Python part of radio playout (pypo)
""" """
from __future__ import absolute_import
from optparse import OptionParser
from datetime import datetime
import telnetlib
import time
import sys
import signal
import logging
import locale import locale
import logging
import os import os
import re import re
import signal
import sys
import telnetlib
import time
from Queue import Queue from api_clients import api_client
from configobj import ConfigObj
from datetime import datetime
from optparse import OptionParser
from queue import Queue
from threading import Lock from threading import Lock
from pypopush import PypoPush from .listenerstat import ListenerStat
from pypofetch import PypoFetch from .pypofetch import PypoFetch
from pypofile import PypoFile from .pypofile import PypoFile
from recorder import Recorder from .pypoliquidsoap import PypoLiquidsoap
from listenerstat import ListenerStat from .pypomessagehandler import PypoMessageHandler
from pypomessagehandler import PypoMessageHandler from .pypopush import PypoPush
from pypoliquidsoap import PypoLiquidsoap from .recorder import Recorder
from timeout import ls_timeout from .timeout import ls_timeout
from . import pure
from configobj import ConfigObj
# custom imports LOG_PATH = "/var/log/airtime/pypo/pypo.log"
from api_clients import api_client
import pure
LOG_PATH = '/var/log/airtime/pypo/pypo.log'
LOG_LEVEL = logging.INFO LOG_LEVEL = logging.INFO
logging.captureWarnings(True) logging.captureWarnings(True)
@ -45,42 +42,54 @@ usage = "%prog [options]" + " - python playout system"
parser = OptionParser(usage=usage) parser = OptionParser(usage=usage)
# Options # Options
parser.add_option("-v", "--compat", parser.add_option(
help="Check compatibility with server API version", "-v",
default=False, "--compat",
action="store_true", help="Check compatibility with server API version",
dest="check_compat") default=False,
action="store_true",
dest="check_compat",
)
parser.add_option("-t", "--test", parser.add_option(
help="Do a test to make sure everything is working properly.", "-t",
default=False, "--test",
action="store_true", help="Do a test to make sure everything is working properly.",
dest="test") default=False,
action="store_true",
dest="test",
)
parser.add_option("-b", parser.add_option(
"--cleanup", "-b",
help="Cleanup", "--cleanup",
default=False, help="Cleanup",
action="store_true", default=False,
dest="cleanup") action="store_true",
dest="cleanup",
)
parser.add_option("-c", parser.add_option(
"--check", "-c",
help="Check the cached schedule and exit", "--check",
default=False, help="Check the cached schedule and exit",
action="store_true", default=False,
dest="check") action="store_true",
dest="check",
)
# parse options # parse options
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
LIQUIDSOAP_MIN_VERSION = "1.1.1" LIQUIDSOAP_MIN_VERSION = "1.1.1"
PYPO_HOME='/var/tmp/airtime/pypo/' PYPO_HOME = "/var/tmp/airtime/pypo/"
def configure_environment(): def configure_environment():
os.environ["HOME"] = PYPO_HOME os.environ["HOME"] = PYPO_HOME
os.environ["TERM"] = 'xterm' os.environ["TERM"] = "xterm"
configure_environment() configure_environment()
@ -90,23 +99,27 @@ logging.captureWarnings(True)
# configure logging # configure logging
try: try:
# Set up logging # Set up logging
logFormatter = logging.Formatter("%(asctime)s [%(module)s] [%(levelname)-5.5s] %(message)s") logFormatter = logging.Formatter(
"%(asctime)s [%(module)s] [%(levelname)-5.5s] %(message)s"
)
rootLogger = logging.getLogger() rootLogger = logging.getLogger()
rootLogger.setLevel(LOG_LEVEL) rootLogger.setLevel(LOG_LEVEL)
logger = rootLogger logger = rootLogger
fileHandler = logging.handlers.RotatingFileHandler(filename=LOG_PATH, maxBytes=1024 * 1024 * 30, fileHandler = logging.handlers.RotatingFileHandler(
backupCount=8) filename=LOG_PATH, maxBytes=1024 * 1024 * 30, backupCount=8
)
fileHandler.setFormatter(logFormatter) fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler) rootLogger.addHandler(fileHandler)
consoleHandler = logging.StreamHandler() consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter) consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler) rootLogger.addHandler(consoleHandler)
except Exception, e: except Exception as e:
print "Couldn't configure logging", e print("Couldn't configure logging", e)
sys.exit(1) sys.exit(1)
def configure_locale(): def configure_locale():
""" """
Silly hacks to force Python 2.x to run in UTF-8 mode. Not portable at all, Silly hacks to force Python 2.x to run in UTF-8 mode. Not portable at all,
@ -123,21 +136,26 @@ def configure_locale():
default_locale = locale.getdefaultlocale() default_locale = locale.getdefaultlocale()
if default_locale[1] is None: if default_locale[1] is None:
logger.debug("No default locale exists. Let's try loading from \ logger.debug(
/etc/default/locale") "No default locale exists. Let's try loading from \
/etc/default/locale"
)
if os.path.exists("/etc/default/locale"): if os.path.exists("/etc/default/locale"):
locale_config = ConfigObj('/etc/default/locale') locale_config = ConfigObj("/etc/default/locale")
lang = locale_config.get('LANG') lang = locale_config.get("LANG")
new_locale = lang new_locale = lang
else: else:
logger.error("/etc/default/locale could not be found! Please \ logger.error(
run 'sudo update-locale' from command-line.") "/etc/default/locale could not be found! Please \
run 'sudo update-locale' from command-line."
)
sys.exit(1) sys.exit(1)
else: else:
new_locale = default_locale new_locale = default_locale
logger.info("New locale set to: %s", \ logger.info(
locale.setlocale(locale.LC_ALL, new_locale)) "New locale set to: %s", locale.setlocale(locale.LC_ALL, new_locale)
)
reload(sys) reload(sys)
sys.setdefaultencoding("UTF-8") sys.setdefaultencoding("UTF-8")
@ -145,9 +163,10 @@ def configure_locale():
logger.debug("sys default encoding %s", sys.getdefaultencoding()) logger.debug("sys default encoding %s", sys.getdefaultencoding())
logger.debug("After %s", locale.nl_langinfo(locale.CODESET)) logger.debug("After %s", locale.nl_langinfo(locale.CODESET))
if current_locale_encoding not in ['utf-8', 'utf8']: if current_locale_encoding not in ["utf-8", "utf8"]:
logger.error("Need a UTF-8 locale. Currently '%s'. Exiting..." % \ logger.error(
current_locale_encoding) "Need a UTF-8 locale. Currently '%s'. Exiting..." % current_locale_encoding
)
sys.exit(1) sys.exit(1)
@ -155,11 +174,12 @@ configure_locale()
# loading config file # loading config file
try: try:
config = ConfigObj('/etc/airtime/airtime.conf') config = ConfigObj("/etc/airtime/airtime.conf")
except Exception, e: except Exception as e:
logger.error('Error loading config file: %s', e) logger.error("Error loading config file: %s", e)
sys.exit(1) sys.exit(1)
class Global: class Global:
def __init__(self, api_client): def __init__(self, api_client):
self.api_client = api_client self.api_client = api_client
@ -170,11 +190,13 @@ class Global:
def test_api(self): def test_api(self):
self.api_client.test() self.api_client.test()
def keyboardInterruptHandler(signum, frame): def keyboardInterruptHandler(signum, frame):
logger = logging.getLogger() logger = logging.getLogger()
logger.info('\nKeyboard Interrupt\n') logger.info("\nKeyboard Interrupt\n")
sys.exit(0) sys.exit(0)
@ls_timeout @ls_timeout
def liquidsoap_get_info(telnet_lock, host, port, logger): def liquidsoap_get_info(telnet_lock, host, port, logger):
logger.debug("Checking to see if Liquidsoap is running") logger.debug("Checking to see if Liquidsoap is running")
@ -185,7 +207,7 @@ def liquidsoap_get_info(telnet_lock, host, port, logger):
tn.write(msg) tn.write(msg)
tn.write("exit\n") tn.write("exit\n")
response = tn.read_all() response = tn.read_all()
except Exception, e: except Exception as e:
logger.error(str(e)) logger.error(str(e))
return None return None
finally: finally:
@ -193,6 +215,7 @@ def liquidsoap_get_info(telnet_lock, host, port, logger):
return get_liquidsoap_version(response) return get_liquidsoap_version(response)
def get_liquidsoap_version(version_string): def get_liquidsoap_version(version_string):
m = re.match(r"Liquidsoap (\d+.\d+.\d+)", version_string) m = re.match(r"Liquidsoap (\d+.\d+.\d+)", version_string)
@ -201,42 +224,49 @@ def get_liquidsoap_version(version_string):
else: else:
return None return None
if m: if m:
current_version = m.group(1) current_version = m.group(1)
return pure.version_cmp(current_version, LIQUIDSOAP_MIN_VERSION) >= 0 return pure.version_cmp(current_version, LIQUIDSOAP_MIN_VERSION) >= 0
return False return False
def liquidsoap_startup_test(): def liquidsoap_startup_test():
liquidsoap_version_string = \ liquidsoap_version_string = liquidsoap_get_info(
liquidsoap_get_info(telnet_lock, ls_host, ls_port, logger) telnet_lock, ls_host, ls_port, logger
)
while not liquidsoap_version_string: while not liquidsoap_version_string:
logger.warning("Liquidsoap doesn't appear to be running!, " + \ logger.warning(
"Sleeping and trying again") "Liquidsoap doesn't appear to be running!, " + "Sleeping and trying again"
)
time.sleep(1) time.sleep(1)
liquidsoap_version_string = \ liquidsoap_version_string = liquidsoap_get_info(
liquidsoap_get_info(telnet_lock, ls_host, ls_port, logger) telnet_lock, ls_host, ls_port, logger
)
while pure.version_cmp(liquidsoap_version_string, LIQUIDSOAP_MIN_VERSION) < 0: while pure.version_cmp(liquidsoap_version_string, LIQUIDSOAP_MIN_VERSION) < 0:
logger.warning("Liquidsoap is running but in incorrect version! " + \ logger.warning(
"Make sure you have at least Liquidsoap %s installed" % LIQUIDSOAP_MIN_VERSION) "Liquidsoap is running but in incorrect version! "
+ "Make sure you have at least Liquidsoap %s installed"
% LIQUIDSOAP_MIN_VERSION
)
time.sleep(1) time.sleep(1)
liquidsoap_version_string = \ liquidsoap_version_string = liquidsoap_get_info(
liquidsoap_get_info(telnet_lock, ls_host, ls_port, logger) telnet_lock, ls_host, ls_port, logger
)
logger.info("Liquidsoap version string found %s" % liquidsoap_version_string) logger.info("Liquidsoap version string found %s" % liquidsoap_version_string)
if __name__ == '__main__': if __name__ == "__main__":
logger.info('###########################################') logger.info("###########################################")
logger.info('# *** pypo *** #') logger.info("# *** pypo *** #")
logger.info('# Liquidsoap Scheduled Playout System #') logger.info("# Liquidsoap Scheduled Playout System #")
logger.info('###########################################') logger.info("###########################################")
#Although all of our calculations are in UTC, it is useful to know what timezone # Although all of our calculations are in UTC, it is useful to know what timezone
#the local machine is, so that we have a reference for what time the actual # the local machine is, so that we have a reference for what time the actual
#log entries were made # log entries were made
logger.info("Timezone: %s" % str(time.tzname)) logger.info("Timezone: %s" % str(time.tzname))
logger.info("UTC time: %s" % str(datetime.utcnow())) logger.info("UTC time: %s" % str(datetime.utcnow()))
@ -251,16 +281,16 @@ if __name__ == '__main__':
success = False success = False
while not success: while not success:
try: try:
api_client.register_component('pypo') api_client.register_component("pypo")
success = True success = True
except Exception, e: except Exception as e:
logger.error(str(e)) logger.error(str(e))
time.sleep(10) time.sleep(10)
telnet_lock = Lock() telnet_lock = Lock()
ls_host = config['pypo']['ls_host'] ls_host = config["pypo"]["ls_host"]
ls_port = config['pypo']['ls_port'] ls_port = config["pypo"]["ls_port"]
liquidsoap_startup_test() liquidsoap_startup_test()
@ -272,8 +302,7 @@ if __name__ == '__main__':
recorder_q = Queue() recorder_q = Queue()
pypoPush_q = Queue() pypoPush_q = Queue()
pypo_liquidsoap = PypoLiquidsoap(logger, telnet_lock,\ pypo_liquidsoap = PypoLiquidsoap(logger, telnet_lock, ls_host, ls_port)
ls_host, ls_port)
""" """
This queue is shared between pypo-fetch and pypo-file, where pypo-file This queue is shared between pypo-fetch and pypo-file, where pypo-file
@ -284,19 +313,21 @@ if __name__ == '__main__':
media_q = Queue() media_q = Queue()
# Pass only the configuration sections needed; PypoMessageHandler only needs rabbitmq settings # Pass only the configuration sections needed; PypoMessageHandler only needs rabbitmq settings
pmh = PypoMessageHandler(pypoFetch_q, recorder_q, config['rabbitmq']) pmh = PypoMessageHandler(pypoFetch_q, recorder_q, config["rabbitmq"])
pmh.daemon = True pmh.daemon = True
pmh.start() pmh.start()
pfile = PypoFile(media_q, config['pypo']) pfile = PypoFile(media_q, config["pypo"])
pfile.daemon = True pfile.daemon = True
pfile.start() pfile.start()
pf = PypoFetch(pypoFetch_q, pypoPush_q, media_q, telnet_lock, pypo_liquidsoap, config['pypo']) pf = PypoFetch(
pypoFetch_q, pypoPush_q, media_q, telnet_lock, pypo_liquidsoap, config["pypo"]
)
pf.daemon = True pf.daemon = True
pf.start() pf.start()
pp = PypoPush(pypoPush_q, telnet_lock, pypo_liquidsoap, config['pypo']) pp = PypoPush(pypoPush_q, telnet_lock, pypo_liquidsoap, config["pypo"])
pp.daemon = True pp.daemon = True
pp.start() pp.start()

View File

@ -51,6 +51,7 @@ setup(name='airtime-playout',
'argparse', 'argparse',
'configobj', 'configobj',
'docopt', 'docopt',
'future',
'kombu', 'kombu',
'mutagen', 'mutagen',
'poster', 'poster',