pylucid_plugins.py :  » Content-Management-Systems » PyLucid » PyLucid_standalone » pylucid_project » system » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Content Management Systems » PyLucid 
PyLucid » PyLucid_standalone » pylucid_project » system » pylucid_plugins.py
# coding: utf-8


import os
import sys
import warnings

from django.conf import settings
from django.core import urlresolvers
from django.utils.functional import LazyObject,SimpleLazyObject
from django.utils.importlib import import_module
from django.conf.urls.defaults import patterns,url,include

from pylucid_project.utils.python_tools import has_init_file

#DEBUG = True
DEBUG = False

#PYLUCID_PLUGINS = None

_PLUGIN_OBJ_CACHE = {} # cache for PyLucidPlugin.get_plugin_object()
_PLUGIN_URL_CACHE = {} # cache for PyLucidPlugin.get_prefix_urlpatterns()


class PyLucidPlugin(object):
    """ represents one PyLucid plugins """

    class ObjectNotFound(Exception):
        """ Can't import a plugin module or a module Attribute doesn't exist. """
        pass

    def __init__(self, pkg_path, section, pkg_dir, plugin_name):
        # e.g.: "PYLUCID_BASE_PATH/pylucid_project/pylucid_plugins", "pylucid_project", "pylucid_plugins", "PluginName"
        self.name = plugin_name

        self.fs_path = os.path.join(pkg_path, plugin_name)
        assert os.path.isdir(self.fs_path), "path %r is not a directory or doesn't exist." % self.fs_path
        assert has_init_file(self.fs_path), "%r contains no __init__.py file!" % self.fs_path

        self.pkg_string = ".".join([pkg_dir, plugin_name])
        self.installed_apps_string = ".".join([section, self.pkg_string])

        template_dir = os.path.join(self.fs_path, "templates")
        if os.path.isdir(template_dir):
            self.template_dir = template_dir
        else:
            self.template_dir = None

    def __unicode__(self):
        return u"PyLucid plugin %r (%r)" % (self.name, self.installed_apps_string)

    def __repr__(self):
        return "<%s>" % self.__unicode__()

    def get_plugin_object(self, mod_name, obj_name):
        """
        return a object from this plugin
        argument e.g.: ("admin_urls", "urlpatterns")
        """
        mod_pkg = ".".join([self.pkg_string, mod_name])

        cache_key = mod_pkg + "." + obj_name
        if cache_key in _PLUGIN_OBJ_CACHE:
            #print "use _PLUGIN_OBJ_CACHE[%r]" % cache_key
            return _PLUGIN_OBJ_CACHE[cache_key]

        try:
            mod = import_module(mod_pkg)
        except Exception, err:
            msg = u"Error importing %r from plugin %r" % (mod_pkg, self.name)

            if str(err) == "No module named %s" % mod_name:
                raise self.ObjectNotFound("%s: %s" % (msg, err))

            # insert more information into the traceback
            etype, evalue, etb = sys.exc_info()
            evalue = etype('%s: %s' % (msg, evalue))
            raise etype, evalue, etb

        try:
            object = getattr(mod, obj_name)
        except AttributeError, err:
            raise self.ObjectNotFound(err)

        #print "put in _PLUGIN_OBJ_CACHE[%r]" % cache_key
        _PLUGIN_OBJ_CACHE[cache_key] = object

        return object

    def get_callable(self, mod_name, func_name):
        """ returns the callable function. """
        callable = self.get_plugin_object(mod_name, obj_name=func_name)
        return callable

    def call_plugin_view(self, request, mod_name, func_name, method_kwargs):
        """ Call a plugin view """
        callable = self.get_callable(mod_name, func_name)

        # Add info for pylucid_project.apps.pylucid.context_processors.pylucid
        request.plugin_name = self.name
        request.method_name = func_name

        # call the plugin view method
        response = callable(request, **method_kwargs)

        request.plugin_name = None
        request.method_name = None
