cms/apphook_pool.py
import warnings
from django.core.exceptions import ImproperlyConfigured
from django.utils.module_loading import autodiscover_modules, import_string
from django.utils.translation import gettext as _
from cms.app_base import CMSApp
from cms.exceptions import AppAlreadyRegistered
from cms.utils.conf import get_cms_setting
class ApphookPool:
def __init__(self):
self.apphooks = []
self.apps = {}
self.discovered = False
def clear(self):
# TODO: remove this method, it's Python, we don't need it.
self.apphooks = []
self.apps = {}
self.discovered = False
def register(self, app=None, discovering_apps=False):
# allow use as a decorator
if app is None:
return lambda app: self.register(app, discovering_apps)
if self.apphooks and not discovering_apps:
return app
if app.__name__ in self.apps:
raise AppAlreadyRegistered(
'A CMS application %r is already registered' % app.__name__)
if not issubclass(app, CMSApp):
raise ImproperlyConfigured(
'CMS application must inherit from cms.app_base.CMSApp, '
'but %r does not' % app.__name__)
if not hasattr(app, 'menus') and hasattr(app, 'menu'):
warnings.warn("You define a 'menu' attribute on CMS application "
"%r, but the 'menus' attribute is empty, "
"did you make a typo?" % app.__name__)
self.apps[app.__name__] = app()
return app
def discover_apps(self):
self.apphooks = get_cms_setting('APPHOOKS')
if self.apphooks:
for path in self.apphooks:
cls = import_string(path)
try:
self.register(cls, discovering_apps=True)
except AppAlreadyRegistered:
pass
else:
autodiscover_modules('cms_apps')
self.discovered = True
def get_apphooks(self):
hooks = []
if not self.discovered:
self.discover_apps()
for app_name in self.apps:
app = self.apps[app_name]
if app.get_urls():
hooks.append((app_name, app.name))
# Unfortunately, we lose the ordering since we now have a list of
# tuples. Let's reorder by app_name:
hooks = sorted(hooks, key=lambda hook: hook[1])
return hooks
def get_apphook(self, app_name):
if not self.discovered:
self.discover_apps()
try:
return self.apps[app_name]
except KeyError:
# deprecated: return apphooks registered in db with urlconf name
# instead of apphook class name
for app in self.apps.values():
if app_name in app.get_urls():
return app
warnings.warn(_('No registered apphook "%r" found') % app_name)
return None
apphook_pool = ApphookPool()