a/Allura/allura/lib/package_path_loader.py b/Allura/allura/lib/package_path_loader.py
...
...
122
**TODO:** Support multiple partial themes
122
**TODO:** Support multiple partial themes
123
123
124
"""
124
"""
125
import pkg_resources
125
import pkg_resources
126
import os
126
import os
127
from collections import defaultdict
128
127
129
import jinja2
128
import jinja2
130
from ming.utils import LazyProperty
129
from ming.utils import LazyProperty
131
130
132
from allura.lib.helpers import topological_sort
131
from allura.lib.helpers import topological_sort, iter_entry_points
133
132
134
133
135
class PackagePathLoader(jinja2.BaseLoader):
134
class PackagePathLoader(jinja2.BaseLoader):
136
    def __init__(self, override_entrypoint='allura.theme.override',
135
    def __init__(self, override_entrypoint='allura.theme.override',
137
                default_paths=None,
136
                default_paths=None,
...
...
161
        Load all the paths to be processed, including defaults, in the default order.
160
        Load all the paths to be processed, including defaults, in the default order.
162
        """
161
        """
163
        paths = self.default_paths[:]  # copy default_paths
162
        paths = self.default_paths[:]  # copy default_paths
164
        paths[-1:0] = [  # insert all eps just before last item, by default
163
        paths[-1:0] = [  # insert all eps just before last item, by default
165
                [ep.name, pkg_resources.resource_filename(ep.module_name, "")]
164
                [ep.name, pkg_resources.resource_filename(ep.module_name, "")]
166
                for ep in pkg_resources.iter_entry_points(self.override_entrypoint)
165
                for ep in iter_entry_points(self.override_entrypoint)
167
            ]
166
            ]
168
        return paths
167
        return paths
169
168
170
    def _load_rules(self):
169
    def _load_rules(self):
171
        """
170
        """
...
...
188
        replacement_rules represent all of the '=' rules and are returned as
187
        replacement_rules represent all of the '=' rules and are returned as
189
        a dictionary mapping the paths to replace to the paths to replace with.
188
        a dictionary mapping the paths to replace to the paths to replace with.
190
        """
189
        """
191
        order_rules = []
190
        order_rules = []
192
        replacement_rules = {}
191
        replacement_rules = {}
193
        for ep in pkg_resources.iter_entry_points(self.override_entrypoint):
192
        for ep in iter_entry_points(self.override_entrypoint):
194
            for rule in getattr(ep.load(), 'template_path_rules', []):
193
            for rule in getattr(ep.load(), 'template_path_rules', []):
195
                if rule[0] == '>':
194
                if rule[0] == '>':
196
                    order_rules.append((ep.name, rule[1]))
195
                    order_rules.append((ep.name, rule[1]))
197
                elif rule[0] == '=':
196
                elif rule[0] == '=':
198
                    replacement_rules[rule[1]] = ep.name
197
                    replacement_rules[rule[1]] = ep.name