]> git.openstreetmap.org Git - osqa.git/blob - forum/skins/__init__.py
Merge pull request #46 from udacity/subfolder_fixes
[osqa.git] / forum / skins / __init__.py
1 from django.conf import settings
2 from django.template.loaders import filesystem
3 from django.template import TemplateDoesNotExist, Template as DJTemplate
4 from django.conf import settings as djsettings
5 import os.path
6 import logging
7
8 UNEXISTENT_TEMPLATE = object()
9
10 SKINS_FOLDER = os.path.dirname(__file__)
11 SKIN_TEMPLATES_FOLDER = 'templates'
12 DEFAULT_SKIN_NAME = 'default'
13 FORCE_DEFAULT_PREFIX = "%s/" % DEFAULT_SKIN_NAME
14
15
16 class Template(object):
17
18     def __init__(self, file_name):
19         self._file_name = file_name
20         self._loaded = False
21
22     def _get_mtime(self):
23         return os.path.getmtime(self._file_name)
24
25     def _check_mtime(self):
26         if self._last_mtime is None:
27             return False
28
29         return self._last_mtime == self._get_mtime()
30
31     def _load(self):
32         try:
33             f = open(self._file_name, 'r')
34             self._source = f.read()
35             f.close()
36             self._loaded = True
37
38             self._last_mtime = self._get_mtime()
39         except:
40             self._loaded = False
41             self._last_mtime = None
42
43             raise
44
45     def return_tuple(self):
46         if not (self._loaded and self._check_mtime()):
47             try:
48                 self._load()
49             except:
50                 raise TemplateDoesNotExist, self._file_name
51
52         return self._source, self._file_name
53
54 class BaseTemplateLoader(object):
55     is_usable = True
56
57     def __init__(self):
58         self.cache = {}
59
60     def __call__(self, name=None, dirs=None):
61         if name is None:
62             return self
63
64         return self.load_template(name, dirs)
65
66     def load_template(self, name, dirs=None):
67         if not djsettings.TEMPLATE_DEBUG:
68             if name in self.cache:
69                 if self.cache[name] is UNEXISTENT_TEMPLATE:
70                     raise TemplateDoesNotExist, name
71
72                 try:
73                     return self.cache[name].return_tuple()
74                 except:
75                     del self.cache[name]
76
77         template = self.load_template_source(name, dirs)
78
79         if template is not None:
80             if not djsettings.DEBUG:
81                 self.cache[name] = template
82
83             return template.return_tuple()
84         else:
85             if not djsettings.DEBUG:
86                 self.cache[name] = UNEXISTENT_TEMPLATE
87
88             raise TemplateDoesNotExist, name
89
90     def load_template_source(self, name, dirs=None):
91         raise NotImplementedError
92
93
94 class SkinsTemplateLoader(BaseTemplateLoader):
95
96     def load_template_source(self, name, dirs=None):
97
98         if name.startswith(FORCE_DEFAULT_PREFIX):
99
100             file_name = os.path.join(SKINS_FOLDER, DEFAULT_SKIN_NAME, SKIN_TEMPLATES_FOLDER, name[len(FORCE_DEFAULT_PREFIX):])
101
102             if os.path.exists(file_name):
103                 return Template(file_name)
104             else:
105                 return None
106
107         for skin in (settings.OSQA_DEFAULT_SKIN, DEFAULT_SKIN_NAME):
108             file_name = os.path.join(SKINS_FOLDER, skin, SKIN_TEMPLATES_FOLDER, name)
109
110             if os.path.exists(file_name):
111                 return Template(file_name)
112
113         return None
114
115 load_template_source = SkinsTemplateLoader()
116
117
118 def find_media_source(url):
119     """returns url prefixed with the skin name
120     of the first skin that contains the file 
121     directories are searched in this order:
122     settings.OSQA_DEFAULT_SKIN, then 'default', then 'commmon'
123     if file is not found - returns None
124     and logs an error message
125     """
126     while url[0] == '/': url = url[1:]
127     d = os.path.dirname
128     n = os.path.normpath
129     j = os.path.join
130     f = os.path.isfile
131     skins = n(j(d(d(__file__)),'skins'))
132     try:
133         media = os.path.join(skins, settings.OSQA_DEFAULT_SKIN, url)
134         assert(f(media))
135         use_skin = settings.OSQA_DEFAULT_SKIN
136     except:
137         try:
138             media = j(skins, 'default', url)
139             assert(f(media))
140             use_skin = 'default'
141         except:
142             media = j(skins, 'common', url)
143             try:
144                 assert(f(media))
145                 use_skin = 'common'
146             except:
147                 logging.error('could not find media for %s' % url)
148                 use_skin = ''
149                 return None
150     return use_skin + '/' + url
151