summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRocky Meza <rocky@fusionbox.com>2014-02-01 19:29:22 -0700
committerRocky Meza <rocky@fusionbox.com>2014-02-01 19:29:22 -0700
commit64cb29c8bb81c1b7ed9fbc08966dd918f4a12ca0 (patch)
treef137a4eda3a036d01485fd42c84732626fe432e7
parent2a53a7abd1ddba02c44b81a24305b03532b45fee (diff)
downloaddjango-pyscss-64cb29c8bb81c1b7ed9fbc08966dd918f4a12ca0.tar.gz
updated to PyScss 1.2.0
-rw-r--r--django_pyscss/scss.py90
-rw-r--r--setup.py2
-rw-r--r--tests/test_import.py14
3 files changed, 69 insertions, 37 deletions
diff --git a/django_pyscss/scss.py b/django_pyscss/scss.py
index 9837436..5990d2b 100644
--- a/django_pyscss/scss.py
+++ b/django_pyscss/scss.py
@@ -1,5 +1,6 @@
from __future__ import absolute_import, unicode_literals
+import os
import fnmatch
from django.contrib.staticfiles import finders
@@ -7,8 +8,7 @@ from django.contrib.staticfiles.storage import staticfiles_storage
from django.conf import settings
from scss import (
- Scss, dequote, log, spawn_rule,
- OPTIONS, PROPERTIES,
+ Scss, dequote, log, SourceFile, SassRule,
)
@@ -42,53 +42,77 @@ class DjangoScss(Scss):
# remote storages don't implement path
pass
finally:
- with staticfiles_storage.open(filename) as f:
- return f.read()
+ return filename, staticfiles_storage
def get_file_from_finders(self, filename):
- path, storage = find_one_file(filename)
- with storage.open(path) as f:
- return f.read()
+ return find_one_file(filename)
- def get_file_contents(self, filename):
+ def get_file_and_storage(self, filename):
# TODO: the switch probably shouldn't be on DEBUG
if settings.DEBUG:
return self.get_file_from_finders(filename)
else:
return self.get_file_from_storage(filename)
- def _do_import(self, rule, p_selectors, p_parents, p_children, scope, media, c_lineno, c_property, c_codestr, code, name):
+ def _find_source_file(self, name):
+ full_filename, storage = self.get_file_and_storage(name)
+ if name not in self.source_files:
+ with storage.open(full_filename) as f:
+ source = f.read()
+ source_file = SourceFile(
+ full_filename,
+ source,
+ parent_dir=os.path.realpath(os.path.dirname(full_filename)),
+ )
+ self.source_files.append(source_file)
+ self.source_file_index[full_filename] = source_file
+ return self.source_file_index[full_filename]
+
+ def _do_import(self, rule, scope, block):
"""
Implements @import using the django storages API.
"""
# Protect against going to prohibited places...
- if '..' in name or '://' in name or 'url(' in name:
- rule[PROPERTIES].append((c_lineno, c_property, None))
+ if any(scary_token in block.argument for scary_token in ('..', '://', 'url(')):
+ rule.properties.append((block.prop, None))
return
full_filename = None
- i_codestr = None
- names = name.split(',')
- for filename in names:
- filename = dequote(name.strip())
- if '@import ' + filename in rule[OPTIONS]:
+ names = block.argument.split(',')
+ for name in names:
+ name = dequote(name.strip())
+
+ source_file = self._find_source_file(name)
+
+ if source_file is None:
+ i_codestr = self._do_magic_import(rule, scope, block)
+
+ if i_codestr is not None:
+ source_file = SourceFile.from_string(i_codestr)
+ self.source_files.append(source_file)
+ self.source_file_index[full_filename] = source_file
+
+ if source_file is None:
+ log.warn("File to import not found or unreadable: '%s' (%s)", name, rule.file_and_line)
+ continue
+
+ import_key = (name, source_file.parent_dir)
+ if rule.namespace.has_import(import_key):
# If already imported in this scope, skip
continue
- try:
- i_codestr = self.scss_files[filename]
- except KeyError:
- i_codestr = self.get_file_contents(filename)
-
- if i_codestr is None:
- i_codestr = self._do_magic_import(rule, p_selectors, p_parents, p_children, scope, media, c_lineno, c_property, c_codestr, code, name)
- if i_codestr is None:
- log.warn("I couldn't find this file (%s)." % filename)
-
- i_codestr = self.scss_files[name] = i_codestr and self.load_string(i_codestr, full_filename)
- if name not in self.scss_files:
- self._scss_files_order.append(name)
- if i_codestr is not None:
- _rule = spawn_rule(rule, codestr=i_codestr, path=full_filename, lineno=c_lineno)
- self.manage_children(_rule, p_selectors, p_parents, p_children, scope, media)
- rule[OPTIONS]['@import ' + name] = True
+ _rule = SassRule(
+ source_file=source_file,
+ lineno=block.lineno,
+ import_key=import_key,
+ unparsed_contents=source_file.contents,
+
+ # rule
+ options=rule.options,
+ properties=rule.properties,
+ extends_selectors=rule.extends_selectors,
+ ancestry=rule.ancestry,
+ namespace=rule.namespace,
+ )
+ rule.namespace.add_import(import_key, rule.import_key, rule.file_and_line)
+ self.manage_children(_rule, scope)
diff --git a/setup.py b/setup.py
index c0da811..d49ed1c 100644
--- a/setup.py
+++ b/setup.py
@@ -14,7 +14,7 @@ def read(fname):
install_requires = [
'Django>=1.3',
- 'PyScss>=1.1.5',
+ 'PyScss>=1.2.0',
]
version = (0, 0, 1, 'final')
diff --git a/tests/test_import.py b/tests/test_import.py
index 1fdab51..6e65de5 100644
--- a/tests/test_import.py
+++ b/tests/test_import.py
@@ -40,18 +40,26 @@ IMPORT_APP2 = """
APP2_CONTENTS = FOO_CONTENTS + APP1_CONTENTS
+def clean_css(string):
+ # The output of the compiled CSS doesn't have a newline between the ; and
+ # the } for some reason.
+ return string.strip() \
+ .replace('\n', '') \
+ .replace('; ', ';')
+
+
class ImportTestMixin(object):
def test_import_from_staticfiles_dirs(self):
actual = compile_string(IMPORT_FOO)
- self.assertEqual(actual.strip(), FOO_CONTENTS.strip())
+ self.assertEqual(clean_css(actual), clean_css(FOO_CONTENTS))
def test_import_from_app(self):
actual = compile_string(IMPORT_APP1)
- self.assertEqual(actual.strip(), APP1_CONTENTS.strip())
+ self.assertEqual(clean_css(actual), clean_css(APP1_CONTENTS))
def test_imports_within_file(self):
actual = compile_string(IMPORT_APP2)
- self.assertEqual(actual.strip(), APP2_CONTENTS.strip())
+ self.assertEqual(clean_css(actual), clean_css(APP2_CONTENTS))
@override_settings(DEBUG=True)