django-app-plugins-0.1.1/0000755000076500000240000000000011265233110015114 5ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/0000755000076500000240000000000011265233110017435 5ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/__init__.py0000644000076500000240000000003511041270322021542 0ustar pyconuserstafffrom library import Library django-app-plugins-0.1.1/app_plugins/admin.py0000644000076500000240000000151011076010521021073 0ustar pyconuserstafffrom django.contrib import admin from app_plugins.models import PluginPoint, Plugin, UserPluginPreference from app_plugins.forms import AdminPluginPointForm, AdminPluginForm class PluginPointAdmin(admin.ModelAdmin): list_display = ('label', 'index', 'registered', 'status') list_filter = ('registered', 'status') form = AdminPluginPointForm class PluginAdmin(admin.ModelAdmin): list_display = ('label', 'index', 'registered', 'required', 'status') list_filter = ('registered', 'status') form = AdminPluginForm class UserPluginPreferenceAdmin(admin.ModelAdmin): list_display = ('plugin', 'user', 'index', 'visible') list_filter = ('visible',) admin.site.register(PluginPoint, PluginPointAdmin) admin.site.register(Plugin, PluginAdmin) admin.site.register(UserPluginPreference, UserPluginPreferenceAdmin) django-app-plugins-0.1.1/app_plugins/forms.py0000644000076500000240000000144311076010521021136 0ustar pyconuserstaff from django import forms from django.utils.translation import ugettext, ugettext_lazy as _ from app_plugins.models import PluginPoint, Plugin, LABEL_RE def validate_label(value): if not LABEL_RE.search(value): raise forms.ValidationError(ugettext( u"This value must contain only letters, " u"numbers, underscores, and '.' dots." )) else: return value class AdminPluginPointForm(forms.ModelForm): class Meta: model = PluginPoint def clean_label(self): value = self.cleaned_data["label"] return validate_label(value) class AdminPluginForm(forms.ModelForm): class Meta: model = Plugin def clean_label(self): value = self.cleaned_data["label"] return validate_label(value)django-app-plugins-0.1.1/app_plugins/library.py0000644000076500000240000000434711041270322021461 0ustar pyconuserstafffrom django.core.exceptions import ImproperlyConfigured from django.utils.functional import curry from django.utils.datastructures import SortedDict libraries = {} def _register(lib, store, prefix, options, do_error, call): 'generic module library registration decorator passthrough' if call is None: if do_error: raise RuntimeError, "No callable recieved." return curry(_register, lib, store, prefix, options, True) if not callable(call): raise SyntaxError, "must supply callable" if not hasattr(call, '__module__'): raise SyntaxError, "callable must have __module__ defined" if not hasattr(call, '__name__'): raise SyntaxError, "callable must have __name__ defined" name = call.__name__ if prefix: name = prefix + '.' + call.__name__ if name in store: raise RuntimeError, "library already has a call for " + name if lib.app_name is None: lib.app_name = call.__module__ libraries[lib.app_name] = lib elif lib.app_name != call.__module__: raise RuntimeError, ("library is for module %s, not %s." % (lib.app_name, call.__module__)) store[name] = call call.options = options return call class Library(object): def __init__(self): self.app_name = None self.point_calls = SortedDict() self.plugin_calls = SortedDict() @property def plugin_points(self): return ('.'.join([self.app_name, p]) for p in self.point_calls) @property def plugins(self): return ('.'.join([self.app_name, p]) for p in self.plugin_calls) def get_plugin_point_call(self, name): return self.point_calls[name] def get_plugin_call(self, name): return self.plugin_calls[name] def plugin_point(self, call=None, **options): return _register(self, self.point_calls, '', options, False, call) def plugin(self, call=None, **options): if not callable(call) and cal is not None: point_app = call call = None else: point_app = '' return _register(self, self.plugin_calls, point_app, options, False, call) def get_library(app): return libraries.get(app, None) django-app-plugins-0.1.1/app_plugins/locale/0000755000076500000240000000000011265233110020674 5ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/locale/fr/0000755000076500000240000000000011265233110021303 5ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/locale/fr/LC_MESSAGES/0000755000076500000240000000000011265233110023070 5ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/locale/fr/LC_MESSAGES/._django.po0000644000076500000240000000030511047605547025124 0ustar pyconuserstaffMac OS X  2“ÅATTR ,Ř-˜-com.apple.quarantineq/0000;48a0b65d;Firefox;|org.mozilla.firefoxdjango-app-plugins-0.1.1/app_plugins/locale/fr/LC_MESSAGES/django.po0000644000076500000240000000314711047605547024716 0ustar pyconuserstaff# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: app_plugins\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-07-29 13:19+0200\n" "PO-Revision-Date: 2008-08-09 21:25+0100\n" "Last-Translator: Roland Frédéric \n" "Language-Team: Frédéric Roland \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: French\n" #: models.py:14 msgid "Enabled" msgstr "Activé" #: models.py:15 msgid "Disabled" msgstr "Désactivé" #: models.py:16 msgid "Removed" msgstr "Retiré" #: models.py:31 msgid "This value must contain only letters, numbers, underscores, and '.' dots." msgstr "Cette valeur ne peut contenir que des lettres, des chiffres ou des caractères de soulignement et des points '.'." #: models.py:38 #: models.py:101 msgid "The label for the plugin point." msgstr "L'étiquette pour le point d'ancrage." #: models.py:42 msgid "is this a registered plugin point with a library entry?" msgstr "est-ce un point d'ancrage enregistré avec une entrée dans une librairie ?" #: models.py:106 msgid "is this a registered plugin?" msgstr "est-ce un greffon enregistré ?" #: models.py:111 msgid "users can not remove this plugin." msgstr "les utilisateurs ne peuvent pas enlever ce greffon." #: models.py:113 msgid "template to load for the plugin." msgstr "modèle à charger pour le greffon." django-app-plugins-0.1.1/app_plugins/management/0000755000076500000240000000000011265233110021551 5ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/management/__init__.py0000644000076500000240000000051511164302760023671 0ustar pyconuserstafffrom django.db.models import signals from commands.sync_plugins import sync_app_plugins from app_plugins import models as sender_app def do_sync(*args, **kwdargs): sync_app_plugins(verbosity=kwdargs.get("verbosity", 1)) signals.post_syncdb.connect(do_sync, sender=sender_app) if __name__ == "__main__": sync_app_plugins() django-app-plugins-0.1.1/app_plugins/management/commands/0000755000076500000240000000000011265233110023352 5ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/management/commands/__init__.py0000644000076500000240000000000011041270322025447 0ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/management/commands/sync_plugins.py0000644000076500000240000002166311164302760026457 0ustar pyconuserstaff"""Load up the registered plugins and plugin points. New model instances will be created for registered poings and plugins. Any unregistered plugins for a registered point will have an instance created. Any unregistered points for a registered plugin will have an instance created. Registered plugins and points which are no longer in the library system are marked unregistered and un-enabled. FUTURE: We could try to do a file system search for all unregistered plugins and determine the connected points, but we would not be able to find db plugins easily or those provided by more custom loaders. At some future point we may consider having a loader extension API for listing unregistered plugins. """ from django.conf import settings from django.template import loader, TemplateDoesNotExist #from library import libraries #from models import Plugin, PluginPoint, REMOVED, ENABLED #from models import construct_template_path from django.core.management.base import NoArgsCommand from optparse import make_option class Command(NoArgsCommand): option_list = NoArgsCommand.option_list + ( make_option('--delete', action='store_true', dest='delete', help='delete the REMOVED Plugin and PluginPoint instances. '), ) help = ("Syncs the registered plugin and plugin points with the model " "versions.") requires_model_validation = True def handle_noargs(self, **options): sync_app_plugins(options.get('delete', False)) def sync_app_plugins(delete_removed=False, verbosity=1): """ We need to do a complicated dance to sync the current registered and unregistered implicit plugins and points with the instances in the DB. Plugins and points which are removed (or can no longer be found) are marked REMOVED (sometimes only to be re-enabed shortly there after). There is the option to delete all entries which are marked removed, but this should be done carefully. Other apps may have relations to the plugins and points for user preferences and customizaiton settings. We do not want to blindly delete these in a chain delete, as they may need to be migrated to a renamed plugin or point which has now been created as part of the sync. The process: 1. for each registered Plugin Point 1.1. if no instance exists, create it enabled. 1.2. mark it registered 1.2. if it was 'removed' then mark it enabled 2. For each non-removed, registered instance for which there was no reg 2.1. mark removed 2.2. mark plugins removed 3. for each registered plugin 3.1. if there is no point, create it as unregistered 3.2. if there is no plugin, create it as reg and enabled, w/template 3.3. test the template load 3.4. if the plugin was marked REMOVED 3.4.1. mark it enabled 3.4.2. if its point is REMOVED and it is not marked reg, enable it 4. for each registered plugin for which there is no registration 4.1. mark it removed 5. for each non-REMOVED point, get all unregistered plugins via load: 5.1. if plugin instance does not exist, create unregistered and enable 5.2. if it does exist and is marked REMOVED, mark unreg-enabled w/ point 6. for each unreg-non-removed point 6.1. if all plugins are REMOVED, mark REMOVED. 7. if asked to delete the removed, do so. """ from app_plugins.library import libraries from app_plugins.models import Plugin, PluginPoint, REMOVED, ENABLED from app_plugins.models import construct_template_path instances = dict((p.label, p) for p in PluginPoint.objects.all()) ## section 1 - registered plugin points for app_label, lib in libraries.iteritems(): for label in lib.plugin_points: pp = instances.pop(label, None) if pp is None: if verbosity > 1: print "Creating registered PluginPoint:", label pp = PluginPoint(label=label) pp.registered = True if pp.status == REMOVED: if verbosity > 1: print "Updating registered PluginPoint:", label # re-enable a previously removed plugin point and its plugins pp.status = ENABLED for p in Plugin.objects.filter(point=pp, status=REMOVED): p.status = ENABLED p.save() pp.save() # search for unregistered plugins we do not yet know about? ## section 2 - removed plugin points for pp in instances.itervalues(): if pp.status != REMOVED: pp.status = REMOVED pp.save() for p in pp.plugin_set.all(): p.status = REMOVED p.save() instances = dict((p.label, p) for p in Plugin.objects.all()) ## section 3 - registered plugins for app_label, lib in libraries.iteritems(): for label in lib.plugins: p = instances.pop(label, None) point_label = label[len(lib.app_name):] if p is None: p = Plugin() p.label = label if verbosity > 1: print "Creating registered Plugin:", label try: point = PluginPoint.objects.get(label=point_label) p.point = point if point.status == REMOVED: # point was removed at some point... point.status = ENABLED if point.registered: point.registered = False point.save() except PluginPoint.DoesNotExist: if verbosity > 1: print "Creating unregistered PluginPoint:", point_label point = PluginPoint(label=point_label) point.save() p.point = point p.registered = True if p.status == REMOVED: # re-enable a previously removed plugin if verbosity > 1: print "Updating registered Plugin:", p.label p.status = ENABLED options = lib.get_plugin_call(point_label).options default = construct_template_path(lib.app_name, point_label, options.get('ext', '.html')) # raise an error if it does not exist... template = options.get('template', default) loader.find_template_source(template) p.template = template p.save() ## section 4 - initial marking of unregistered known plugins for p in instances.itervalues(): if p.status != REMOVED: p.status = REMOVED p.save() ## section 5 - unregistered plugins instances = dict((p.label, p) for p in Plugin.objects.all()) for pp in PluginPoint.objects.exclude(status=REMOVED): ext = pp.get_options().get('ext', '.html') name = pp.label for app in settings.INSTALLED_APPS: label = u'.'.join([app, name]) template = construct_template_path(app, name, ext) bFound = True try: loader.find_template_source(template) except TemplateDoesNotExist: bFound = False p = instances.get(label, None) if p is None: if bFound: if verbosity > 1: print "Creating unregistered Plugin:", label p = Plugin(point=pp, label=label, template=template) else: if p.status == REMOVED and bFound: p.status = ENABLED p.template = template p.registered = False #if verbosity > 1: # print "Updating unregistered Plugin:", label elif not p.registered and not bFound and p.status != REMOVED: p.status = REMOVED else: p = None if p is not None: p.save() ## section 6 - removed unregistered plugin points for pp in PluginPoint.objects.filter(registered=False).exclude(status=REMOVED): if not pp.plugin_set.exclude(status=REMOVED).count(): if verbosity > 1: print "Removing unregistered PluginPoint:", pp.label pp.status = REMOVED pp.save() ## section 7 - delete removed if delete_removed: count = Plugin.objects.filter(status=REMOVED).count() if count: if verbosity > 1: print "Deleting %d Removed Plugins" % count Plugin.objects.filter(status=REMOVED).delete() count = PluginPoints.objects.filter(status=REMOVED).count() if count: if verbosity > 1: print "Deleting %d Removed PluginPoint" % count PluginPoints.objects.filter(status=REMOVED).delete() django-app-plugins-0.1.1/app_plugins/models.py0000644000076500000240000001227511076166155021317 0ustar pyconuserstafffrom django.db import models from django.db.models import Q from django.utils.translation import ugettext_lazy as _ from django.contrib.auth.models import User from library import get_library import re ENABLED = 0 DISABLED = 1 REMOVED = 2 STATUS_CHOICES = ( (ENABLED, _('Enabled')), (DISABLED, _('Disabled')), (REMOVED, _('Removed')) ) LABEL_RE = re.compile('^[a-zA-Z_][a-zA-Z_0-9.]*$') def is_valid_label(name): return bool(LABEL_RE.match(name)) def construct_template_path(app, name, ext='.html'): if not is_valid_label(name): raise RuntimeError, u"invalid label: " + name if not is_valid_label(app): raise RuntimeError, u"invalid label: " + app return '/'.join([app.split('.')[-1], 'plugins', name.replace('.','/')])+ext class PluginPoint(models.Model): label = models.CharField(max_length=255, unique=True, help_text=_("The label for the plugin point.")) index = models.IntegerField(default=0) registered = models.BooleanField(default=False, help_text=_("is this a registered plugin point with a " "library entry?")) status = models.SmallIntegerField(choices=STATUS_CHOICES, default=ENABLED) class Meta: ordering = ('index', 'id') def __unicode__(self): return u'plugin_point:' + self.label @property def app(self): if not self.registered: return '' return self.label.rsplit('.', 1)[0] @property def name(self): return self.label.rsplit('.', 1)[-1] def get_plugins(self, user=None): """get all the plugins in appropriate order""" if self.status: return [] if user is None: return self.plugin_set.filter(status=ENABLED).order_by('index','id') upref = user.userpluginpreference_set.filter(plugin__status=ENABLED, plugin__point=self) #.order_by('index', 'id').select_related() visible = [up.plugin for up in upref.filter(Q(visible=True)|Q(plugin__required=True))] plugins = self.plugin_set.filter(status=ENABLED).exclude( id__in=[x['plugin'] for x in upref.values('plugin')] ).order_by('index', 'id') return visible + list(plugins) def get_options(self): if not self.registered: return {} lib = get_library(self.app) call = lib.get_plugin_point_call(self.name) return call.options # __call__ not allowed def call(self, context, user, **args): if not self.registered: return {} lib = get_library(self.app) call = lib.get_plugin_point_call(self.name) options = call.options base = [self,] if options.get('takes_context', False): base.append(context) if options.get('takes_user', False): base.append(user) if options.get('takes_args', False): return call(*base, **args) return call(self, *base) class Plugin(models.Model): point = models.ForeignKey(PluginPoint) label = models.CharField(max_length=255, unique=True, help_text=_("The label for the plugin point.")) index = models.IntegerField(default=0) registered = models.BooleanField(default=False, help_text=_("is this a registered plugin?")) status = models.SmallIntegerField(choices=STATUS_CHOICES, default=ENABLED) required = models.BooleanField(default=False, help_text=_("users can not remove this plugin.")) template = models.TextField( help_text=_("template to load for the plugin.")) class Meta: order_with_respect_to = 'point' ordering = ('point', 'index', 'id') def __unicode__(self): return u'plugin:' + self.label @property def app(self): #if not self.registered: return '' return self.label[:-(len(self.point.label)+1)] @property def name(self): return self.point.label def get_options(self): if not self.registered: return {} lib = get_library(self.app) call = lib.get_plugin_call(self.name) return call.options #__call__ not allowed... def call(self, context, user, **args): if not self.registered: return {} lib = get_library(self.app) call = lib.get_plugin_call(self.name) options = call.options base = [self,] if options.get('takes_context', False): base.append(context) if options.get('takes_user', False): base.append(user) if options.get('takes_args', False): return call(*base, **args) return call(self, *base) class UserPluginPreference(models.Model): user = models.ForeignKey(User) plugin = models.ForeignKey(Plugin) visible = models.BooleanField(default=True) index = models.IntegerField(default=0) class Meta: unique_together = ['user', 'plugin'] order_with_respect_to = 'plugin' ordering = ('plugin', 'user', 'index', 'id') def __unicode__(self): return u':'.join(['pluginpref', self.user.username, self.plugin.label]) django-app-plugins-0.1.1/app_plugins/templates/0000755000076500000240000000000011265233110021433 5ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/templates/app_plugins/0000755000076500000240000000000011265233110023754 5ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/templates/app_plugins/app_plugin.html0000644000076500000240000000004211041270322026772 0ustar pyconuserstaff{% include app_plugin_template %} django-app-plugins-0.1.1/app_plugins/templates/app_plugins/plugin_point.html0000644000076500000240000000060411041270322027347 0ustar pyconuserstaff{% load app_plugins %}{% if app_plugin_plugins %} {% for plugin in app_plugin_plugins %} {% app_plugin plugin.app app_plugin_point plugin=plugin user=app_plugin_user args=app_plugin_args ext=app_plugin_ext %} {% endfor %}{% else %} {% for app in app_plugin_apps %} {% app_plugin app app_plugin_point user=app_plugin_user args=app_plugin_args ext=app_plugin_ext %} {% endfor %}{% endif %} django-app-plugins-0.1.1/app_plugins/templatetags/0000755000076500000240000000000011265233110022127 5ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/templatetags/__init__.py0000644000076500000240000000000011041270322024224 0ustar pyconuserstaffdjango-app-plugins-0.1.1/app_plugins/templatetags/app_plugins.py0000644000076500000240000002113111041270322025016 0ustar pyconuserstaff"""plugins template tag root hooks. """ from django.conf import settings from django.db.models.loading import get_app from django import template from inspect import getargspec from django.template.context import Context from django.utils.functional import curry from django.utils.encoding import smart_str from django.template import loader, VariableDoesNotExist, Variable, Node from django.template import TemplateDoesNotExist, TemplateSyntaxError from django.core.cache.backends.locmem import CacheClass as LocalMemCache TAG_KEYWORD_ARGUMENT_SEPARATOR = '=' ## RED_FLAG: this feels wrong... #from app_plugins.models import PluginPoint, Plugin #from app_plugins.models import is_valid_label, construct_template_path models = get_app('app_plugins') APP_PLUGINS_CACHE_PARAMS = getattr(settings, 'APP_PLUGINS_CACHE_PARAMS', {'cull_frequency': 4, 'max_entries': 3000, 'timeout': 60*60*24*3, # 3 days }) app_plugin_apps_with_templates = LocalMemCache('localhost', APP_PLUGINS_CACHE_PARAMS) # at import cache the app names for indexing app_names = [] for app in settings.INSTALLED_APPS: name = app.split('.')[-1] if name not in app_names: app_names.append(name) app_names = tuple(app_names) def callback(func, variables, context, takes_context): """ resolve an iterable of Variable objects into a list of args and a dict of keyword arguments. support full python style keyword argument processing:: >>> def foo(a, b, c=1, d=2): ... pass >>> foo(1, 2) >>> foo(1, b=2) >>> foo(b=2, a=1, d=3) """ name = getattr(func, "_decorated_function", func).__name__ params, varargs, varkw, defaults = getargspec(func) if takes_context: if params[0] == 'context': params.pop(0) else: raise TemplateSyntaxError( "Any tag function decorated with takes_context=True " "must have a first argument of 'context'") num_defaults = len(defaults) num_params = len(params) num_req = num_params - num_defaults args = [] kwdargs = {} found_kwd = False for variable in variables: if not found_kwd: try: args.append(variable.resolve(context)) except VariableDoesNotExist: if variable.var.count(TAG_KEYWORD_ARGUMENT_SEPARATOR) != 1: raise found_kwd = True if found_kwd: try: var, path = variable.var.split(TAG_KEYWORD_ARGUMENT_SEPARATOR) except ValueError: raise TemplateSyntaxError( "Expected keyword assignemnt, found '%s' instead" % variable.var) if params and not varkw and name not in params: raise TemplateSyntaxError( "%s got an unexpected keyword argument '%s'" % (name, var)) if var in kwdargs: raise TemplateSyntaxError( "%s got multiple values for keyword argument '%s'" % (name, var)) kwdargs[smart_str(var)] = Variable(path).resolve(context) num_args = len(args) num_kwds = len(kwdargs) num_all = num_args + num_kwds if ((num_args > num_params and not varargs) or (num_all> num_params and not varkw)): raise TemplateSyntaxError( "%s takes at most %s arguments. (%s given)" % ( name, num_params, num_all) ) if num_args != num_req: if num_args > num_req: # some args are kwd args (maybe multiple keyword error) if not varargs: allowed = set(params[num_args:]) not_allowed = set(kwdargs) - allowed if not_allowed: raise TemplateSyntaxError( "%s got multiple values for keyword arguments: %s" % ( name, ", ".join(not_allowed) )) elif not varkw: # not enough required parameters error required = set(params[num_args:-num_default]) missing = required - set(kwdargs) if missing: raise TemplateSyntaxError( "%s takes at least %s non-keyword arguments (%s given)" % ( name, num_req, num_args)) if takes_context: args.insert(0, context) return func(*args, **kwdargs) def compiler(node_class, parser, token): bits = token.split_contents()[1:] return node_class(bits) def inclusion_kwdtag(register, file_name, context_class=Context, takes_context=False): def dec(func): class InclusionKwdNode(Node): def __init__(self, vars_to_resolve): self.vars_to_resolve = map(Variable, vars_to_resolve) def render(self, context): new_context = callback(func, self.vars_to_resolve, context, takes_context) if not getattr(self, 'nodelist', False): if (not isinstance(file_name, basestring) and is_iterable(file_name)): t = loader.select_template(file_name) else: t = loader.get_template(file_name) self.nodelist = t.nodelist res = self.nodelist.render(context_class(new_context, autoescape=context.autoescape)) context.pop() # local context context.pop() # args context.pop() # callback context (or empty) return res compile_func = curry(compiler, InclusionKwdNode) compile_func.__doc__ = func.__doc__ register.tag(getattr(func, "_decorated_function", func).__name__, compile_func) return func return dec register = template.Library() @register.filter def template_exists(templ): if templ is None: return False try: #loader.get_template(templ) loader.find_template_source(templ) except TemplateDoesNotExist: return False return True def validate_name(name): ## red_flag: turn into a string if not models.is_valid_label(name): raise TemplateSyntaxError, "invalid plugin point name '%s'." % name @inclusion_kwdtag(register, "app_plugins/app_plugin.html", takes_context=True) def app_plugin(context, app, name, plugin=None, user=None, args=None, ext='.html', **extra_args): validate_name(app) validate_name(name) if plugin is None: try: plugin = models.Plugin.objects.get(label=u'.'.join([app, name])) except models.Plugin.DoesNotExist: pass nc = context if args is None: args = extra_args else: args.update(extra_args) template = '' if plugin is None: template = models.construct_template_path(app, name, ext) nc.push() else: nc.update(plugin.call(nc, user, **args)) template = plugin.template nc.update(args) nc.push() nc['app_plugin'] = plugin nc['app_plugin_app'] = app nc['app_plugin_point'] = name nc['app_plugin_args'] = args nc['app_plugin_user'] = user nc['app_plugin_template'] = template return nc @inclusion_kwdtag(register, "app_plugins/plugin_point.html", takes_context=True) def plugin_point(context, name, point=None, user=None, ext='.html', **args): validate_name(name) if point is None: try: point = models.PluginPoint.objects.select_related().get(label=name) except models.PluginPoint.DoesNotExist: pass nc = context plugins = None if point is None: apps = app_plugin_apps_with_templates.get(name+ext, None) if apps is None: tpls = ((app, models.construct_template_path(app, name, ext)) for app in app_names) apps = [ app for app, tpl in tpls if template_exists(tpl) ] app_plugin_apps_with_templates.set(name+ext, apps) nc.push() else: nc.update(point.call(nc, user, **args)) plugins = point.get_plugins(user) apps = [ p.app for p in plugins ] nc.update(args) nc.push() nc['app_plugin_ext'] = ext nc['app_plugin_point'] = name nc['app_plugin_apps'] = apps nc['app_plugin_args'] = args nc['app_plugin_user'] = user nc['app_plugin_plugins'] = plugins return nc django-app-plugins-0.1.1/django_app_plugins.egg-info/0000755000076500000240000000000011265233110022451 5ustar pyconuserstaffdjango-app-plugins-0.1.1/django_app_plugins.egg-info/dependency_links.txt0000644000076500000240000000000111265233110026517 0ustar pyconuserstaff django-app-plugins-0.1.1/django_app_plugins.egg-info/not-zip-safe0000644000076500000240000000000111265227472024715 0ustar pyconuserstaff django-app-plugins-0.1.1/django_app_plugins.egg-info/PKG-INFO0000644000076500000240000000105511265233110023547 0ustar pyconuserstaffMetadata-Version: 1.0 Name: django-app-plugins Version: 0.1.1 Summary: UNKNOWN Home-page: http://code.google.com/p/django-app-plugins/ Author: Doug Napoleone Author-email: doug.napoleone@gmail.com License: UNKNOWN Description: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Framework :: Django django-app-plugins-0.1.1/django_app_plugins.egg-info/requires.txt0000644000076500000240000000001211265233110025042 0ustar pyconuserstaffsetuptoolsdjango-app-plugins-0.1.1/django_app_plugins.egg-info/SOURCES.txt0000644000076500000240000000132011265233110024331 0ustar pyconuserstaffsetup.py app_plugins/__init__.py app_plugins/admin.py app_plugins/forms.py app_plugins/library.py app_plugins/models.py app_plugins/locale/fr/LC_MESSAGES/django.po app_plugins/management/__init__.py app_plugins/management/commands/__init__.py app_plugins/management/commands/sync_plugins.py app_plugins/templates/app_plugins/app_plugin.html app_plugins/templates/app_plugins/plugin_point.html app_plugins/templatetags/__init__.py app_plugins/templatetags/app_plugins.py django_app_plugins.egg-info/PKG-INFO django_app_plugins.egg-info/SOURCES.txt django_app_plugins.egg-info/dependency_links.txt django_app_plugins.egg-info/not-zip-safe django_app_plugins.egg-info/requires.txt django_app_plugins.egg-info/top_level.txt django-app-plugins-0.1.1/django_app_plugins.egg-info/top_level.txt0000644000076500000240000000001411265233110025176 0ustar pyconuserstaffapp_plugins django-app-plugins-0.1.1/PKG-INFO0000644000076500000240000000105511265233110016212 0ustar pyconuserstaffMetadata-Version: 1.0 Name: django-app-plugins Version: 0.1.1 Summary: UNKNOWN Home-page: http://code.google.com/p/django-app-plugins/ Author: Doug Napoleone Author-email: doug.napoleone@gmail.com License: UNKNOWN Description: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Framework :: Django django-app-plugins-0.1.1/setup.cfg0000644000076500000240000000007311265233110016735 0ustar pyconuserstaff[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 django-app-plugins-0.1.1/setup.py0000644000076500000240000000141511265227222016636 0ustar pyconuserstafffrom setuptools import setup, find_packages setup( name='django-app-plugins', version='0.1.1', description='', author='Doug Napoleone', author_email='doug.napoleone@gmail.com', url='http://code.google.com/p/django-app-plugins/', packages=find_packages(), classifiers=[ 'Development Status :: 3 - Alpha', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Framework :: Django', ], package_data = { 'app_plugins': ['templates/app_plugins/*.html'], }, include_package_data=True, zip_safe=False, install_requires=['setuptools'], )