<commit_before>#!/usr/bin/env python
#
# Licensed under the BSD license.  See full license in LICENSE file.
# http://www.lightshowpi.com/
#
# Author: <NAME> (<EMAIL>)
#
# TODO(todd): Refactor the configuration manager into a configuration manager class (to remove
#                  the extensive use of globals currently used).
# TODO(todd): Add a main and allow running configuration manager alone to view the current
#                  configuration, and potentially edit it.
"""Configuration management for the lightshow.

Configuration files are all located in the <homedir>/config directory. This file contains tools to
manage these configuration files.
"""
# The home directory and configuration directory for the application.

import ConfigParser
import ast
import datetime
import fcntl
import logging
import os
import os.path
import sys
import warnings
import json


HOME_DIR = os.getenv("SYNCHRONIZED_LIGHTS_HOME")
if not HOME_DIR:
    print("Need to setup SYNCHRONIZED_LIGHTS_HOME environment variable, "
          "see readme")
    sys.exit()
CONFIG_DIR = HOME_DIR + '/config'
LOG_DIR = HOME_DIR + '/logs'

# Load configuration file, loads defaults from config directory, and then
# overrides from the same directory cfg file, then from /home/pi/.lights.cfg
# and then from ~/.lights.cfg (which will be the root's home).
CONFIG = ConfigParser.RawConfigParser(allow_no_value=True)
CONFIG.readfp(open(CONFIG_DIR + '/defaults.cfg'))
CONFIG.read([CONFIG_DIR + '/overrides.cfg', '/home/pi/.lights.cfg',
             os.path.expanduser('~/.lights.cfg')])

def _as_list(list_str, delimiter=','):
    """Return a list of items from a delimited string (after stripping whitespace)."""
    return [str.strip(item) for item in list_str.split(delimiter)]

# Retrieve hardware configuration
_HARDWARE_CONFIG = {}
def hardware():
    """
    Retrieves the hardware configuration

    loading and parsing it from a file if necessary.
    """

    global _HARDWARE_CONFIG
    if len(_HARDWARE_CONFIG) == 0:
        _HARDWARE_CONFIG = dict(CONFIG.items('hardware'))

        # Devices
        devices = dict()

        try:
            devices = json.loads(_HARDWARE_CONFIG['devices'])
        except Exception as error:
            logging.error("devices not defined or not in JSON format." \
                + str(error))

        _HARDWARE_CONFIG["devices"] = devices

    return _HARDWARE_CONFIG

# Retrieve light show configuration
_LIGHTSHOW_CONFIG = {}
def lightshow():
    """
    Retrieve the lightshow configuration

    loading and parsing it from a file as necessary.
    """
    global _LIGHTSHOW_CONFIG
    if len(_LIGHTSHOW_CONFIG) == 0:
        _LIGHTSHOW_CONFIG = dict(CONFIG.items('lightshow'))

        _LIGHTSHOW_CONFIG['audio_in_channels'] = \
            CONFIG.getint('lightshow', 'audio_in_channels')
        _LIGHTSHOW_CONFIG['audio_in_sample_rate'] = \
            CONFIG.getint('lightshow', 'audio_in_sample_rate')

        # setup up preshow
        preshow = dict()

        if "preshow_configuration" in _LIGHTSHOW_CONFIG:
            try:
                preshow = \
                    json.loads(_LIGHTSHOW_CONFIG['preshow_configuration'])
            except (ValueError, TypeError) as error:
                logging.error("Preshow_configuration not defined or not in "
                              "JSON format." + str(error))

        if "preshow_script" in _LIGHTSHOW_CONFIG:
            if os.path.isfile(_LIGHTSHOW_CONFIG['preshow_script']):
                preshow = _LIGHTSHOW_CONFIG['preshow_script']

        _LIGHTSHOW_CONFIG['preshow'] = preshow

        # setup postshow
        postshow = dict()

        if "postshow_configuration" in _LIGHTSHOW_CONFIG:
            try:
                postshow = \
                    json.loads(_LIGHTSHOW_CONFIG['postshow_configuration'])
            except (ValueError, TypeError) as error:
                logging.error("Postshow_configuration not "
                              "defined or not in JSON format." + str(error))

        if "postshow_script" in _LIGHTSHOW_CONFIG:
            if os.path.isfile(_LIGHTSHOW_CONFIG['postshow_script']):
                postshow = _LIGHTSHOW_CONFIG['postshow_script']
        _LIGHTSHOW_CONFIG['postshow'] = postshow

    return _LIGHTSHOW_CONFIG

_SMS_CONFIG = {}
_WHO_CAN = {}
def sms():
    """Retrieves and validates sms configuration"""
    global _SMS_CONFIG, _WHO_CAN
    if len(_SMS_CONFIG) == 0:
        _SMS_CONFIG = dict(CONFIG.items('sms'))
        _WHO_CAN = dict()
        _WHO_CAN['all'] = set()

        # Commands
        _SMS_CONFIG['commands'] = _as_list(_SMS_CONFIG['commands'])
        for cmd in _SMS_CONFIG['commands']:
            try:
                _SMS_CONFIG[cmd + '_aliases'] = _as_list(_SMS_CONFIG[cmd \
                    + '_aliases'])
            except:
                _SMS_CONFIG[cmd + '_aliases'] = []
            _WHO_CAN[cmd] = set()

        # Groups / Permissions
        _SMS_CONFIG['groups'] = _as_list(_SMS_CONFIG['groups'])
        _SMS_CONFIG['throttled_groups'] = dict()
        for group in _SMS_CONFIG['groups']:
            try:<commit_msg>Get rid of logging error of no preshow or postshow if not defined<commit_after>#!/usr/bin/env python
