diff options
author | Eevee (Alex Munroe) <eevee.git@veekun.com> | 2013-08-21 15:23:59 -0700 |
---|---|---|
committer | Eevee (Alex Munroe) <eevee.git@veekun.com> | 2013-08-21 15:23:59 -0700 |
commit | 93385fec068470e50a7d6f67aaa13098dc2826b6 (patch) | |
tree | bbc573daa8efa06a18c530be42a44271a9993782 | |
parent | 0e499cb186e3a5fc96558549fb008f218ed998d7 (diff) | |
download | pyscss-93385fec068470e50a7d6f67aaa13098dc2826b6.tar.gz |
Numbers can always compare to unitless numbers. Expand Number tests.
-rw-r--r-- | scss/tests/test_types.py | 27 | ||||
-rw-r--r-- | scss/types.py | 34 |
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) |