diff options
author | Eevee <eevee.git@veekun.com> | 2013-06-26 18:22:16 -0700 |
---|---|---|
committer | Eevee <eevee.git@veekun.com> | 2013-06-26 18:22:16 -0700 |
commit | 55e5ea914e3c0e7da69ff7d51d633d7e6c4da42b (patch) | |
tree | c302cab00b8cbb99576378c6e4489d49ad2e5ff4 | |
parent | 58b2e0ffee613d9401b59c71956b24c6e6b09cc6 (diff) | |
download | pyscss-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.py | 62 | ||||
-rw-r--r-- | scss/tests/functions/compass/test_helpers.py | 45 | ||||
-rw-r--r-- | scss/types.py | 9 |
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)) |