summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEevee (Alex Munroe) <eevee.git@veekun.com>2013-08-09 15:28:18 -0700
committerEevee (Alex Munroe) <eevee.git@veekun.com>2013-08-09 15:28:18 -0700
commit6f9547f7ffcbdec7a29e5f7976e1e7b81c092b9e (patch)
tree60a006a4b804d9234a2a93e8b37e422ee0574626
parent94b0e49bdf14b9637ffac6a40ded6cf19f7a3df1 (diff)
downloadpyscss-6f9547f7ffcbdec7a29e5f7976e1e7b81c092b9e.tar.gz
Better parity for default operator behavior. Also fix some bare bools.
-rw-r--r--scss/expression.py7
-rw-r--r--scss/types.py105
2 files changed, 37 insertions, 75 deletions
diff --git a/scss/expression.py b/scss/expression.py
index e24733f..b3224e5 100644
--- a/scss/expression.py
+++ b/scss/expression.py
@@ -223,7 +223,7 @@ class AnyOp(Expression):
def evaluate(self, calculator, divide=False):
operands = [operand.evaluate(calculator, divide=True) for operand in self.operands]
- return any(operands)
+ return BooleanValue(any(operands))
class AllOp(Expression):
def __init__(self, *operands):
@@ -231,14 +231,15 @@ class AllOp(Expression):
def evaluate(self, calculator, divide=False):
operands = [operand.evaluate(calculator, divide=True) for operand in self.operands]
- return all(operands)
+ return BooleanValue(all(operands))
class NotOp(Expression):
def __init__(self, operand):
self.operand = operand
def evaluate(self, calculator, divide=False):
- return not(self.operand.evaluate(calculator, divide=True))
+ operand = self.operand.evaluate(calculator, divide=True)
+ return BooleanValue(not(operand))
class CallOp(Expression):
def __init__(self, func_name, argspec):
diff --git a/scss/types.py b/scss/types.py
index e8d3226..f9da805 100644
--- a/scss/types.py
+++ b/scss/types.py
@@ -59,34 +59,33 @@ class Value(object):
# Math ops
def __add__(self, other):
- return self._do_op(self, other, operator.__add__)
-
- def __radd__(self, other):
- return self._do_op(other, self, operator.__add__)
-
- def __truediv__(self, other):
- return self._do_op(self, other, operator.__truediv__)
+ # Default behavior is to treat both sides like strings
+ if isinstance(other, String):
+ return String(self.render() + other.value, quotes=other.quotes)
+ return String(self.render() + other.render())
- def __rtruediv__(self, other):
- return self._do_op(other, self, operator.__truediv__)
+ def __sub__(self, other):
+ # Default behavior is to treat the whole expression like one string
+ return String(self.render() + "-" + other.render())
def __div__(self, other):
- return self.__truediv__(other)
-
- def __rdiv__(self, other):
- return self.__rtruediv__(other)
+ return String(self.render() + "/" + other.render())
- def __sub__(self, other):
- return self._do_op(self, other, operator.__sub__)
+ # Sass types have no notion of floor vs true division
+ def __truediv__(self, other):
+ return self.__div__(other)
- def __rsub__(self, other):
- return self._do_op(other, self, operator.__sub__)
+ def __floordiv__(self, other):
+ return self.__div__(other)
def __mul__(self, other):
- return self._do_op(self, other, operator.__mul__)
+ raise NotImplementedError
+
+ def __pos__(self):
+ return String("+" + self.render())
- def __rmul__(self, other):
- return self._do_op(other, self, operator.__mul__)
+ def __neg__(self):
+ return String("-" + self.render())
def merge(self, obj):
if isinstance(obj, Value):
@@ -140,32 +139,6 @@ class BooleanValue(Value):
def __bool__(self):
return self.value
- @classmethod
- def _do_op(cls, first, second, op):
- if isinstance(first, ListValue) and isinstance(second, ListValue):
- ret = ListValue(first)
- for k, v in ret.items():
- try:
- ret.value[k] = op(ret.value[k], second.value[k])
- except KeyError:
- pass
- return ret
- if isinstance(first, ListValue):
- ret = ListValue(first)
- for k, v in ret.items():
- ret.value[k] = op(ret.value[k], second)
- return ret
- if isinstance(second, ListValue):
- ret = ListValue(second)
- for k, v in ret.items():
- ret.value[k] = op(first, ret.value[k])
- return ret
-
- first = BooleanValue(first)
- second = BooleanValue(second)
- val = op(first.value, second.value)
- return BooleanValue(val)
-
def render(self, compress=False, short_colors=False):
if self.value:
return 'true'
@@ -486,28 +459,6 @@ class List(Value):
else:
return ' '
- @classmethod
- def _do_op(cls, first, second, op):
- if isinstance(first, ListValue) and isinstance(second, ListValue):
- ret = ListValue(first)
- for k, v in ret.items():
- try:
- ret.value[k] = op(ret.value[k], second.value[k])
- except KeyError:
- pass
- return ret
- if isinstance(first, ListValue):
- ret = ListValue(first)
- for k, v in ret.items():
- ret.value[k] = op(ret.value[k], second)
- return ret
- if isinstance(second, ListValue):
- ret = ListValue(second)
-
- for k, v in ret.items():
- ret.value[k] = op(first, ret.value[k])
- return ret
-
def _reorder_list(self, lst):
return dict((i if isinstance(k, int) else k, v) for i, (k, v) in enumerate(sorted(lst.items())))
@@ -691,11 +642,21 @@ class ColorValue(Value):
# float errors make equality fail for HSL colors.
left = tuple(round(n, 5) for n in self.value)
right = tuple(round(n, 5) for n in other.value)
- return left == right
+ return BooleanValue(left == right)
- @classmethod
- def _do_op(cls, first, second, op):
- first = ColorValue(first)
+ def __add__(self, other):
+ return self._operate(other, operator.add)
+
+ def __sub__(self, other):
+ return self._operate(other, operator.sub)
+
+ def __mul__(self, other):
+ return self._operate(other, operator.mul)
+
+ def __div__(self, other):
+ return self._operate(other, operator.div)
+
+ def _operate(first, second, op):
second = ColorValue(second)
val = [op(first.value[i], second.value[i]) for i in range(4)]
val[3] = (first.value[3] + second.value[3]) / 2