#
# Licensed under the BSD license.  See full license in LICENSE file.
# http://www.lightshowpi.com/
#
# Author: <NAME> (<EMAIL>)
#
# TODO(todd): Refactor the configuration manager into a configuration manager class (to remove
#                  the extensive use of globals currently used).
# TODO(todd): Add a main and allow running configuration manager alone to view the current
#                  configuration, and potentially edit it.
"""Configuration management for the lightshow.

Configuration files are all located in the <homedir>/config directory. This file contains tools to
manage these configuration files.
"""
# The home directory and configuration directory for the application.

import ConfigParser
import ast
import datetime
import fcntl
import logging
import os
import os.path
import sys
import warnings
import json


HOME_DIR = os.getenv("SYNCHRONIZED_LIGHTS_HOME")
if not HOME_DIR:
    print("Need to setup SYNCHRONIZED_LIGHTS_HOME environment variable, "
          "see readme")
    sys.exit()
CONFIG_DIR = HOME_DIR + '/config'
LOG_DIR = HOME_DIR + '/logs'

# Load configuration file, loads defaults from config directory, and then
# overrides from the same directory cfg file, then from /home/pi/.lights.cfg
# and then from ~/.lights.cfg (which will be the root's home).
CONFIG = ConfigParser.RawConfigParser(allow_no_value=True)
CONFIG.readfp(open(CONFIG_DIR + '/defaults.cfg'))
CONFIG.read([CONFIG_DIR + '/overrides.cfg', '/home/pi/.lights.cfg',
             os.path.expanduser('~/.lights.cfg')])

def _as_list(list_str, delimiter=','):
    """Return a list of items from a delimited string (after stripping whitespace)."""
    return [str.strip(item) for item in list_str.split(delimiter)]

# Retrieve hardware configuration
_HARDWARE_CONFIG = {}
def hardware():
    """
    Retrieves the hardware configuration

    loading and parsing it from a file if necessary.
    """

    global _HARDWARE_CONFIG
    if len(_HARDWARE_CONFIG) == 0:
        _HARDWARE_CONFIG = dict(CONFIG.items('hardware'))

        # Devices
        devices = dict()

        try:
            devices = json.loads(_HARDWARE_CONFIG['devices'])
        except Exception as error:
            logging.error("devices not defined or not in JSON format." \
                + str(error))

        _HARDWARE_CONFIG["devices"] = devices

    return _HARDWARE_CONFIG

# Retrieve light show configuration
_LIGHTSHOW_CONFIG = {}
def lightshow():
    """
    Retrieve the lightshow configuration

    loading and parsing it from a file as necessary.
    """
    global _LIGHTSHOW_CONFIG
    if len(_LIGHTSHOW_CONFIG) == 0:
        _LIGHTSHOW_CONFIG = dict(CONFIG.items('lightshow'))

        _LIGHTSHOW_CONFIG['audio_in_channels'] = \
            CONFIG.getint('lightshow', 'audio_in_channels')
        _LIGHTSHOW_CONFIG['audio_in_sample_rate'] = \
            CONFIG.getint('lightshow', 'audio_in_sample_rate')

        # setup up preshow
        preshow = None
        if (CONFIG.get('lightshow', 'preshow_configuration') 
            and not CONFIG.get('lightshow', 'preshow_script')):
            try:
                preshow = \
                    json.loads(_LIGHTSHOW_CONFIG['preshow_configuration'])
            except (ValueError, TypeError) as error:
                logging.error("Preshow_configuration not defined or not in "
                              "JSON format." + str(error))
        else:
            if os.path.isfile(_LIGHTSHOW_CONFIG['preshow_script']):
                preshow = _LIGHTSHOW_CONFIG['preshow_script']

        _LIGHTSHOW_CONFIG['preshow'] = preshow

        # setup postshow
        postshow = None
        if (CONFIG.get('lightshow', 'postshow_configuration') 
            and not CONFIG.get('lightshow', 'postshow_script')):
            try:
                postshow = \
                    json.loads(_LIGHTSHOW_CONFIG['postshow_configuration'])
            except (ValueError, TypeError) as error:
                logging.error("Postshow_configuration not "
                              "defined or not in JSON format." + str(error))
        else:
            if os.path.isfile(_LIGHTSHOW_CONFIG['postshow_script']):
                postshow = _LIGHTSHOW_CONFIG['postshow_script']
        _LIGHTSHOW_CONFIG['postshow'] = postshow

    return _LIGHTSHOW_CONFIG

_SMS_CONFIG = {}
_WHO_CAN = {}
def sms():
    """Retrieves and validates sms configuration"""
    global _SMS_CONFIG, _WHO_CAN
    if len(_SMS_CONFIG) == 0:
        _SMS_CONFIG = dict(CONFIG.items('sms'))
        _WHO_CAN = dict()
        _WHO_CAN['all'] = set()

        # Commands
        _SMS_CONFIG['commands'] = _as_list(_SMS_CONFIG['commands'])
        for cmd in _SMS_CONFIG['commands']:
            try:
                _SMS_CONFIG[cmd + '_aliases'] = _as_list(_SMS_CONFIG[cmd \
                    + '_aliases'])
            except:
                _SMS_CONFIG[cmd + '_aliases'] = []
            _WHO_CAN[cmd] = set()

        # Groups / Permissions
        _SMS_CONFIG['groups'] = _as_list(_SMS_CONFIG['groups'])
        _SMS_CONFIG['throttled_groups'] = dict()
        for group in _SMS_CONFIG['groups']:
            try:
{'fraction_non_alphanumeric': 0.09974869514788325, 'fraction_numerical': 0.0005799342741156003, 'mean_word_length': 2.680896478121665, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3367391', 'n_tokens_mistral': 3067, 'n_tokens_neox': 2970, 'n_words': 791}