1# Copyright 2010 Google Inc. 2# 3# Permission is hereby granted, free of charge, to any person obtaining a 4# copy of this software and associated documentation files (the 5# "Software"), to deal in the Software without restriction, including 6# without limitation the rights to use, copy, modify, merge, publish, dis- 7# tribute, sublicense, and/or sell copies of the Software, and to permit 8# persons to whom the Software is furnished to do so, subject to the fol- 9# lowing conditions: 10# 11# The above copyright notice and this permission notice shall be included 12# in all copies or substantial portions of the Software. 13# 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 17# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20# IN THE SOFTWARE. 21 22 23""" 24Implements plugin related api. 25 26To define a new plugin just subclass Plugin, like this. 27 28class AuthPlugin(Plugin): 29 pass 30 31Then start creating subclasses of your new plugin. 32 33class MyFancyAuth(AuthPlugin): 34 capability = ['sign', 'vmac'] 35 36The actual interface is duck typed. 37""" 38 39import glob 40import imp 41import os.path 42 43 44class Plugin(object): 45 """Base class for all plugins.""" 46 47 capability = [] 48 49 @classmethod 50 def is_capable(cls, requested_capability): 51 """Returns true if the requested capability is supported by this plugin 52 """ 53 for c in requested_capability: 54 if c not in cls.capability: 55 return False 56 return True 57 58 59def get_plugin(cls, requested_capability=None): 60 if not requested_capability: 61 requested_capability = [] 62 result = [] 63 for handler in cls.__subclasses__(): 64 if handler.is_capable(requested_capability): 65 result.append(handler) 66 return result 67 68 69def _import_module(filename): 70 (path, name) = os.path.split(filename) 71 (name, ext) = os.path.splitext(name) 72 73 (file, filename, data) = imp.find_module(name, [path]) 74 try: 75 return imp.load_module(name, file, filename, data) 76 finally: 77 if file: 78 file.close() 79 80_plugin_loaded = False 81 82 83def load_plugins(config): 84 global _plugin_loaded 85 if _plugin_loaded: 86 return 87 _plugin_loaded = True 88 89 if not config.has_option('Plugin', 'plugin_directory'): 90 return 91 directory = config.get('Plugin', 'plugin_directory') 92 for file in glob.glob(os.path.join(directory, '*.py')): 93 _import_module(file) 94