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, |