Merge branch 'merge-python3-port'
[mediagoblin.git] / mediagoblin / tools / staticdirect.py
CommitLineData
8e1e744d 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
f75a49b2
CAW
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 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 Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
f75a49b2
CAW
17####################################
18# Staticdirect infrastructure.
19# Borrowed largely from cc.engine
20# by Chris Webber & Creative Commons
285ffedd 21#
f75a49b2
CAW
22# This needs documentation!
23####################################
24
1b876ac2
E
25import logging
26
386c9c7c
BP
27import six
28
1b876ac2 29_log = logging.getLogger(__name__)
f75a49b2 30
285ffedd 31
f75a49b2 32class StaticDirect(object):
5377114c
CAW
33 """
34 Direct to a static resource.
35
36 This StaticDirect class can take a series of "domains" to
37 staticdirect to. In general, you should supply a None domain, as
38 that's the "default" domain.
39
b33feb18
CAW
40 Things work like this::
41
5377114c
CAW
42 >>> staticdirect = StaticDirect(
43 ... {None: "/static/",
44 ... "theme": "http://example.org/themestatic/"})
45 >>> staticdirect("css/monkeys.css")
46 "/static/css/monkeys.css"
47 >>> staticdirect("images/lollerskate.png", "theme")
48 "http://example.org/themestatic/images/lollerskate.png"
49 """
50 def __init__(self, domains):
51 self.domains = dict(
52 [(key, value.rstrip('/'))
386c9c7c 53 for key, value in six.iteritems(domains)])
f75a49b2
CAW
54 self.cache = {}
55
5377114c
CAW
56 def __call__(self, filepath, domain=None):
57 if domain in self.cache and filepath in self.cache[domain]:
58 return self.cache[domain][filepath]
f75a49b2 59
5377114c
CAW
60 static_direction = self.cache.setdefault(
61 domain, {})[filepath] = self.get(filepath, domain)
f75a49b2 62 return static_direction
f75a49b2 63
5377114c 64 def get(self, filepath, domain=None):
f75a49b2 65 return '%s/%s' % (
5377114c 66 self.domains[domain], filepath.lstrip('/'))
d6d2c771
CAW
67
68
69class PluginStatic(object):
70 """Pass this into the ``'static_setup'`` hook to register your
71 plugin's static directory.
72
73 This has two mandatory attributes that you must pass in on class
74 init:
b33feb18
CAW
75
76 - *name:* this name will be both used for lookup in "urlgen" for
77 your plugin's static resources and for the subdirectory that
78 it'll be "mounted" to for serving via your web browser. It
79 *MUST* be unique. If writing a plugin bundled with MediaGoblin
80 please use the pattern 'coreplugin__foo' where 'foo' is your
81 plugin name. All external plugins should use their modulename,
82 so if your plugin is 'mg_bettertags' you should also call this
83 name 'mg_bettertags'.
84 - *file_path:* the directory your plugin's static resources are
85 located in. It's recommended that you use
86 pkg_resources.resource_filename() for this.
d6d2c771
CAW
87
88 An example of using this::
89
90 from pkg_resources import resource_filename
91 from mediagoblin.tools.staticdirect import PluginStatic
92
93 hooks = {
94 'static_setup': lambda: PluginStatic(
95 'mg_bettertags',
96 resource_filename('mg_bettertags', 'static'))
97 }
98
99 """
100 def __init__(self, name, file_path):
101 self.name = name
102 self.file_path = file_path
103
104 def __call__(self):
105 return self