import os import imp import sys import re import inspect pluginSubDir = "pythonplugins" gimmickSubDir = "gimmicks" baseDir = os.path.dirname(__file__) pluginBaseDir = os.path.join( baseDir ,pluginSubDir) import __builtin__ import site import nuke import nukescripts class KellerNukePluginException(Exception): def __init__(self, *args, **kwargs): Exception.__init__(self, *args, **kwargs) class KellerNukePlugin(): STATE_UNLOADED = 00 STATE_ERROR = 05 STATE_LOADED = 10 STATE_INACTIVE = 20 STATE_ACTIVE = 30 _STATE_STR_ = { 00: "UNLOADED", 05: "ERROR", 10: "LOADED", 20: "INACTIVE", 30: "ACTIVE" } def __init__(self, module): pass self.module = module self.pluginName = self.__class__.__name__ self.state = KellerNukePlugin.STATE_LOADED self.valid = True def setInvalid(self): self.valid = False self.state = KellerNukePlugin.STATE_UNLOADED def checkValid(self): if not self.valid: raise KellerNukePluginException("plugin unloaded. instance is no longer valid") def getName(self): return self.pluginName def getState(self): return self.state def getStateAsString(self): return KellerNukePlugin._STATE_STR_[self.getState()] def getModule(self): return self.module def activate(self): self.checkValid() if (self.state == KellerNukePlugin.STATE_INACTIVE) or (self.state == KellerNukePlugin.STATE_LOADED): self.configurePluginInternal() self.state = KellerNukePlugin.STATE_ACTIVE #else: # raise KellerNukePluginException("Plugin has wrong state for this operation") def deactivate(self): self.checkValid() if self.state == KellerNukePlugin.STATE_ACTIVE: try: self.unconfigurePluginInternal() except: # TODO, handle this logDebug("Error while unconfiguring plugin %s" % self.getName()) self.state = KellerNukePlugin.STATE_INACTIVE #else: # raise KellerNukePluginException("Plugin has wrong state for this operation") def configurePluginInternal(self): pass logDebug("configure plugin %s" % self.pluginName) # configure folders baseDir = os.path.dirname(__file__) self.configurePlugin() def unconfigurePluginInternal(self): self.unconfigurePlugin() logDebug("unconfigure plugin %s" % self.getName()) def unconfigurePlugin(self): pass def configurePlugin(self): pass def __str2__(self): return "%s > %s[%s]" % (super(KellerNukePlugin, self), self.getName(), self.getStateAsString()) def logDebug(msg): import inspect, sys, os frm = inspect.stack()[1] mod = inspect.getmodule(frm[0]) caller = mod.__name__ #caller = os.path.basename(sys._getframe(0).f_back.f_code.co_filename) nuke.debug("[%s] %s" % (caller,msg)) class KellerPluginManagerImpl(): def __init__(self): pass self.kellerPluginPool = dict() self.serviceData = dict() def getPlugins(self): return self.kellerPluginPool.values() def getPluginByName(self, pluginName): if pluginName in self.kellerPluginPool: return self.kellerPluginPool[pluginName] return None def deactivatePlugins(self): # iterate over list COPY for plugin in self.kellerPlugins.values[:]: if plugin.getState() == KellerNukePlugin.STATE_ACTIVE: plugin.deactivate() def dumpPlugins(self): pattern = "{0:<25} {1:<10}\n" s = "" s = s + pattern.format("Name", "State") s = s + "---------------------------------------------------------------------------------\n" for plugin in self.kellerPluginPool.values(): s = s + pattern.format(plugin.getName(), plugin.getStateAsString()) def reloadPluginByName(self, pluginName): plugin = self.getPluginByName(pluginName) if plugin is None: logDebug("plugin %s not found " % pluginName) return return self.reloadPlugin(plugin) def reloadPlugin(self, plugin): pluginName = plugin.getName() if (plugin.getState() == KellerNukePlugin.STATE_ACTIVE): plugin.deactivate() if (plugin.getState() == KellerNukePlugin.STATE_INACTIVE): plugin.setInvalid() # remove from pool del self.kellerPluginPool[pluginName] reload(plugin.module) plugin = self.loadPluginModuleContents(plugin.module) return plugin # add to pool # add to plugin pool def loadPluginModuleContents(self, module): for (mname, mobj) in inspect.getmembers(module): #print mname #print mobj #print AbstractNukePlugin if inspect.ismodule(mobj): #nuke.debug("importing %s" % mname) #__import__(mname) __builtin__.__dict__[mname] = mobj if (inspect.isclass(mobj)) and (issubclass(mobj, KellerNukePlugin)): #nuke.debug(">>>> Found plugin definition for %s" % mname) minstance = mobj(module) # add to pool self.kellerPluginPool[minstance.getName()] = minstance minstance.activate() return minstance def setServiceData(self, name, service): self.serviceData[name] = service def getServiceData(self, name): if name in self.serviceData.keys(): return self.serviceData[name] else: return None def removeServiceData(self, name): if name in self.serviceData.keys(): del self.serviceData[name] def loadPluginDir(self, pluginDir, loadPluginInstance=False): if not os.path.isdir(pluginDir): return #logDebug("Adding plugin dir %s" % pluginDir) #site.addsitedir(pluginDir) # get python type descriptions type_descriptions = dict() for description in imp.get_suffixes(): type_descriptions[description[0]] = description #print "basedir is %s " %pluginBaseDir #nuke.debug("basedir is %s" % pluginBaseDir) pythonFiles = os.listdir(pluginDir) for pyFile in pythonFiles: filename = os.path.basename(pyFile) #print "found " + filename match = re.match("(?P.*)(?P\..*)", filename) if match is not None: prefix = match.group("prefix") ext = match.group("postfix") if ext in [".py"]: fileObj = open(os.path.join(pluginDir,filename)) module = imp.load_module(prefix, fileObj, os.path.join(pluginDir,filename), type_descriptions[ext]) __builtin__.__dict__[module.__name__] = module if loadPluginInstance: self.loadPluginModuleContents(module) fileObj.close() # create PluginManager instance __builtin__.KellerPluginManager = KellerPluginManagerImpl() __builtin__.KellerNukePlugin = KellerNukePlugin __builtin__.KellerNukePluginException = KellerNukePluginException __builtin__.nuke = nuke __builtin__.nukescripts = nukescripts __builtin__.WORKGROUP_BASEDIR = baseDir __builtin__.logDebug = logDebug sys.dont_write_bytecode = True # allowed python suffixes for modules #suffixes = [str(suff[0]) for suff in imp.get_suffixes()] def addSiteDir(pluginDir): if not os.path.isdir(pluginDir): return #logDebug("Adding to site: %s" % pluginDir) if pluginDir not in sys.path: site.addsitedir(pluginDir) def loadPlugins(pluginBaseDir, loadPluginInstance = False): pluginDirList = os.listdir(pluginBaseDir) for pluginDir in pluginDirList: addSiteDir(os.path.join(pluginBaseDir,pluginDir)) # process plugins for pluginDir in pluginDirList: KellerPluginManager.loadPluginDir(os.path.join(pluginBaseDir,pluginDir), loadPluginInstance) #def reloadPlugins(): # unloadPlugins() # loadPlugins() def init(pluginBaseDir): # add all dirs to site and make them visible logDebug("Initializing Keller PluginCore...") # process and register all plugins, but to not activate loadPlugins(pluginBaseDir, loadPluginInstance=False) def start(pluginBaseDir): # process all plugins and activate instances loadPlugins(pluginBaseDir, loadPluginInstance=True)