Skip to content

Commit 62d1913

Browse files
author
Rocky Meza
committed
Added a django-compressor Filter class.
1 parent 2e832c5 commit 62d1913

File tree

9 files changed

+108
-25
lines changed

9 files changed

+108
-25
lines changed

README.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ A collection of tools for making it easier to use PyScss within Django.
1515
and will only use staticfiles_storage to find the file.
1616

1717

18+
Using in conjunction with django-compressor.
19+
============================================
20+
21+
django-pyscss comes with support for django-compressor. All you have to do is
22+
add it to your ``COMPRESS_PRECOMPILERS`` setting. ::
23+
24+
COMPRESS_PRECOMPILERS = (
25+
# ...
26+
('text/x-scss', 'django_pyscss.compressor.DjangoScssFilter'),
27+
# ...
28+
)
29+
30+
1831
Running the tests
1932
=================
2033

django_pyscss/compressor.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from __future__ import absolute_import
2+
3+
import os
4+
5+
from compressor.filters import FilterBase
6+
7+
from django_pyscss.scss import DjangoScss, config
8+
9+
10+
class DjangoScssFilter(FilterBase):
11+
compiler = DjangoScss()
12+
13+
def __init__(self, content, attrs=None, filter_type=None, filename=None):
14+
# It looks like there is a bug in django-compressor because it expects
15+
# us to accept attrs.
16+
super(DjangoScssFilter, self).__init__(content, filter_type, filename)
17+
18+
def input(self, **kwargs):
19+
if not os.path.exists(config.ASSETS_ROOT):
20+
os.makedirs(config.ASSETS_ROOT)
21+
return self.compiler.compile(self.content)

django_pyscss/scss.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,25 @@
11
from __future__ import absolute_import, unicode_literals
22

33
import os
4-
import fnmatch
54

6-
from django.contrib.staticfiles import finders
75
from django.contrib.staticfiles.storage import staticfiles_storage
86
from django.conf import settings
97

108
from scss import (
11-
Scss, dequote, log, SourceFile, SassRule,
9+
Scss, dequote, log, SourceFile, SassRule, config,
1210
)
1311

12+
from django_pyscss.utils import find_one_file
1413

15-
def find_all_files(glob):
16-
"""
17-
Finds all files in the django finders for a given glob,
18-
returns the file path, if available, and the django storage object.
19-
storage objects must implement the File storage API:
20-
https://docs.djangoproject.com/en/dev/ref/files/storage/
21-
"""
22-
for finder in finders.get_finders():
23-
for path, storage in finder.list([]):
24-
if fnmatch.fnmatchcase(path, glob):
25-
yield path, storage
2614

15+
# This is where PyScss is supposed to find the image files for making sprites.
16+
config.STATIC_ROOT = find_one_file
17+
config.STATIC_URL = staticfiles_storage.url('scss/')
2718

28-
def find_one_file(path):
29-
for file in find_all_files(path):
30-
return file
19+
# This is where PyScss places the sprite files.
20+
config.ASSETS_ROOT = os.path.join(settings.STATIC_ROOT, 'scss', 'assets')
21+
# PyScss expects a trailing slash.
22+
config.ASSETS_URL = staticfiles_storage.url('scss/assets/')
3123

3224

3325
class DjangoScss(Scss):

django_pyscss/utils.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import fnmatch
2+
3+
from django.contrib.staticfiles import finders
4+
5+
6+
def find_all_files(glob):
7+
"""
8+
Finds all files in the django finders for a given glob,
9+
returns the file path, if available, and the django storage object.
10+
storage objects must implement the File storage API:
11+
https://docs.djangoproject.com/en/dev/ref/files/storage/
12+
"""
13+
for finder in finders.get_finders():
14+
for path, storage in finder.list([]):
15+
if fnmatch.fnmatchcase(path, glob):
16+
yield path, storage
17+
18+
19+
def find_one_file(path):
20+
for file in find_all_files(path):
21+
return file

setup.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ def read(fname):
1616
'Django>=1.3',
1717
'PyScss>=1.2.0',
1818
]
19+
tests_require = [
20+
'django-compressor>=1.3',
21+
]
1922

2023
version = (0, 0, 1, 'final')
2124

@@ -37,6 +40,7 @@ def get_version():
3740
long_description=read('README.rst'),
3841
packages=[package for package in find_packages() if package.startswith('django_pyscss')],
3942
install_requires=install_requires,
43+
tests_require=tests_require,
4044
zip_safe=False,
4145
include_package_data=True,
4246
test_suite='testproject.runtests.runtests',

testproject/testproject/settings.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
'django.contrib.messages',
3838
'django.contrib.staticfiles',
3939

40+
'compressor',
41+
4042
'testproject.testapp1',
4143
'testproject.testapp2',
4244
)
@@ -88,3 +90,15 @@
8890
STATICFILES_DIRS = (
8991
os.path.join(BASE_DIR, 'testproject', 'static'),
9092
)
93+
94+
# It doesn't seem like django-compressor respects override_settings
95+
COMPRESS_ENABLED = True
96+
COMPRESS_PRECOMPILERS = (
97+
('text/x-scss', 'django_pyscss.compressor.DjangoScssFilter'),
98+
)
99+
100+
STATICFILES_FINDERS = (
101+
'compressor.finders.CompressorFinder',
102+
'django.contrib.staticfiles.finders.FileSystemFinder',
103+
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
104+
)

tests/test_compressor.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from django.test import TestCase
2+
from django.template.loader import Template, Context
3+
4+
5+
APP2_LINK_TAG = """
6+
{% load staticfiles compress %}
7+
{% compress css %}
8+
<link rel="stylesheet" type="text/x-scss" href="{% static 'css/app2.scss' %}">
9+
{% endcompress %}
10+
"""
11+
12+
13+
class CompressorTest(TestCase):
14+
def test_compressor_can_compile_scss(self):
15+
actual = Template(APP2_LINK_TAG).render(Context())
16+
self.assertIn('4b368862ec8c.css', actual)

tests/test_import.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
from django_pyscss.scss import DjangoScss
88

9+
from tests.utils import clean_css
10+
911

1012
compiler = DjangoScss(scss_opts={
1113
# No compress so that I can compare more easily
@@ -40,14 +42,6 @@ def compile_string(string):
4042
APP2_CONTENTS = FOO_CONTENTS + APP1_CONTENTS
4143

4244

43-
def clean_css(string):
44-
# The output of the compiled CSS doesn't have a newline between the ; and
45-
# the } for some reason.
46-
return string.strip() \
47-
.replace('\n', '') \
48-
.replace('; ', ';')
49-
50-
5145
class ImportTestMixin(object):
5246
def test_import_from_staticfiles_dirs(self):
5347
actual = compile_string(IMPORT_FOO)

tests/utils.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
3+
def clean_css(string):
4+
# The output of the compiled CSS doesn't have a newline between the ; and
5+
# the } for some reason.
6+
return string.strip() \
7+
.replace('\n', '') \
8+
.replace('; ', ';')

0 commit comments

Comments
 (0)