#        del(request.plugin_name)
#        del(request.method_name)

        return response

    def get_urlpatterns(self, urls_filename):
        """ returns the plugin urlpatterns """
        if "." in urls_filename:
            urls_filename = os.path.splitext(urls_filename)[0]

        raw_plugin_urlpatterns = self.get_plugin_object(mod_name=urls_filename, obj_name="urlpatterns")
        return raw_plugin_urlpatterns


    def get_prefix_urlpatterns(self, url_prefix, urls_filename):
        """ include the plugin urlpatterns with the url prefix """
        url_prefix = url_prefix.rstrip("/") + "/"

        cache_key = self.pkg_string + url_prefix
        if cache_key in _PLUGIN_URL_CACHE:
            #print "use _PLUGIN_URL_CACHE[%r]" % cache_key
            return _PLUGIN_URL_CACHE[cache_key]

        raw_plugin_urlpatterns = self.get_urlpatterns(urls_filename)

        plugin_urlpatterns = patterns('',
            (url_prefix, include(raw_plugin_urlpatterns)),
        )

        if DEBUG:
            print "url prefix: %r" % url_prefix
            print "raw_plugin_urlpatterns: %r" % raw_plugin_urlpatterns

        #print "put in _PLUGIN_URL_CACHE[%r]" % cache_key
        _PLUGIN_URL_CACHE[cache_key] = plugin_urlpatterns

        return plugin_urlpatterns


    def get_plugin_url_resolver(self, url_prefix, urls_filename="urls"):
        prefix_urlpatterns = self.get_prefix_urlpatterns(url_prefix, urls_filename)

        if DEBUG:
            print "prefix_urlpatterns: %r" % prefix_urlpatterns

        plugin_url_resolver = urlresolvers.RegexURLResolver(r'^/', prefix_urlpatterns)

        if DEBUG:
            for key, value in plugin_url_resolver.reverse_dict.items():
                print key, value

        return plugin_url_resolver

    def get_merged_url_resolver(self, url_prefix, urls_filename="urls"):
        """ Merge the globale url patterns with the plugin one, so the plugin can reverse all urls """
        prefix_urlpatterns = self.get_prefix_urlpatterns(url_prefix, urls_filename)

        ROOT_URLCONF_PATTERNS = import_module(settings.ROOT_URLCONF).urlpatterns
        merged_urlpatterns = ROOT_URLCONF_PATTERNS + prefix_urlpatterns

        # Make a own url resolver
#        merged_url_resolver = urlresolvers.RegexURLResolver(r'^/', merged_urlpatterns)
        merged_url_resolver = urlresolvers.RegexURLResolver(r'^/', merged_urlpatterns)
        return merged_url_resolver




class PyLucidPlugins(dict):
    """
    Storage for all existing PyLucid plugins
    FIXME: How can we make this lazy?
    or how can we initializied after settings?
    """

    def __init__(self):
        super(PyLucidPlugins, self).__init__()
        self.__initialized = False

    def __getattr__(self, name):
        if not self.__initialized:
            self._setup()
        return getattr(self, name)

    def __getitem__(self, key):
        if not self.__initialized:
            self._setup()
        return dict.__getitem__(self, key)

    def _setup(self):
#        print " *** init PyLucidPlugins():", settings.PYLUCID_PLUGIN_SETUP_INFO.keys()
        for plugin_name, data in settings.PYLUCID_PLUGIN_SETUP_INFO.iteritems():
            pkg_path, section, pkg_dir = data
            self[plugin_name] = PyLucidPlugin(pkg_path, section, pkg_dir, plugin_name)
        self.__initialized = True

    def get_admin_urls(self):
        """
        return all existing plugin.admin_urls prefixed with the plugin name.
        Used in apps/pylucid_admin/urls.py
        """
        if not self.__initialized:
            self._setup()
        urls = []
        for plugin_name, plugin_instance in self.iteritems():
            try:
                admin_urls = plugin_instance.get_plugin_object(
                    mod_name="admin_urls", obj_name="urlpatterns"
                )
            except plugin_instance.ObjectNotFound, err:
                continue

            urls += patterns('',
                (r"^%s/" % plugin_name, include(admin_urls)),
            )

        return urls

    def call_get_views(self, request):
        """ call a pylucid plugin "html get view" and return the response. """
        if not self.__initialized:
            self._setup()
        method_name = settings.PYLUCID.HTTP_GET_VIEW_NAME
        for plugin_name in request.GET.keys():
            if plugin_name not in self:
                # get parameter is not a plugin or unknwon plugin
                continue

            plugin_instance = self[plugin_name]
            try:
                response = plugin_instance.call_plugin_view(
                    request, mod_name="views", func_name=method_name, method_kwargs={}
                )
            except plugin_instance.ObjectNotFound, err:
                # plugin or view doesn't exist
                if settings.DEBUG:
                    raise # Give a developer the full traceback page ;)
                else:
                    # ignore the get parameter
                    continue
            except:
                # insert more information into the traceback
                etype, evalue, etb = sys.exc_info()
                evalue = etype('Error rendering plugin view "%s.%s": %s' % (plugin_name, method_name, evalue))
                raise etype, evalue, etb

            return response



PYLUCID_PLUGINS = PyLucidPlugins()






www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.