def __init_config(self): """search for and set all config options to default or user-specified""" dup_plugins = False duplicates = None # we need to get cmd_dir and chat_proto from the config file first # don't log the first set of default opts to avoid duplicates later self.conf = Config(self.conf_file) self.conf.reload(log=False) # check for duplicate plugin files (_,files) = util.rlistdir(self.opt('cmd_dir')) files = [os.path.splitext(x)[0] for x in files if ('__init__' not in x and x.split(os.path.extsep)[-1]=='py')] files = sorted(files,key=os.path.basename) files = [x for x in files if os.path.basename(x) not in self.opt('disable')] if self.opt('enable'): files = [x for x in files if os.path.basename(x) in self.opt('enable')] base_names = [os.path.basename(x) for x in files] if len(files)!=len(set(base_names)): dup = set([x for x in base_names if base_names.count(x)>1]) dup_plugins = 'Multiple plugins named %s' % list(dup) # register config options from plugins for f in files: (d,f) = (os.path.dirname(f),os.path.basename(f)) # import errors will be logged and handled in __load_plugins try: mod = util.load_module(f,d) except: continue duplicates = (not self.__load_conf(mod,f) or duplicates) # load protocol config options if protocols were loaded without errors if [x for x in self.opt('protocols').values() if x is not None]: for pname in self.opt('protocols'): mod = util.load_module('sibyl_'+pname,'protocols') duplicates = (not self.__load_conf(mod,pname) or duplicates) # now that we know all the options, read every option from the config file return (self.conf.reload(),dup_plugins,duplicates)
def __load_plugins(self,d): """recursively load all plugins from all sub-directories""" success = True # build file list before-hand so we can check dependencies (_,files) = util.rlistdir(d) files = [x for x in files if (x.split(os.path.extsep)[-1]=='py' and '__init__' not in x)] files = sorted(files,key=os.path.basename) mods = {} # load hooks from every file for f in files: (d,f) = (os.path.dirname(f),os.path.basename(f)) f = os.path.splitext(f)[0] # if "enable" is specified, only load plugins found in "enable" # the "disable" option overrides anything in the "enable" option if ((f not in self.opt('disable')) and ((not self.opt('enable')) or (f in self.opt('enable')))): self.log.info('Loading plugin "%s"' % f) try: mod = util.load_module(f,d) except Exception as e: msg = 'Error loading plugin "%s"' % f self.log_ex(e,msg) self.errors.append('(startup.sibyl) '+msg) continue mods[f] = mod success = (self.__load_funcs(mod,f) and success) else: self.log.debug('Skipping plugin "%s" (disabled in config)' % f) # check dependencies for (name,mod) in mods.items(): if hasattr(mod,'__depends__'): for dep in mod.__depends__: if dep not in mods: success = False self.log.critical('Missing dependency "%s" from plugin "%s"' % (dep,name)) if hasattr(mod,'__wants__'): for dep in mod.__wants__: if dep not in mods: self.log.warning('Missing plugin "%s" limits funcionality of "%s"' % (dep,name)) self.plugins = sorted(mods.keys()) return success
def parse_protocols(self, opt, val): """parse the protocols and return the subclasses""" val = util.split_strip(val, ',') protocols = {} success = False for proto in val: protocols[proto] = None fname = os.path.join('protocols', 'sibyl_' + proto + os.path.extsep + 'py') if not os.path.isfile(fname): self.log('critical', 'No matching file in protocols/ for "%s"' % proto) continue try: mod = util.load_module('sibyl_' + proto, 'protocols') for (name, clas) in inspect.getmembers(mod, inspect.isclass): if issubclass(clas, Protocol) and clas != Protocol: protocols[proto] = clas if protocols[proto] is None: self.log( 'critical', 'Protocol "%s" does not contain a lib.protocol.Protocol subclass' % proto) except Exception as e: full = traceback.format_exc(e) short = full.split('\n')[-2] self.log( 'critical', 'Exception importing protocols/%s:' % ('sibyl_' + proto)) self.log('critical', ' %s' % short) self.log('debug', full) if None in protocols.values(): raise ValueError return protocols
def parse_protocols(self,opt,val): """parse the protocols and return the subclasses""" val = util.split_strip(val,',') protocols = {} success = False for proto in val: protocols[proto] = None fname = os.path.join('protocols','sibyl_'+proto+os.path.extsep+'py') if not os.path.isfile(fname): self.log('critical','No matching file in protocols/ for "%s"' % proto) continue try: mod = util.load_module('sibyl_'+proto,'protocols') for (name,clas) in inspect.getmembers(mod,inspect.isclass): if issubclass(clas,Protocol) and clas!=Protocol: protocols[proto] = clas if protocols[proto] is None: self.log('critical', 'Protocol "%s" does not contain a lib.protocol.Protocol subclass' % proto) except Exception as e: full = traceback.format_exc(e) short = full.split('\n')[-2] self.log('critical','Exception importing protocols/%s:' % ('sibyl_'+proto)) self.log('critical',' %s' % short) self.log('debug',full) if None in protocols.values(): raise ValueError return protocols
ext = os.path.extsep pwd = os.path.abspath(os.path.dirname(__file__)) ignore = ['__init__',os.path.basename(__file__).split(ext)[0],'skeleton'] files = [x for x in os.listdir(pwd) if x.startswith('sibyl_') and x.endswith(ext+'py') and x.split(ext)[0] not in ignore] __all__ = ['PROTOCOLS','FAILED'] PROTOCOLS = {} FAILED = [] for mod in files: fname = mod.split(ext)[0] protocol = fname.split('_')[1] try: mod = load_module(fname,pwd) except: FAILED.append(protocol) continue for (name,clas) in inspect.getmembers(mod,inspect.isclass): if issubclass(clas,Protocol) and clas!=Protocol: PROTOCOLS[fname] = {'class':clas,'config':None} __all__.append(name) exec('from %s import %s' % (fname,name)) for (name,func) in inspect.getmembers(mod,inspect.isfunction): if getattr(func,'_sibylbot_dec_conf',False): PROTOCOLS[fname]['config'] = func