home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / lib / site-packages / cgkit / pluginmanager.py < prev    next >
Encoding:
Python Source  |  2007-01-11  |  24.8 KB  |  760 lines

  1. # ***** BEGIN LICENSE BLOCK *****
  2. # Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. #
  4. # The contents of this file are subject to the Mozilla Public License Version
  5. # 1.1 (the "License"); you may not use this file except in compliance with
  6. # the License. You may obtain a copy of the License at
  7. # http://www.mozilla.org/MPL/
  8. #
  9. # Software distributed under the License is distributed on an "AS IS" basis,
  10. # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. # for the specific language governing rights and limitations under the
  12. # License.
  13. #
  14. # The Original Code is the Python Computer Graphics Kit.
  15. #
  16. # The Initial Developer of the Original Code is Matthias Baas.
  17. # Portions created by the Initial Developer are Copyright (C) 2004
  18. # the Initial Developer. All Rights Reserved.
  19. #
  20. # Contributor(s):
  21. #
  22. # Alternatively, the contents of this file may be used under the terms of
  23. # either the GNU General Public License Version 2 or later (the "GPL"), or
  24. # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  25. # in which case the provisions of the GPL or the LGPL are applicable instead
  26. # of those above. If you wish to allow use of your version of this file only
  27. # under the terms of either the GPL or the LGPL, and not to allow others to
  28. # use your version of this file under the terms of the MPL, indicate your
  29. # decision by deleting the provisions above and replace them with the notice
  30. # and other provisions required by the GPL or the LGPL. If you do not delete
  31. # the provisions above, a recipient may use your version of this file under
  32. # the terms of any one of the MPL, the GPL or the LGPL.
  33. #
  34. # ***** END LICENSE BLOCK *****
  35. # $Id: pluginmanager.py,v 1.2 2005/07/12 16:19:40 mbaas Exp $
  36.  
  37. ## \file pluginmanager.py
  38. ## Contains the PluginManager class.
  39.  
  40. # (this line separates the \file comment from the module docs)
  41.  
  42. """This module contains the plugin manager and associated functions.
  43.  
  44. The PluginManager class contains all the functionality to load plugins
  45. and retrieve the objects inside the plugins.
  46.  
  47. The module already initializes a global plugin manager that can be
  48. accessed using the functions with the same name than the manager methods.
  49. """
  50.  
  51. import os, os.path, sys, copy, types, glob, imp, inspect, traceback
  52. try:
  53.     import logging
  54. except:
  55.     # Define a dummy class that does nothing
  56.     class DummyLogger:
  57.         def debug(self, *args, **kwargs): pass
  58.         def info(self, *args, **kwargs): pass
  59.         def warning(self, *args, **kwargs): pass
  60.         def error(self, *args, **kwargs): pass
  61.         def critical(self, *args, **kwargs): pass
  62.         def exception(self, *args, **kwargs): pass
  63.     logging = DummyLogger()
  64.  
  65. # Exceptions:
  66. class DuplicateObject(Exception):
  67.     """Exception."""
  68.     pass
  69.  
  70. class PluginAlreadyLoaded(Exception):
  71.     """Exception."""
  72.     pass
  73.  
  74. class UnknownFileType(Exception):
  75.     """Exception."""
  76.     pass
  77.  
  78. class ProtocolSpecsMissing(Exception):
  79.     """Exception."""
  80.     pass
  81.  
  82. class MissingName(Exception):
  83.     """Exception."""
  84.     pass
  85.  
  86.  
  87. # Status flags
  88. STATUS_OK         = 0x00
  89. STATUS_EXCEPTION  = 0x01
  90. STATUS_DUPLICATE  = 0x02
  91.  
  92. # PluginDescriptor
  93. class PluginDescriptor:
  94.     """Status descriptor of a plugin file.
  95.  
  96.     This class is just a container for a couple of info attributes about
  97.     a plugin. The attributes are:
  98.  
  99.     - \b filename: The absolute file name of the plugin
  100.     - \b filedesc: A file descriptor tuple (\em suffix, \em mode, \em type)
  101.                  as returned by the get_suffixes() function in the \c imp
  102.                  module (\em type is one of imp.PY_SOURCE, imp.PY_COMPILED
  103.                  or imp.C_EXTENSION)
  104.     - \b objcount: Number of imported objects (usually this should be
  105.                  #classes + #functions)
  106.     - \b classcount: Number of imported classes
  107.     - \b funccount: Number of imported functions
  108.     - \b status: Status flags. If everything is ok the status is STATUS_OK,
  109.                 otherwise its a combination of STATUS_EXCEPTION and
  110.                 STATUS_DUPLICATE.
  111.     - \b traceback: A string containing the traceback message if the 
  112.                 STATUS_EXCEPTION flag is set.
  113.     - \b objdescs: A list of object descriptors of all imported objects
  114.     - \b module: The module object of the imported plugin
  115.     - \b modulename: The name of the plugin module
  116.  
  117.     \see PluginManager, PluginObjectDescriptor
  118.     """
  119.     def __init__(self, filename="<unknown>", filedesc=None,
  120.                  status=STATUS_OK, traceback=None,
  121.                  objcount=0, classcount=0, funccount=0, module=None):
  122.         self.filename   = filename
  123.         self.filedesc   = filedesc
  124.         self.status     = status
  125.         self.traceback  = traceback
  126.         self.objcount   = objcount
  127.         self.classcount = classcount
  128.         self.funccount  = funccount
  129.         self.module     = module
  130.         self.objdescs   = []
  131.         self.modulename = None
  132.  
  133.  
  134.     def __repr__(self):
  135.         res = '<PluginDescriptor file:"%s" status:%s #objs:%s #cls:%s #func:%s>'%(self.filename, self.status, self.objcount, self.classcount, self.funccount)
  136.         return res
  137.  
  138.     def __str__(self):
  139.         res = 'Plugin "%s":\n'%self.filename
  140.         s = "?"
  141.         if self.filedesc!=None:
  142.             t = self.filedesc[2]
  143.             if t==imp.PY_SOURCE:
  144.                 s = "Python source"
  145.             elif t==imp.PY_COMPILED:
  146.                 s = "Compiled Python code"
  147.             elif t==imp.C_EXTENSION:
  148.                 s = "C extension"
  149.             else:
  150.                 s += " (%s)"%t
  151.         res += "  File type  : %s\n"%s
  152.         res += "  Status     : %s\n"%self.status
  153.         res += "  #Objects   : %s\n"%self.objcount
  154.         res += "  #Classes   : %s\n"%self.classcount
  155.         res += "  #Functions : %s\n"%self.funccount
  156.         res += "  Objects    : %s\n"%self.objdescs
  157.         res += "  Module     : %s"%getattr(self.module, "__name__", None)
  158.         if self.status==STATUS_EXCEPTION:
  159.             res += "\n  Traceback:\n%s"%self.traceback
  160.         return res
  161.  
  162.     def setStatusFlag(self, flags):
  163.         self.status |= flags
  164.  
  165. # PluginObjectDescriptor
  166. class PluginObjectDescriptor:
  167.     """Descriptor for a plugin object.
  168.  
  169.     - \b object: The actual plugin object
  170.     - \b name: Object name
  171.     - \b plugindesc: Associated plugin
  172.     - \b status: Status flags. If everything is ok the status is STATUS_OK,
  173.                 otherwise its STATUS_DUPLICATE.
  174.  
  175.     \see PluginManager, PluginDescriptor
  176.     """
  177.     def __init__(self, object=None, name=None,
  178.                  plugindesc=None, status=STATUS_OK):
  179.         self.object = object
  180.         self.name = name
  181.         self.plugindesc = plugindesc
  182.         self.status = status
  183.  
  184.     def __repr__(self):
  185.         res = "<Plugin object '%s', status=%s>"%(self.objectIdentifier(), self.status)
  186.         return res
  187.  
  188.     def moduleName(self):
  189.         if self.plugindesc==None:
  190.             return None
  191.         else:
  192.             return self.plugindesc.modulename
  193.  
  194.     def objectIdentifier(self):
  195.         res = self.name
  196.         modname = self.moduleName()
  197.         if modname!=None:
  198.             res = modname+"."+res
  199.         return res
  200.  
  201.     def setStatusFlag(self, flags):
  202.         self.status |= flags
  203.  
  204.  
  205. # PluginManager
  206. class PluginManager:
  207.     """Loads and manages plugins.
  208.  
  209.     This class imports and manages plugins. A plugin is a file that
  210.     gets imported just like a regular Python module. Each plugin can
  211.     be uniquely identified either by its absolute filename or its
  212.     module name. The module name is only available once the plugin is
  213.     loaded. Any objects (usually classes) that are specially marked
  214.     will be made available by the plugin manager for later retrieval.
  215.  
  216.     A class gets imported if it has an attribute \c _protocols which
  217.     is a list of supported protocols (a protocol is identified by an
  218.     arbitrary hashable object). Each class can be uniquely identified
  219.     by its module name and class name.
  220.     
  221.     Plugins are loaded via calls to importPlugin() or importPlugins().
  222.     You can also register any class as plugin class any time via
  223.     the register() function. When a plugin is loaded or an object
  224.     is registered the plugin/object is represented by a descriptor
  225.     class (PluginDescriptor resp. PluginObjectDescriptor). These
  226.     descriptor objects contain information about the plugin/object.
  227.     The object descriptor also holds a reference to the actual plugin
  228.     object.
  229.  
  230.     You can iterate over all currently available protocols via the
  231.     iterProtocols() method. The iterProtoObjects() method can be used
  232.     to iterate over all objects that support a particular protocol
  233.     and iterObjects() can be used to iterate over all objects.
  234.     The default iterator iterates over all plugin descriptors.
  235.  
  236.     Example plugin class:
  237.     
  238.     \code
  239.     # file: plugin.py
  240.     
  241.     class PluginClass:
  242.  
  243.         _protocols = ["MyProtocol"]
  244.  
  245.         def __init__(self):
  246.             ...
  247.         ...
  248.     \endcode
  249.  
  250.     And here's how to use it:
  251.  
  252.     \code
  253.     pm = PluginManager()
  254.     
  255.     # Load the plugin
  256.     pdesc = pm.importPlugin("plugin.py")
  257.     if pdesc.status!=STATUS_OK:
  258.       # there was an error...
  259.  
  260.     # Search a plugin class
  261.     objdesc = pm.findObject("plugin.PluginClass")
  262.     # Create an instance of the plugin class...
  263.     PluginClass = objdesc.object
  264.     instance = PluginClass()
  265.     
  266.     \endcode
  267.  
  268.     \see PluginDescriptor, PluginObjectDescriptor
  269.     """
  270.  
  271.     def __init__(self):
  272.         """Constructor."""
  273.         
  274.         # A list with plugin descriptors of all imported plugins
  275.         self._plugins = []
  276.  
  277.         # A dictionary containing all objects.
  278.         # Key is the object identifier string, value is the descriptor
  279.         self._objects = {}
  280.  
  281.         # A dictionary with all available protocols. The key is the protocol
  282.         # identifier (an arbitrary hashable object), the value is a list
  283.         # of object descriptors.
  284.         self._protocols = {}
  285.         
  286.  
  287.  
  288.     ######################################################################
  289.     # Neue Schnittstelle:
  290.  
  291.     def __iter__(self):
  292.         """Return an iterator that iterates over all plugin descriptors."""
  293.         return iter(self._plugins)
  294.  
  295.     def iterProtocols(self):
  296.         """Return an iterator that iterates over all protocols."""
  297.         return iter(self._protocols)
  298.  
  299.     def iterProtoObjects(self, proto):
  300.         """Return an iterator that iterates over all object descriptors supporting a particular protocol."""
  301.         if self._protocols.has_key(proto):
  302.             return iter(self._protocols[proto])
  303.         else:
  304.             return iter([])
  305.  
  306.     def iterObjects(self):
  307.         """Return an iterator that iterates over all object descriptors.
  308.         """
  309.         return self._objects.itervalues()
  310.  
  311.     # removeAll
  312.     def removeAll(self):
  313.         """Remove all plugins and plugin objects.
  314.         """
  315.         
  316.         while len(self._objects)>0:
  317.             key = self._objects.keys()[0]
  318.             self.remove(self._objects[key])
  319.             
  320.         self._plugins = []
  321.         self._objects = {}
  322.         self._protocols = {}
  323.  
  324.     # importPlugin
  325.     def importPlugin(self, filename, overwrite=False):
  326.         """Load a plugin file.
  327.  
  328.         The given file is executed, i.e. it is imported like a module.
  329.         Any object (usually class or function) that has an attribute
  330.         "_protocols" is stored in the plugin manager. This attribute
  331.         is a list of protocol specifiers (which are just arbitrary
  332.         hashable objects).
  333.  
  334.         The file must have a suffix that's recognized as a module by
  335.         the Python interpreter (one of the suffixes returned by
  336.         imp.get_suffixes()), otherwise an UnknownFileType exception is
  337.         thrown.
  338.  
  339.         It is possible to load a plugin several times if \a overwrite
  340.         is set to True. The new definitions override the previous ones.
  341.         However, if references or instances to old objects are kept somewhere
  342.         they still refer to the old definition. When writing a plugin you
  343.         should always bear in mind that the file could be executed several
  344.         times and write your initialization code accordingly.
  345.  
  346.         The function returns a PluginDescriptor object which contains
  347.         information about the imported plugin. 
  348.         
  349.         \param filename (\c str) Name of the plugin file (including path)
  350.         \param overwrite (\c bool) Flag that indicates if objects are allowed
  351.                   to overwrite existing plugin objects
  352.         \return Plugin descriptor object (\c PluginDescriptor)
  353.         \todo Lokalen Modul-Import innerhalb des Plugins testen
  354.         """
  355.         
  356.         # Make the filename absolute (and normalized)
  357.         filename = os.path.abspath(filename)
  358.         # path: Absolute path to the file
  359.         path, name = os.path.split(filename)
  360.         # ext: Extension of the file
  361.         name, ext  = os.path.splitext(filename)
  362.         # modname: Module name (only the file name, without path and extension)
  363.         modname = os.path.basename(name)
  364.  
  365.         # Check if the file is already imported
  366.         oldpdesc = self.findPlugin(filename)
  367.         if oldpdesc!=None:
  368.             if overwrite:
  369.                 self.removePlugin(oldpdesc)
  370.             else:
  371.                 raise PluginAlreadyLoaded, "Plugin '%s' is already loaded."%filename
  372.  
  373.         # Find the file description tuple  (suffix, mode, type)
  374.         filedesc = filter(lambda x: x[0]==ext, imp.get_suffixes())
  375.         if filedesc==[]:
  376.             raise UnknownFileType, 'File "%s" is of unknown type."'%filename
  377.         filedesc = filedesc[0]
  378.  
  379.         # Create a plugin descriptor class where all sorts of
  380.         # info is gathered
  381.         pdesc = PluginDescriptor(filename=filename, filedesc=filedesc)
  382.  
  383.         # Open the file
  384.         f = file(filename)
  385.  
  386.         # Add the plugin to the list of imported plugins
  387.         self._plugins.append(pdesc)
  388.  
  389.         # Import the file as a module
  390.         # The path to the file is added to the search path for modules,
  391.         # so the file can import local modules
  392.         try:
  393.             oldpath = copy.copy(sys.path)
  394.             sys.path.append(path)
  395.             try:
  396.                 mod = imp.load_module(modname, f, filename, filedesc)
  397.                 pdesc.module = mod
  398.                 pdesc.modulename = mod.__name__
  399.             finally:
  400.                 f.close()
  401.                 sys.path = oldpath
  402.         except:
  403.             # Extract the traceback message...
  404.             lst = traceback.extract_tb(sys.exc_info()[2])
  405.             flst = traceback.format_list(lst[1:])
  406.             pdesc.traceback = "".join(flst)
  407.             # Add the actual exception to the message...
  408.             t,v = sys.exc_info()[:2]
  409.             elst = traceback.format_exception_only(t,v)
  410.             pdesc.traceback += "".join(elst)
  411.             
  412.             pdesc.setStatusFlag(STATUS_EXCEPTION)
  413.             return pdesc
  414.  
  415.         # Examine the module namespace and register all objects that
  416.         # have a "_protocols" attribute...
  417.         for objname in mod.__dict__:
  418.             obj = mod.__dict__[objname]
  419.             if hasattr(obj, "_protocols"):
  420.                 self.register(obj, pdesc=pdesc)
  421.                 
  422.         return pdesc
  423.  
  424.     # importPlugins
  425.     def importPlugins(self, plugins, out = sys.stderr):
  426.         """Import several plugins at once.
  427.  
  428.         \a plugins can be a single file/directory name or a sequence
  429.         of file/directory names. Directories are recursively descended.
  430.  
  431.         \return A list of plugin descriptors.
  432.         """
  433.  
  434.         if isinstance(plugins, types.StringTypes):
  435.             plugins = [plugins]
  436.         
  437.         res = []
  438.         for plugin in plugins:
  439.             # Check if the file/dir is there...
  440.             if not os.path.exists(plugin):
  441.                 out.write('ERROR: Plugin file or directory "%s" does not exist.\n'%plugin)
  442.                 continue
  443.  
  444.             # Get a list of files (either the single file or the contents
  445.             # of the directory)
  446.             if os.path.isfile(plugin):
  447.                 files = [plugin]
  448.             else:
  449.                 files = glob.glob(os.path.join(plugin,"*"))
  450.  
  451.             # Import each file...
  452.             for f in files:
  453.                 # Directory? then import recursively
  454.                 if os.path.isdir(f):
  455.                     res += self.importPlugins(f, out)
  456.                 # File...
  457.                 else:
  458.                     name, ext = os.path.splitext(f)
  459.                     ext = ext.lower()
  460.                     # Only try to import if the file is actually a
  461.                     # Python module (other than .pyc)...
  462.                     filedesc = filter(lambda x: x[0]==ext, imp.get_suffixes())
  463.                     if filedesc!=[] and ext!=".pyc":
  464.                         out.write('Loading plugin "'+f+'"...\n')
  465.                         d = self.importPlugin(f)
  466.                         res.append(d)
  467.         return res
  468.  
  469.     # register
  470.     def register(self, obj, name=None, pdesc=None, overwrite=False):
  471.         """Register a plugin object.
  472.  
  473.         If \a name is None then the name of the object will be used.      
  474.  
  475.         \param obj  The plugin object
  476.         \param name (\c str) The name of the object or None
  477.         \param pdesc (\c PluginDescriptor) The corresponding plugin or None
  478.         \param overwrite (\c bool) If True the object will overwrite any existing objects.
  479.         \return Object descriptor (\c PluginObjectDescriptor)
  480.         """
  481.  
  482.         # Fill in name automatically?
  483.         if name==None:
  484.             name = getattr(obj, "__name__", None)
  485.             if name==None:
  486.                 raise MissingName, "Cannot determine the name of the object."
  487.         if not hasattr(obj, "_protocols"):
  488.             raise ProtocolSpecsMissing, "Attribut '_protocols' in object '%s' is missing."%name
  489.  
  490.         # Create an object descriptor
  491.         desc = PluginObjectDescriptor(object=obj, name=name, plugindesc=pdesc)
  492.  
  493.         # Check if the object already exists...
  494.         id = desc.objectIdentifier()
  495.         if self._objects.has_key(id):
  496.             if overwrite:
  497.                 olddesc = self._objects[id]
  498.                 self._removeObjectDesc(olddesc)
  499.             else:                
  500.                 raise DuplicateObject, "Plugin object '%s' already exists."%id
  501.  
  502.         # Add the descriptor to the protocol lists...
  503.         self._insertObjectDesc(desc)
  504.  
  505.         return desc
  506.  
  507.     # remove
  508.     def remove(self, objdesc):
  509.         """Remove a plugin object.
  510.  
  511.         \param objdesc (\c PluginObjectDescriptor) Object descriptor
  512.         """
  513.         # Check if the object is really managed by the plugin manager
  514.         id = objdesc.objectIdentifier()
  515.         if not self._objects.has_key(objdesc.objectIdentifier()):
  516.             raise ValueError, "The object '%s' does not exist."%id
  517.  
  518.         self._removeObjectDesc(objdesc)
  519.  
  520.     # removePlugin
  521.     def removePlugin(self, pdesc):
  522.         """Remove a plugin and its imported objects from the manager.
  523.  
  524.         Note: If some classes are still used somewhere those classes
  525.         remain active. It's just that you won't be able to retrieve
  526.         those classes via the plugin manager.
  527.  
  528.         \param pdesc (\c PluginDescriptor) Descriptor of the plugin that should be removed
  529.         """
  530.         # Remove all imported objects...
  531.         while len(pdesc.objdescs)>0:
  532.             self.remove(pdesc.objdescs[0])
  533.  
  534.         # Remove the plugin
  535.         self._plugins.remove(pdesc)
  536.  
  537.  
  538.     # findPlugin
  539.     def findPlugin(self, filename):
  540.         """Return the plugin descriptor for a given filename.
  541.  
  542.         \param filename (\c str) Plugin filename
  543.         \return Plugin descriptor (\c PluginDescriptor) or None
  544.         """
  545.         filename = os.path.abspath(filename)
  546.         pl = filter(lambda d: d.filename==filename, self._plugins)
  547.         if pl==[]:
  548.             return None
  549.         else:
  550.             return pl[0]
  551.  
  552.     # findObject
  553.     def findObject(self, name, modname=None):
  554.         """Return the object descriptor for the specified object.
  555.  
  556.         \param name (\c str) Object name
  557.         \param modname (\c str) Module name
  558.         \return Object descriptor or None
  559.         """
  560.         if modname!=None:
  561.             name = modname+"."+name
  562.         return self._objects.get(name, None)
  563.  
  564.         
  565.     ######################################################################
  566.     ## protected:
  567.  
  568.     def _insertObjectDesc(self, desc):
  569.         """Insert a plugin object.
  570.  
  571.         \pre The object isn't already stored in the manager
  572.         \pre The field desc.name contains a string
  573.         \pre The object has a valid _protocols attribute (a sequence)
  574.         \param desc (\c PluginObjectDescriptor) Object descriptor
  575.         """
  576.  
  577.         # Add the object descriptor to the manager
  578.         self._objects[desc.objectIdentifier()] = desc
  579.  
  580.         # Insert the object descriptor into the corresponding protocol dicts
  581.         for prot in desc.object._protocols:
  582.             if not self._protocols.has_key(prot):
  583.                 self._protocols[prot] = []
  584.             self._protocols[prot].append(desc)
  585.  
  586.         # Update the plugin descriptor
  587.         pdesc = desc.plugindesc
  588.         if pdesc!=None:
  589.             pdesc.objdescs.append(desc)
  590.             pdesc.objcount += 1
  591.             if inspect.isclass(desc.object):
  592.                 pdesc.classcount += 1
  593.             if inspect.isfunction(desc.object):
  594.                 pdesc.funccount += 1
  595.  
  596.  
  597.     def _removeObjectDesc(self, desc):
  598.         """Remove a plugin object from the manager.
  599.  
  600.         \pre The object is stored in the manager
  601.         \param desc (\c PluginObjectDescriptor) Object descriptor
  602.         """
  603.  
  604.         # Update the plugin descriptor
  605.         pdesc = desc.plugindesc
  606.         if pdesc!=None:
  607.             pdesc.objdescs.remove(desc)
  608.             pdesc.objcount -= 1
  609.             if inspect.isclass(desc.object):
  610.                 pdesc.classcount -= 1
  611.             if inspect.isfunction(desc.object):
  612.                 pdesc.funccount -= 1
  613.         
  614.         # Remove the object from the protocol dicts
  615.         for prot in desc.object._protocols:
  616.             self._protocols[prot].remove(desc)
  617.                 
  618.         # Remove the object descriptor
  619.         del self._objects[desc.objectIdentifier()]
  620.         
  621.  
  622. ######################################################################
  623.  
  624. # Global default plugin manager
  625. _plugin_manager = PluginManager()
  626.  
  627. def iterPlugins():
  628.     """Iterate over all global plugins.
  629.  
  630.     This is equivalent to calling \c iter(pm) (with \c pm being the global
  631.     plugin manager).
  632.  
  633.     \see PluginManager::__iter__()
  634.     """
  635.     global _plugin_manager
  636.     return iter(_plugin_manager)
  637.  
  638. def iterProtocols():
  639.     """Global %iterPrototols() function.
  640.  
  641.     \see PluginManager::iterProtocols()
  642.     """
  643.     global _plugin_manager
  644.     return _plugin_manager.iterProtocols()
  645.  
  646. def iterProtoObjects(proto):
  647.     """Global %iterProtoObjects() function.
  648.  
  649.     \see PluginManager::iterProtoObjects()
  650.     """
  651.     global _plugin_manager
  652.     return _plugin_manager.iterProtoObjects(proto)
  653.  
  654. def iterObjects(proto):
  655.     """Global %iterObjects() function.
  656.  
  657.     \see PluginManager::iterObjects()
  658.     """
  659.     global _plugin_manager
  660.     return _plugin_manager.iterObjects()
  661.  
  662. def removeAll(obj):
  663.     """Global %removeAll() function.
  664.  
  665.     \see PluginManager::removeAll()
  666.     """
  667.     global _plugin_manager
  668.     _plugin_manager.removeAll()
  669.  
  670. def importPlugin(filename, overwrite=False):
  671.     """Global %importPlugin() function.
  672.  
  673.     \see PluginManager::importPlugin()
  674.     """
  675.     global _plugin_manager
  676.     return _plugin_manager.importPlugin(filename, overwrite)
  677.  
  678. def importPlugins(dir, out=sys.stdout):
  679.     """Global %importPlugins() function.
  680.  
  681.     \see PluginManager::importPlugins()
  682.     """
  683.     global _plugin_manager
  684.     return _plugin_manager.importPlugins(dir, out)
  685.  
  686. def register(obj, name=None, pdesc=None, overwrite=False):
  687.     """Global %register() function.
  688.  
  689.     \see PluginManager::register()
  690.     """
  691.     global _plugin_manager
  692.     return _plugin_manager.register(obj, name, pdesc, overwrite)
  693.  
  694. def remove(objdesc):
  695.     """Global %remove() function.
  696.  
  697.     \see PluginManager::remove()
  698.     """
  699.     global _plugin_manager
  700.     _plugin_manager.remove(objdesc)
  701.  
  702. def removePlugin(pdesc):
  703.     """Global %removePlugin() function.
  704.  
  705.     \see PluginManager::removePlugin()
  706.     """
  707.     global _plugin_manager
  708.     _plugin_manager.removePlugin(pdesc)
  709.  
  710. def findPlugin(filename):
  711.     """Global %findPlugin() function.
  712.  
  713.     \see PluginManager::findPlugin()
  714.     """
  715.     global _plugin_manager
  716.     return _plugin_manager.findPlugin(filename)
  717.  
  718. def findObject(name, modname=None):
  719.     """Global %findObject() function.
  720.  
  721.     \see PluginManager::findObject()
  722.     """
  723.     global _plugin_manager
  724.     return _plugin_manager.findObject(name, modname)
  725.  
  726.  
  727.  
  728. ######################################################################
  729.  
  730. if __name__=="__main__":
  731.  
  732.     class TestClass:
  733.         _protocols = ["myproto"]
  734.  
  735.     pm = PluginManager()
  736.  
  737. #    desc = pm.register(TestClass)                      
  738. #    print desc.objectIdentifier()
  739.  
  740.     pm.importPlugins(".")
  741. #    pm.importPlugin("testplugin.py")
  742. #    pm.importPlugin("testplugin.py", overwrite=True)
  743.  
  744.     for pdesc in pm:
  745.         print pdesc
  746.  
  747.     for prot in pm.iterProtocols():
  748.         print "Protokoll:",prot
  749.         for odesc in pm.iterProtoObjects(prot):
  750.             print odesc
  751.  
  752.     print "Objects:"
  753.     for desc in pm.iterObjects():
  754.         print desc
  755.  
  756. #    print "Plugins:",pm._plugins
  757. #    print "Objects:",pm._objects
  758. #    print "Protocols:",pm._protocols
  759.  
  760.