Skip to content

Commit dfb5237

Browse files
committed
Parsing lists or vectors with parentheses or brackets in units expressions fixed
1 parent 6b330c6 commit dfb5237

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

pyunitwizard/parse.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,28 @@
55
import ast
66
from typing import Optional
77

8+
def _find_closing_bracket_position(string):
9+
stack = 0
10+
for i, char in enumerate(string):
11+
if char == '[':
12+
stack += 1
13+
elif char == ']':
14+
stack -= 1
15+
if stack == 0:
16+
return i
17+
raise ValueError # If there is no closing bracket
18+
19+
def _find_closing_parenthesis_position(string):
20+
stack = 0
21+
for i, char in enumerate(string):
22+
if char == '(':
23+
stack += 1
24+
elif char == ')':
25+
stack -= 1
26+
if stack == 0:
27+
return i
28+
raise ValueError # If there is no closing parenthesis
29+
830
def _parse_with_pint(string: str):
931
""" Parses a string and returns a pint quantity.
1032
@@ -19,13 +41,22 @@ def _parse_with_pint(string: str):
1941
A pint quantity.
2042
"""
2143
# Check if it's a non scalar quantity
22-
if string.startswith('[') or string.startswith('('):
44+
if string.startswith('['):
2345

24-
end_list = max(string.rfind(')')+1, string.rfind(']')+1)
25-
value_string = string[:end_list]
26-
unit_string = string[end_list:]
46+
end_list = _find_closing_bracket_position(string)
47+
value_string = string[:(end_list+1)]
48+
unit_string = string[(end_list+1):]
2749

2850
return ast.literal_eval(value_string)*dict_translate_quantity['string']['pint'](unit_string)
51+
52+
elif string.startswith('('):
53+
54+
end_list = _find_closing_parenthesis_position(string)
55+
value_string = string[:(end_list+1)]
56+
unit_string = string[(end_list+1):]
57+
58+
return ast.literal_eval(value_string)*dict_translate_quantity['string']['pint'](unit_string)
59+
2960
else:
3061
return dict_translate_quantity['string']['pint'](string)
3162

tests/test_parse.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ def test_parse_with_pint_array():
2222
assert np.allclose(quantity.magnitude, np.array([3, 2, 1]))
2323
assert str(quantity.units) == "meter"
2424

25-
quantity = _parse_with_pint("[[2, 5, 7], [7, 8, 9]] joules")
25+
quantity = _parse_with_pint("[[2, 5, 7], [7, 8, 9]] kilojoules/(mol*nanometer)")
2626
assert np.allclose(quantity.magnitude, np.array([[2, 5, 7], [7, 8, 9]]))
27-
assert str(quantity.units) == "joule"
27+
assert str(quantity.units) == "kilojoule / mole / nanometer"
2828

2929
def test_parse_to_pint():
3030

0 commit comments

Comments
 (0)