Skip to content

Commit 513ce65

Browse files
author
Stephen Burrows
authored
Merge pull request #46 from roverdotcom/configurable-css-loader
Configurable CSS Loader
2 parents 0532324 + a4127aa commit 513ce65

File tree

5 files changed

+123
-30
lines changed

5 files changed

+123
-30
lines changed

django_inlinecss/conf.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,23 @@
1010
from django.utils import importlib
1111

1212
DEFAULT_ENGINE = 'django_inlinecss.engines.PynlinerEngine'
13+
DEFAULT_CSS_LOADER = 'django_inlinecss.css_loaders.StaticfilesStorageCSSLoader'
14+
15+
16+
def load_class_by_path(path):
17+
i = path.rfind('.')
18+
module_path, class_name = path[:i], path[i + 1:]
19+
module = importlib.import_module(module_path)
20+
return getattr(module, class_name)
1321

1422

1523
def get_engine():
1624
from django.conf import settings
1725
engine_path = getattr(settings, 'INLINECSS_ENGINE', DEFAULT_ENGINE)
18-
i = engine_path.rfind('.')
19-
module_path, class_name = engine_path[:i], engine_path[i + 1:]
20-
module = importlib.import_module(module_path)
21-
return getattr(module, class_name)
26+
return load_class_by_path(engine_path)
27+
28+
29+
def get_css_loader():
30+
from django.conf import settings
31+
engine_path = getattr(settings, 'INLINECSS_CSS_LOADER', DEFAULT_CSS_LOADER)
32+
return load_class_by_path(engine_path)

django_inlinecss/css_loaders.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from __future__ import absolute_import
2+
from __future__ import division
3+
from __future__ import print_function
4+
from __future__ import unicode_literals
5+
6+
from django.contrib.staticfiles import finders
7+
from django.contrib.staticfiles.storage import staticfiles_storage
8+
9+
10+
class BaseCSSLoader(object):
11+
def __init__(self):
12+
pass
13+
14+
def load(self, path):
15+
"""
16+
Retrieves the contents of the static asset specified
17+
:param path: path to the desired asset
18+
:return: contents of asset
19+
"""
20+
raise NotImplementedError()
21+
22+
23+
class StaticfilesFinderCSSLoader(BaseCSSLoader):
24+
def load(self, path):
25+
"""
26+
Retrieve CSS contents from the local filesystem with static finders
27+
"""
28+
expanded_path = finders.find(path)
29+
30+
if expanded_path is None:
31+
raise IOError('{} does not exist'.format(path))
32+
33+
with open(expanded_path, 'rb') as css_file:
34+
return css_file.read().decode('utf-8')
35+
36+
37+
class StaticfilesStorageCSSLoader(BaseCSSLoader):
38+
def load(self, path):
39+
"""
40+
Retrieve CSS contents with staticfiles storage
41+
"""
42+
return staticfiles_storage.open(path).read().decode('utf-8')

django_inlinecss/templatetags/inlinecss.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
from __future__ import unicode_literals
55

66
from django import template
7-
from django.conf import settings
8-
from django.contrib.staticfiles import finders
9-
from django.contrib.staticfiles.storage import staticfiles_storage
107
from django.utils.encoding import smart_text
118

129
from django_inlinecss import conf
@@ -27,13 +24,9 @@ def render(self, context):
2724
path = expression.resolve(context, True)
2825
if path is not None:
2926
path = smart_text(path)
30-
if settings.DEBUG:
31-
expanded_path = finders.find(path)
32-
else:
33-
expanded_path = staticfiles_storage.path(path)
3427

35-
with open(expanded_path) as css_file:
36-
css = ''.join((css, css_file.read()))
28+
css_loader = conf.get_css_loader()()
29+
css = ''.join((css, css_loader.load(path)))
3730

