#!/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: float 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 Creates necessary data directory and data file. If they exist, no error occurs. Checks that the data directory and data file are group and other readable. Sets some correct permissions if they are not. Other errors may raise an exception. """ USER.datadir.mkdir(mode=0o755, exist_ok=True) if not USER.settingsfile.is_file(): with open(USER.settingsfile, "w+") as the_file: the_file.write( "[User Status]\nlastlogin = 0.0\n\n[User Settings]\nbrowser = lynx" ) 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) 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" )