~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to django/contrib/staticfiles/finders.py

  • Committer: Package Import Robot
  • Author(s): Raphaël Hertzog
  • Date: 2014-09-17 14:15:11 UTC
  • mfrom: (1.3.17) (6.2.18 experimental)
  • Revision ID: package-import@ubuntu.com-20140917141511-icneokthe9ww5sk4
Tags: 1.7-2
* Release to unstable.
* Add a migrate-south sample script to help users apply their South
  migrations. Thanks to Brian May.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from collections import OrderedDict
1
2
import os
 
3
 
 
4
from django.apps import apps
2
5
from django.conf import settings
3
6
from django.core.exceptions import ImproperlyConfigured
4
7
from django.core.files.storage import default_storage, Storage, FileSystemStorage
5
 
from django.utils.datastructures import SortedDict
6
 
from django.utils.functional import empty, memoize, LazyObject
7
 
from django.utils.module_loading import import_by_path
 
8
from django.utils.functional import empty, LazyObject
 
9
from django.utils.module_loading import import_string
8
10
from django.utils._os import safe_join
9
 
from django.utils import six
 
11
from django.utils import six, lru_cache
10
12
 
11
13
from django.contrib.staticfiles import utils
12
 
from django.contrib.staticfiles.storage import AppStaticStorage
13
14
 
14
 
_finders = SortedDict()
 
15
# To keep track on which directories the finder has searched the static files.
 
16
searched_locations = []
15
17
 
16
18
 
17
19
class BaseFinder(object):
18
20
    """
19
21
    A base file finder to be used for custom staticfiles finder classes.
20
22
    """
 
23
 
21
24
    def find(self, path, all=False):
22
25
        """
23
26
        Given a relative file path this ought to find an
27
30
        the first found file path will be returned; if set
28
31
        to ``True`` a list of all found files paths is returned.
29
32
        """
30
 
        raise NotImplementedError()
 
33
        raise NotImplementedError('subclasses of BaseFinder must provide a find() method')
31
34
 
32
35
    def list(self, ignore_patterns):
33
36
        """
35
38
        a two item iterable consisting of the relative path and storage
36
39
        instance.
37
40
        """
38
 
        raise NotImplementedError()
 
41
        raise NotImplementedError('subclasses of BaseFinder must provide a list() method')
39
42
 
40
43
 
41
44
class FileSystemFinder(BaseFinder):
43
46
    A static files finder that uses the ``STATICFILES_DIRS`` setting
44
47
    to locate files.
45
48
    """
46
 
    def __init__(self, apps=None, *args, **kwargs):
 
49
    def __init__(self, app_names=None, *args, **kwargs):
47
50
        # List of locations with static files
48
51
        self.locations = []
49
52
        # Maps dir paths to an appropriate storage instance
50
 
        self.storages = SortedDict()
 
53
        self.storages = OrderedDict()
51
54
        if not isinstance(settings.STATICFILES_DIRS, (list, tuple)):
52
55
            raise ImproperlyConfigured(
53
56
                "Your STATICFILES_DIRS setting is not a tuple or list; "
76
79
        """
77
80
        matches = []
78
81
        for prefix, root in self.locations:
 
82
            if root not in searched_locations:
 
83
                searched_locations.append(root)
79
84
            matched_path = self.find_location(root, path, prefix)
80
85
            if matched_path:
81
86
                if not all:
110
115
class AppDirectoriesFinder(BaseFinder):
111
116
    """
112
117
    A static files finder that looks in the directory of each app as
113
 
    specified in the source_dir attribute of the given storage class.
 
118
    specified in the source_dir attribute.
114
119
    """
115
 
    storage_class = AppStaticStorage
 
120
    storage_class = FileSystemStorage
 
121
    source_dir = 'static'
116
122
 
117
 
    def __init__(self, apps=None, *args, **kwargs):
 
123
    def __init__(self, app_names=None, *args, **kwargs):
118
124
        # The list of apps that are handled
119
125
        self.apps = []
120
 
        # Mapping of app module paths to storage instances
121
 
        self.storages = SortedDict()
122
 
        if apps is None:
123
 
            apps = settings.INSTALLED_APPS
124
 
        for app in apps:
125
 
            app_storage = self.storage_class(app)
 
126
        # Mapping of app names to storage instances
 
127
        self.storages = OrderedDict()
 
128
        app_configs = apps.get_app_configs()
 
129
        if app_names:
 
130
            app_names = set(app_names)
 
131
            app_configs = [ac for ac in app_configs if ac.name in app_names]
 
132
        for app_config in app_configs:
 
133
            app_storage = self.storage_class(
 
134
                os.path.join(app_config.path, self.source_dir))
126
135
            if os.path.isdir(app_storage.location):
127
 
                self.storages[app] = app_storage
128
 
                if app not in self.apps:
129
 
                    self.apps.append(app)
 
136
                self.storages[app_config.name] = app_storage
 
137
                if app_config.name not in self.apps:
 
138
                    self.apps.append(app_config.name)
130
139
        super(AppDirectoriesFinder, self).__init__(*args, **kwargs)
131
140
 
132
141
    def list(self, ignore_patterns):
144
153
        """
145
154
        matches = []
146
155
        for app in self.apps:
 
156
            app_location = self.storages[app].location
 
157
            if app_location not in searched_locations:
 
158
                searched_locations.append(app_location)
147
159
            match = self.find_in_app(app, path)
148
160
            if match:
149
161
                if not all:
157
169
        """
158
170
        storage = self.storages.get(app, None)
159
171
        if storage:
160
 
            if storage.prefix:
161
 
                prefix = '%s%s' % (storage.prefix, os.sep)
162
 
                if not path.startswith(prefix):
163
 
                    return None
164
 
                path = path[len(prefix):]
165
172
            # only try to find a file if the source dir actually exists
166
173
            if storage.exists(path):
167
174
                matched_path = storage.path(path)
197
204
        except NotImplementedError:
198
205
            pass
199
206
        else:
 
207
            if self.storage.location not in searched_locations:
 
208
                searched_locations.append(self.storage.location)
200
209
            if self.storage.exists(path):
201
210
                match = self.storage.path(path)
202
211
                if all:
234
243
    If ``all`` is ``False`` (default), return the first matching
235
244
    absolute path (or ``None`` if no match). Otherwise return a list.
236
245
    """
 
246
    searched_locations[:] = []
237
247
    matches = []
238
248
    for finder in get_finders():
239
249
        result = finder.find(path, all=all)
253
263
        yield get_finder(finder_path)
254
264
 
255
265
 
256
 
def _get_finder(import_path):
 
266
@lru_cache.lru_cache(maxsize=None)
 
267
def get_finder(import_path):
257
268
    """
258
269
    Imports the staticfiles finder class described by import_path, where
259
270
    import_path is the full Python path to the class.
260
271
    """
261
 
    Finder = import_by_path(import_path)
 
272
    Finder = import_string(import_path)
262
273
    if not issubclass(Finder, BaseFinder):
263
274
        raise ImproperlyConfigured('Finder "%s" is not a subclass of "%s"' %
264
275
                                   (Finder, BaseFinder))
265
276
    return Finder()
266
 
get_finder = memoize(_get_finder, _finders, 1)