Projet

Général

Profil

0001-general-revamp-static-file-serving-to-use-external-m.patch

Frédéric Péters, 14 juin 2016 21:55

Télécharger (7,27 ko)

Voir les différences:

Subject: [PATCH] general: revamp static file serving to use external modules
 (#11355)

 wcs/ctl/collectstatic.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
 wcs/root.py              | 56 ++++++++++++++++++++++++++++++++-------
 2 files changed, 115 insertions(+), 9 deletions(-)
 create mode 100644 wcs/ctl/collectstatic.py
wcs/ctl/collectstatic.py
1
# w.c.s. - web application for online forms
2
# Copyright (C) 2005-2016  Entr'ouvert
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16

  
17
import os
18
import shutil
19

  
20
from qommon.ctl import Command, make_option
21

  
22

  
23
class CmdCollectStatic(Command):
24
    name = 'collectstatic'
25

  
26
    def __init__(self):
27
        Command.__init__(self, [
28
                make_option('-c', '--clear', action='store_true',
29
                            dest='clear', default=False),
30
                make_option('-l', '--link', action='store_true',
31
                            dest='link', default=False),
32
                ])
33

  
34
    def execute(self, base_options, sub_options, args):
35
        import publisher
36
        publisher.WcsPublisher.configure(self.config)
37
        pub = publisher.WcsPublisher.create_publisher(
38
                register_cron=False, register_tld_names=False)
39
        return self.collecstatic(pub,
40
                clear=sub_options.clear, link=sub_options.link)
41

  
42
    def collecstatic(self, pub, clear=False, link=False):
43
        root_directory_class = pub.root_directory_class
44
        static_dir = os.path.join(pub.app_dir, 'static')
45
        if clear and os.path.exists(static_dir):
46
            shutil.rmtree(static_dir)
47
        if not os.path.exists(static_dir):
48
            os.mkdir(static_dir)
49
        for prefix in root_directory_class.static_directories:
50
            for directory in root_directory_class.resolve_static_directories(prefix):
51
                if not os.path.exists(directory):
52
                    continue
53
                real_prefix = prefix.replace('_', '/') # xstatic hack
54
                dst_base = os.path.join(static_dir, real_prefix)
55
                for basedir, dirnames, filenames in os.walk(directory):
56
                    for filename in filenames:
57
                        dst_path = os.path.join(dst_base, basedir[len(directory)+1:])
58
                        dst_filename = os.path.join(dst_path, filename)
59
                        if not os.path.exists(dst_path):
60
                            os.makedirs(dst_path)
61
                        if os.path.exists(dst_filename):
62
                            os.unlink(dst_filename)
63
                        if link:
64
                            os.symlink(os.path.join(basedir, filename), dst_filename)
65
                        else:
66
                            shutil.copy(os.path.join(basedir, filename), dst_filename)
67

  
68
CmdCollectStatic.register()
wcs/root.py
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17
from importlib import import_module
17 18
import json
18 19
import os
19 20
import re
......
207 208
    pages = qommon.pages.PagesDirectory()
208 209
    fargo = file_validation.FargoDirectory()
209 210

  
211
    static_directories = {
212
        'css': ['web/css'],
213
        'images': ['web/images'],
214
        'themes': ['web/themes'],
215
        'qo': ['qommon'],
216
        # maps /leaflet/ to the directory provided by the libjs-openlayers package
217
        'leaflet': ['/usr/share/javascript/leaflet'],
218
        'static': ['django:gadjo'],
219
        'static_xstatic': ['xstatic:jquery', 'xstatic:font_awesome'],
220
    }
221

  
210 222
    def tryauth(self):
211 223
        return forms.root.tryauth(get_publisher().get_root_url())
212 224

  
......
287 299
        if not self.backoffice:
288 300
            self.backoffice = get_publisher().backoffice_directory_class()
289 301

  
302
        if path[:2] == ['static', 'xstatic']:
303
            # hack path so it's easier to lookup files from xstatic modules
304
            # (the gadjo xstatic storage adds a "xstatic" prefix that is not on
305
            # the filesystem, while StaticDirectory expects the filesystem
306
            # layout to match exactly; so we merge the first two elements in a
307
            # single one, so we get the real path in path[1:])
308
            path = ['static_xstatic'] + path[2:]
309

  
290 310
        try:
291 311
            return Directory._q_traverse(self, path)
292 312
        except errors.TraversalError:
......
294 314

  
295 315
        return forms.root.RootDirectory()._q_traverse(path)
296 316

  
297
    def _q_lookup(self, component):
298
        if component in ('css','images'):
299
            return StaticDirectory(os.path.join(get_publisher().data_dir, 'web', component), follow_symlinks = True)
300
        if component == 'qo':
301
            dirname = os.path.join(get_publisher().data_dir, 'qommon')
302
            return StaticDirectory(dirname, follow_symlinks = True)
317
    @classmethod
318
    def resolve_static_directories(cls, prefix):
319
        directories = cls.static_directories[prefix]
320
        for directory in directories:
321
            if directory[0] == '/':
322
                yield directory
323
            elif not ':' in directory:
324
                yield os.path.join(get_publisher().data_dir, directory)
325
            else:
326
                directory_type, value = directory.split(':')
327
                if directory_type == 'xstatic':
328
                    module = import_module('xstatic.pkg.%s' % value)
329
                    yield module.BASE_DIR
330
                elif directory_type == 'django':
331
                    module = import_module(value)
332
                    yield os.path.join(os.path.dirname(module.__file__), 'static')
333

  
334
    def serve_statics(self, component):
335
        for directory in self.resolve_static_directories(component):
336
            try:
337
                return StaticDirectory(directory, follow_symlinks=True)
338
            except errors.TraversalError:
339
                pass
340
            raise errors.TraversalError()
303 341

  
304
        # maps /leaflet/ to the directory provided by the libjs-openlayers package
305
        if component == 'leaflet':
306
            return StaticDirectory('/usr/share/javascript/leaflet')
342
    def _q_lookup(self, component):
343
        if component in self.static_directories:
344
            return self.serve_statics(component)
307 345

  
308 346
        # is this a category ?
309 347
        try:
310
-