import os, argparse from tomlkit import loads from tomlkit import dump def nest_dictionary(d, keys, val): for key in keys: d = d.setdefault(key, val) return d class MicroblogConfig: def __init__(self, given_config): self.is_outdated = False self.updated = given_config def compare(self, sref, suser, keylist=[]): # subtable of ref, subtable of user updated = self.updated # nnavigate to table if keylist != []: for key in keylist: sref = sref[key] for key in keylist: suser = suser[key] for key in keylist: updated = updated[key] for key in sref: if key not in suser: self.is_outdated = True updated[key] =sref[key] print("noticed '", key, "' missing from ", keylist) nest_dictionary(self.updated, keylist, updated) return def check(self, r, u): # (reference, user) for key in r: if key == "latestpages": continue # post and webring have subtables # webring.profile # webring.following # webring.following.internal-avatars # post.gallery # post.buttons try: self.compare(r, u, [key]) except KeyError: u[key] = dict() print("missing top-level table '", key, '\'') self.compare(r, u, [key]) if key == "webring": self.compare(r, u, ["webring", "profile"]) self.compare(r, u, ["webring", "following"]) self.compare(r, u, ["webring", "following", "internal-avatars"]) if key == "post": self.compare(r, u, ["post", "gallery"]) self.compare(r, u, ["post", "buttons"]) pass def load_files(user_conf_file): script_dir = os.path.dirname( os.path.abspath(__file__)) parent_dir = os.path.abspath( os.path.join(script_dir, os.pardir)) target_folder = "example" example = os.path.abspath( os.path.join(parent_dir, target_folder)) ref_file = "%s/%s" % (example, "/settings.toml") if not os.path.exists(ref_file): return ref_conf = dict() with open(ref_file, 'r') as f: ref_conf = loads(f.read()) user_conf = dict() with open(user_conf_file, 'r') as f: user_conf = loads(f.read()) return ref_conf, user_conf def multi_prompt(message): try: while True: user_input = int(input(f"{message}").lower()) if user_input < 3: return user_input else: return 0 except KeyboardInterrupt: print() except ValueError: pass return 0 def get_args(): p = argparse.ArgumentParser() p.add_argument("--no-prompt", action="store_true", \ help="does not ask what to do if missing keys are detected") p.add_argument("-c", "--check", type=str,\ help="sets/changes the file to be checked (default: settings.toml)") args = p.parse_args() if args.no_prompt: print("'--no-prompt' set") if args.check: print("--check set", args.check) else: args.check = "settings.toml" return args.no_prompt, args.check def main(is_no_prompt, user_conf_file="settings.toml"): print("checking ", user_conf_file) reference, user_edited = load_files(user_conf_file) mcfg = MicroblogConfig(user_edited) mcfg.check(reference, user_edited) if mcfg.is_outdated == False: print("Your settings file is OK!") return message = """ Your settings file is outdated. Do you want to... \t 1. save new settings to new file \t 2. update/overwrite existing settings \t *. do nothing """ response = 0 if is_no_prompt else multi_prompt(message) out_file = str() if response == 0: return elif response == 1: out_file = "new.toml" elif response == 2: out_file = user_conf_file with open(out_file, 'w') as f: dump(mcfg.updated, f) print("Wrote updated config to ", out_file) pass if __name__ == "__main__": main(*get_args())