Merge pull request #19 from saschpe/master
More fixes, mostly rounding :-)
This commit is contained in:
@@ -105,7 +105,7 @@ class Color():
|
||||
if isinstance(s, str):
|
||||
s = int(s.strip('%'))
|
||||
rgb = colorsys.hls_to_rgb(int(h) / 360.0, l / 100.0, s / 100.0)
|
||||
color = (round(c * 255) for c in rgb)
|
||||
color = (utility.convergent_round(c * 255) for c in rgb)
|
||||
return self._rgbatohex(color)
|
||||
raise ValueError('Illegal color values')
|
||||
|
||||
@@ -123,8 +123,8 @@ class Color():
|
||||
if isinstance(s, str):
|
||||
s = int(s.strip('%'))
|
||||
rgb = colorsys.hls_to_rgb(int(h) / 360.0, l / 100.0, s / 100.0)
|
||||
color = [float(round(c * 255)) for c in rgb]
|
||||
color.append(round(float(a[:-1]) / 100.0, 2))
|
||||
color = [float(utility.convergent_round(c * 255)) for c in rgb]
|
||||
color.append(utility.convergent_round(float(a[:-1]) / 100.0, 2))
|
||||
return "rgba(%s,%s,%s,%s)" % tuple(color)
|
||||
raise ValueError('Illegal color values')
|
||||
|
||||
@@ -139,7 +139,7 @@ class Color():
|
||||
"""
|
||||
if color:
|
||||
h, l, s = self._hextohls(color)
|
||||
return round(h * 360.0, 3)
|
||||
return utility.convergent_round(h * 360.0, 3)
|
||||
raise ValueError('Illegal color values')
|
||||
|
||||
def saturation(self, color, *args):
|
||||
@@ -260,7 +260,7 @@ class Color():
|
||||
h = ((h * 360.0) + degree) % 360.0
|
||||
h = 360.0 + h if h < 0 else h
|
||||
rgb = colorsys.hls_to_rgb(h / 360.0, l, s)
|
||||
color = (round(c * 255) for c in rgb)
|
||||
color = (utility.convergent_round(c * 255) for c in rgb)
|
||||
return self._rgbatohex(color)
|
||||
raise ValueError('Illegal color values')
|
||||
|
||||
@@ -364,5 +364,5 @@ class Color():
|
||||
hls = list(self._hextohls(color))
|
||||
hls[idx] = self._clamp(getattr(hls[idx], op)(diff / 100.0))
|
||||
rgb = colorsys.hls_to_rgb(*hls)
|
||||
color = (round(c * 255) for c in rgb)
|
||||
color = (utility.away_from_zero_round(c * 255) for c in rgb)
|
||||
return self._rgbatohex(color)
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import collections
|
||||
import math
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def flatten(lst):
|
||||
@@ -243,3 +245,36 @@ def split_unit(value):
|
||||
"""
|
||||
r = re.search('^(\-?[\d\.]+)(.*)$', str(value))
|
||||
return r.groups() if r else ('', '')
|
||||
|
||||
|
||||
def away_from_zero_round(value, ndigits=0):
|
||||
"""Round half-way away from zero.
|
||||
|
||||
Python2's round() method.
|
||||
"""
|
||||
if sys.version_info[0] >= 3:
|
||||
p = 10 ** ndigits
|
||||
return float(math.floor((value * p) + math.copysign(0.5, value))) / p
|
||||
else:
|
||||
return round(value, ndigits)
|
||||
|
||||
|
||||
def convergent_round(value, ndigits=0):
|
||||
"""Convergent rounding.
|
||||
|
||||
Round to neareas even, similar to Python3's round() method.
|
||||
"""
|
||||
if sys.version_info[0] < 3:
|
||||
if value < 0.0:
|
||||
return -convergent_round(-value)
|
||||
|
||||
epsilon = 0.0000001
|
||||
integral_part, _ = divmod(value, 1)
|
||||
|
||||
if abs(value - (integral_part + 0.5)) < epsilon:
|
||||
if integral_part % 2.0 < epsilon:
|
||||
return integral_part
|
||||
else:
|
||||
nearest_even = integral_part + 0.5
|
||||
return math.ceil(nearest_even)
|
||||
return round(value, ndigits)
|
||||
|
||||
@@ -196,7 +196,7 @@ class Call(Node):
|
||||
str
|
||||
"""
|
||||
n, u = utility.analyze_number(value)
|
||||
return utility.with_unit(int(round(float(n))), u)
|
||||
return utility.with_unit(int(utility.away_from_zero_round(float(n))), u)
|
||||
|
||||
def ceil(self, value, *args):
|
||||
""" Ceil number
|
||||
|
||||
@@ -96,7 +96,7 @@ class Expression(Node):
|
||||
return str(val) + ua
|
||||
elif ub:
|
||||
return str(val) + ub
|
||||
return str(val)
|
||||
return repr(val)
|
||||
|
||||
def operate(self, vala, valb, oper):
|
||||
"""Perform operation
|
||||
@@ -125,7 +125,9 @@ class Expression(Node):
|
||||
else:
|
||||
ret = getattr(vala, operation)(valb)
|
||||
if ret is NotImplemented:
|
||||
ret = getattr(valb, operation)(vala)
|
||||
# __truediv__(int, float) isn't implemented, but __truediv__(float, float) is.
|
||||
# __add__(int, float) is similar. Simply cast vala to float:
|
||||
ret = getattr(float(vala), operation)(valb)
|
||||
if oper in '+-*/':
|
||||
try:
|
||||
if int(ret) == ret:
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
decrement: 9;
|
||||
rounded: 11;
|
||||
roundedpx: 3px;
|
||||
round25: 3;
|
||||
round15: 2;
|
||||
}
|
||||
#escapes {
|
||||
escaped: -Some::weird(#thing, y);
|
||||
@@ -19,7 +21,7 @@
|
||||
format-url-encode: 'red is %23ff0000';
|
||||
}
|
||||
#more {
|
||||
width: 1px;
|
||||
width: 2px;
|
||||
height: 1px;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
4
lesscpy/test/css/calls.min.css
vendored
4
lesscpy/test/css/calls.min.css
vendored
@@ -1,6 +1,6 @@
|
||||
#standard{width:16;height:undefined("self");border-width:5;variable:11;decrement:9;rounded:11;roundedpx:3px;}
|
||||
#standard{width:16;height:undefined("self");border-width:5;variable:11;decrement:9;rounded:11;roundedpx:3px;round25:3;round15:2;}
|
||||
#escapes{escaped:-Some::weird(#thing, y);escaped1:-Some::weird(#thing, z);eformat:rgb(32, 128, 64);}
|
||||
#format{format:"rgb(32, 128, 64)";format-string:"hello world";format-multiple:"hello earth 2";format-url-encode:'red is %23ff0000';}
|
||||
#more{width:1px;height:1px;top:50%;}
|
||||
#more{width:2px;height:1px;top:50%;}
|
||||
#colors{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#333333', GradientType=1);}
|
||||
a{background-image:linear-gradient(top,#ffffff,#333333);background-image:linear-gradient(top,#a6a6a6,#000000);}
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
color: #c1cdc8;
|
||||
color: #ffffff;
|
||||
}
|
||||
.lighten {
|
||||
.darken {
|
||||
color: #525252;
|
||||
color: #3b3b3b;
|
||||
color: #222222;
|
||||
|
||||
2
lesscpy/test/css/colors.min.css
vendored
2
lesscpy/test/css/colors.min.css
vendored
@@ -13,7 +13,7 @@
|
||||
.saturate{color:#565454;color:#5e4c4c;color:#664444;color:#773333;color:#882222;color:#aa0000;color:#000000;color:#000000;color:#ffffff;color:#ffffff;color:#29332f;color:#243830;color:#203c31;color:#174533;color:#0d4f35;color:#005c37;}
|
||||
.desaturate{color:#555555;color:#555555;color:#555555;color:#555555;color:#555555;color:#555555;color:#000000;color:#000000;color:#ffffff;color:#ffffff;color:#29332f;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;}
|
||||
.lighten{color:#585858;color:#6f6f6f;color:#888888;color:#bbbbbb;color:#eeeeee;color:#ffffff;color:#ffffff;color:#000000;color:#ffffff;color:#ffffff;color:#2b3632;color:#404f49;color:#566c63;color:#88a096;color:#c1cdc8;color:#ffffff;}
|
||||
.lighten{color:#525252;color:#3b3b3b;color:#222222;color:#000000;color:#000000;color:#000000;color:#000000;color:#000000;color:#000000;color:#ffffff;color:#27302c;color:#121715;color:#000000;color:#000000;color:#000000;color:#000000;}
|
||||
.darken{color:#525252;color:#3b3b3b;color:#222222;color:#000000;color:#000000;color:#000000;color:#000000;color:#000000;color:#000000;color:#ffffff;color:#27302c;color:#121715;color:#000000;color:#000000;color:#000000;color:#000000;}
|
||||
.spin{color:#555555;color:#555555;color:#555555;color:#555555;color:#555555;color:#555555;color:#000000;color:#000000;color:#ffffff;color:#ffffff;color:#29332f;color:#29332d;color:#293332;color:#2a3329;color:#292d33;color:#2c2933;}
|
||||
.grayscale{color:#000000;color:#000000;color:#ffffff;color:#ffffff;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;}
|
||||
.mix{color:#7f007f;color:#7f7f7f;color:#7f9055;color:#3f00bf;color:#ff0000;color:#0000ff;}
|
||||
|
||||
@@ -124,13 +124,13 @@
|
||||
margin-left: 59.1;
|
||||
}
|
||||
.offset3 {
|
||||
margin-left: 87.8;
|
||||
margin-left: 87.80000000000001;
|
||||
}
|
||||
.offset4 {
|
||||
margin-left: 116.5;
|
||||
}
|
||||
.offset5 {
|
||||
margin-left: 145.2;
|
||||
margin-left: 145.20000000000002;
|
||||
}
|
||||
.offset6 {
|
||||
margin-left: 173.9;
|
||||
|
||||
4
lesscpy/test/css/grid.min.css
vendored
4
lesscpy/test/css/grid.min.css
vendored
@@ -39,9 +39,9 @@
|
||||
.span12,.container{width:342.7;}
|
||||
.offset1{margin-left:30.4;}
|
||||
.offset2{margin-left:59.1;}
|
||||
.offset3{margin-left:87.8;}
|
||||
.offset3{margin-left:87.80000000000001;}
|
||||
.offset4{margin-left:116.5;}
|
||||
.offset5{margin-left:145.2;}
|
||||
.offset5{margin-left:145.20000000000002;}
|
||||
.offset6{margin-left:173.9;}
|
||||
.offset7{margin-left:202.6;}
|
||||
.offset8{margin-left:231.3;}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
decrement: decrement(@var);
|
||||
rounded: round(@r/3);
|
||||
roundedpx: round(10px / 3);
|
||||
round25: round(2.5);
|
||||
round15: round(1.5);
|
||||
}
|
||||
#escapes {
|
||||
escaped: e("-Some::weird(#thing, y)");
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
color: lighten(#29332f, 60%);
|
||||
color: lighten(#29332f, 100%);
|
||||
}
|
||||
.lighten {
|
||||
.darken {
|
||||
color: darken(#555, 1%);
|
||||
color: darken(#555, 10%);
|
||||
color: darken(#555, 20%);
|
||||
|
||||
@@ -92,6 +92,20 @@ class TestUtility(unittest.TestCase):
|
||||
self.assertEqual('1', test(1, None))
|
||||
self.assertEqual('1', test(1,))
|
||||
|
||||
def test_convergent_round(self):
|
||||
test = utility.convergent_round
|
||||
self.assertEqual(-4, test(-4.5))
|
||||
self.assertEqual(-4, test(-3.5))
|
||||
self.assertEqual(-2, test(-2.5))
|
||||
self.assertEqual(-2, test(-1.5))
|
||||
self.assertEqual(0, test(-0.5))
|
||||
self.assertEqual(0, test(0.5))
|
||||
self.assertEqual(2, test(1.5))
|
||||
self.assertEqual(2, test(2.5))
|
||||
self.assertEqual(3.0, test(10.0 / 3, 0))
|
||||
self.assertEqual(4, test(3.5))
|
||||
self.assertEqual(4, test(4.5))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user