Skip to content

Commit 9f7aaa1

Browse files
authored
More flexible _parse_size (#125)
* More flexible _parse_size with tests * add regex comment
1 parent 7188ab5 commit 9f7aaa1

File tree

2 files changed

+44
-12
lines changed

2 files changed

+44
-12
lines changed

branca/utilities.py

+16-12
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import json
1111
import math
1212
import os
13+
import re
1314
import struct
1415
import zlib
1516

@@ -387,19 +388,22 @@ def _camelify(out):
387388

388389

389390
def _parse_size(value):
390-
try:
391-
if isinstance(value, int) or isinstance(value, float):
392-
value_type = "px"
393-
value = float(value)
394-
assert value > 0
391+
if isinstance(value, (int, float)):
392+
return float(value), "px"
393+
elif isinstance(value, str):
394+
# match digits or a point, possibly followed by a space,
395+
# followed by a unit: either 1 to 5 letters or a percent sign
396+
match = re.fullmatch(r"([\d.]+)\s?(\w{1,5}|%)", value.strip())
397+
if match:
398+
return float(match.group(1)), match.group(2)
395399
else:
396-
value_type = "%"
397-
value = float(value.strip("%"))
398-
assert 0 <= value <= 100
399-
except Exception:
400-
msg = "Cannot parse value {!r} as {!r}".format
401-
raise ValueError(msg(value, value_type))
402-
return value, value_type
400+
raise ValueError(
401+
f"Cannot parse {value!r}, it should be a number followed by a unit.",
402+
)
403+
else:
404+
raise TypeError(
405+
f"Cannot parse {value!r}, it should be a number or a string containing a number and a unit.",
406+
)
403407

404408

405409
def _locations_mirror(x):

tests/test_utilities.py

+28
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,31 @@ def test_color_avoid_unexpected_error():
104104
for n in [str(color_brewer_minimum_n), float(color_brewer_minimum_n), "abc"]:
105105
with pytest.raises(TypeError):
106106
ut.color_brewer(sname, n)
107+
108+
109+
@pytest.mark.parametrize(
110+
"value,result",
111+
[
112+
(1, (1.0, "px")),
113+
("1 px", (1.0, "px")),
114+
("80 % ", (80.0, "%")),
115+
("100% ", (100.0, "%")),
116+
("3 vw", (3.0, "vw")),
117+
("3.14 rem", (3.14, "rem")),
118+
],
119+
)
120+
def test_parse_size(value, result):
121+
assert ut._parse_size(value) == result
122+
123+
124+
@pytest.mark.parametrize(
125+
"value",
126+
[
127+
"what?",
128+
"1.21 jigawatts",
129+
ut._parse_size,
130+
],
131+
)
132+
def test_parse_size_exceptions(value):
133+
with pytest.raises((ValueError, TypeError)):
134+
ut._parse_size(value)

0 commit comments

Comments
 (0)