def process_config(config_path, py3_wrapper=None):
def notify_user(error):<EOL><INDENT>if py3_wrapper:<EOL><INDENT>py3_wrapper.notify_user(error)<EOL><DEDENT>else:<EOL><INDENT>print(error)<EOL><DEDENT><DEDENT>def parse_config(config):<EOL><INDENT>"""<STR_LIT>"""<EOL>if hasattr(config, "<STR_LIT>"):<EOL><INDENT>config = "<STR_LIT>".join(config.readlines())<EOL><DEDENT>parser = ConfigParser(config, py3_wrapper)<EOL>parser.parse()<EOL>parsed = parser.config<EOL>del parser<EOL>return parsed<EOL><DEDENT>def parse_config_error(e, config_path):<EOL><INDENT>error = e.one_line(config_path)<EOL>notify_user(error)<EOL>for char in ['<STR_LIT:">', "<STR_LIT:{>", "<STR_LIT:|>"]:<EOL><INDENT>error = error.replace(char, "<STR_LIT:\\>" + char)<EOL><DEDENT>error_config = Template(ERROR_CONFIG).substitute(error=error)<EOL>return parse_config(error_config)<EOL><DEDENT>config = {}<EOL>try:<EOL><INDENT>encoding = check_output(<EOL>["<STR_LIT:file>", "<STR_LIT>", "<STR_LIT>", "<STR_LIT>", config_path]<EOL>)<EOL>encoding = encoding.strip().decode("<STR_LIT:utf-8>")<EOL><DEDENT>except CalledProcessError:<EOL><INDENT>encoding = "<STR_LIT:utf-8>"<EOL><DEDENT>try:<EOL><INDENT>with codecs.open(config_path, "<STR_LIT:r>", encoding) as f:<EOL><INDENT>try:<EOL><INDENT>config_info = parse_config(f)<EOL><DEDENT>except ParseException as e:<EOL><INDENT>config_info = parse_config_error(e, config_path)<EOL><DEDENT><DEDENT><DEDENT>except LookupError:<EOL><INDENT>with codecs.open(config_path) as f:<EOL><INDENT>try:<EOL><INDENT>config_info = parse_config(f)<EOL><DEDENT>except ParseException as e:<EOL><INDENT>config_info = parse_config_error(e, config_path)<EOL><DEDENT><DEDENT><DEDENT>general_defaults = GENERAL_DEFAULTS.copy()<EOL>if "<STR_LIT>" in config_info:<EOL><INDENT>general_defaults.update(config_info["<STR_LIT>"])<EOL><DEDENT>config["<STR_LIT>"] = general_defaults<EOL>config["<STR_LIT>"] = config_info.get("<STR_LIT>", {})<EOL>modules = {}<EOL>on_click = {}<EOL>i3s_modules = []<EOL>py3_modules = []<EOL>module_groups = {}<EOL>def process_onclick(key, value, group_name):<EOL><INDENT>"""<STR_LIT>"""<EOL>button_error = False<EOL>button = "<STR_LIT>"<EOL>try:<EOL><INDENT>button = key.split()[<NUM_LIT:1>]<EOL>if int(button) not in range(<NUM_LIT:1>, <NUM_LIT:20>):<EOL><INDENT>button_error = True<EOL><DEDENT><DEDENT>except (ValueError, IndexError):<EOL><INDENT>button_error = True<EOL><DEDENT>if button_error:<EOL><INDENT>err = "<STR_LIT>"<EOL>notify_user(err.format(group_name, button))<EOL>return False<EOL><DEDENT>clicks = on_click.setdefault(group_name, {})<EOL>clicks[button] = value<EOL>return True<EOL><DEDENT>def get_module_type(name):<EOL><INDENT>"""<STR_LIT>"""<EOL>if name.split()[<NUM_LIT:0>] in I3S_MODULE_NAMES:<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>return "<STR_LIT>"<EOL><DEDENT>def process_module(name, module, parent):<EOL><INDENT>if parent:<EOL><INDENT>modules[parent]["<STR_LIT>"].append(name)<EOL>mg = module_groups.setdefault(name, [])<EOL>mg.append(parent)<EOL>if get_module_type(name) == "<STR_LIT>":<EOL><INDENT>module["<STR_LIT>"] = parent<EOL><DEDENT><DEDENT>for k, v in list(module.items()):<EOL><INDENT>if k.startswith("<STR_LIT>"):<EOL><INDENT>process_onclick(k, v, name)<EOL>del module[k]<EOL><DEDENT>if isinstance(v, ModuleDefinition):<EOL><INDENT>module["<STR_LIT>"] = []<EOL><DEDENT><DEDENT>return module<EOL><DEDENT>def get_modules(data, parent=None):<EOL><INDENT>for k, v in data.items():<EOL><INDENT>if isinstance(v, ModuleDefinition):<EOL><INDENT>module = process_module(k, v, parent)<EOL>modules[k] = module<EOL>get_modules(v, parent=k)<EOL><DEDENT><DEDENT><DEDENT>get_modules(config_info)<EOL>config["<STR_LIT>"] = []<EOL>def remove_any_contained_modules(module):<EOL><INDENT>"""<STR_LIT>"""<EOL>fixed = {}<EOL>for k, v in module.items():<EOL><INDENT>if not isinstance(v, ModuleDefinition):<EOL><INDENT>fixed[k] = v<EOL><DEDENT><DEDENT>return fixed<EOL><DEDENT>def append_modules(item):<EOL><INDENT>module_type = get_module_type(item)<EOL>if module_type == "<STR_LIT>":<EOL><INDENT>if item not in i3s_modules:<EOL><INDENT>i3s_modules.append(item)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if item not in py3_modules:<EOL><INDENT>py3_modules.append(item)<EOL><DEDENT><DEDENT><DEDENT>def add_container_items(module_name):<EOL><INDENT>module = modules.get(module_name, {})<EOL>items = module.get("<STR_LIT>", [])<EOL>for item in items:<EOL><INDENT>if item in config:<EOL><INDENT>continue<EOL><DEDENT>append_modules(item)<EOL>module = modules.get(item, {})<EOL>config[item] = remove_any_contained_modules(module)<EOL>add_container_items(item)<EOL><DEDENT><DEDENT>for name in config_info.get("<STR_LIT>", []):<EOL><INDENT>if name in module_groups:<EOL><INDENT>msg = "<STR_LIT>"<EOL>msg += "<STR_LIT>"<EOL>notify_user(msg.format(name))<EOL>continue<EOL><DEDENT>module_name = name.split("<STR_LIT:U+0020>")[<NUM_LIT:0>]<EOL>if module_name in RETIRED_MODULES:<EOL><INDENT>notify_user(<EOL>"<STR_LIT>".format(module_name)<EOL>+ "<STR_LIT>".format(<EOL>"<STR_LIT:U+002CU+0020>".join("<STR_LIT>".format(x) for x in RETIRED_MODULES[module_name])<EOL>)<EOL>)<EOL>continue<EOL><DEDENT>module = modules.get(name, {})<EOL>config["<STR_LIT>"].append(name)<EOL>add_container_items(name)<EOL>append_modules(name)<EOL>config[name] = remove_any_contained_modules(module)<EOL><DEDENT>config["<STR_LIT>"] = on_click<EOL>config["<STR_LIT>"] = i3s_modules<EOL>config["<STR_LIT>"] = py3_modules<EOL>config["<STR_LIT>"] = module_groups<EOL>for name in config:<EOL><INDENT>if name.split()[<NUM_LIT:0>] in TIME_MODULES and "<STR_LIT>" not in config[name]:<EOL><INDENT>if name.split()[<NUM_LIT:0>] == "<STR_LIT:time>":<EOL><INDENT>config[name]["<STR_LIT>"] = TIME_FORMAT<EOL><DEDENT>else:<EOL><INDENT>config[name]["<STR_LIT>"] = TZTIME_FORMAT<EOL><DEDENT><DEDENT><DEDENT>if not config["<STR_LIT>"]:<EOL><INDENT>notify_user(<EOL>"<STR_LIT>"<EOL>'<STR_LIT>'<EOL>)<EOL><DEDENT>return config<EOL>
Parse i3status.conf so we can adapt our code to the i3status config.