summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-10-10 23:20:27 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-10-10 23:20:27 -0400
commitd23043cfd1221546e63ac98723ae0329edecd42d (patch)
tree5791919f1004a7c166ad8ed18969692664b20ce7
parent077cbd288ad7fde99fe42693dddd473b7ea4b404 (diff)
downloadaskbot-d23043cfd1221546e63ac98723ae0329edecd42d.tar.gz
askbot-d23043cfd1221546e63ac98723ae0329edecd42d.tar.bz2
askbot-d23043cfd1221546e63ac98723ae0329edecd42d.zip
removed coffin, from trunk, added dependencies and updated the version
-rw-r--r--askbot/__init__.py2
-rw-r--r--askbot/setup_templates/settings.py2
-rw-r--r--coffin/.___init__.pybin187 -> 0 bytes
-rw-r--r--coffin/._common.pybin187 -> 0 bytes
-rw-r--r--coffin/._interop.pybin184 -> 0 bytes
-rw-r--r--coffin/__init__.py44
-rw-r--r--coffin/common.py148
-rw-r--r--coffin/conf/.___init__.pybin184 -> 0 bytes
-rw-r--r--coffin/conf/__init__.py0
-rw-r--r--coffin/conf/urls/__init__.py0
-rw-r--r--coffin/conf/urls/defaults.py4
-rw-r--r--coffin/contrib/__init__.py0
-rw-r--r--coffin/contrib/markup/__init__.py0
-rw-r--r--coffin/contrib/markup/models.py0
-rw-r--r--coffin/contrib/markup/templatetags/__init__.py0
-rw-r--r--coffin/contrib/markup/templatetags/markup.py15
-rw-r--r--coffin/contrib/syndication/__init__.py0
-rw-r--r--coffin/contrib/syndication/feeds.py36
-rw-r--r--coffin/interop.py120
-rw-r--r--coffin/shortcuts/.___init__.pybin187 -> 0 bytes
-rw-r--r--coffin/shortcuts/__init__.py25
-rw-r--r--coffin/template/.___init__.pybin187 -> 0 bytes
-rw-r--r--coffin/template/._defaultfilters.pybin185 -> 0 bytes
-rw-r--r--coffin/template/._defaulttags.pybin184 -> 0 bytes
-rw-r--r--coffin/template/._library.pybin187 -> 0 bytes
-rw-r--r--coffin/template/._loader.pybin187 -> 0 bytes
-rw-r--r--coffin/template/._loaders.pybin184 -> 0 bytes
-rw-r--r--coffin/template/__init__.py93
-rw-r--r--coffin/template/defaultfilters.py99
-rw-r--r--coffin/template/defaulttags.py364
-rw-r--r--coffin/template/library.py215
-rw-r--r--coffin/template/loader.py66
-rw-r--r--coffin/template/loaders.py38
-rw-r--r--coffin/views/__init__.py0
-rw-r--r--coffin/views/defaults.py35
-rw-r--r--coffin/views/generic/._simple.pybin185 -> 0 bytes
-rw-r--r--coffin/views/generic/__init__.py1
-rw-r--r--coffin/views/generic/simple.py6
-rw-r--r--setup.py2
39 files changed, 4 insertions, 1311 deletions
diff --git a/askbot/__init__.py b/askbot/__init__.py
index 8e5e3242..026a8a85 100644
--- a/askbot/__init__.py
+++ b/askbot/__init__.py
@@ -22,7 +22,7 @@ def get_version():
"""returns version of the askbot app
this version is meaningful for pypi only
"""
- return '0.6.14'
+ return '0.6.15'
#todo: maybe send_mail functions belong to models
#or the future API
diff --git a/askbot/setup_templates/settings.py b/askbot/setup_templates/settings.py
index c9075c2b..abb2ac6d 100644
--- a/askbot/setup_templates/settings.py
+++ b/askbot/setup_templates/settings.py
@@ -168,7 +168,7 @@ AUTHENTICATION_BACKENDS = (
LOG_FILENAME = 'askbot.log'
logging.basicConfig(
filename=os.path.join(os.path.dirname(__file__), 'log', LOG_FILENAME),
- level=logging.DEBUG,
+ level=logging.CRITICAL,
format='%(pathname)s TIME: %(asctime)s MSG: %(filename)s:%(funcName)s:%(lineno)d %(message)s',
)
diff --git a/coffin/.___init__.py b/coffin/.___init__.py
deleted file mode 100644
index b44b5fae..00000000
--- a/coffin/.___init__.py
+++ /dev/null
Binary files differ
diff --git a/coffin/._common.py b/coffin/._common.py
deleted file mode 100644
index c83780af..00000000
--- a/coffin/._common.py
+++ /dev/null
Binary files differ
diff --git a/coffin/._interop.py b/coffin/._interop.py
deleted file mode 100644
index 94121d1f..00000000
--- a/coffin/._interop.py
+++ /dev/null
Binary files differ
diff --git a/coffin/__init__.py b/coffin/__init__.py
deleted file mode 100644
index df89bdd6..00000000
--- a/coffin/__init__.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-Coffin
-~~~~~~
-
-`Coffin <http://www.github.com/dcramer/coffin>` is a package that resolves the
-impedance mismatch between `Django <http://www.djangoproject.com/>` and `Jinja2
-<http://jinja.pocoo.org/2/>` through various adapters. The aim is to use Coffin
-as a drop-in replacement for Django's template system to whatever extent is
-reasonable.
-
-:copyright: 2008 by Christopher D. Leary
-:license: BSD, see LICENSE for more details.
-"""
-
-
-__all__ = ('__version__', '__build__', '__docformat__', 'get_revision')
-__version__ = (0, 3)
-__docformat__ = 'restructuredtext en'
-
-import os
-
-def _get_git_revision(path):
- revision_file = os.path.join(path, 'refs', 'heads', 'master')
- if not os.path.exists(revision_file):
- return None
- fh = open(revision_file, 'r')
- try:
- return fh.read()
- finally:
- fh.close()
-
-def get_revision():
- """
- :returns: Revision number of this branch/checkout, if available. None if
- no revision number can be determined.
- """
- package_dir = os.path.dirname(__file__)
- checkout_dir = os.path.normpath(os.path.join(package_dir, '..'))
- path = os.path.join(checkout_dir, '.git')
- if os.path.exists(path):
- return _get_git_revision(path)
- return None
-
-__build__ = get_revision()
diff --git a/coffin/common.py b/coffin/common.py
deleted file mode 100644
index 2e381ff3..00000000
--- a/coffin/common.py
+++ /dev/null
@@ -1,148 +0,0 @@
-import os
-import warnings
-
-from django import dispatch
-from jinja2 import Environment, loaders
-
-__all__ = ('env', 'need_env')
-
-env = None
-
-_JINJA_I18N_EXTENSION_NAME = 'jinja2.ext.i18n'
-
-# TODO: This should be documented (as even I'm not sure where it's use-case is)
-need_env = dispatch.Signal(providing_args=['arguments', 'loaders',
- 'filters', 'extensions',
- 'globals', 'tests'])
-
-class CoffinEnvironment(Environment):
- def __init__(self, filters={}, globals={}, tests={}, loader=None, extensions=[], **kwargs):
- if not loader:
- loader = loaders.ChoiceLoader(self._get_loaders())
- all_ext = self._get_all_extensions()
-
- extensions.extend(all_ext['extensions'])
- super(CoffinEnvironment, self).__init__(extensions=extensions, loader=loader, **kwargs)
- self.filters.update(filters)
- self.filters.update(all_ext['filters'])
- self.globals.update(globals)
- self.globals.update(all_ext['globals'])
- self.tests.update(tests)
- self.tests.update(all_ext['tests'])
-
- from coffin.template import Template as CoffinTemplate
- self.template_class = CoffinTemplate
-
- def _get_loaders(self):
- """Tries to translate each template loader given in the Django settings
- (:mod:`django.settings`) to a similarly-behaving Jinja loader.
- Warns if a similar loader cannot be found.
- Allows for Jinja2 loader instances to be placed in the template loader
- settings.
- """
- loaders = []
-
- from coffin.template.loaders import jinja_loader_from_django_loader
-
- from django.conf import settings
- for loader in settings.TEMPLATE_LOADERS:
- if isinstance(loader, basestring):
- loader_obj = jinja_loader_from_django_loader(loader)
- if loader_obj:
- loaders.append(loader_obj)
- else:
- warnings.warn('Cannot translate loader: %s' % loader)
- else: # It's assumed to be a Jinja2 loader instance.
- loaders.append(loader)
- return loaders
-
-
- def _get_templatelibs(self):
- """Return an iterable of template ``Library`` instances.
-
- Since we cannot support the {% load %} tag in Jinja, we have to
- register all libraries globally.
- """
- from django.conf import settings
- from django.template import get_library, InvalidTemplateLibrary
-
- libs = []
- for a in settings.INSTALLED_APPS:
- try:
- path = __import__(a + '.templatetags', {}, {}, ['__file__']).__file__
- path = os.path.dirname(path) # we now have the templatetags/ directory
- except ImportError:
- pass
- else:
- for f in os.listdir(path):
- if f == '__init__.py':
- continue
- if f.endswith('.py'):
- try:
- # TODO: will need updating when #6587 lands
- libs.append(get_library(
- "django.templatetags.%s" % os.path.splitext(f)[0]))
- except InvalidTemplateLibrary:
- pass
- return libs
-
- def _get_all_extensions(self):
- from django.conf import settings
- from coffin.template import builtins
- from django.core.urlresolvers import get_callable
-
- extensions, filters, globals, tests = [], {}, {}, {}
-
- # start with our builtins
- for lib in builtins:
- extensions.extend(getattr(lib, 'jinja2_extensions', []))
- filters.update(getattr(lib, 'jinja2_filters', {}))
- globals.update(getattr(lib, 'jinja2_globals', {}))
- tests.update(getattr(lib, 'jinja2_tests', {}))
-
- if settings.USE_I18N:
- extensions.append(_JINJA_I18N_EXTENSION_NAME)
-
- # add the globally defined extension list
- extensions.extend(list(getattr(settings, 'JINJA2_EXTENSIONS', [])))
-
- def from_setting(setting):
- retval = {}
- setting = getattr(settings, setting, {})
- if isinstance(setting, dict):
- for key, value in setting.iteritems():
- retval[user] = callable(value) and value or get_callable(value)
- else:
- for value in setting:
- value = callable(value) and value or get_callable(value)
- retval[value.__name__] = value
- return retval
-
- filters.update(from_setting('JINJA2_FILTERS'))
- globals.update(from_setting('JINJA2_GLOBALS'))
- tests.update(from_setting('JINJA2_TESTS'))
-
- # add extensions defined in application's templatetag libraries
- for lib in self._get_templatelibs():
- extensions.extend(getattr(lib, 'jinja2_extensions', []))
- filters.update(getattr(lib, 'jinja2_filters', {}))
- globals.update(getattr(lib, 'jinja2_globals', {}))
- tests.update(getattr(lib, 'jinja2_tests', {}))
-
- return dict(
- extensions=extensions,
- filters=filters,
- globals=globals,
- tests=tests,
- )
-
-def get_env():
- """
- :return: A Jinja2 environment singleton.
- """
- # need_env.send(sender=Environment, arguments=arguments,
- # loaders=loaders_, extensions=extensions,
- # filters=filters, tests=tests, globals=globals)
- return CoffinEnvironment(autoescape=True)
-
-env = get_env()
diff --git a/coffin/conf/.___init__.py b/coffin/conf/.___init__.py
deleted file mode 100644
index c6b47018..00000000
--- a/coffin/conf/.___init__.py
+++ /dev/null
Binary files differ
diff --git a/coffin/conf/__init__.py b/coffin/conf/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/coffin/conf/__init__.py
+++ /dev/null
diff --git a/coffin/conf/urls/__init__.py b/coffin/conf/urls/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/coffin/conf/urls/__init__.py
+++ /dev/null
diff --git a/coffin/conf/urls/defaults.py b/coffin/conf/urls/defaults.py
deleted file mode 100644
index 3049e2b9..00000000
--- a/coffin/conf/urls/defaults.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from django.conf.urls.defaults import *
-
-handler404 = 'coffin.views.defaults.page_not_found'
-handler500 = 'coffin.views.defaults.server_error' \ No newline at end of file
diff --git a/coffin/contrib/__init__.py b/coffin/contrib/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/coffin/contrib/__init__.py
+++ /dev/null
diff --git a/coffin/contrib/markup/__init__.py b/coffin/contrib/markup/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/coffin/contrib/markup/__init__.py
+++ /dev/null
diff --git a/coffin/contrib/markup/models.py b/coffin/contrib/markup/models.py
deleted file mode 100644
index e69de29b..00000000
--- a/coffin/contrib/markup/models.py
+++ /dev/null
diff --git a/coffin/contrib/markup/templatetags/__init__.py b/coffin/contrib/markup/templatetags/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/coffin/contrib/markup/templatetags/__init__.py
+++ /dev/null
diff --git a/coffin/contrib/markup/templatetags/markup.py b/coffin/contrib/markup/templatetags/markup.py
deleted file mode 100644
index 0d6b92f9..00000000
--- a/coffin/contrib/markup/templatetags/markup.py
+++ /dev/null
@@ -1,15 +0,0 @@
-"""Makes the template filters from the ``django.contrib.markup`` app
-available to both the Jinja2 and Django engines.
-
-In other words, adding ``coffin.contrib.markup`` to your INSTALLED_APPS
-setting will enable the markup filters not only through Coffin, but
-also through the default Django template system.
-"""
-
-from coffin.template import Library as CoffinLibrary
-from django.contrib.markup.templatetags.markup import register
-
-
-# Convert Django's Library into a Coffin Library object, which will
-# make sure the filters are correctly ported to Jinja2.
-register = CoffinLibrary.from_django(register) \ No newline at end of file
diff --git a/coffin/contrib/syndication/__init__.py b/coffin/contrib/syndication/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/coffin/contrib/syndication/__init__.py
+++ /dev/null
diff --git a/coffin/contrib/syndication/feeds.py b/coffin/contrib/syndication/feeds.py
deleted file mode 100644
index f8f0701f..00000000
--- a/coffin/contrib/syndication/feeds.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from django.contrib.syndication.feeds import * # merge modules
-
-import sys
-from django.contrib.syndication.feeds import Feed as DjangoFeed
-from coffin.template import loader as coffin_loader
-
-
-class Feed(DjangoFeed):
- """A ``Feed`` implementation that renders it's title and
- description templates using Jinja2.
-
- Unfortunately, Django's base ``Feed`` class is not very extensible
- in this respect at all. For a real solution, we'd have to essentially
- have to duplicate the whole class. So for now, we use this terrible
- non-thread safe hack.
-
- Another, somewhat crazy option would be:
- * Render the templates ourselves through Jinja2 (possible
- introduce new attributes to avoid having to rewrite the
- existing ones).
- * Make the rendered result available to Django/the superclass by
- using a custom template loader using a prefix, say
- "feed:<myproject.app.views.MyFeed>". The loader would simply
- return the Jinja-rendered template (escaped), the Django template
- mechanism would find no nodes and just pass the output through.
- Possible even worse than this though.
- """
-
- def get_feed(self, *args, **kwargs):
- parent_module = sys.modules[DjangoFeed.__module__]
- old_loader = parent_module.loader
- parent_module.loader = coffin_loader
- try:
- return super(Feed, self).get_feed(*args, **kwargs)
- finally:
- parent_module.loader = old_loader \ No newline at end of file
diff --git a/coffin/interop.py b/coffin/interop.py
deleted file mode 100644
index 54120004..00000000
--- a/coffin/interop.py
+++ /dev/null
@@ -1,120 +0,0 @@
-"""Compatibility functions between Jinja2 and Django.
-
-General notes:
-
- - The Django ``stringfilter`` decorator is supported, but should not be
- used when writing filters specifically for Jinja: It will lose the
- attributes attached to the filter function by Jinja's
- ``environmentfilter`` and ``contextfilter`` decorators, when used
- in the wrong order.
-
- Maybe coffin should provide a custom version of stringfilter.
-
- - While transparently converting filters between Django and Jinja works
- for the most part, there is an issue with Django's
- ``mark_for_escaping``, as Jinja does not support a similar mechanism.
- Instead, for Jinja, we escape such strings immediately (whereas Django
- defers it to the template engine).
-"""
-
-import inspect
-from django.utils.safestring import SafeUnicode, SafeData, EscapeData
-from jinja2 import Markup, environmentfilter
-
-
-__all__ = (
- 'DJANGO', 'JINJA2',
- 'django_filter_to_jinja2',
- 'jinja2_filter_to_django',
- 'guess_filter_type',)
-
-
-DJANGO = 'django'
-JINJA2 = 'jinja2'
-
-
-def django_filter_to_jinja2(filter_func):
- """
- Note: Due to the way this function is used by
- ``coffin.template.Library``, it needs to be able to handle native
- Jinja2 filters and pass them through unmodified. This necessity
- stems from the fact that it is not always possible to determine
- the type of a filter.
-
- TODO: Django's "func.is_safe" is not yet handled
- """
- def _convert(v):
- if isinstance(v, SafeData):
- return Markup(v)
- if isinstance(v, EscapeData):
- return Markup.escape(v) # not 100% equivalent, see mod docs
- return v
- def conversion_wrapper(*args, **kwargs):
- result = filter_func(*args, **kwargs)
- return _convert(result)
- # Jinja2 supports a similar machanism to Django's
- # ``needs_autoescape`` filters: environment filters. We can
- # thus support Django filters that use it in Jinja2 with just
- # a little bit of argument rewriting.
- if hasattr(filter_func, 'needs_autoescape'):
- @environmentfilter
- def autoescape_wrapper(environment, *args, **kwargs):
- kwargs['autoescape'] = environment.autoescape
- return conversion_wrapper(*args, **kwargs)
- return autoescape_wrapper
- else:
- return conversion_wrapper
-
-
-def jinja2_filter_to_django(filter_func):
- """
- Note: Due to the way this function is used by
- ``coffin.template.Library``, it needs to be able to handle native
- Django filters and pass them through unmodified. This necessity
- stems from the fact that it is not always possible to determine
- the type of a filter.
- """
- if guess_filter_type(filter_func)[0] == DJANGO:
- return filter_func
- def _convert(v):
- # TODO: for now, this is not even necessary: Markup strings have
- # a custom replace() method that is immume to Django's escape()
- # attempts.
- #if isinstance(v, Markup):
- # return SafeUnicode(v) # jinja is always unicode
- # ... Jinja does not have a EscapeData equivalent
- return v
- def wrapped(value, *args, **kwargs):
- result = filter_func(value, *args, **kwargs)
- return _convert(result)
- return wrapped
-
-
-def guess_filter_type(filter_func):
- """Returns a 2-tuple of (type, can_be_ported).
-
- ``type`` is one of DJANGO, JINJA2, or ``False`` if the type can
- not be determined.
-
- ``can_be_ported`` is ``True`` if we believe the filter could be
- ported to the other engine, respectively, or ``False`` if we know
- it can't.
-
- TODO: May not yet use all possible clues, e.g. decorators like
- ``stringfilter``.
- TOOD: Needs tests.
- """
- if hasattr(filter_func, 'contextfilter') or \
- hasattr(filter_func, 'environmentfilter'):
- return JINJA2, False
-
- args = inspect.getargspec(filter_func)
- if len(args[0]) - (len(args[3]) if args[3] else 0) > 2:
- return JINJA2, False
-
- if hasattr(filter_func, 'needs_autoescape'):
- return DJANGO, True
-
- # Looks like your run of the mill Python function, which are
- # easily convertible in either direction.
- return False, True \ No newline at end of file
diff --git a/coffin/shortcuts/.___init__.py b/coffin/shortcuts/.___init__.py
deleted file mode 100644
index c21832ed..00000000
--- a/coffin/shortcuts/.___init__.py
+++ /dev/null
Binary files differ
diff --git a/coffin/shortcuts/__init__.py b/coffin/shortcuts/__init__.py
deleted file mode 100644
index c882dfcd..00000000
--- a/coffin/shortcuts/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from django.http import HttpResponse
-
-# Merge with original namespace so user
-# doesn't have to import twice.
-from django.shortcuts import *
-
-
-__all__ = ('render_to_string', 'render_to_response',)
-
-
-# Is within ``template.loader`` as per Django specification -
-# but I think it fits very well here.
-from coffin.template.loader import render_to_string
-
-
-def render_to_response(template_name, dictionary=None, context_instance=None,
- mimetype=None):
- """
- :param template_name: Filename of the template to get or a sequence of
- filenames to try, in order.
- :param dictionary: Rendering context for the template.
- :returns: A response object with the evaluated template as a payload.
- """
- rendered = render_to_string(template_name, dictionary, context_instance)
- return HttpResponse(rendered, mimetype=mimetype)
diff --git a/coffin/template/.___init__.py b/coffin/template/.___init__.py
deleted file mode 100644
index 87947898..00000000
--- a/coffin/template/.___init__.py
+++ /dev/null
Binary files differ
diff --git a/coffin/template/._defaultfilters.py b/coffin/template/._defaultfilters.py
deleted file mode 100644
index 8fd7d746..00000000
--- a/coffin/template/._defaultfilters.py
+++ /dev/null
Binary files differ
diff --git a/coffin/template/._defaulttags.py b/coffin/template/._defaulttags.py
deleted file mode 100644
index db9dcec7..00000000
--- a/coffin/template/._defaulttags.py
+++ /dev/null
Binary files differ
diff --git a/coffin/template/._library.py b/coffin/template/._library.py
deleted file mode 100644
index 18fe8260..00000000
--- a/coffin/template/._library.py
+++ /dev/null
Binary files differ
diff --git a/coffin/template/._loader.py b/coffin/template/._loader.py
deleted file mode 100644
index 3b699201..00000000
--- a/coffin/template/._loader.py
+++ /dev/null
Binary files differ
diff --git a/coffin/template/._loaders.py b/coffin/template/._loaders.py
deleted file mode 100644
index e17a06d5..00000000
--- a/coffin/template/._loaders.py
+++ /dev/null
Binary files differ
diff --git a/coffin/template/__init__.py b/coffin/template/__init__.py
deleted file mode 100644
index b487c8f5..00000000
--- a/coffin/template/__init__.py
+++ /dev/null
@@ -1,93 +0,0 @@
-from django.template import (
- Context as DjangoContext,
- add_to_builtins as django_add_to_builtins,
- get_library)
-from jinja2 import Template as _Jinja2Template
-
-# Merge with ``django.template``.
-from django.template import __all__
-from django.template import *
-
-# Override default library class with ours
-from library import *
-
-
-class Template(_Jinja2Template):
- """Fixes the incompabilites between Jinja2's template class and
- Django's.
-
- The end result should be a class that renders Jinja2 templates but
- is compatible with the interface specfied by Django.
-
- This includes flattening a ``Context`` instance passed to render
- and making sure that this class will automatically use the global
- coffin environment.
- """
-
- def __new__(cls, template_string, origin=None, name=None):
- # We accept the "origin" and "name" arguments, but discard them
- # right away - Jinja's Template class (apparently) stores no
- # equivalent information.
- from coffin.common import env
-
- return env.from_string(template_string, template_class=cls)
-
- def __iter__(self):
- # TODO: Django allows iterating over the templates nodes. Should
- # be parse ourself and iterate over the AST?
- raise NotImplementedError()
-
- def render(self, context=None):
- """Differs from Django's own render() slightly in that makes the
- ``context`` parameter optional. We try to strike a middle ground
- here between implementing Django's interface while still supporting
- Jinja's own call syntax as well.
- """
- if context is None:
- context = {}
- else:
- context = dict_from_django_context(context)
- assert isinstance(context, dict) # Required for **-operator.
- return super(Template, self).render(**context)
-
-
-def dict_from_django_context(context):
- """Flattens a Django :class:`django.template.context.Context` object.
- """
- if not isinstance(context, DjangoContext):
- return context
- else:
- dict_ = {}
- # Newest dicts are up front, so update from oldest to newest.
- for subcontext in reversed(list(context)):
- dict_.update(dict_from_django_context(subcontext))
- return dict_
-
-
-# libraries to load by default for a new environment
-builtins = []
-
-
-def add_to_builtins(module_name):
- """Add the given module to both Coffin's list of default template
- libraries as well as Django's. This makes sense, since Coffin
- libs are compatible with Django libraries.
-
- You can still use Django's own ``add_to_builtins`` to register
- directly with Django and bypass Coffin.
-
- TODO: Allow passing path to (or reference of) extensions and
- filters directly. This would make it easier to use this function
- with 3rd party Jinja extensions that do not know about Coffin and
- thus will not provide a Library object.
-
- XXX/TODO: Why do we need our own custom list of builtins? Our
- Library object is compatible, remember!? We can just add them
- directly to Django's own list of builtins.
- """
- builtins.append(get_library(module_name))
- django_add_to_builtins(module_name)
-
-
-add_to_builtins('coffin.template.defaulttags')
-add_to_builtins('coffin.template.defaultfilters') \ No newline at end of file
diff --git a/coffin/template/defaultfilters.py b/coffin/template/defaultfilters.py
deleted file mode 100644
index c566a7d2..00000000
--- a/coffin/template/defaultfilters.py
+++ /dev/null
@@ -1,99 +0,0 @@
-"""Jinja2-ports of many of Django's default filters.
-
-TODO: Most of the filters in here need to be updated for autoescaping.
-"""
-
-from coffin.template import Library
-from jinja2.runtime import Undefined
-# from jinja2 import Markup
-
-register = Library()
-
-@register.filter(jinja2_only=True)
-def url(view_name, *args, **kwargs):
- from coffin.template.defaulttags import url
- return url._reverse(view_name, args, kwargs)
-
-@register.filter(jinja2_only=True)
-def timesince(value, arg=None):
- if value is None or isinstance(value, Undefined):
- return u''
- from django.utils.timesince import timesince
- if arg:
- return timesince(value, arg)
- return timesince(value)
-
-@register.filter(jinja2_only=True)
-def timeuntil(value, arg=None):
- if value is None or isinstance(value, Undefined):
- return u''
- from django.utils.timesince import timeuntil
- return timeuntil(date, arg)
-
-@register.filter(jinja2_only=True)
-def date(value, arg=None):
- if value is None or isinstance(value, Undefined):
- return u''
- from django.conf import settings
- from django.utils.dateformat import format
- if arg is None:
- arg = settings.DATE_FORMAT
- return format(value, arg)
-
-@register.filter(jinja2_only=True)
-def time(value, arg=None):
- if value is None or isinstance(value, Undefined):
- return u''
- from django.conf import settings
- from django.utils.dateformat import time_format
- if arg is None:
- arg = settings.TIME_FORMAT
- return time_format(value, arg)
-
-@register.filter(jinja2_only=True)
-def truncatewords(value, length):
- # Jinja2 has it's own ``truncate`` filter that supports word
- # boundaries and more stuff, but cannot deal with HTML.
- from django.utils.text import truncate_words
- return truncate_words(value, int(length))
-
-@register.filter(jinja2_only=True)
-def truncatewords_html(value, length):
- from django.utils.text import truncate_html_words
- return truncate_html_words(value, int(length))
-
-@register.filter(jinja2_only=True)
-def pluralize(value, s1='s', s2=None):
- """Like Django's pluralize-filter, but instead of using an optional
- comma to separate singular and plural suffixes, it uses two distinct
- parameters.
-
- It also is less forgiving if applied to values that do not allow
- making a decision between singular and plural.
- """
- if s2 is not None:
- singular_suffix, plural_suffix = s1, s2
- else:
- plural_suffix = s1
- singular_suffix = ''
-
- try:
- if int(value) != 1:
- return plural_suffix
- except TypeError: # not a string or a number; maybe it's a list?
- if len(value) != 1:
- return plural_suffix
- return singular_suffix
-
-@register.filter(jinja2_only=True)
-def floatformat(value, arg=-1):
- """Builds on top of Django's own version, but adds strict error
- checking, staying with the philosophy.
- """
- from django.template.defaultfilters import floatformat
- from coffin.interop import django_filter_to_jinja2
- arg = int(arg) # raise exception
- result = django_filter_to_jinja2(floatformat)(value, arg)
- if result == '': # django couldn't handle the value
- raise ValueError(value)
- return result \ No newline at end of file
diff --git a/coffin/template/defaulttags.py b/coffin/template/defaulttags.py
deleted file mode 100644
index b9994257..00000000
--- a/coffin/template/defaulttags.py
+++ /dev/null
@@ -1,364 +0,0 @@
-from jinja2 import nodes
-from jinja2.ext import Extension
-from jinja2.exceptions import TemplateSyntaxError
-from django.conf import settings
-from coffin.template import Library
-
-
-class LoadExtension(Extension):
- """The load-tag is a no-op in Coffin. Instead, all template libraries
- are always loaded.
-
- Note: Supporting a functioning load-tag in Jinja is tough, though
- theoretically possible. The trouble is activating new extensions while
- parsing is ongoing. The ``Parser.extensions`` dict of the current
- parser instance needs to be modified, but apparently the only way to
- get access would be by hacking the stack.
- """
-
- tags = set(['load'])
-
- def parse(self, parser):
- while not parser.stream.current.type == 'block_end':
- parser.stream.next()
- return []
-
-
-"""class AutoescapeExtension(Extension):
- ""#"
- Template to output works in three phases in Jinja2: parsing,
- generation (compilation, AST-traversal), and rendering (execution).
-
- Unfortunatly, the environment ``autoescape`` option comes into effect
- during traversal, the part where we happen to have basically no control
- over as an extension. It determines whether output is wrapped in
- ``escape()`` calls.
-
- Solutions that could possibly work:
-
- * This extension could preprocess it's childnodes and wrap
- everything output related inside the appropriate
- ``Markup()`` or escape() call.
-
- * We could use the ``preprocess`` hook to insert the
- appropriate ``|safe`` and ``|escape`` filters on a
- string-basis. This is very unlikely to work well.
-
- There's also the issue of inheritance and just generally the nesting
- of autoescape-tags to consider.
-
- Other things of note:
-
- * We can access ``parser.environment``, but that would only
- affect the **parsing** of our child nodes.
-
- * In the commented-out code below we are trying to affect the
- autoescape setting during rendering. As noted, this could be
- necessary for rare border cases where custom extension use
- the autoescape attribute.
-
- Both the above things would break Environment thread-safety though!
-
- Overall, it's not looking to good for this extension.
- ""#"
-
- tags = ['autoescape']
-
- def parse(self, parser):
- lineno = parser.stream.next().lineno
-
- old_autoescape = parser.environment.autoescape
- parser.environment.autoescape = True
- try:
- body = parser.parse_statements(
- ['name:endautoescape'], drop_needle=True)
- finally:
- parser.environment.autoescape = old_autoescape
-
- # Not sure yet if the code below is necessary - it changes
- # environment.autoescape during template rendering. If for example
- # a CallBlock function accesses ``environment.autoescape``, it
- # presumably is.
- # This also should use try-finally though, which Jinja's API
- # doesn't support either. We could fake that as well by using
- # InternalNames that output the necessary indentation and keywords,
- # but at this point it starts to get really messy.
- #
- # TODO: Actually, there's ``nodes.EnvironmentAttribute``.
- #ae_setting = object.__new__(nodes.InternalName)
- #nodes.Node.__init__(ae_setting, 'environment.autoescape', lineno=lineno)
- #temp = parser.free_identifier()
- #body.insert(0, nodes.Assign(temp, ae_setting))
- #body.insert(1, nodes.Assign(ae_setting, nodes.Const(True)))
- #body.insert(len(body), nodes.Assign(ae_setting, temp))
- return body
-"""
-
-
-class URLExtension(Extension):
- """Returns an absolute URL matching given view with its parameters.
-
- This is a way to define links that aren't tied to a particular URL
- configuration::
-
- {% url path.to.some_view arg1,arg2,name1=value1 %}
-
- Known differences to Django's url-Tag:
-
- - In Django, the view name may contain any non-space character.
- Since Jinja's lexer does not identify whitespace to us, only
- characters that make up valid identifers, plus dots and hyphens
- are allowed. Note that identifers in Jinja 2 may not contain
- non-ascii characters.
-
- As an alternative, you may specifify the view as a string,
- which bypasses all these restrictions. It further allows you
- to apply filters:
-
- {% url "меткаda.some-view"|afilter %}
- """
-
- tags = set(['url'])
-
- def parse(self, parser):
- stream = parser.stream
-
- tag = stream.next()
-
- # get view name
- if stream.current.test('string'):
- viewname = parser.parse_primary()
- else:
- # parse valid tokens and manually build a string from them
- bits = []
- name_allowed = True
- while True:
- if stream.current.test_any('dot', 'sub'):
- bits.append(stream.next())
- name_allowed = True
- elif stream.current.test('name') and name_allowed:
- bits.append(stream.next())
- name_allowed = False
- else:
- break
- viewname = nodes.Const("".join([b.value for b in bits]))
- if not bits:
- raise TemplateSyntaxError("'%s' requires path to view" %
- tag.value, tag.lineno)
-
- # get arguments
- args = []
- kwargs = []
- while not stream.current.test_any('block_end', 'name:as'):
- if args or kwargs:
- stream.expect('comma')
- if stream.current.test('name') and stream.look().test('assign'):
- key = nodes.Const(stream.next().value)
- stream.skip()
- value = parser.parse_expression()
- kwargs.append(nodes.Pair(key, value, lineno=key.lineno))
- else:
- args.append(parser.parse_expression())
-
- make_call_node = lambda *kw: \
- self.call_method('_reverse',
- args=[viewname, nodes.List(args), nodes.Dict(kwargs)],
- kwargs=kw)
-
- # if an as-clause is specified, write the result to context...
- if stream.next_if('name:as'):
- var = nodes.Name(stream.expect('name').value, 'store')
- call_node = make_call_node(nodes.Keyword('fail', nodes.Const(False)))
- return nodes.Assign(var, call_node)
- # ...otherwise print it out.
- else:
- return nodes.Output([make_call_node()]).set_lineno(tag.lineno)
-
- @classmethod
- def _reverse(self, viewname, args, kwargs, fail=True):
- from django.core.urlresolvers import reverse, NoReverseMatch
-
- # Try to look up the URL twice: once given the view name,
- # and again relative to what we guess is the "main" app.
- url = ''
- try:
- url = reverse(viewname, args=args, kwargs=kwargs)
- except NoReverseMatch:
- projectname = settings.SETTINGS_MODULE.split('.')[0]
- try:
- url = reverse(projectname + '.' + viewname,
- args=args, kwargs=kwargs)
- except NoReverseMatch:
- if fail:
- raise
- else:
- return ''
-
- return url
-
-
-class WithExtension(Extension):
- """Adds a value to the context (inside this block) for caching and
- easy access, just like the Django-version does.
-
- For example::
-
- {% with person.some_sql_method as total %}
- {{ total }} object{{ total|pluralize }}
- {% endwith %}
-
- TODO: The new Scope node introduced in Jinja2 6334c1eade73 (the 2.2
- dev version) would help here, but we don't want to rely on that yet.
- See also:
- http://dev.pocoo.org/projects/jinja/browser/tests/test_ext.py
- http://dev.pocoo.org/projects/jinja/ticket/331
- http://dev.pocoo.org/projects/jinja/ticket/329
- """
-
- tags = set(['with'])
-
- def parse(self, parser):
- lineno = parser.stream.next().lineno
-
- value = parser.parse_expression()
- parser.stream.expect('name:as')
- name = parser.stream.expect('name')
-
- body = parser.parse_statements(['name:endwith'], drop_needle=True)
- return nodes.CallBlock(
- self.call_method('_render_block', args=[value]),
- [nodes.Name(name.value, 'store')], [], body).\
- set_lineno(lineno)
-
- def _render_block(self, value, caller=None):
- return caller(value)
-
-
-class CacheExtension(Extension):
- """Exactly like Django's own tag, but supports full Jinja2
- expressiveness for all arguments.
-
- {% cache gettimeout()*2 "foo"+options.cachename %}
- ...
- {% endcache %}
-
- This actually means that there is a considerable incompatibility
- to Django: In Django, the second argument is simply a name, but
- interpreted as a literal string. This tag, with Jinja2 stronger
- emphasis on consistent syntax, requires you to actually specify the
- quotes around the name to make it a string. Otherwise, allowing
- Jinja2 expressions would be very hard to impossible (one could use
- a lookahead to see if the name is followed by an operator, and
- evaluate it as an expression if so, or read it as a string if not.
- TODO: This may not be the right choice. Supporting expressions
- here is probably not very important, so compatibility should maybe
- prevail. Unfortunately, it is actually pretty hard to be compatibly
- in all cases, simply because Django's per-character parser will
- just eat everything until the next whitespace and consider it part
- of the fragment name, while we have to work token-based: ``x*2``
- would actually be considered ``"x*2"`` in Django, while Jinja2
- would give us three tokens: ``x``, ``*``, ``2``.
-
- General Syntax:
-
- {% cache [expire_time] [fragment_name] [var1] [var2] .. %}
- .. some expensive processing ..
- {% endcache %}
-
- Available by default (does not need to be loaded).
-
- Partly based on the ``FragmentCacheExtension`` from the Jinja2 docs.
-
- TODO: Should there be scoping issues with the internal dummy macro
- limited access to certain outer variables in some cases, there is a
- different way to write this. Generated code would look like this:
-
- internal_name = environment.extensions['..']._get_cache_value():
- if internal_name is not None:
- yield internal_name
- else:
- internal_name = "" # or maybe use [] and append() for performance
- internalname += "..."
- internalname += "..."
- internalname += "..."
- environment.extensions['..']._set_cache_value(internalname):
- yield internalname
-
- In other words, instead of using a CallBlock which uses a local
- function and calls into python, we have to separate calls into
- python, but put the if-else logic itself into the compiled template.
- """
-
- tags = set(['cache'])
-
- def parse(self, parser):
- lineno = parser.stream.next().lineno
-
- expire_time = parser.parse_expression()
- fragment_name = parser.parse_expression()
- vary_on = []
- while not parser.stream.current.test('block_end'):
- vary_on.append(parser.parse_expression())
-
- body = parser.parse_statements(['name:endcache'], drop_needle=True)
-
- return nodes.CallBlock(
- self.call_method('_cache_support',
- [expire_time, fragment_name,
- nodes.List(vary_on), nodes.Const(lineno)]),
- [], [], body).set_lineno(lineno)
-
- def _cache_support(self, expire_time, fragm_name, vary_on, lineno, caller):
- from django.core.cache import cache # delay depending in settings
- from django.utils.http import urlquote
-
- try:
- expire_time = int(expire_time)
- except (ValueError, TypeError):
- raise TemplateSyntaxError('"%s" tag got a non-integer '
- 'timeout value: %r' % (list(self.tags)[0], expire_time), lineno)
-
- cache_key = u':'.join([fragm_name] + [urlquote(v) for v in vary_on])
- value = cache.get(cache_key)
- if value is None:
- value = caller()
- cache.set(cache_key, value, expire_time)
- return value
-
-
-class SpacelessExtension(Extension):
- """Removes whitespace between HTML tags, including tab and
- newline characters.
-
- Works exactly like Django's own tag.
- """
-
- tags = ['spaceless']
-
- def parse(self, parser):
- lineno = parser.stream.next().lineno
- body = parser.parse_statements(['name:endspaceless'], drop_needle=True)
- return nodes.CallBlock(
- self.call_method('_strip_spaces', [], [], None, None),
- [], [], body
- ).set_lineno(lineno)
-
- def _strip_spaces(self, caller=None):
- from django.utils.html import strip_spaces_between_tags
- return strip_spaces_between_tags(caller().strip())
-
-
-# nicer import names
-load = LoadExtension
-url = URLExtension
-with_ = WithExtension
-cache = CacheExtension
-spaceless = SpacelessExtension
-
-
-register = Library()
-register.tag(load)
-register.tag(url)
-register.tag(with_)
-register.tag(cache)
-register.tag(spaceless) \ No newline at end of file
diff --git a/coffin/template/library.py b/coffin/template/library.py
deleted file mode 100644
index 8e80edc5..00000000
--- a/coffin/template/library.py
+++ /dev/null
@@ -1,215 +0,0 @@
-from django.template import Library as DjangoLibrary, InvalidTemplateLibrary
-from jinja2.ext import Extension as Jinja2Extension
-from coffin.interop import (
- DJANGO, JINJA2,
- guess_filter_type, jinja2_filter_to_django, django_filter_to_jinja2)
-
-
-__all__ = ['Library']
-
-
-class Library(DjangoLibrary):
- """Version of the Django ``Library`` class that can handle both
- Django template engine tags and filters, as well as Jinja2
- extensions and filters.
-
- Tries to present a common registration interface to the extension
- author, but provides both template engines with only those
- components they can support.
-
- Since custom Django tags and Jinja2 extensions are two completely
- different beasts, they are handled completely separately. You can
- register custom Django tags as usual, for example:
-
- register.tag('current_time', do_current_time)
-
- Or register a Jinja2 extension like this:
-
- register.tag(CurrentTimeNode)
-
- Filters, on the other hand, work similarily in both engines, and
- for the most one can't tell whether a filter function was written
- for Django or Jinja2. A compatibility layer is used to make to
- make the filters you register usuable with both engines:
-
- register.filter('cut', cut)
-
- However, some of the more powerful filters just won't work in
- Django, for example if more than one argument is required, or if
- context- or environmentfilters are used. If ``cut`` in the above
- example where such an extended filter, it would only be registered
- with Jinja.
-
- See also the module documentation for ``coffin.interop`` for
- information on some of the limitations of this conversion.
-
- TODO: Jinja versions of the ``simple_tag`` and ``inclusion_tag``
- helpers would be nice, though since custom tags are not needed as
- often in Jinja, this is not urgent.
- """
-
- def __init__(self):
- super(Library, self).__init__()
- self.jinja2_filters = {}
- self.jinja2_extensions = []
- self.jinja2_globals = {}
- self.jinja2_tests = {}
-
- @classmethod
- def from_django(cls, django_library):
- """Create a Coffin library object from a Django library.
-
- Specifically, this ensures that filters already registered
- with the Django library are also made available to Jinja,
- where applicable.
- """
- from copy import copy
- result = cls()
- result.filters = copy(django_library.filters)
- result.tags = copy(django_library.tags)
- for name, func in result.filters.iteritems():
- result._register_filter(name, func, jinja2_only=True)
- return result
-
- def test(self, name=None, func=None):
- def inner(f):
- name = getattr(f, "_decorated_function", f).__name__
- self.jinja2_tests[name] = f
- return f
- if name == None and func == None:
- # @register.test()
- return inner
- elif func == None:
- if (callable(name)):
- # register.test()
- return inner(name)
- else:
- # @register.test('somename') or @register.test(name='somename')
- def dec(func):
- return self.test(name, func)
- return dec
- elif name != None and func != None:
- # register.filter('somename', somefunc)
- self.jinja2_tests[name] = func
- return func
- else:
- raise InvalidTemplateLibrary("Unsupported arguments to "
- "Library.test: (%r, %r)", (name, func))
-
- def object(self, name=None, func=None):
- def inner(f):
- name = getattr(f, "_decorated_function", f).__name__
- self.jinja2_globals[name] = f
- return f
- if name == None and func == None:
- # @register.object()
- return inner
- elif func == None:
- if (callable(name)):
- # register.object()
- return inner(name)
- else:
- # @register.object('somename') or @register.object(name='somename')
- def dec(func):
- return self.object(name, func)
- return dec
- elif name != None and func != None:
- # register.object('somename', somefunc)
- self.jinja2_globals[name] = func
- return func
- else:
- raise InvalidTemplateLibrary("Unsupported arguments to "
- "Library.object: (%r, %r)", (name, func))
-
- def tag(self, name_or_node=None, compile_function=None):
- """Register a Django template tag (1) or Jinja 2 extension (2).
-
- For (1), supports the same invocation syntax as the original
- Django version, including use as a decorator.
-
- For (2), since Jinja 2 extensions are classes (which can't be
- decorated), and have the tag name effectively built in, only the
- following syntax is supported:
-
- register.tag(MyJinjaExtensionNode)
- """
- if isinstance(name_or_node, Jinja2Extension):
- if compile_function:
- raise InvalidTemplateLibrary('"compile_function" argument not supported for Jinja2 extensions')
- self.jinja2_extensions.append(name_or_node)
- return name_or_node
- else:
- return super(Library, self).tag(name_or_node, compile_function)
-
- def tag_function(self, func_or_node):
- if issubclass(func_or_node, Jinja2Extension):
- self.jinja2_extensions.append(func_or_node)
- return func_or_node
- else:
- return super(Library, self).tag_function(func_or_node)
-
- def filter(self, name=None, filter_func=None, jinja2_only=False):
- """Register a filter with both the Django and Jinja2 template
- engines, if possible - or only Jinja2, if ``jinja2_only`` is
- specified. ``jinja2_only`` does not affect conversion of the
- filter if neccessary.
-
- Implements a compatibility layer to handle the different
- auto-escaping approaches transparently. Extended Jinja2 filter
- features like environment- and contextfilters are however not
- supported in Django. Such filters will only be registered with
- Jinja.
-
- Supports the same invocation syntax as the original Django
- version, including use as a decorator.
-
- If the function is supposed to return the registered filter
- (by example of the superclass implementation), but has
- registered multiple filters, a tuple of all filters is
- returned.
- """
- def filter_function(f):
- return self._register_filter(
- getattr(f, "_decorated_function", f).__name__,
- f, jinja2_only=jinja2_only)
- if name == None and filter_func == None:
- # @register.filter()
- return filter_function
- elif filter_func == None:
- if (callable(name)):
- # @register.filter
- return filter_function(name)
- else:
- # @register.filter('somename') or @register.filter(name='somename')
- def dec(func):
- return self.filter(name, func, jinja2_only=jinja2_only)
- return dec
- elif name != None and filter_func != None:
- # register.filter('somename', somefunc)
- return self._register_filter(name, filter_func,
- jinja2_only=jinja2_only)
- else:
- raise InvalidTemplateLibrary("Unsupported arguments to "
- "Library.filter: (%r, %r)", (name, filter_func))
-
- def _register_filter(self, name, func, jinja2_only=None):
- filter_type, can_be_ported = guess_filter_type(func)
- if filter_type == JINJA2 and not can_be_ported:
- self.jinja2_filters[name] = func
- return func
- elif filter_type == DJANGO and not can_be_ported:
- if jinja2_only:
- raise ValueError('This filter cannot be ported to Jinja2.')
- self.filters[name] = func
- return func
- elif jinja2_only:
- func = django_filter_to_jinja2(func)
- self.jinja2_filters[name] = func
- return func
- else:
- # register the filter with both engines
- django_func = jinja2_filter_to_django(func)
- jinja2_func = django_filter_to_jinja2(func)
- self.filters[name] = django_func
- self.jinja2_filters[name] = jinja2_func
- return (django_func, jinja2_func)
diff --git a/coffin/template/loader.py b/coffin/template/loader.py
deleted file mode 100644
index 1f2bbb1f..00000000
--- a/coffin/template/loader.py
+++ /dev/null
@@ -1,66 +0,0 @@
-"""Replacement for ``django.template.loader`` that uses Jinja 2.
-
-The module provides a generic way to load templates from an arbitrary
-backend storage (e.g. filesystem, database).
-"""
-
-from coffin.template import Template as CoffinTemplate
-from jinja2 import TemplateNotFound
-
-
-def find_template_source(name, dirs=None):
- # This is Django's most basic loading function through which
- # all template retrievals go. Not sure if Jinja 2 publishes
- # an equivalent, but no matter, it mostly for internal use
- # anyway - developers will want to start with
- # ``get_template()`` or ``get_template_from_string`` anyway.
- raise NotImplementedError()
-
-
-def get_template(template_name):
- # Jinja will handle this for us, and env also initializes
- # the loader backends the first time it is called.
- from coffin.common import env
- return env.get_template(template_name)
-
-
-def get_template_from_string(source):
- """
- Does not support then ``name`` and ``origin`` parameters from
- the Django version.
- """
- from coffin.common import env
- return env.from_string(source)
-
-
-def render_to_string(template_name, dictionary=None, context_instance=None):
- """Loads the given ``template_name`` and renders it with the given
- dictionary as context. The ``template_name`` may be a string to load
- a single template using ``get_template``, or it may be a tuple to use
- ``select_template`` to find one of the templates in the list.
-
- ``dictionary`` may also be Django ``Context`` object.
-
- Returns a string.
- """
- dictionary = dictionary or {}
- if isinstance(template_name, (list, tuple)):
- template = select_template(template_name)
- else:
- template = get_template(template_name)
- if context_instance:
- context_instance.update(dictionary)
- else:
- context_instance = dictionary
- return template.render(context_instance)
-
-
-def select_template(template_name_list):
- "Given a list of template names, returns the first that can be loaded."
- for template_name in template_name_list:
- try:
- return get_template(template_name)
- except TemplateNotFound:
- continue
- # If we get here, none of the templates could be loaded
- raise TemplateNotFound(', '.join(template_name_list))
diff --git a/coffin/template/loaders.py b/coffin/template/loaders.py
deleted file mode 100644
index cb42fd5d..00000000
--- a/coffin/template/loaders.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from jinja2 import loaders
-
-
-def jinja_loader_from_django_loader(django_loader):
- """Attempts to make a conversion from the given Django loader to an
- similarly-behaving Jinja loader.
-
- :param django_loader: Django loader module string.
- :return: The similarly-behaving Jinja loader, or None if a similar loader
- could not be found.
- """
- for substr, func in _JINJA_LOADER_BY_DJANGO_SUBSTR.iteritems():
- if substr in django_loader:
- return func()
- return None
-
-
-def _make_jinja_app_loader():
- """Makes an 'app loader' for Jinja which acts like
- :mod:`django.template.loaders.app_directories`.
- """
- from django.template.loaders.app_directories import app_template_dirs
- return loaders.FileSystemLoader(app_template_dirs)
-
-
-def _make_jinja_filesystem_loader():
- """Makes a 'filesystem loader' for Jinja which acts like
- :mod:`django.template.loaders.filesystem`.
- """
- from django.conf import settings
- return loaders.FileSystemLoader(settings.TEMPLATE_DIRS)
-
-
-# Determine loaders from Django's conf.
-_JINJA_LOADER_BY_DJANGO_SUBSTR = { # {substr: callable, ...}
- 'app_directories': _make_jinja_app_loader,
- 'filesystem': _make_jinja_filesystem_loader,
-}
diff --git a/coffin/views/__init__.py b/coffin/views/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/coffin/views/__init__.py
+++ /dev/null
diff --git a/coffin/views/defaults.py b/coffin/views/defaults.py
deleted file mode 100644
index 4386a49b..00000000
--- a/coffin/views/defaults.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from django import http
-from django.template import Context, RequestContext
-from coffin.template.loader import render_to_string
-
-
-__all__ = ('page_not_found', 'server_error', 'shortcut')
-
-
-# no Jinja version for this needed
-from django.views.defaults import shortcut
-
-
-def page_not_found(request, template_name='404.html'):
- """
- Default 404 handler.
-
- Templates: `404.html`
- Context:
- request_path
- The path of the requested URL (e.g., '/app/pages/bad_page/')
- """
- content = render_to_string(template_name,
- RequestContext(request, {'request_path': request.path}))
- return http.HttpResponseNotFound(content)
-
-
-def server_error(request, template_name='500.html'):
- """
- 500 error handler.
-
- Templates: `500.html`
- Context: None
- """
- content = render_to_string(template_name, Context({}))
- return http.HttpResponseServerError(content)
diff --git a/coffin/views/generic/._simple.py b/coffin/views/generic/._simple.py
deleted file mode 100644
index a1bb18de..00000000
--- a/coffin/views/generic/._simple.py
+++ /dev/null
Binary files differ
diff --git a/coffin/views/generic/__init__.py b/coffin/views/generic/__init__.py
deleted file mode 100644
index 7ea80e4c..00000000
--- a/coffin/views/generic/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from django.views.generic import *
diff --git a/coffin/views/generic/simple.py b/coffin/views/generic/simple.py
deleted file mode 100644
index ff7678b2..00000000
--- a/coffin/views/generic/simple.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import inspect
-
-from django.views.generic.simple import *
-from coffin.template import loader, RequestContext
-
-exec inspect.getsource(direct_to_template)
diff --git a/setup.py b/setup.py
index 50c72ddb..f1ab7da0 100644
--- a/setup.py
+++ b/setup.py
@@ -8,6 +8,8 @@ import sys
install_requires = [
'django==1.1.2',
+ 'Jinja2',
+ 'Coffin==0.3.0',
'South>=0.7.1',
'oauth2',
'recaptcha-client',