diff --git a/django/template/loader.py b/django/template/loader.py
index 4185017..98ea96c 100644
|
a
|
b
|
|
| 3 | 3 | # This uses the TEMPLATE_LOADERS setting, which is a list of loaders to use. |
| 4 | 4 | # Each loader is expected to have this interface: |
| 5 | 5 | # |
| 6 | | # callable(name, dirs=[]) |
| | 6 | # callable(name) |
| 7 | 7 | # |
| 8 | 8 | # name is the template name. |
| 9 | | # dirs is an optional list of directories to search instead of TEMPLATE_DIRS. |
| 10 | 9 | # |
| 11 | 10 | # The loader should return a tuple of (template_source, path). The path returned |
| 12 | 11 | # might be shown to the user for debugging purposes, so it should identify where |
| … |
… |
class BaseLoader(object):
|
| 38 | 37 | def __init__(self, *args, **kwargs): |
| 39 | 38 | pass |
| 40 | 39 | |
| 41 | | def __call__(self, template_name, template_dirs=None): |
| 42 | | return self.load_template(template_name, template_dirs) |
| | 40 | def __call__(self, template_name): |
| | 41 | return self.load_template(template_name) |
| 43 | 42 | |
| 44 | | def load_template(self, template_name, template_dirs=None): |
| 45 | | source, display_name = self.load_template_source(template_name, template_dirs) |
| 46 | | origin = make_origin(display_name, self.load_template_source, template_name, template_dirs) |
| | 43 | def load_template(self, template_name): |
| | 44 | source, display_name = self.load_template_source(template_name) |
| | 45 | origin = make_origin(display_name, self.load_template_source, template_name) |
| 47 | 46 | try: |
| 48 | 47 | template = get_template_from_string(source, origin, template_name) |
| 49 | 48 | return template, None |
| … |
… |
class BaseLoader(object):
|
| 54 | 53 | # not exist. |
| 55 | 54 | return source, display_name |
| 56 | 55 | |
| 57 | | def load_template_source(self, template_name, template_dirs=None): |
| | 56 | def load_template_source(self, template_name): |
| 58 | 57 | """ |
| 59 | 58 | Returns a tuple containing the source and origin for the given template |
| 60 | 59 | name. |
| … |
… |
class BaseLoader(object):
|
| 71 | 70 | pass |
| 72 | 71 | |
| 73 | 72 | class LoaderOrigin(Origin): |
| 74 | | def __init__(self, display_name, loader, name, dirs): |
| | 73 | def __init__(self, display_name, loader, name): |
| 75 | 74 | super(LoaderOrigin, self).__init__(display_name) |
| 76 | | self.loader, self.loadname, self.dirs = loader, name, dirs |
| | 75 | self.loader, self.loadname = loader, name |
| 77 | 76 | |
| 78 | 77 | def reload(self): |
| 79 | | return self.loader(self.loadname, self.dirs)[0] |
| | 78 | return self.loader(self.loadname)[0] |
| 80 | 79 | |
| 81 | | def make_origin(display_name, loader, name, dirs): |
| | 80 | def make_origin(display_name, loader, name): |
| 82 | 81 | if settings.TEMPLATE_DEBUG and display_name: |
| 83 | | return LoaderOrigin(display_name, loader, name, dirs) |
| | 82 | return LoaderOrigin(display_name, loader, name) |
| 84 | 83 | else: |
| 85 | 84 | return None |
| 86 | 85 | |
| … |
… |
def find_template_loader(loader):
|
| 117 | 116 | else: |
| 118 | 117 | raise ImproperlyConfigured('Loader does not define a "load_template" callable template source loader') |
| 119 | 118 | |
| 120 | | def find_template(name, dirs=None): |
| | 119 | def find_template(name): |
| 121 | 120 | # Calculate template_source_loaders the first time the function is executed |
| 122 | 121 | # because putting this logic in the module-level namespace may cause |
| 123 | 122 | # circular import errors. See Django ticket #1292. |
| … |
… |
def find_template(name, dirs=None):
|
| 131 | 130 | template_source_loaders = tuple(loaders) |
| 132 | 131 | for loader in template_source_loaders: |
| 133 | 132 | try: |
| 134 | | source, display_name = loader(name, dirs) |
| 135 | | return (source, make_origin(display_name, loader, name, dirs)) |
| | 133 | source, display_name = loader(name) |
| | 134 | return (source, make_origin(display_name, loader, name)) |
| 136 | 135 | except TemplateDoesNotExist: |
| 137 | 136 | pass |
| 138 | 137 | raise TemplateDoesNotExist(name) |
diff --git a/django/template/loaders/app_directories.py b/django/template/loaders/app_directories.py
index b0560b4..2db1a47 100644
|
a
|
b
|
Wrapper for loading templates from "templates" directories in INSTALLED_APPS
|
| 3 | 3 | packages. |
| 4 | 4 | """ |
| 5 | 5 | |
| 6 | | import os |
| 7 | | import sys |
| | 6 | import pkgutil |
| 8 | 7 | |
| 9 | 8 | from django.conf import settings |
| 10 | | from django.core.exceptions import ImproperlyConfigured |
| 11 | 9 | from django.template.base import TemplateDoesNotExist |
| 12 | 10 | from django.template.loader import BaseLoader |
| 13 | 11 | from django.utils._os import safe_join |
| 14 | | from django.utils.importlib import import_module |
| 15 | 12 | |
| 16 | | # At compile time, cache the directories to search. |
| 17 | | fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() |
| 18 | | app_template_dirs = [] |
| 19 | | for app in settings.INSTALLED_APPS: |
| 20 | | try: |
| 21 | | mod = import_module(app) |
| 22 | | except ImportError, e: |
| 23 | | raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0])) |
| 24 | | template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates') |
| 25 | | if os.path.isdir(template_dir): |
| 26 | | app_template_dirs.append(template_dir.decode(fs_encoding)) |
| 27 | | |
| 28 | | # It won't change, so convert it to a tuple to save memory. |
| 29 | | app_template_dirs = tuple(app_template_dirs) |
| 30 | 13 | |
| 31 | 14 | class Loader(BaseLoader): |
| 32 | 15 | is_usable = True |
| 33 | 16 | |
| 34 | | def get_template_sources(self, template_name, template_dirs=None): |
| 35 | | """ |
| 36 | | Returns the absolute paths to "template_name", when appended to each |
| 37 | | directory in "template_dirs". Any paths that don't lie inside one of the |
| 38 | | template dirs are excluded from the result set, for security reasons. |
| 39 | | """ |
| 40 | | if not template_dirs: |
| 41 | | template_dirs = app_template_dirs |
| 42 | | for template_dir in template_dirs: |
| | 17 | def load_template_source(self, template_name): |
| | 18 | for app in settings.INSTALLED_APPS: |
| | 19 | resource = safe_join('/templates', template_name)[1:] |
| 43 | 20 | try: |
| 44 | | yield safe_join(template_dir, template_name) |
| 45 | | except UnicodeDecodeError: |
| 46 | | # The template dir name was a bytestring that wasn't valid UTF-8. |
| 47 | | raise |
| 48 | | except ValueError: |
| 49 | | # The joined path was located outside of template_dir. |
| | 21 | data = pkgutil.get_data(app, resource) |
| | 22 | if data is not None: |
| | 23 | return data, 'app:' + app + ':'+resource |
| | 24 | except Exception: |
| 50 | 25 | pass |
| 51 | 26 | |
| 52 | | def load_template_source(self, template_name, template_dirs=None): |
| 53 | | for filepath in self.get_template_sources(template_name, template_dirs): |
| 54 | | try: |
| 55 | | file = open(filepath) |
| 56 | | try: |
| 57 | | return (file.read().decode(settings.FILE_CHARSET), filepath) |
| 58 | | finally: |
| 59 | | file.close() |
| 60 | | except IOError: |
| 61 | | pass |
| 62 | 27 | raise TemplateDoesNotExist(template_name) |
| 63 | 28 | |
| 64 | 29 | _loader = Loader() |
diff --git a/django/template/loaders/cached.py b/django/template/loaders/cached.py
index 4c25acd..eeb1e6e 100644
|
a
|
b
|
class Loader(BaseLoader):
|
| 27 | 27 | self._cached_loaders = cached_loaders |
| 28 | 28 | return self._cached_loaders |
| 29 | 29 | |
| 30 | | def find_template(self, name, dirs=None): |
| | 30 | def find_template(self, name): |
| 31 | 31 | for loader in self.loaders: |
| 32 | 32 | try: |
| 33 | | template, display_name = loader(name, dirs) |
| 34 | | return (template, make_origin(display_name, loader, name, dirs)) |
| | 33 | template, display_name = loader(name) |
| | 34 | return (template, make_origin(display_name, loader, name)) |
| 35 | 35 | except TemplateDoesNotExist: |
| 36 | 36 | pass |
| 37 | 37 | raise TemplateDoesNotExist(name) |
| 38 | 38 | |
| 39 | | def load_template(self, template_name, template_dirs=None): |
| 40 | | key = template_name |
| 41 | | if template_dirs: |
| 42 | | # If template directories were specified, use a hash to differentiate |
| 43 | | key = '-'.join([template_name, hashlib.sha1('|'.join(template_dirs)).hexdigest()]) |
| 44 | | |
| 45 | | if key not in self.template_cache: |
| 46 | | template, origin = self.find_template(template_name, template_dirs) |
| | 39 | def load_template(self, template_name): |
| | 40 | if template_name not in self.template_cache: |
| | 41 | template, origin = self.find_template(template_name) |
| 47 | 42 | if not hasattr(template, 'render'): |
| 48 | 43 | try: |
| 49 | 44 | template = get_template_from_string(template, origin, template_name) |
| … |
… |
class Loader(BaseLoader):
|
| 53 | 48 | # we were asked to load. This allows for correct identification (later) |
| 54 | 49 | # of the actual template that does not exist. |
| 55 | 50 | return template, origin |
| 56 | | self.template_cache[key] = template |
| 57 | | return self.template_cache[key], None |
| | 51 | self.template_cache[template_name] = template |
| | 52 | return self.template_cache[template_name], None |
| 58 | 53 | |
| 59 | 54 | def reset(self): |
| 60 | 55 | "Empty the template cache." |
diff --git a/django/template/loaders/eggs.py b/django/template/loaders/eggs.py
deleted file mode 100644
index 42f87a4..0000000
|
+
|
-
|
|
| 1 | | # Wrapper for loading templates from eggs via pkg_resources.resource_string. |
| 2 | | |
| 3 | | try: |
| 4 | | from pkg_resources import resource_string |
| 5 | | except ImportError: |
| 6 | | resource_string = None |
| 7 | | |
| 8 | | from django.template.base import TemplateDoesNotExist |
| 9 | | from django.template.loader import BaseLoader |
| 10 | | from django.conf import settings |
| 11 | | |
| 12 | | class Loader(BaseLoader): |
| 13 | | is_usable = resource_string is not None |
| 14 | | |
| 15 | | def load_template_source(self, template_name, template_dirs=None): |
| 16 | | """ |
| 17 | | Loads templates from Python eggs via pkg_resource.resource_string. |
| 18 | | |
| 19 | | For every installed app, it tries to get the resource (app, template_name). |
| 20 | | """ |
| 21 | | if resource_string is not None: |
| 22 | | pkg_name = 'templates/' + template_name |
| 23 | | for app in settings.INSTALLED_APPS: |
| 24 | | try: |
| 25 | | return (resource_string(app, pkg_name).decode(settings.FILE_CHARSET), 'egg:%s:%s' % (app, pkg_name)) |
| 26 | | except: |
| 27 | | pass |
| 28 | | raise TemplateDoesNotExist(template_name) |
| 29 | | |
| 30 | | _loader = Loader() |
diff --git a/django/template/loaders/filesystem.py b/django/template/loaders/filesystem.py
index 51025ac..b926c6b 100644
|
a
|
b
|
from django.utils._os import safe_join
|
| 10 | 10 | class Loader(BaseLoader): |
| 11 | 11 | is_usable = True |
| 12 | 12 | |
| 13 | | def get_template_sources(self, template_name, template_dirs=None): |
| | 13 | def __init__(self, template_dirs=None): |
| | 14 | self.template_dirs = template_dirs or settings.TEMPLATE_DIRS |
| | 15 | |
| | 16 | def get_template_sources(self, template_name): |
| 14 | 17 | """ |
| 15 | 18 | Returns the absolute paths to "template_name", when appended to each |
| 16 | 19 | directory in "template_dirs". Any paths that don't lie inside one of the |
| 17 | 20 | template dirs are excluded from the result set, for security reasons. |
| 18 | 21 | """ |
| 19 | | if not template_dirs: |
| 20 | | template_dirs = settings.TEMPLATE_DIRS |
| 21 | | for template_dir in template_dirs: |
| | 22 | for template_dir in self.template_dirs: |
| 22 | 23 | try: |
| 23 | 24 | yield safe_join(template_dir, template_name) |
| 24 | 25 | except UnicodeDecodeError: |
| … |
… |
class Loader(BaseLoader):
|
| 30 | 31 | # fatal). |
| 31 | 32 | pass |
| 32 | 33 | |
| 33 | | def load_template_source(self, template_name, template_dirs=None): |
| | 34 | def load_template_source(self, template_name): |
| 34 | 35 | tried = [] |
| 35 | | for filepath in self.get_template_sources(template_name, template_dirs): |
| | 36 | for filepath in self.get_template_sources(template_name): |
| 36 | 37 | try: |
| 37 | 38 | file = open(filepath) |
| 38 | 39 | try: |
diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index 76c9bfc..158357c 100644
|
a
|
b
|
import re
|
| 6 | 6 | import sys |
| 7 | 7 | import gettext as gettext_module |
| 8 | 8 | from threading import local |
| | 9 | import pkgutil |
| | 10 | import copy |
| 9 | 11 | |
| 10 | 12 | try: |
| 11 | 13 | from cStringIO import StringIO |
| … |
… |
def translation(language):
|
| 121 | 123 | |
| 122 | 124 | loc = to_locale(lang) |
| 123 | 125 | |
| 124 | | def _translation(path): |
| 125 | | try: |
| 126 | | t = gettext_module.translation('django', path, [loc], DjangoTranslation) |
| 127 | | t.set_language(lang) |
| 128 | | return t |
| 129 | | except IOError: |
| 130 | | return None |
| | 126 | def _translation(path_or_appname, is_appname=False): |
| | 127 | if is_appname: |
| | 128 | nelangs = gettext_module._expand_lang(loc) |
| | 129 | for nelang in nelangs: |
| | 130 | locpath = os.path.join('locale', nelang, 'LC_MESSAGES', 'django.mo') |
| | 131 | try: |
| | 132 | data = pkgutil.get_data(path_or_appname, locpath) |
| | 133 | except: |
| | 134 | continue |
| | 135 | |
| | 136 | if data is not None: |
| | 137 | t = DjangoTranslation(StringIO(data)) |
| | 138 | t = copy.copy(t) |
| | 139 | break |
| | 140 | else: |
| | 141 | return None |
| | 142 | else: |
| | 143 | try: |
| | 144 | t = gettext_module.translation('django', path_or_appname, [loc], DjangoTranslation) |
| | 145 | except IOError: |
| | 146 | return None |
| | 147 | |
| | 148 | t.set_language(lang) |
| | 149 | return t |
| 131 | 150 | |
| 132 | 151 | res = _translation(globalpath) |
| 133 | 152 | |
| … |
… |
def translation(language):
|
| 140 | 159 | res._info = res._info.copy() |
| 141 | 160 | res._catalog = res._catalog.copy() |
| 142 | 161 | |
| 143 | | def _merge(path): |
| 144 | | t = _translation(path) |
| | 162 | def _merge(path_or_appname, is_appname=False): |
| | 163 | t = _translation(path_or_appname, is_appname) |
| 145 | 164 | if t is not None: |
| 146 | 165 | if res is None: |
| 147 | 166 | return t |
| … |
… |
def translation(language):
|
| 150 | 169 | return res |
| 151 | 170 | |
| 152 | 171 | for appname in reversed(settings.INSTALLED_APPS): |
| 153 | | app = import_module(appname) |
| 154 | | apppath = os.path.join(os.path.dirname(app.__file__), 'locale') |
| 155 | | |
| 156 | | if os.path.isdir(apppath): |
| 157 | | res = _merge(apppath) |
| | 172 | res = _merge(appname, is_appname=True) |
| 158 | 173 | |
| 159 | 174 | for localepath in reversed(settings.LOCALE_PATHS): |
| 160 | 175 | if os.path.isdir(localepath): |
diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt
index 03fef1d..8154d2c 100644
|
a
|
b
|
class. Here are the template loaders that come with Django:
|
| 655 | 655 | This loader is enabled by default. |
| 656 | 656 | |
| 657 | 657 | ``django.template.loaders.app_directories.Loader`` |
| 658 | | Loads templates from Django apps on the filesystem. For each app in |
| 659 | | :setting:`INSTALLED_APPS`, the loader looks for a ``templates`` |
| 660 | | subdirectory. If the directory exists, Django looks for templates in there. |
| | 658 | Loads templates from Django apps. For each app in :setting:`INSTALLED_APPS`, |
| | 659 | the loader looks for a ``templates`` subdirectory. If the directory exists, |
| | 660 | Django looks for templates in there. |
| 661 | 661 | |
| 662 | 662 | This means you can store templates with your individual apps. This also |
| 663 | 663 | makes it easy to distribute Django apps with default templates. |
| … |
… |
class. Here are the template loaders that come with Django:
|
| 672 | 672 | * ``/path/to/myproject/polls/templates/foo.html`` |
| 673 | 673 | * ``/path/to/myproject/music/templates/foo.html`` |
| 674 | 674 | |
| 675 | | Note that the loader performs an optimization when it is first imported: It |
| 676 | | caches a list of which :setting:`INSTALLED_APPS` packages have a |
| 677 | | ``templates`` subdirectory. |
| 678 | | |
| 679 | 675 | This loader is enabled by default. |
| 680 | 676 | |
| 681 | | ``django.template.loaders.eggs.Loader`` |
| 682 | | Just like ``app_directories`` above, but it loads templates from Python |
| 683 | | eggs rather than from the filesystem. |
| 684 | | |
| 685 | | This loader is disabled by default. |
| 686 | | |
| 687 | 677 | ``django.template.loaders.cached.Loader`` |
| 688 | 678 | By default, the templating system will read and compile your templates every |
| 689 | 679 | time they need to be rendered. While the Django templating system is quite |
| … |
… |
of the ``load_template_source()`` method implemented there::
|
| 838 | 828 | class Loader(app_directories.Loader): |
| 839 | 829 | is_usable = True |
| 840 | 830 | |
| 841 | | def load_template(self, template_name, template_dirs=None): |
| 842 | | source, origin = self.load_template_source(template_name, template_dirs) |
| | 831 | def load_template(self, template_name): |
| | 832 | source, origin = self.load_template_source(template_name) |
| 843 | 833 | template = Template(source) |
| 844 | 834 | return template, origin |
| 845 | 835 | |
diff --git a/tests/regressiontests/i18n/eggs/localeegg.egg b/tests/regressiontests/i18n/eggs/localeegg.egg
new file mode 100644
index 0000000000000000000000000000000000000000..37b082e54f2cbbf5f7b7e88e61e34a15b22a9d6e
GIT binary patch
literal 1855
zcmWIWW@Zs#W&naGrL7Ji8V0z5jH1-y{G8H~%=|q40H8uHu)>3(z78-&AX*HFkrc+q
zXXa&=#K-FuRD$$iH(Ur+PfmVvVooa94(#ehv8qqOr$rH$79Zz$U)SJZM|am?xQ!eP
zAYX;5aAqbjGBCUZVl85{r(`AOrRVGA=7&x=>vzaO;P~t72j}&q^FQ`Y7K>77)Nxu7
zz~R}=E5d)QS$j?C#y4iWyDzeT+*rdp@90Xo3n%}j{hR#fdvaNI)sL46G79M)%$80{
zOM2X&NF<(6{M2Rh#?r6xE6Y!(w@G)Cjy`>3z1u?LazkX?)}*s@xA=61Y46*RvPY#n
zMtY%2>(j22K8;V0NtK`CUaH&at2XUP+GNQ|T3mTWvnTC)cIFXZ&^*tD&wk2%%sP_a
zaDU0yU!vdSq)txR&-wZM^XYc$IqT;B(s=cvd&WkUt3I>lL@w3jc^=3zS%L4NRZnx_
z6>hfXOpDp27qvF?p0@C`j1KN-I+-EYb3xp7Z%oLPbG!0v`VQZ9sXJQy+bc@%V_$z$
zu*|!=Vcl~$Z?+xfzT9^EoQ>?HYv;oEJ)M~?bgDIqYi3}EE$3^spKhDy@Jx-9=Gycl
z(|7r`w)mSnCluUc{C`RJf7Rx7_lgrADtS!ue%}9w4VIE1@$~Z4M5bfFI6A^aT09lx
z$4<=8zhxkB?Ed%QI}eUJ%x*leEbQHkS**+#ojQerS6;ri<B8NA)v^@p%Rjz(|5$u!
z->17jzyH|zxl}QBy~LRaDV4-ChuPU|o(M|Elqz1hdhbNd^9ABx9!~tp`9Zb$27lcz
z?r(;z39|NT50g$N?(9p`$uy}^*R?s#w9wKxbM8d{t%rHCrY>aM?z~}<i^dbNsjdRs
z*3P}(;+6BiLniur<%}gVe|Y293I8}2Rwr@y=jO;mm%jXd?rhFm8hR@x?ZV3~j>*^D
z=H7TAe#c5E?FnP=)TqD{aV@7zEw-Hd7sfj!VQH`O>M;MhD?3$Vf-Pc>X8SQUA2Rha
z66VwFalhBmbL_}(rhBGyee6tszF?Wm^55%s+t;YF65e|)RlWw68z*k)D^Q-I+j6<>
zP>rx_!Ta?$elz;-IF&t7`Jsjv*Tnk$H-2=t^)A}&#JA;S{~fKEjn_T*9=xb?;nc#c
zKi@=y3VxjDUG3yi%6)sTf!N)W!_S{QYqI_Nt*6ak>(!YdmaVhZU-mVNZ53plnH?O(
zwaRKqnbp45WQ(_&KMYvc-@g<d%eC~}h7HYG{_4+73nL%BURAfS<ih92JO0Og_^Ojp
zU-CjPG<T(5`}AA?QOlzL^HK|diGcxxMNo5XZhlH?PBE|~QV#HDWU^<*UbuitItUPG
z`0EH_Ar)s3jkrrbh(?8mEsdI}8d1tY+?In%LI?m^9t&h5Sq?83aq9<_j1U0Q-wR}7
z>IavTxQ$SRnZN)t;s7oqP|Ho2ao9^vh>4(3`A>{-@NyIpP1tif!rbM+ypPqV$j*eC
mTab?)i|A<vVeVEI6m#JzD8QSQ4Wx<#2pxfTzW}OZU;qGci;V67
literal 0
HcmV?d00001
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index faed4e5..4287573 100644
|
a
|
b
|
from __future__ import absolute_import
|
| 4 | 4 | import datetime |
| 5 | 5 | import decimal |
| 6 | 6 | import os |
| | 7 | import sys |
| 7 | 8 | import pickle |
| 8 | 9 | from threading import local |
| 9 | 10 | |
| … |
… |
class LocalePathsResolutionOrderI18NTests(ResolutionOrderI18NTests):
|
| 868 | 869 | with self.settings(INSTALLED_APPS=extended_apps): |
| 869 | 870 | self.assertUgettext('Time', 'LOCALE_PATHS') |
| 870 | 871 | |
| | 872 | class EggResolutionOrderI18NTests(ResolutionOrderI18NTests): |
| | 873 | |
| | 874 | def setUp(self): |
| | 875 | self.old_path = sys.path[:] |
| | 876 | self.egg_dir = '%s/eggs' % os.path.dirname(__file__) |
| | 877 | egg_name = '%s/localeegg.egg' % self.egg_dir |
| | 878 | sys.path.insert(0, egg_name) |
| | 879 | super(EggResolutionOrderI18NTests, self).setUp() |
| | 880 | |
| | 881 | def tearDown(self): |
| | 882 | super(EggResolutionOrderI18NTests, self).tearDown() |
| | 883 | sys.path = self.old_path |
| | 884 | |
| | 885 | class EggAppResolutionOrderI18NTests(EggResolutionOrderI18NTests): |
| | 886 | |
| | 887 | def setUp(self): |
| | 888 | self.old_installed_apps = settings.INSTALLED_APPS |
| | 889 | settings.INSTALLED_APPS = ['resolution'] + list(settings.INSTALLED_APPS) |
| | 890 | super(EggAppResolutionOrderI18NTests, self).setUp() |
| | 891 | |
| | 892 | def tearDown(self): |
| | 893 | settings.INSTALLED_APPS = self.old_installed_apps |
| | 894 | super(EggAppResolutionOrderI18NTests, self).tearDown() |
| | 895 | |
| | 896 | def test_app_translation(self): |
| | 897 | self.assertUgettext('Date/time', 'APP') |
| | 898 | |
| 871 | 899 | class DjangoFallbackResolutionOrderI18NTests(ResolutionOrderI18NTests): |
| 872 | 900 | |
| 873 | 901 | def test_django_fallback(self): |
diff --git a/tests/regressiontests/templates/eggs/templatesegg.egg b/tests/regressiontests/templates/eggs/templatesegg.egg
new file mode 100644
index 0000000000000000000000000000000000000000..9a8f315f883b1d895f1d5926ca7ad3134c23287f
GIT binary patch
literal 663
zcmWIWW@Zs#W&naW+0_mp8V1;ajMVh>ctiaFpc*c)npbFQ1mSAp<1_OzOXB183MxU$
zAx3^eQ!W5kUXq$ykds)FT8v~kNVTZi?ca<*RUj;eMRlcKMoDfCk`>R<tl)xb0-9e^
ziDWpsI#CpLD6VH@vS-E}BtU&YAkgsF5k$iR2&4yh5P?)OFeo%^X;cBy5Is1o#1>>=
z-C!$&;o6Y{5MepCAcW`!S>A|6HzYs<yb+#84=GTHLIB9q+ki}v2Vmigup3<;D1;#Z
cWcNKF6QK{q^Q@qh#=r)I1;A(*1Vudq052GO+5i9m
literal 0
HcmV?d00001
diff --git a/tests/regressiontests/templates/loaders.py b/tests/regressiontests/templates/loaders.py
index 5c11916..287bfdd 100644
|
a
|
b
|
|
| 1 | 1 | """ |
| 2 | 2 | Test cases for the template loaders |
| 3 | | |
| 4 | | Note: This test requires setuptools! |
| 5 | 3 | """ |
| 6 | 4 | |
| 7 | 5 | from django.conf import settings |
| … |
… |
if __name__ == '__main__':
|
| 10 | 8 | settings.configure() |
| 11 | 9 | |
| 12 | 10 | import sys |
| 13 | | import pkg_resources |
| 14 | 11 | import imp |
| 15 | 12 | import StringIO |
| 16 | 13 | import os.path |
| 17 | 14 | |
| 18 | 15 | from django.template import TemplateDoesNotExist, Context |
| 19 | | from django.template.loaders.eggs import Loader as EggLoader |
| | 16 | from django.template.loaders.app_directories import Loader as EggLoader |
| 20 | 17 | from django.template import loader |
| 21 | 18 | from django.utils import unittest |
| 22 | 19 | |
| 23 | 20 | |
| 24 | | # Mock classes and objects for pkg_resources functions. |
| 25 | | class MockProvider(pkg_resources.NullProvider): |
| 26 | | def __init__(self, module): |
| 27 | | pkg_resources.NullProvider.__init__(self, module) |
| 28 | | self.module = module |
| 29 | | |
| 30 | | def _has(self, path): |
| 31 | | return path in self.module._resources |
| 32 | | |
| 33 | | def _isdir(self,path): |
| 34 | | return False |
| 35 | | |
| 36 | | def get_resource_stream(self, manager, resource_name): |
| 37 | | return self.module._resources[resource_name] |
| 38 | | |
| 39 | | def _get(self, path): |
| 40 | | return self.module._resources[path].read() |
| 41 | | |
| 42 | | class MockLoader(object): |
| 43 | | pass |
| 44 | | |
| 45 | | def create_egg(name, resources): |
| 46 | | """ |
| 47 | | Creates a mock egg with a list of resources. |
| 48 | | |
| 49 | | name: The name of the module. |
| 50 | | resources: A dictionary of resources. Keys are the names and values the data. |
| 51 | | """ |
| 52 | | egg = imp.new_module(name) |
| 53 | | egg.__loader__ = MockLoader() |
| 54 | | egg._resources = resources |
| 55 | | sys.modules[name] = egg |
| 56 | | |
| 57 | | |
| 58 | 21 | class EggLoaderTest(unittest.TestCase): |
| 59 | 22 | def setUp(self): |
| 60 | | pkg_resources._provider_factories[MockLoader] = MockProvider |
| 61 | | |
| 62 | | self.empty_egg = create_egg("egg_empty", {}) |
| 63 | | self.egg_1 = create_egg("egg_1", { |
| 64 | | os.path.normcase('templates/y.html') : StringIO.StringIO("y"), |
| 65 | | os.path.normcase('templates/x.txt') : StringIO.StringIO("x"), |
| 66 | | }) |
| 67 | | self._old_installed_apps = settings.INSTALLED_APPS |
| 68 | | settings.INSTALLED_APPS = [] |
| | 23 | self.old_path = sys.path[:] |
| | 24 | self.old_apps = settings.INSTALLED_APPS |
| | 25 | self.egg_dir = '%s/eggs' % os.path.dirname(__file__) |
| | 26 | egg_name = '%s/templatesegg.egg' % self.egg_dir |
| | 27 | sys.path.append(egg_name) |
| 69 | 28 | |
| 70 | 29 | def tearDown(self): |
| 71 | | settings.INSTALLED_APPS = self._old_installed_apps |
| | 30 | settings.INSTALLED_APPS = self.old_apps |
| | 31 | sys.path = self.old_path |
| 72 | 32 | |
| 73 | 33 | def test_empty(self): |
| 74 | 34 | "Loading any template on an empty egg should fail" |
| … |
… |
class EggLoaderTest(unittest.TestCase):
|
| 88 | 48 | egg_loader = EggLoader() |
| 89 | 49 | contents, template_name = egg_loader.load_template_source("y.html") |
| 90 | 50 | self.assertEqual(contents, "y") |
| 91 | | self.assertEqual(template_name, "egg:egg_1:templates/y.html") |
| | 51 | self.assertEqual(template_name, u"app:egg_1:templates/y.html") |
| 92 | 52 | |
| 93 | 53 | def test_not_installed(self): |
| 94 | 54 | "Loading an existent template from an egg not included in INSTALLED_APPS should fail" |
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index e166f7e..d6d6991 100644
|
a
|
b
|
from .nodelist import NodelistTest, ErrorIndexTest
|
| 39 | 39 | from .smartif import SmartIfTests |
| 40 | 40 | from .response import (TemplateResponseTest, BaseTemplateResponseTest, |
| 41 | 41 | CacheMiddlewareTest, SimpleTemplateResponseTest, CustomURLConfTest) |
| | 42 | from .loaders import RenderToStringTest, EggLoaderTest |
| 42 | 43 | |
| 43 | | try: |
| 44 | | from .loaders import RenderToStringTest, EggLoaderTest |
| 45 | | except ImportError, e: |
| 46 | | if "pkg_resources" in e.message: |
| 47 | | pass # If setuptools isn't installed, that's fine. Just move on. |
| 48 | | else: |
| 49 | | raise |
| 50 | 44 | |
| 51 | 45 | from . import filters |
| 52 | 46 | |
| … |
… |
class Templates(unittest.TestCase):
|
| 167 | 161 | restore_warnings_state(self._warnings_state) |
| 168 | 162 | |
| 169 | 163 | def test_loaders_security(self): |
| 170 | | ad_loader = app_directories.Loader() |
| 171 | | fs_loader = filesystem.Loader() |
| 172 | 164 | def test_template_sources(path, template_dirs, expected_sources): |
| 173 | 165 | if isinstance(expected_sources, list): |
| 174 | 166 | # Fix expected sources so they are abspathed |
| 175 | 167 | expected_sources = [os.path.abspath(s) for s in expected_sources] |
| 176 | | # Test the two loaders (app_directores and filesystem). |
| 177 | | func1 = lambda p, t: list(ad_loader.get_template_sources(p, t)) |
| 178 | | func2 = lambda p, t: list(fs_loader.get_template_sources(p, t)) |
| 179 | | for func in (func1, func2): |
| 180 | | if isinstance(expected_sources, list): |
| 181 | | self.assertEqual(func(path, template_dirs), expected_sources) |
| 182 | | else: |
| 183 | | self.assertRaises(expected_sources, func, path, template_dirs) |
| | 168 | # Test filesystem loader. |
| | 169 | func = lambda p, t: list(filesystem.Loader(t).get_template_sources(p)) |
| | 170 | if isinstance(expected_sources, list): |
| | 171 | self.assertEqual(func(path, template_dirs), expected_sources) |
| | 172 | else: |
| | 173 | self.assertRaises(expected_sources, func, path, template_dirs) |
| 184 | 174 | |
| 185 | 175 | template_dirs = ['/dir1', '/dir2'] |
| 186 | 176 | test_template_sources('index.html', template_dirs, |