Fix import loop and move plugins collection into its own class.

Loading plugin controller modules at the bottom of
controllers/__init__.py led to a circular dependency. Registering
controllers via decorator allows controllers/__init__.py to load
completely before plugin controllers are loaded.
This commit is contained in:
Max Goodman
2012-02-07 12:26:30 -08:00
parent 0412e87cb8
commit 0332d0ca55
5 changed files with 44 additions and 19 deletions

View File

@@ -33,7 +33,7 @@ from r2.config import routing
import r2.lib.app_globals as app_globals
from r2.lib import rpc
import r2.lib.helpers
from r2.lib.plugin import load_plugins
from r2.lib.plugin import PluginLoader
import r2.config as reddit_config
from r2.templates import tmpl_dirs
@@ -58,7 +58,7 @@ def load_environment(global_conf={}, app_conf={}, setup_globals=True):
config['pylons.h'] = r2.lib.helpers
config['r2.plugins'] = load_plugins(getattr(g, 'plugins', []))
config['r2.plugins'] = PluginLoader().load_plugins(getattr(g, 'plugins', []))
config['routes.map'] = routing.make_map()
#override the default response options

View File

@@ -515,6 +515,7 @@ class RedditApp(PylonsBaseWSGIApp):
class_name = controller.capitalize() + 'Controller'
__import__(self.package_name + '.controllers')
config['r2.plugins'].load_controllers()
mycontroller = getattr(sys.modules[full_module_name], class_name)
self.controller_classes[controller] = mycontroller
return mycontroller
@@ -576,7 +577,7 @@ def make_app(global_conf, full_stack=True, **app_conf):
static_cascade = [static_app, javascripts_app, app]
if config['r2.plugins']:
plugin_static_apps = Cascade([StaticURLParser(plugin.static_dir)
for plugin in config['r2.plugins'].itervalues()])
for plugin in config['r2.plugins']])
static_cascade.insert(0, plugin_static_apps)
app = Cascade(static_cascade)

View File

@@ -31,7 +31,7 @@ def make_map():
map = Mapper()
mc = map.connect
for plugin in config['r2.plugins'].itervalues():
for plugin in config['r2.plugins']:
plugin.add_routes(mc)
admin_routes.add(mc)

View File

@@ -67,6 +67,7 @@ from admin import AdminController
from redirect import RedirectController
from ipn import IpnController
from pylons import config
for plugin in config['r2.plugins'].itervalues():
locals().update(plugin.load_controllers())
def add_controller(controller):
assert controller.__name__ not in globals()
globals()[controller.__name__] = controller
return controller

View File

@@ -22,16 +22,39 @@ class Plugin(object):
def add_routes(self, mc):
pass
def load_controllers(self):
pass
def load_plugins(plugin_names):
plugins = {}
for name in plugin_names:
try:
entry_point = pkg_resources.iter_entry_points('r2.plugin', name).next()
except StopIteration:
config['pylons.g'].log.warning('Unable to locate plugin "%s". Skipping.' % name)
continue
plugin_cls = entry_point.load()
plugin = plugins[name] = plugin_cls()
config['pylons.paths']['templates'].extend(plugin.template_dirs)
return plugins
class PluginLoader(object):
def __init__(self):
self.plugins = {}
self.controllers_loaded = False
def __len__(self):
return len(self.plugins)
def __iter__(self):
return self.plugins.itervalues()
def __getitem__(self, key):
return self.plugins[key]
def load_plugins(self, plugin_names):
for name in plugin_names:
try:
entry_point = pkg_resources.iter_entry_points('r2.plugin', name).next()
except StopIteration:
config['pylons.g'].log.warning('Unable to locate plugin "%s". Skipping.' % name)
continue
plugin_cls = entry_point.load()
plugin = self.plugins[name] = plugin_cls()
config['pylons.paths']['templates'].extend(plugin.template_dirs)
return self
def load_controllers(self):
if self.controllers_loaded:
return
for plugin in self:
plugin.load_controllers()
self.controllers_loaded = True