#!/usr/bin/env python3 """stores configuration settings for linkulator""" import configparser import stat from pathlib import Path from time import time class DefaultPaths: """data class containing configurable path defaults""" all_homedir_pattern: str = "/home/*/" datadir: str = ".linkulator" datafile: str = "linkulator.data" ignorefile: str = "ignore" settingsfile: str = "linkulatorrc" PATHS = DefaultPaths() class DefaultUser: """data class containing user defaults""" datadir: Path = Path.home() / PATHS.datadir datafile: Path = datadir / PATHS.datafile ignorefile: Path = datadir / PATHS.ignorefile settingsfile: Path = datadir / PATHS.settingsfile lastlogin: str = "0.0" browser: str = "lynx" def save(self): """Saves config data to file""" config = configparser.ConfigParser() config["User Status"] = {"lastlogin": time()} config["User Settings"] = {"browser": self.browser} with open(self.settingsfile, "w") as file: config.write(file) def load(self): """Loads from config file""" config = configparser.ConfigParser() ret = config.read(self.settingsfile) if len(ret) > 0: self.lastlogin = config["User Status"]["lastlogin"] self.browser = config["User Settings"]["browser"] USER = DefaultUser() def is_readable(st_mode: int) -> bool: """Checks the provided mode is group and other readable, returns true if this is the case Check if 700 is readable: >>> is_readable(16832) False Check if 755 is readable: >>> is_readable(16877) True """ if bool(st_mode & stat.S_IRGRP) & bool(st_mode & stat.S_IROTH): return True return False def init(): """Performs startup checks to ensure environment is set up for use If required, creates necessary data directory and data file. If required, sets permissions to ensure the data directory and data file are group and other readable. Finally, tries to load the linkulator user configuration file, overwriting with defaults if any issues. """ if not USER.datadir.exists(): USER.datadir.mkdir(mode=0o755, exist_ok=True) if not is_readable(USER.datadir.stat().st_mode): print( "Warning: %s is not group or other readable - changing permissions" % str(USER.datadir) ) USER.datadir.chmod(0o755) if not USER.datafile.exists(): USER.datafile.touch(mode=0o644, exist_ok=True) if not is_readable(USER.datafile.stat().st_mode): print( "Warning: %s is not group or other readable - changing permissions" % str(USER.datafile) ) USER.datafile.chmod(0o644) try: USER.load() except configparser.MissingSectionHeaderError: print( "Warning: config file has invalid syntax and will be overwritten with default values" )