summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEevee <eevee.git@veekun.com>2013-06-26 18:22:16 -0700
committerEevee <eevee.git@veekun.com>2013-06-26 18:22:16 -0700
commit55e5ea914e3c0e7da69ff7d51d633d7e6c4da42b (patch)
treec302cab00b8cbb99576378c6e4489d49ad2e5ff4
parent58b2e0ffee613d9401b59c71956b24c6e6b09cc6 (diff)
downloadpyscss-55e5ea914e3c0e7da69ff7d51d633d7e6c4da42b.tar.gz
Start on tests for Compass helpers.
Fixed some bugs while I was at it. - Boolean conversion was totally wrong; Sass uses Ruby rules. - blank() was wrong. - compact() was needlessly complicated.
-rw-r--r--scss/functions/compass/helpers.py62
-rw-r--r--scss/tests/functions/compass/test_helpers.py45
-rw-r--r--scss/types.py9
3 files changed, 73 insertions, 43 deletions
diff --git a/scss/functions/compass/helpers.py b/scss/functions/compass/helpers.py
index 172bd57..7dc08a4 100644
--- a/scss/functions/compass/helpers.py
+++ b/scss/functions/compass/helpers.py
@@ -17,7 +17,7 @@ import time
from scss import config
from scss.cssdefs import _undefined_re
from scss.functions.library import FunctionLibrary
-from scss.types import BooleanValue, ListValue, NumberValue, StringValue
+from scss.types import BooleanValue, ListValue, NumberValue, QuotedStringValue, StringValue
from scss.util import escape, to_str
log = logging.getLogger(__name__)
@@ -47,55 +47,33 @@ def add_cache_buster(url, mtime):
def blank(*objs):
"""Returns true when the object is false, an empty string, or an empty list"""
for o in objs:
- if bool(o):
+ if isinstance(o, BooleanValue):
+ is_blank = not o
+ elif isinstance(o, QuotedStringValue):
+ is_blank = not len(o.value.strip())
+ elif isinstance(o, ListValue):
+ is_blank = all(blank(el) for el in o)
+ else:
+ is_blank = False
+
+ if not is_blank:
return BooleanValue(False)
+
return BooleanValue(True)
@register('compact')
def compact(*args):
"""Returns a new list after removing any non-true values"""
- ret = {}
- if len(args) == 1:
+ sep = ','
+ if len(args) == 1 and isinstance(args[0], ListValue):
+ sep = args[0].value.get('_', '')
args = args[0]
- if isinstance(args, ListValue):
- args = args.value
- if isinstance(args, dict):
- for i, item in args.items():
- if isinstance(item, (basestring, StringValue)):
- if item != 'false' and not _undefined_re.match(unicode(item)):
- ret[i] = item
- elif isinstance(item, (bool, BooleanValue)):
- if bool(item):
- ret[i] = item
- else:
- ret[i] = item
- elif isinstance(args, (basestring, StringValue)):
- if args != 'false' and not _undefined_re.match(unicode(args)):
- ret[0] = args
- elif isinstance(args, (bool, BooleanValue)):
- if bool(args):
- ret[0] = args
- else:
- ret[0] = args
- else:
- ret['_'] = ','
- for i, item in enumerate(args):
- if isinstance(item, (basestring, StringValue)):
- if item != 'false' and not _undefined_re.match(unicode(item)):
- ret[i] = item
- elif isinstance(item, (bool, BooleanValue)):
- if bool(item):
- ret[i] = item
- else:
- ret[i] = item
- if isinstance(args, ListValue):
- args = args.value
- if isinstance(args, dict):
- separator = args.get('_', None)
- if separator is not None:
- ret['_'] = separator
- return ListValue(ret)
+
+ return ListValue(
+ [arg for arg in args if arg],
+ separator=sep,
+ )
@register('reject')
diff --git a/scss/tests/functions/compass/test_helpers.py b/scss/tests/functions/compass/test_helpers.py
new file mode 100644
index 0000000..07a7b5c
--- /dev/null
+++ b/scss/tests/functions/compass/test_helpers.py
@@ -0,0 +1,45 @@
+"""Tests for the Compass helper functions.
+
+Not all of Compass is implemented, and the arrangement of Compass functions
+doesn't exactly match the arrangement in the original documentation.
+Regardless, this is a good starting place:
+
+http://compass-style.org/reference/compass/helpers/
+
+Some functions appear to be undocumented, but nonetheless are part of Compass's
+Ruby code.
+"""
+
+from scss.expression import Calculator
+from scss.functions.compass.helpers import COMPASS_HELPERS_LIBRARY
+from scss.rule import Namespace
+from scss.types import ColorValue, NumberValue
+
+import pytest
+xfail = pytest.mark.xfail
+
+# TODO many of these tests could also stand to test for failure cases
+
+@pytest.fixture
+def calc():
+ ns = Namespace(functions=COMPASS_HELPERS_LIBRARY)
+ return Calculator(ns).evaluate_expression
+
+# ------------------------------------------------------------------------------
+# Listish functions
+# See: http://ruby-doc.org/gems/docs/c/compass-0.12.2/Compass/SassExtensions/Functions/Lists.html
+
+def test_blank(calc):
+ assert calc('blank(false)')
+ assert calc('blank("")')
+ assert calc('blank(" ")')
+ # TODO this is a syntax error; see #166
+ #assert calc('blank(())')
+
+ assert not calc('blank(null)') # yes, really
+ assert not calc('blank(1)')
+ assert not calc('blank((1, 2))')
+ assert not calc('blank(0)')
+
+def test_compact(calc):
+ assert calc('compact(1 2 3 false 4 5 null 6 7)') == calc('1 2 3 4 5 6 7')
diff --git a/scss/types.py b/scss/types.py
index c579efe..77e6b5c 100644
--- a/scss/types.py
+++ b/scss/types.py
@@ -40,7 +40,8 @@ class Value(object):
return self._do_cmps(self, other, operator.__ge__)
def __nonzero__(self):
- return bool(self.value)
+ # Sass values are all true, except for booleans and nulls
+ return True
def __add__(self, other):
return self._do_op(self, other, operator.__add__)
@@ -83,6 +84,9 @@ class NullValue(Value):
def __str__(self):
return 'null'
+ def __nonzero__(self):
+ return False
+
class BooleanValue(Value):
def __init__(self, value):
@@ -94,6 +98,9 @@ class BooleanValue(Value):
def __str__(self):
return 'true' if self.value else 'false'
+ def __nonzero__(self):
+ return self.value
+
@classmethod
def _do_cmps(cls, first, second, op):
return op(bool(first), bool(second))