815e8e228649d4294a51169aa75c13b620ca4ae5
[myslice.git] / unfold / static.py
1 import os
2 from django.conf import settings
3 from django.utils.datastructures import SortedDict
4 from django.contrib.staticfiles.finders import BaseFinder, FileSystemFinder
5 from django.core.files.storage import FileSystemStorage
6
7 class PluginFinder(FileSystemFinder):
8     """
9     A static files finder that looks in the directory of each plugin as
10     specified in the source_dir attribute of the given storage class.
11     """
12     def __init__(self, *args, **kwargs):
13         # The list of plugins that are handled
14         self.locations = []
15         # Mapping of plugin module paths to storage instances
16         self.storages = SortedDict()
17         plugins_dir = self.get_immediate_subdirs(settings.PLUGIN_DIR)
18         for root in plugins_dir:
19             if not os.path.exists(root) or not os.path.isdir(root):
20                 continue
21             if ('', root) not in self.locations:
22                 self.locations.append(('', root))
23         for _, root in self.locations:
24             filesystem_storage = FileSystemStorage(location=root)
25             filesystem_storage.prefix = ''
26             self.storages[root] = filesystem_storage
27
28     def get_immediate_subdirs(self, dir):
29         return [os.path.join(dir, name, 'static') for name in os.listdir(dir) 
30                 if os.path.isdir(os.path.join(dir, name))]
31
32 class ThirdPartyFinder(BaseFinder):
33     """
34     A static files inder that looks in the directory of each third-party
35     resources and tries to preserve the location of each file
36     """
37     # third-party/MODULE/path/to/js
38     extensions = {
39         # PREFIX : EXTENSIONS
40         ''   : ('.html',),
41         'js' : ('.js',),
42         'css': ('.css',),
43         'img': ('.png', '.ico',),
44     }
45
46     def find(self, search_path, all=False):
47         """
48         Given a relative file path this ought to find an
49         absolute file path.
50
51         If the ``all`` parameter is ``False`` (default) only
52         the first found file path will be returned; if set
53         to ``True`` a list of all found files paths is returned.
54         """
55         matches = []
56         #all_extensions = reduce(lambda x,y : x + y, extensions.values())
57
58         for (path, dirs, files) in os.walk(settings.THIRDPARTY_DIR):
59             for file in files:
60                 name, extension = os.path.splitext(file)
61
62                 for type, extensions in self.extensions.items():
63                     if not extension in extensions:
64                         continue
65                     if search_path == os.path.join(type, file):
66                         matched_path = os.path.join(path, file) 
67                         if not all:
68                             return matched_path
69                         matches.append(matched_path)
70         return matches
71
72     def list(self, ignore_patterns):
73         """
74         Given an optional list of paths to ignore, this should return
75         a two item iterable consisting of the relative path and storage
76         instance.
77         """
78         for (path, dirs, files) in os.walk(settings.THIRDPARTY_DIR):
79             for file in files:
80                 name, extension = os.path.splitext(file)
81
82                 for type, extensions in self.extensions.items():
83                     if not extension in extensions:
84                         continue
85                     filesystem_storage = FileSystemStorage(location=path)
86                     filesystem_storage.prefix = type
87                     yield file, filesystem_storage
88
89 class BaseFinder(object):
90     """
91     A base file finder to be used for custom staticfiles finder classes.
92     """
93
94     def list(self, ignore_patterns):
95         """
96         Given an optional list of paths to ignore, this should return
97         a two item iterable consisting of the relative path and storage
98         instance.
99         """
100         raise NotImplementedError()
101