Revamp controller lookup to be case insensitive and thread-safe.

This commit is contained in:
Max Goodman
2012-05-17 10:40:41 -07:00
parent 1ebddc5185
commit 95171cc0e0
4 changed files with 87 additions and 62 deletions

View File

@@ -41,6 +41,7 @@ from r2.lib.html_source import HTMLValidationParser
from cStringIO import StringIO
import sys, tempfile, urllib, re, os, sha, subprocess
from httplib import HTTPConnection
from threading import Lock
# hack in Paste support for HTTP 429 "Too Many Requests"
from paste import httpexceptions, wsgiwrappers
@@ -519,18 +520,29 @@ class CleanupMiddleware(object):
#god this shit is disorganized and confusing
class RedditApp(PylonsBaseWSGIApp):
def find_controller(self, controller):
if controller in self.controller_classes:
return self.controller_classes[controller]
def __init__(self, *args, **kwargs):
super(RedditApp, self).__init__(*args, **kwargs)
self._loading_lock = Lock()
self._controllers = None
full_module_name = self.package_name + '.controllers'
class_name = controller.capitalize() + 'Controller'
def load_controllers(self):
with self._loading_lock:
if not self._controllers:
controllers = __import__(self.package_name + '.controllers').controllers
controllers.load_controllers()
config['r2.plugins'].load_controllers()
self._controllers = controllers
__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
return self._controllers
def find_controller(self, controller_name):
if controller_name in self.controller_classes:
return self.controller_classes[controller_name]
controllers = self.load_controllers()
controller_cls = controllers.get_controller(controller_name)
self.controller_classes[controller_name] = controller_cls
return controller_cls
def make_app(global_conf, full_stack=True, **app_conf):
"""Create a Pylons WSGI application and return it

View File

@@ -19,55 +19,72 @@
# All portions of the code written by CondeNet are Copyright (c) 2006-2010
# CondeNet, Inc. All Rights Reserved.
################################################################################
from listingcontroller import ListingController
from listingcontroller import HotController
from listingcontroller import NewController
from listingcontroller import BrowseController
from listingcontroller import MessageController
from listingcontroller import RedditsController
from listingcontroller import ByIDController as ByidController
from listingcontroller import RandomrisingController
from listingcontroller import UserController
from listingcontroller import CommentsController
from listingcontroller import MyredditsController
_reddit_controllers = {}
_plugin_controllers = {}
from feedback import FeedbackController
from front import FormsController
from front import FrontController
from health import HealthController
from buttons import ButtonsController
from buttons import ButtonjsController
from captcha import CaptchaController
from embed import EmbedController
from error import ErrorController
from post import PostController
from toolbar import ToolbarController
from awards import AwardsController
from ads import AdsController
from usage import UsageController
from errorlog import ErrorlogController
from promotecontroller import PromoteController
from mediaembed import MediaembedController
from mediaembed import AdController
from querycontroller import QueryController
try:
from r2admin.controllers.adminapi import ApiController
except ImportError:
from api import ApiController
from api import ApiminimalController
from api_docs import ApidocsController
from apiv1 import APIv1Controller as Apiv1Controller
from oauth2 import OAuth2FrontendController as Oauth2frontendController
from oauth2 import OAuth2AccessController as Oauth2accessController
from admin import AdminController
from redirect import RedirectController
from ipn import IpnController
def get_controller(name):
name = name.lower() + 'controller'
if name in _reddit_controllers:
return _reddit_controllers[name]
elif name in _plugin_controllers:
return _plugin_controllers[name]
else:
raise KeyError(name)
def add_controller(controller):
assert controller.__name__ not in globals()
globals()[controller.__name__] = controller
name = controller.__name__.lower()
assert name not in _plugin_controllers
_plugin_controllers[name] = controller
return controller
def load_controllers():
from listingcontroller import ListingController
from listingcontroller import HotController
from listingcontroller import NewController
from listingcontroller import BrowseController
from listingcontroller import MessageController
from listingcontroller import RedditsController
from listingcontroller import ByIDController
from listingcontroller import RandomrisingController
from listingcontroller import UserController
from listingcontroller import CommentsController
from listingcontroller import MyredditsController
from feedback import FeedbackController
from front import FormsController
from front import FrontController
from health import HealthController
from buttons import ButtonsController
from buttons import ButtonjsController
from captcha import CaptchaController
from embed import EmbedController
from error import ErrorController
from post import PostController
from toolbar import ToolbarController
from awards import AwardsController
from ads import AdsController
from usage import UsageController
from errorlog import ErrorlogController
from promotecontroller import PromoteController
from mediaembed import MediaembedController
from mediaembed import AdController
from querycontroller import QueryController
try:
from r2admin.controllers.adminapi import ApiController
except ImportError:
from api import ApiController
from api import ApiminimalController
from api_docs import ApidocsController
from apiv1 import APIv1Controller
from oauth2 import OAuth2FrontendController
from oauth2 import OAuth2AccessController
from admin import AdminController
from redirect import RedirectController
from ipn import IpnController
_reddit_controllers.update((name.lower(), obj) for name, obj in locals().iteritems())

View File

@@ -27,7 +27,7 @@ from r2.lib.pages import *
from r2.lib.pages.things import wrap_links
from r2.lib.strings import strings
from r2.lib.menus import *
from r2.controllers import ListingController
from r2.controllers.listingcontroller import ListingController
from r2.lib.db import queries
import sha

View File

@@ -46,7 +46,6 @@ class Plugin(object):
class PluginLoader(object):
def __init__(self):
self.plugins = {}
self.controllers_loaded = False
def __len__(self):
return len(self.plugins)
@@ -78,11 +77,8 @@ class PluginLoader(object):
return self
def load_controllers(self):
if self.controllers_loaded:
return
for plugin in self:
plugin.load_controllers()
self.controllers_loaded = True
if __name__ == '__main__':
if sys.argv[1] == 'list':