summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEevee (Alex Munroe) <eevee.git@veekun.com>2013-08-21 15:23:59 -0700
committerEevee (Alex Munroe) <eevee.git@veekun.com>2013-08-21 15:23:59 -0700
commit93385fec068470e50a7d6f67aaa13098dc2826b6 (patch)
treebbc573daa8efa06a18c530be42a44271a9993782
parent0e499cb186e3a5fc96558549fb008f218ed998d7 (diff)
downloadpyscss-93385fec068470e50a7d6f67aaa13098dc2826b6.tar.gz
Numbers can always compare to unitless numbers. Expand Number tests.
-rw-r--r--scss/tests/test_types.py27
-rw-r--r--scss/types.py34
2 files changed, 52 insertions, 9 deletions
diff --git a/scss/tests/test_types.py b/scss/tests/test_types.py
index b55c5f2..48f8223 100644
--- a/scss/tests/test_types.py
+++ b/scss/tests/test_types.py
@@ -10,10 +10,23 @@ import pytest
# Test them all!
def test_addition():
+ # Numbers are a little complicated, what with all the units
+ # Simple case
assert Number(123) + Number(456) == Number(579)
-
+ # Simple equal units
assert Number(1, "px") + Number(2, "px") == Number(3, "px")
-
+ # Unitless values inherit units of the other operand
+ assert Number(5) + Number(6, "px") == Number(11, "px")
+ # Zero values can cast to any units
+ assert Number(0, "in") + Number(24, "deg") == Number(24, "deg")
+ # With different units, the left operand wins
+ assert Number(10, "cm") + Number(100, "mm") == Number(20, "cm")
+ assert Number(100, "mm") + Number(10, "cm") == Number(200, "mm")
+ # Unconvertible units raise an error
+ with pytest.raises(ValueError):
+ Number(1, "px") + Number(1, "em")
+
+ # Adding anything to a string makes a string
assert Number(123) + String('abc') == String('123abc')
assert String('abc') + Number(123) == String('abc123')
@@ -66,6 +79,16 @@ def test_comparison_numeric():
assert not lo != lo
assert not lo == hi
+ # Numbers with units should also auto-cast numbers with units
+ units = Number(123, "px")
+ plain = Number(123)
+ assert units == plain
+ assert units <= plain
+ assert units >= plain
+ assert not units != plain
+ assert not units < plain
+ assert not units > plain
+
def test_comparison_stringerific():
abc = String('abc')
diff --git a/scss/types.py b/scss/types.py
index af67cd3..870f479 100644
--- a/scss/types.py
+++ b/scss/types.py
@@ -292,14 +292,21 @@ class Number(Value):
if not isinstance(other, Number):
raise TypeError("Can't compare %r and %r" % (self, other))
- left = self.to_base_units()
- right = other.to_base_units()
+ # A unitless operand is treated as though it had the other operand's
+ # units, and zero values can cast to anything, so in both cases the
+ # units can be ignored
+ if (self.is_unitless or other.is_unitless or
+ self.value == 0 or other.value == 0):
+ left = self
+ right = other
+ else:
+ left = self.to_base_units()
+ right = other.to_base_units()
- if (left.value != 0 or left.unit_numer or left.unit_denom) and (right.value != 0 or right.unit_numer or right.unit_denom):
if left.unit_numer != right.unit_numer or left.unit_denom != right.unit_denom:
raise ValueError("Can't reconcile units: %r and %r" % (self, other))
- return op(round(left.value, 5), round(right.value, 5))
+ return Boolean(op(round(left.value, 5), round(right.value, 5)))
def __pow__(self, exp):
if not isinstance(exp, Number):
@@ -367,13 +374,26 @@ class Number(Value):
unit_denom=self.unit_denom or other.unit_denom,
)
+ # Likewise, if either side is zero, it can auto-cast to any units
+ if self.value == 0:
+ return Number(
+ op(self.value, other.value),
+ unit_numer=other.unit_numer,
+ unit_denom=other.unit_denom,
+ )
+ elif other.value == 0:
+ return Number(
+ op(self.value, other.value),
+ unit_numer=self.unit_numer,
+ unit_denom=self.unit_denom,
+ )
+
# Reduce both operands to the same units
left = self.to_base_units()
right = other.to_base_units()
- if (left.value != 0 or left.unit_numer or left.unit_denom) and (right.value != 0 or right.unit_numer or right.unit_denom):
- if left.unit_numer != right.unit_numer or left.unit_denom != right.unit_denom:
- raise ValueError("Can't reconcile units: %r and %r" % (self, other))
+ if left.unit_numer != right.unit_numer or left.unit_denom != right.unit_denom:
+ raise ValueError("Can't reconcile units: %r and %r" % (self, other))
new_amount = op(left.value, right.value)