def setup_file_handler(logger, path, max_size=100, backup_ct=5): """ Returns a rotating file handler. """ # Confirm that the path exists path = get_path(path) folder = os.path.dirname(path) if not os.path.exists(folder): raise IOError("Unable to create file logger " "- path '{}' doesn't exist".format(folder)) # Create the handler handler = logging.handlers.RotatingFileHandler( filename=path, maxBytes=max_size * (10**6), backupCount=backup_ct) handler.setFormatter(FORMATTER) handler.addFilter(ContextFilter()) # Attach it to the logger logger.addHandler(handler)
def setup_file_handler(logger, path, max_size=100, backup_ct=5): """ Returns a rotating file handler. """ # Confirm that the path exists path = get_path(path) folder = os.path.dirname(path) if not os.path.exists(folder): raise IOError("Unable to create file logger " "- path '{}' doesn't exist".format(folder)) # Create the handler handler = logging.handlers.RotatingFileHandler(filename=path, maxBytes=max_size * (10**6), backupCount=backup_ct) handler.setFormatter(FORMATTER) handler.addFilter(ContextFilter()) # Attach it to the logger logger.addHandler(handler)
def get_grunt_gender(grunt_id): try: if not hasattr(get_grunt_gender, 'id'): get_grunt_gender.genders = {} file_ = get_path('locales/en.json') with open(file_, 'r') as f: j = json.loads(f.read()) j = j['grunt_genders'] for id_ in j: get_grunt_gender.genders[id_] = j[id_] try: return get_grunt_gender.genders['{:03d}'.format(grunt_id)] except KeyError: return '?' except ValueError: raise ValueError( 'Unable to interpret `{}` as a valid grunt id'.format(grunt_id))
def get_type_id(type_name): try: name = str(type_name).lower() if not hasattr(get_type_id, 'types'): get_type_id.ids = {} files = glob(get_path('locales/*.json')) for file_ in files: with open(file_, 'r') as f: j = json.loads(f.read()) j = j['types'] for id_ in j: nm = j[id_].lower() get_type_id.ids[nm] = int(id_) if name in get_type_id.ids: return get_type_id.ids[name] else: return int(name) # try as an integer except Exception: raise ValueError("Unable to interpret `{}` as a valid" " type name or id.".format(type_name))
def get_team_id(team_name): try: name = str(team_name).lower() if not hasattr(get_team_id, 'ids'): get_team_id.ids = {} files = glob(get_path('locales/*.json')) for file_ in files: with open(file_, 'r') as f: j = json.loads(f.read()) j = j['teams'] for id_ in j: nm = j[id_].lower() get_team_id.ids[nm] = int(id_) if name in get_team_id.ids: return get_team_id.ids[name] else: return int(name) # try as an integer except ValueError: raise ValueError("Unable to interpret `{}` as a valid " " team name or id.".format(team_name))
def get_monster_id(pokemon_name): try: name = unicode(pokemon_name).lower() if not hasattr(get_monster_id, 'ids'): get_monster_id.ids = {} files = glob(get_path('locales/*.json')) for file_ in files: with open(file_, 'r') as f: j = json.loads(f.read()) j = j['pokemon'] for id_ in j: nm = j[id_].lower() get_monster_id.ids[nm] = int(id_) if name in get_monster_id.ids: return get_monster_id.ids[name] else: return int(name) # try as an integer except ValueError: raise ValueError("Unable to interpret `{}` as a valid " " monster name or id.".format(pokemon_name))
def get_day_or_night_id(day_or_night): try: name = str(day_or_night).lower() if not hasattr(get_day_or_night_id, 'ids'): get_day_or_night_id.ids = {} files = glob(get_path('locales/*.json')) for file_ in files: with open(file_, 'r') as f: j = json.loads(f.read()) j = j['day_or_night'] for id_ in j: nm = j[id_].lower() get_day_or_night_id.ids[nm] = int(id_) if name in get_day_or_night_id.ids: return get_day_or_night_id.ids[name] else: return int(name) # try as an integer except ValueError: raise ValueError("Unable to interpret `{}` as a valid " " day or night name or id.".format(day_or_night))
def get_grunt_type_id(grunt_name): try: name = str(grunt_name).lower() if not hasattr(get_grunt_type_id, 'types'): get_grunt_type_id.types = {} files = glob(get_path('locales/*.json')) for file_ in files: with open(file_, 'r') as f: j = json.loads(f.read()) j = j['types'] for id_ in j: nm = j[id_].lower() get_grunt_type_id.types[nm] = int(id_) if name in get_grunt_type_id.types: return get_grunt_type_id.types[name] else: return int(name) # try as an integer except ValueError: # Some grunt types don't match up to a monster type return '?'
def get_grunt_id(grunt_name): try: name = unicode(grunt_name).lower() if not hasattr(get_grunt_id, 'ids'): get_grunt_id.ids = {} files = glob(get_path('locales/*.json')) for file_ in files: with open(file_, 'r') as f: j = json.loads(f.read()) j = j['grunt_types'] for id_ in j: nm = j[id_].lower() try: if get_grunt_id.ids[nm]: get_grunt_id.ids[nm].append(int(id_)) except KeyError: get_grunt_id.ids[nm] = [int(id_)] if name in get_grunt_id.ids: return get_grunt_id.ids[name] else: return int(name) # try as an integer except ValueError: raise ValueError("Unable to interpret `{}` as a valid " " grunt name or id.".format(grunt_name))
def parse_settings(root_path): config['ROOT_PATH'] = root_path # Set the default config files up config_files = [get_path('config/config.ini')] if '-cf' not in sys.argv and '--config' not in sys.argv else [] parser = configargparse.ArgParser(default_config_files=config_files) parser.add_argument('-cf', '--config', is_config_file=True, help='Configuration file') parser.add_argument('-d', '--debug', help='Debug Mode', action='store_true', default=False) parser.add_argument('-H', '--host', help='Set web server listening host', default='127.0.0.1') parser.add_argument('-P', '--port', type=int, help='Set web server listening port', default=4000) parser.add_argument('-m', '--manager_count', type=int, default=1, help='Number of Manager processes to start.') parser.add_argument('-M', '--manager_name', type=parse_unicode, action='append', default=[], help='Names of Manager processes to start.') parser.add_argument('-k', '--key', type=parse_unicode, action='append', default=[None], help='Specify a Google API Key to use.') parser.add_argument('-f', '--filters', type=parse_unicode, action='append', default=['filters.json'], help='Filters configuration file. default: filters.json') parser.add_argument('-a', '--alarms', type=parse_unicode, action='append', default=['alarms.json'], help='Alarms configuration file. default: alarms.json') parser.add_argument('-gf', '--geofences', type=parse_unicode, action='append', default=[None], help='Alarms configuration file. default: None') parser.add_argument('-l', '--location', type=parse_unicode, action='append', default=[None], help='Location, can be an address or coordinates') parser.add_argument('-L', '--locale', type=parse_unicode, action='append', default=['en'], choices=['de', 'en', 'es', 'fr', 'it', 'ko', 'zh_hk'], help='Locale for Pokemon and Move names: default en, check locale folder for more options') parser.add_argument('-u', '--units', type=parse_unicode, default=['imperial'], action='append', choices=['metric', 'imperial'], help='Specify either metric or imperial units to use for distance measurements. ') parser.add_argument('-tl', '--timelimit', type=int, default=[0], action='append', help='Minimum number of seconds remaining on a pokemon to send a notify') parser.add_argument('-ma', '--max_attempts', type=int, default=[3], action='append', help='Maximum number of attempts an alarm makes to send a notification.') parser.add_argument('-tz', '--timezone', type=str, action='append', default=[None], help='Timezone used for notifications. Ex: "America/Los_Angeles"') args = parser.parse_args() if args.debug: log.setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG) logging.getLogger('PokeAlarm').setLevel(logging.DEBUG) logging.getLogger('Manager').setLevel(logging.DEBUG) log.debug("Debug mode enabled!") config['HOST'] = args.host config['PORT'] = args.port config['DEBUG'] = args.debug # Check to make sure that the same number of arguements are included for list_ in [args.key, args.filters, args.alarms, args.geofences, args.location, args.locale, args.units, args.timelimit, args.max_attempts, args.timezone]: if len(list_) > 1: # Remove defaults from the list list_.pop(0) size = len(list_) if size != 1 and size != args.manager_count: log.critical("Number of arguments must be either 1 for all managers or ".format(args.manager_count) + "equal to Manager Count. Please provided the correct number of arguments.") log.critical(list_) sys.exit(1) # Attempt to parse the timezones for i in range(len(args.timezone)): if str(args.timezone[i]).lower() == "none": args.timezone[i] = None continue try: log.info(args.timezone[i]) args.timezone[i] = pytz.timezone(args.timezone[i]) except pytz.exceptions.UnknownTimeZoneError: log.error("Invalid timezone. For a list of valid timezones, " + "see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones") sys.exit(1) # Build the managers for m_ct in range(args.manager_count): # This needs to be changed a few times... because config['UNITS'] = args.units[m_ct] if len(args.units) > 1 else args.units[0] m = Manager( name=args.manager_name[m_ct] if m_ct < len(args.manager_name) else "Manager_{}".format(m_ct), google_key=args.key[m_ct] if len(args.key) > 1 else args.key[0], locale=args.locale[m_ct] if len(args.locale) > 1 else args.locale[0], units=args.units[m_ct] if len(args.units) > 1 else args.units[0], timezone=args.timezone[m_ct] if len(args.timezone) > 1 else args.timezone[0], time_limit=args.timelimit[m_ct] if len(args.timelimit) > 1 else args.timelimit[0], max_attempts=args.max_attempts[m_ct] if len(args.max_attempts) > 1 else args.max_attempts[0], quiet=False, # TODO: I'll totally document this some day. Promise. location=args.location[m_ct] if len(args.location) > 1 else args.location[0], filter_file=args.filters[m_ct] if len(args.filters) > 1 else args.filters[0], geofence_file=args.geofences[m_ct] if len(args.geofences) > 1 else args.geofences[0], alarm_file=args.alarms[m_ct] if len(args.alarms) > 1 else args.alarms[0], debug=config['DEBUG'] ) if m.get_name() not in managers: # Add the manager to the map managers[m.get_name()] = m else: log.critical("Names of Manager processes must be unique (regardless of capitalization)! Process will exit.") sys.exit(1) log.info("Starting up the Managers") for m_name in managers: managers[m_name].start()
def parse_settings(root_path): config['ROOT_PATH'] = root_path # Set the default config files up config_files = [get_path('config/config.ini')] if '-cf' in sys.argv or '--config' in sys.argv: config_files = [] parser = configargparse.ArgParser(default_config_files=config_files) parser.add_argument('-cf', '--config', is_config_file=True, help='Configuration file') # Webserver Settings: parser.add_argument('-d', '--debug', help='Debug Mode', action='store_true', default=False) parser.add_argument('-H', '--host', help='Set web server listening host', default='127.0.0.1') parser.add_argument('-P', '--port', type=int, help='Set web server listening port', default=4000) parser.add_argument( '-C', '--concurrency', type=int, help='Maximum concurrent connections for the webserver.', default=200) # Manager Settings parser.add_argument('-m', '--manager_count', type=int, default=1, help='Number of Manager processes to start.') parser.add_argument('-M', '--manager_name', type=parse_unicode, action='append', default=[], help='Names of Manager processes to start.') # Files parser.add_argument( '-f', '--filters', type=parse_unicode, action='append', default=['filters.json'], help='Filters configuration file. default: filters.json') parser.add_argument('-a', '--alarms', type=parse_unicode, action='append', default=['alarms.json'], help='Alarms configuration file. default: alarms.json') parser.add_argument('-r', '--rules', type=parse_unicode, action='append', default=[None], help='Rules configuration file. default: None') parser.add_argument('-gf', '--geofences', type=parse_unicode, action='append', default=[None], help='Alarms configuration file. default: None') # Location Specific parser.add_argument('-l', '--location', type=parse_unicode, action='append', default=[None], help='Location, can be an address or coordinates') parser.add_argument( '-L', '--locale', type=parse_unicode, action='append', default=['en'], choices=['de', 'en', 'es', 'fr', 'it', 'ko', 'pt', 'zh_hk'], help='Locale for Pokemon and Move names: default en," ' '+ " check locale folder for more options') parser.add_argument( '-u', '--units', type=parse_unicode, default=['imperial'], action='append', choices=['metric', 'imperial'], help='Specify either metric or imperial units to use for distance " ' '+ "measurements. ') parser.add_argument( '-tz', '--timezone', type=str, action='append', default=[None], help='Timezone used for notifications. Ex: "America/Los_Angeles"') # GMaps parser.add_argument('-k', '--gmaps-key', type=str, action='append', default=[], help='Specify a Google API Key to use.') parser.add_argument('--gmaps-rev-geocode', type=parse_boolean, action='append', default=[None], help='Enable Walking Distance Matrix DTS.') parser.add_argument('--gmaps-dm-walk', type=parse_boolean, action='append', default=[None], help='Enable Walking Distance Matrix DTS.') parser.add_argument('--gmaps-dm-bike', type=parse_boolean, action='append', default=[None], help='Enable Bicycling Distance Matrix DTS.') parser.add_argument('--gmaps-dm-drive', type=parse_boolean, action='append', default=[None], help='Enable Driving Distance Matrix DTS.') parser.add_argument('--gmaps-dm-transit', type=parse_boolean, action='append', default=[None], help='Enable Transit Distance Matrix DTS.') # Misc parser.add_argument('-ct', '--cache_type', type=parse_unicode, action='append', default=['mem'], choices=cache_options, help="Specify the type of cache to use. Options: " + "['mem', 'file'] (Default: 'mem')") parser.add_argument('-tl', '--timelimit', type=int, default=[0], action='append', help='Minimum limit') parser.add_argument( '-ma', '--max_attempts', type=int, default=[3], action='append', help='Maximum attempts an alarm makes to send a notification.') parser.add_argument( '-api', '--channel_id', type=parse_unicode, action='append', default=['channel_id.json'], help= 'Translate Filter set and Geofence to Discord API key. default: channel_id.json' ) args = parser.parse_args() if args.debug: log.setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG) logging.getLogger('PokeAlarm').setLevel(logging.DEBUG) logging.getLogger('Manager').setLevel(logging.DEBUG) log.debug("Debug mode enabled!") config['HOST'] = args.host config['PORT'] = args.port config['CONCURRENCY'] = args.concurrency config['DEBUG'] = args.debug # Check to make sure that the same number of arguments are included for arg in [ args.filters, args.alarms, args.rules, args.geofences, args.location, args.locale, args.units, args.cache_type, args.timelimit, args.max_attempts, args.timezone, args.gmaps_rev_geocode, args.gmaps_dm_walk, args.channel_id, args.gmaps_dm_bike, args.gmaps_dm_drive, args.gmaps_dm_transit ]: if len(arg) > 1: # Remove defaults from the list arg.pop(0) size = len(arg) if size != 1 and size != args.manager_count: log.critical("Number of arguments must be either 1 for all " + "managers or equal to Manager Count. Please " + "provided the correct number of arguments.") log.critical(arg) sys.exit(1) # Attempt to parse the timezones for i in range(len(args.timezone)): if str(args.timezone[i]).lower() == "none": args.timezone[i] = None continue try: log.info(args.timezone[i]) args.timezone[i] = pytz.timezone(args.timezone[i]) except pytz.exceptions.UnknownTimeZoneError: log.error("Invalid timezone. For a list of valid timezones, see " + "https://en.wikipedia.org/wiki" + "/List_of_tz_database_time_zones") sys.exit(1) # Pad manager_name to match manager_count while len(args.manager_name) < args.manager_count: m_ct = len(args.manager_name) args.manager_name.append("Manager_{}".format(m_ct)) # Build the managers for m_ct in range(args.manager_count): # TODO: Fix this mess better next time config['UNITS'] = get_from_list(args.units, m_ct, args.units[0]) m = Manager( name=args.manager_name[m_ct], google_key=args.gmaps_key, locale=get_from_list(args.locale, m_ct, args.locale[0]), units=get_from_list(args.units, m_ct, args.units[0]), timezone=get_from_list(args.timezone, m_ct, args.timezone[0]), time_limit=get_from_list(args.timelimit, m_ct, args.timelimit[0]), max_attempts=get_from_list(args.max_attempts, m_ct, args.max_attempts[0]), quiet=False, # TODO: I'll totally document this some day. Promise. cache_type=get_from_list(args.cache_type, m_ct, args.cache_type[0]), location=get_from_list(args.location, m_ct, args.location[0]), filter_file=get_from_list(args.filters, m_ct, args.filters[0]), geofence_file=get_from_list(args.geofences, m_ct, args.geofences[0]), alarm_file=get_from_list(args.alarms, m_ct, args.alarms[0]), debug=config['DEBUG'], channel_id_file=get_from_list(args.channel_id, m_ct, args.channel_id[0])) parse_rules_file(m, get_from_list(args.rules, m_ct, args.rules[0])) # Set up GMaps stuff if get_from_list(args.gmaps_rev_geocode, m_ct, args.gmaps_rev_geocode[0]): m.enable_gmaps_reverse_geocoding() if get_from_list(args.gmaps_dm_walk, m_ct, args.gmaps_dm_walk[0]): m.enable_gmaps_distance_matrix('walking') if get_from_list(args.gmaps_dm_bike, m_ct, args.gmaps_dm_bike[0]): m.enable_gmaps_distance_matrix('biking') if get_from_list(args.gmaps_dm_drive, m_ct, args.gmaps_dm_drive[0]): m.enable_gmaps_distance_matrix('driving') if get_from_list(args.gmaps_dm_transit, m_ct, args.gmaps_dm_transit[0]): m.enable_gmaps_distance_matrix('transit') if m.get_name() not in managers: # Add the manager to the map managers[m.get_name()] = m else: log.critical("Names of Manager processes must be unique " + "(not case sensitive)! Process will exit.") sys.exit(1) log.info("Starting up the Managers") for m_name in managers: managers[m_name].start() # Set up signal handlers for graceful exit signal(signal.SIGINT, exit_gracefully) signal(signal.SIGTERM, exit_gracefully)
def parse_settings(root_path): config['ROOT_PATH'] = root_path # Set the default config files up config_files = [get_path('config/config.ini')] if '-cf' in sys.argv or '--config' in sys.argv: config_files = [] parser = configargparse.ArgParser(default_config_files=config_files) parser.add_argument( '-cf', '--config', is_config_file=True, help='Configuration file') # Webserver Settings: parser.add_argument( '-H', '--host', help='Set web server listening host', default='127.0.0.1') parser.add_argument( '-P', '--port', type=int, help='Set web server listening port', default=4000) parser.add_argument( '-C', '--concurrency', type=int, help='Maximum concurrent connections for the webserver.', default=200) parser.add_argument( '-d', '--debug', action='store_true', default=False, help='Enable debuging mode.') parser.add_argument( '-q', '--quiet', action='store_true', default=False, help='Disables output to console.') parser.add_argument( '-ll', '--log-lvl', type=int, choices=[1, 2, 3, 4, 5], default=3, help='Verbosity of the root logger.') parser.add_argument( '-lf', '--log-file', type=parse_unicode, default='logs/pokealarm.log', help="Path of a file to attach to a manager's logger.") parser.add_argument( '-ls', '--log-size', type=int, default=100, help="Maximum size in mb of a log before rollover.") parser.add_argument( '-lc', '--log-ct', type=int, default=5, help="Maximum number of logs to keep.") # Manager Settings parser.add_argument( '-m', '--manager_count', type=int, default=1, help='Number of Manager processes to start.') parser.add_argument( '-M', '--manager_name', type=parse_unicode, action='append', default=[], help='Names of Manager processes to start.') parser.add_argument( '-mll', '--mgr-log-lvl', type=int, choices=[1, 2, 3, 4, 5], action='append', default=[3], help="Set the verbosity of a manager's logger.") parser.add_argument( '-mlf', '--mgr-log-file', type=parse_unicode, action='append', default=[None], help="Path of a file to attach to a manager's logger.") parser.add_argument( '-mls', '--mgr-log-size', type=int, action='append', default=[100], help="Maximum megabytes of a manager's log before rollover.") parser.add_argument( '-mlc', '--mgr-log-ct', type=int, action='append', default=[5], help="Maximum number of old manager's logs to keep before deletion.") # Files parser.add_argument( '-f', '--filters', type=parse_unicode, action='append', default=['filters.json'], help='Filters configuration file. default: filters.json') parser.add_argument( '-a', '--alarms', type=parse_unicode, action='append', default=['alarms.json'], help='Alarms configuration file. default: alarms.json') parser.add_argument( '-r', '--rules', type=parse_unicode, action='append', default=[None], help='Rules configuration file. default: None') parser.add_argument( '-gf', '--geofences', type=parse_unicode, action='append', default=[None], help='Alarms configuration file. default: None') # Location Specific parser.add_argument( '-l', '--location', type=parse_unicode, action='append', default=[None], help='Location, can be an address or coordinates') parser.add_argument( '-L', '--locale', type=parse_unicode, action='append', default=['en'], choices=['de', 'en', 'es', 'fr', 'it', 'ko', 'pt', 'zh_hk'], help='Locale for Pokemon and Move names: default en," ' '+ " check locale folder for more options') parser.add_argument( '-u', '--units', type=parse_unicode, default=['imperial'], action='append', choices=['metric', 'imperial'], help='Specify either metric or imperial units to use for distance " ' '+ "measurements. ') parser.add_argument( '-tz', '--timezone', type=str, action='append', default=[None], help='Timezone used for notifications. Ex: "America/Los_Angeles"') # GMaps parser.add_argument( '-k', '--gmaps-key', type=parse_unicode, action='append', default=[None], help='Specify a Google API Key to use.') parser.add_argument( '--gmaps-rev-geocode', type=parse_boolean, action='append', default=[None], help='Enable Walking Distance Matrix DTS.') parser.add_argument( '--gmaps-dm-walk', type=parse_boolean, action='append', default=[None], help='Enable Walking Distance Matrix DTS.') parser.add_argument( '--gmaps-dm-bike', type=parse_boolean, action='append', default=[None], help='Enable Bicycling Distance Matrix DTS.') parser.add_argument( '--gmaps-dm-drive', type=parse_boolean, action='append', default=[None], help='Enable Driving Distance Matrix DTS.') parser.add_argument( '--gmaps-dm-transit', type=parse_boolean, action='append', default=[None], help='Enable Transit Distance Matrix DTS.') # Misc parser.add_argument( '-ct', '--cache_type', type=parse_unicode, action='append', default=['mem'], choices=cache_options, help="Specify the type of cache to use. Options: " + "['mem', 'file'] (Default: 'mem')") parser.add_argument( '-tl', '--timelimit', type=int, default=[0], action='append', help='Minimum limit') parser.add_argument( '-ma', '--max_attempts', type=int, default=[3], action='append', help='Maximum attempts an alarm makes to send a notification.') args = parser.parse_args() root_logger = logging.getLogger() if not args.quiet: setup_std_handler(root_logger) # Setup file logging if not os.path.exists(get_path('logs')): os.mkdir(get_path('logs')) setup_file_handler(root_logger, args.log_file, args.log_size, args.log_ct) if args.debug: # Set everything to VERY VERBOSE args.log_lvl = 5 args.mgr_log_lvl = [5] log.info("Debug mode enabled!") logging.getLogger('webserver.internal').setLevel(logging.WARNING) # Set up webserver logging if args.log_lvl == 1: logging.getLogger('pokealarm.webserver').setLevel(logging.WARNING) logging.getLogger('pokealarm.setup').setLevel(logging.WARNING) elif args.log_lvl == 2: logging.getLogger('pokealarm.webserver').setLevel(logging.INFO) logging.getLogger('pokealarm.setup').setLevel(logging.WARNING) elif args.log_lvl == 3: logging.getLogger('pokealarm.webserver').setLevel(logging.INFO) logging.getLogger('pokealarm.setup').setLevel(logging.INFO) elif args.log_lvl == 4: logging.getLogger('pokealarm.webserver').setLevel(logging.INFO) logging.getLogger('pokealarm.setup').setLevel(logging.DEBUG) elif args.log_lvl == 5: logging.getLogger('pokealarm.webserver').setLevel(logging.DEBUG) logging.getLogger('pokealarm.setup').setLevel(logging.DEBUG) config['HOST'] = args.host config['PORT'] = args.port config['CONCURRENCY'] = args.concurrency config['DEBUG'] = args.debug # Check to make sure that the same number of arguments are included for arg in [args.gmaps_key, args.filters, args.alarms, args.rules, args.geofences, args.location, args.locale, args.units, args.cache_type, args.timelimit, args.max_attempts, args.timezone, args.gmaps_rev_geocode, args.gmaps_dm_walk, args.gmaps_dm_bike, args.gmaps_dm_drive, args.gmaps_dm_transit, args.mgr_log_lvl, args.mgr_log_size, args.mgr_log_file]: if len(arg) > 1: # Remove defaults from the list arg.pop(0) size = len(arg) if size != 1 and size != args.manager_count: log.critical("Number of arguments must be either 1 for all " + "managers or equal to Manager Count. Please " + "provided the correct number of arguments.") log.critical(arg) sys.exit(1) # Attempt to parse the timezones for i in range(len(args.timezone)): if str(args.timezone[i]).lower() == "none": args.timezone[i] = None continue try: log.info(args.timezone[i]) args.timezone[i] = pytz.timezone(args.timezone[i]) except pytz.exceptions.UnknownTimeZoneError: log.error("Invalid timezone. For a list of valid timezones, see " + "https://en.wikipedia.org/wiki" + "/List_of_tz_database_time_zones") sys.exit(1) # Pad manager_name to match manager_count while len(args.manager_name) < args.manager_count: m_ct = len(args.manager_name) args.manager_name.append("Manager_{}".format(m_ct)) # Build the managers for m_ct in range(args.manager_count): # TODO: Fix this mess better next time log.info("----------- Setting up 'manager_0'") config['UNITS'] = get_from_list(args.units, m_ct, args.units[0]) m = Manager( name=args.manager_name[m_ct], google_key=get_from_list( args.gmaps_key, m_ct, args.gmaps_key[0]), locale=get_from_list(args.locale, m_ct, args.locale[0]), units=get_from_list(args.units, m_ct, args.units[0]), timezone=get_from_list(args.timezone, m_ct, args.timezone[0]), time_limit=get_from_list(args.timelimit, m_ct, args.timelimit[0]), max_attempts=get_from_list( args.max_attempts, m_ct, args.max_attempts[0]), cache_type=get_from_list( args.cache_type, m_ct, args.cache_type[0]), location=get_from_list(args.location, m_ct, args.location[0]), geofence_file=get_from_list( args.geofences, m_ct, args.geofences[0]), debug=config['DEBUG'] ) m.set_log_level(get_from_list( args.mgr_log_lvl, m_ct, args.mgr_log_lvl[0])) file_log = get_from_list(args.mgr_log_file, m_ct, args.mgr_log_file[0]) if str(file_log).lower() != "none": size = get_from_list(args.mgr_log_size, m_ct, args.mgr_log_size[0]) log_ct = get_from_list(args.mgr_log_ct, m_ct, args.mgr_log_ct[0]) m.add_file_logger(file_log, size, log_ct) parse_filters_file( m, get_from_list(args.filters, m_ct, args.filters[0])) parse_alarms_file( m, get_from_list(args.alarms, m_ct, args.alarms[0])) parse_rules_file(m, get_from_list(args.rules, m_ct, args.rules[0])) # Set up GMaps stuff if get_from_list( args.gmaps_rev_geocode, m_ct, args.gmaps_rev_geocode[0]): m.enable_gmaps_reverse_geocoding() if get_from_list(args.gmaps_dm_walk, m_ct, args.gmaps_dm_walk[0]): m.enable_gmaps_distance_matrix('walking') if get_from_list(args.gmaps_dm_bike, m_ct, args.gmaps_dm_bike[0]): m.enable_gmaps_distance_matrix('biking') if get_from_list(args.gmaps_dm_drive, m_ct, args.gmaps_dm_drive[0]): m.enable_gmaps_distance_matrix('driving') if get_from_list( args.gmaps_dm_transit, m_ct, args.gmaps_dm_transit[0]): m.enable_gmaps_distance_matrix('transit') if m.get_name() not in managers: # Add the manager to the map managers[m.get_name()] = m else: log.critical("Names of Manager processes must be unique " + "(not case sensitive)! Process will exit.") sys.exit(1) log.info("----------- Finished setting up 'manager_0'") for m_name in managers: managers[m_name].start() # Set up signal handlers for graceful exit signal(signal.SIGINT, exit_gracefully) signal(signal.SIGTERM, exit_gracefully)