3831
engine = conf.get_engine()(html=rendered_contents, css=css)
3932
return engine.render()
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
Test CSS loaders
3+
"""
4+
from __future__ import absolute_import
5+
from __future__ import division
6+
from __future__ import print_function
7+
from __future__ import unicode_literals
8+
9+
from django.conf import settings
10+
from django.test import TestCase
11+
from django.test import override_settings
12+
13+
from django_inlinecss.css_loaders import StaticfilesFinderCSSLoader
14+
from django_inlinecss.css_loaders import StaticfilesStorageCSSLoader
15+
16+
17+
@override_settings(STATICFILES_DIRS=[settings.STATIC_ROOT], STATIC_ROOT='')
18+
class StaticfilesFinderCSSLoaderTestCase(TestCase):
19+
def setUp(self):
20+
self.loader = StaticfilesFinderCSSLoader()
21+
super(StaticfilesFinderCSSLoaderTestCase, self).setUp()
22+
23+
def test_loads_existing_css_file(self):
24+
css = self.loader.load('bar.css')
25+
self.assertIn('div.bar {', css)
26+
27+
def test_load_file_does_not_exist(self):
28+
with self.assertRaises(IOError) as e:
29+
self.loader.load('missing.css')
30+
31+
self.assertEqual(str(e.exception), 'missing.css does not exist')
32+
33+
34+
class StaticfilesStorageCSSLoaderTestCase(TestCase):
35+
def setUp(self):
36+
self.loader = StaticfilesStorageCSSLoader()
37+
super(StaticfilesStorageCSSLoaderTestCase, self).setUp()
38+
39+
def test_loads_existing_css_file(self):
40+
css = self.loader.load('bar.css')
41+
self.assertIn('div.bar {', css)
42+
43+
def test_load_file_does_not_exist(self):
44+
with self.assertRaises(IOError) as e:
45+
self.loader.load('missing.css')
46+
47+
self.assertEqual(e.exception.strerror, 'No such file or directory')

django_inlinecss/tests/test_templatetags.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ def assert_foo_and_bar_rendered(self, rendered):
2828
r'<div class="foo" style="margin: 10px 15px 20px 25px">'
2929
r'\s+This is the "foo" div.\s+'
3030
r'<\/div>')
31-
self.assertRegexpMatches(
31+
self.assertRegex(
3232
rendered,
3333
foo_div_regex)
3434

3535
bar_div_regex = (
3636
r'<div class="bar" style="padding: 10px 15px 20px 25px">'
3737
r'\s+This is the "bar" div.\s+'
3838
r'<\/div>')
39-
self.assertRegexpMatches(
39+
self.assertRegex(
4040
rendered,
4141
bar_div_regex)
4242

@@ -120,10 +120,10 @@ def test_unicode_context_variables(self):
120120

121121
rendered = template.render({
122122
'unicode_string': u'I love playing with my pi\xf1ata'})
123-
self.assertRegexpMatches(
123+
self.assertRegex(
124124
rendered,
125125
'<div class="bar" style="padding: 10px 15px 20px 25px">')
126-
self.assertRegexpMatches(
126+
self.assertRegex(
127127
rendered,
128128
u'I love playing with my pi\xf1ata')
129129

@@ -139,37 +139,37 @@ def test_comments_are_ignored(self):
139139
template = get_template('comments_are_ignored.html')
140140

141141
rendered = template.render({})
142-
self.assertRegexpMatches(
142+
self.assertRegex(
143143
rendered,
144144
r'<body>\s+<!-- Here is comment one -->\s+<div')
145-
self.assertRegexpMatches(
145+
self.assertRegex(
146146
rendered,
147147
r'This is the "foo" div.\s+<!-- comment two -->\s+')
148-
self.assertRegexpMatches(
148+
self.assertRegex(
149149
rendered,
150150
r'This is the "bar" div.\s+<!-- comment three -->\s+')
151151

152152

153-
class DebugModeStaticfilesTests(TestCase):
154-
@override_settings(DEBUG=True)
155-
@patch('django.contrib.staticfiles.finders.find')
156-
def test_debug_mode_uses_staticfiles_finder(self, find):
153+
class GetLoaderStaticfilesTests(TestCase):
154+
@patch('django.contrib.staticfiles.storage.staticfiles_storage.path')
155+
def test_default_uses_staticfiles_storage(self, path):
157156
full_path = os.path.join(
158157
settings.STATIC_ROOT,
159158
'foobar.css',
160159
)
161-
find.return_value = full_path
160+
path.return_value = full_path
162161
template = get_template('single_staticfiles_css.html')
163162
template.render({})
164-
find.assert_called_once_with("foobar.css")
163+
path.assert_called_once_with("foobar.css")
165164

166-
@patch('django.contrib.staticfiles.storage.staticfiles_storage.path')
167-
def test_non_debug_mode_uses_staticfiles_storage(self, path):
165+
@override_settings(INLINECSS_CSS_LOADER='django_inlinecss.css_loaders.StaticfilesFinderCSSLoader')
166+
@patch('django.contrib.staticfiles.finders.find')
167+
def test_override_uses_staticfiles_finder(self, find):
168168
full_path = os.path.join(
169169
settings.STATIC_ROOT,
170170
'foobar.css',
171171
)
172-
path.return_value = full_path
172+
find.return_value = full_path
173173
template = get_template('single_staticfiles_css.html')
174174
template.render({})
175-
path.assert_called_once_with("foobar.css")
175+
find.assert_called_once_with("foobar.css")

0 commit comments

Comments
 (0)