class Command: def __init__(self, f_name, f_obj, help, module = "Builtin"): self.log = Log() self.log.newline() self.log.info("Creating command {}".format(f_name)) self.log.line("-") self.name = f_name self.func = f_obj self.help = self.func.__doc__ or "" self.module = module self.admin_required = "admin" in self.func.__code__.co_varnames self.nargs = self.func.__code__.co_argcount self.defaults = self.func.__defaults__ self.argdefault = {} if (self.defaults): self.noptargs = len(self.defaults) else: self.noptargs = 0 self.args = self.func.__code__.co_varnames[:self.nargs - self.noptargs] self.optargs = self.func.__code__.co_varnames[self.nargs-self.noptargs: self.noptargs+1] self.hints = typing.get_type_hints(self.func) if "self" in self.args: self.nargs -= 1 self.args = tuple([x for x in self.args if x != "self"]) for i in range(self.noptargs): self.argdefault[self.optargs[i]] = self.defaults[i] if self.nargs > 0: self.log.info("ARGS: " + ", ".join(self.args)) self.log.info("OPTARGS: " + ", ".join(self.optargs)) self.log.info("DEFAULTS: " + ", ".join( ["{}={}".format( i, self.argdefault[i]) for i in self.argdefault])) else: self.log.info("No arguments") self.delim = "," self.NOSPLIT = "NOSPLIT" in self.func.__code__.co_varnames self.success = True self.log.line("-") self.log.info(self) def getHelp(self): h = self.name + ":\n" + self.help if self.nargs > 0: h += "\nARGS: " + ", ".join(self.args) + "\n" if self.noptargs > 0: h += "\nOPTARGS: " + " , ".join(self.optargs) if "\n" not in h: h += " (No Arguments)" return h def run(self, args, user_is_admin=False): if self.admin_required and not user_is_admin: self.log.warning("{} requires administrative permissions".format(self.name)) self.log.newline() self.log.newline() self.log.line("+") if not self.NOSPLIT: args = self._formatArgs(args.split(self.delim)) else: args = self._formatArgs([args]) self.log.info("Running {} with args {}".format(self.name, args)) output = self.func(**args) self.log.line("+") self.log.newline() self.log.newline() return output def _formatArgs(self, args): args = [x.strip() for x in args if x != ''] processedArgs = {} allargs = self.args + self.optargs for i in range(self.nargs): arg = "" argn = allargs[i] if i >= len(args): arg = self.argdefault[argn] else: arg = args[i] if allargs[i] in self.hints: try: arg = self.hints[argn](arg) except ValueError as ex: raise ArgumentFormatError(ex) processedArgs[argn] = arg return processedArgs def __repr__(self): x = "\n\nCOMMAND DEFINITION ::- \n" return x+"\nCommand (\n Name: {}.{},\n Args: {},\n OptArgs: {}\n Admin: {}\n)\n".format( self.module, self.name, self.args, self.optargs, self.admin_required)
class Conf: """Class for parsing simple (key sep value) format files""" def __init__(self, filename, sep=":"): self.log = Log() self.filename = filename self.log.info("Reading {}".format(filename)) self.config = {} self.sep = sep self._readFile() self._extractConfig() self.log.info("Succesfully parsed {}".format(filename)) def _readFile(self): """Read in the configuration file""" self.log.debug("Opening file {}".format(self.filename)) ##Open the config file try: f = open(self.filename, "r") except FileNotFoundError: self.log.error("File '{}' not found!".format(self.filename)) ##Read in each line, ignoring empty lines self.text = [x[:-1] for x in f.readlines() if x[:-1] != ""] self.log.debug("File read succesfully") ##Close the file f.close() self.log.debug("{} closed".format(self.filename)) def writeFile(self, alternateFile=None): """Write the changed configuration back to a file""" self.log.info("Writing config back to file") filename = self.filename ##Just in case the user wants to change location if alternateFile: filename = alternateFile self.log.info("Writing to {}".format(filename)) try: with open(filename, "w") as f: for i in sorted(self.config): f.write("{}:{}\n".format(i, self.config[i])) except Exception as e: self.log.warning("An error occurred -- {}".format(e)) return 1 self.log.debug("{} Written succesfully".format(filename)) return 0 def _extractConfig(self): """Get all the key value pairs from the config file""" ##Keep track of line of debug purposes lineno = 1 for i in self.text: ##Split the line by the seperator setting, sep, value = i.partition(self.sep) if setting in self.config: ##If we've already seen that key before self.log.warning("Duplicate setting '{}' (Line {})".format( setting, lineno)) else: ##Check for empty setting name if setting == "": self.log.warning( "Empty setting name (Line {})".format(lineno)) else: ##Check for empty value if value == "": self.log.warning( "Empty setting value '{}'(Line {})".format( setting, lineno)) else: ##It all looks good self.config[setting] = value lineno += 1 def getValue(self, key): """Get the value associated with a key""" if key in self.config: return self.config[key] else: ##If we can't find the key self.log.error("Setting '{}' not found!".format(key)) return 0 def getData(self, key): """Get the parsed value of a key - for lists and dicts""" x = self.getValue(key) return eval(x) def setValue(self, key, value): """Change the value of a setting""" if key == "": self.log.warning( "Non-empty keys only please! (value thrown: {})".format(value)) return False else: self.config[key] = value return True
class Command: def __init__(self, f_name, f_obj, help, module="Builtin"): self.log = Log() self.log.newline() self.log.info("Creating command {}".format(f_name)) self.log.line("-") self.name = f_name self.func = f_obj self.help = self.func.__doc__ or "" self.module = module self.admin_required = "admin" in self.func.__code__.co_varnames self.nargs = self.func.__code__.co_argcount self.defaults = self.func.__defaults__ self.argdefault = {} if (self.defaults): self.noptargs = len(self.defaults) else: self.noptargs = 0 self.args = self.func.__code__.co_varnames[:self.nargs - self.noptargs] self.optargs = self.func.__code__.co_varnames[self.nargs - self. noptargs:self.noptargs + 1] self.hints = typing.get_type_hints(self.func) if "self" in self.args: self.nargs -= 1 self.args = tuple([x for x in self.args if x != "self"]) for i in range(self.noptargs): self.argdefault[self.optargs[i]] = self.defaults[i] if self.nargs > 0: self.log.info("ARGS: " + ", ".join(self.args)) self.log.info("OPTARGS: " + ", ".join(self.optargs)) self.log.info("DEFAULTS: " + ", ".join([ "{}={}".format(i, self.argdefault[i]) for i in self.argdefault ])) else: self.log.info("No arguments") self.delim = "," self.NOSPLIT = "NOSPLIT" in self.func.__code__.co_varnames self.success = True self.log.line("-") self.log.info(self) def getHelp(self): h = self.name + ":\n" + self.help if self.nargs > 0: h += "\nARGS: " + ", ".join(self.args) + "\n" if self.noptargs > 0: h += "\nOPTARGS: " + " , ".join(self.optargs) if "\n" not in h: h += " (No Arguments)" return h def run(self, args, user_is_admin=False): if self.admin_required and not user_is_admin: self.log.warning("{} requires administrative permissions".format( self.name)) self.log.newline() self.log.newline() self.log.line("+") if not self.NOSPLIT: args = self._formatArgs(args.split(self.delim)) else: args = self._formatArgs([args]) self.log.info("Running {} with args {}".format(self.name, args)) output = self.func(**args) self.log.line("+") self.log.newline() self.log.newline() return output def _formatArgs(self, args): args = [x.strip() for x in args if x != ''] processedArgs = {} allargs = self.args + self.optargs for i in range(self.nargs): arg = "" argn = allargs[i] if i >= len(args): arg = self.argdefault[argn] else: arg = args[i] if allargs[i] in self.hints: try: arg = self.hints[argn](arg) except ValueError as ex: raise ArgumentFormatError(ex) processedArgs[argn] = arg return processedArgs def __repr__(self): x = "\n\nCOMMAND DEFINITION ::- \n" return x + "\nCommand (\n Name: {}.{},\n Args: {},\n OptArgs: {}\n Admin: {}\n)\n".format( self.module, self.name, self.args, self.optargs, self.admin_required)