Skip to content
Snippets Groups Projects
Commit 553ec794 authored by Benedikt's avatar Benedikt
Browse files

improved error handling

parent a8945280
No related branches found
No related tags found
No related merge requests found
...@@ -34,7 +34,7 @@ class dsiParser: ...@@ -34,7 +34,7 @@ class dsiParser:
warningMessages = [] warningMessages = []
# Catch any double (triple...) \ before they annoy us # Catch any double (triple...) \ before they annoy us
while r'\\' in dsiString: while r'\\' in dsiString:
warningMessages.append(_warn(f"Double backslash found in string, treating as one backslash: \"{dsiString}\"", RuntimeWarning)) warningMessages.append(_warn(f"Double backslash found in string, treating as one backslash: >{dsiString}<", RuntimeWarning))
dsiString = dsiString.replace(r'\\', '\\') dsiString = dsiString.replace(r'\\', '\\')
if dsiString == "": if dsiString == "":
...@@ -90,7 +90,7 @@ class dsiParser: ...@@ -90,7 +90,7 @@ class dsiParser:
if items[0] == '': #first item of List should be empty, remove it if items[0] == '': #first item of List should be empty, remove it
items.pop(0) items.pop(0)
else: else:
warningMessages.append(_warn(f"string should start with \\, string given was \"{dsiString}\"", RuntimeWarning)) warningMessages.append(_warn(f"string should start with \\, string given was >{dsiString}<", RuntimeWarning))
nodes = [] nodes = []
(prefix, unit, exponent) = ('','','') (prefix, unit, exponent) = ('','','')
...@@ -116,7 +116,7 @@ class dsiParser: ...@@ -116,7 +116,7 @@ class dsiParser:
item = '' item = ''
elif re.match(r'tothe\{.*\}', item): elif re.match(r'tothe\{.*\}', item):
exponent = item.split('{')[1].split('}')[0] exponent = item.split('{')[1].split('}')[0]
warningMessages.append(_warn(f"The exponent \"{exponent}\" is not a number!", RuntimeWarning)) warningMessages.append(_warn(f"The exponent >{exponent}< is not a number!", RuntimeWarning))
try: try:
item = items.pop(0) item = items.pop(0)
except IndexError: except IndexError:
...@@ -127,14 +127,20 @@ class dsiParser: ...@@ -127,14 +127,20 @@ class dsiParser:
item = items.pop(0) item = items.pop(0)
except IndexError: except IndexError:
item = '' item = ''
warningMessages.append(_warn(f"The identifier \"{unit}\" does not match any D-SI units!", RuntimeWarning)) closestMatches= _getClosestStr(unit)
if len (closestMatches) > 0:
closestMatchesStr= ', \\'.join(closestMatches)
closestMatchesStr= '\\' + closestMatchesStr
warningMessages.append(_warn(fr"The identifier >{unit}< does not match any D-SI units! Did you mean one of these >{closestMatchesStr}< ?", RuntimeWarning))
else:
warningMessages.append(_warn(fr"The identifier >{unit}< does not match any D-SI units!", RuntimeWarning))
elif unit == '': elif unit == '':
itemStr = "" itemStr = ""
if prefix != "": if prefix != "":
itemStr = itemStr + "\\" + prefix itemStr = itemStr + "\\" + prefix
if exponent != "": if exponent != "":
itemStr = itemStr + r"\tothe{" + exponent + r"}" itemStr = itemStr + r"\tothe{" + exponent + r"}"
warningMessages.append(_warn(f"This D-SI unit seems to be missing the base unit! \"{itemStr}\"", RuntimeWarning)) warningMessages.append(_warn(f"This D-SI unit seems to be missing the base unit! >{itemStr}<", RuntimeWarning))
nodes.append(_node(prefix, unit, exponent)) nodes.append(_node(prefix, unit, exponent))
if (len(items) == 0) and (item == ''): break if (len(items) == 0) and (item == ''): break
...@@ -258,7 +264,7 @@ def _warn(message: str, warningClass): ...@@ -258,7 +264,7 @@ def _warn(message: str, warningClass):
warnings.warn(message, warningClass) warnings.warn(message, warningClass)
return message return message
def _getClosestStrAndType(unkownStr): def _getClosestStr(unkownStr):
"""returns the closest string and type of the given string """returns the closest string and type of the given string
Args: Args:
...@@ -268,19 +274,9 @@ def _getClosestStrAndType(unkownStr): ...@@ -268,19 +274,9 @@ def _getClosestStrAndType(unkownStr):
str: closest string str: closest string
str: type of closest string str: type of closest string
""" """
closestStr = difflib.get_close_matches(unkownStr, _dsiPrefixesLatex.keys(), n=1) possibleDsiKeys = _dsiPrefixesLatex.keys() | _dsiUnitsLatex.keys() | _dsiKeyWords.keys()
if len(closestStr) == 0: closestStr = difflib.get_close_matches(unkownStr, possibleDsiKeys, n=3,cutoff=0.66)
closestStr = difflib.get_close_matches(unkownStr, _dsiUnitsLatex.keys(), n=1) return closestStr
if len(closestStr) == 0:
closestStr = difflib.get_close_matches(unkownStr, _dsiKeyWords.keys(), n=1)
if len(closestStr) == 0:
return (unkownStr, 'unknown')
else:
return (closestStr[0], 'keyWord')
else:
return (closestStr[0], 'unit')
else:
return (closestStr[0], 'prefix')
# mapping D-SI prefixes to latex # mapping D-SI prefixes to latex
_dsiPrefixesLatex = { _dsiPrefixesLatex = {
......
import pytest import pytest
from dsiParser import dsiParser, _node, _getClosestStrAndType from dsiParser import dsiParser, _node, _getClosestStr
p = dsiParser() p = dsiParser()
...@@ -20,30 +20,30 @@ def test_baseCase(): ...@@ -20,30 +20,30 @@ def test_baseCase():
def test_robustness(): def test_robustness():
# Unknown unit # Unknown unit
with pytest.warns(RuntimeWarning, match='The identifier \"foo\" does not match any D-SI units!'): with pytest.warns(RuntimeWarning, match='The identifier >foo< does not match any D-SI units!'):
tree = p.parse(r'\foo') tree = p.parse(r'\foo')
assert tree.toLatex() == r'$${\color{red}\mathrm{foo}}$$' assert tree.toLatex() == r'$${\color{red}\mathrm{foo}}$$'
assert not tree.valid assert not tree.valid
assert len(tree.warnings) == 1 assert len(tree.warnings) == 1
assert tree.warnings == ['The identifier \"foo\" does not match any D-SI units!'] assert tree.warnings == ['The identifier >foo< does not match any D-SI units!']
# Unknown string in the middle of input # Unknown string in the middle of input
with pytest.warns(RuntimeWarning, match='The identifier \"mini\" does not match any D-SI units!'): with pytest.warns(RuntimeWarning, match=r'The identifier >mini< does not match any D-SI units! Did you mean one of these >\\milli< ?'):
tree = p.parse(r'\kilo\metre\per\mini\second') tree = p.parse(r'\kilo\metre\per\mini\second')
print(tree.toLatex()) print(tree.toLatex())
assert tree.toLatex() == r'$$\frac{\mathrm{k}\mathrm{m}}{{\color{red}\mathrm{mini}}\,\mathrm{s}}$$' assert tree.toLatex() == r'$$\frac{\mathrm{k}\mathrm{m}}{{\color{red}\mathrm{mini}}\,\mathrm{s}}$$'
assert not tree.valid assert not tree.valid
assert len(tree.warnings) == 1 assert len(tree.warnings) == 1
assert tree.warnings == ['The identifier \"mini\" does not match any D-SI units!'] assert tree.warnings == ['The identifier >mini< does not match any D-SI units! Did you mean one of these >\\milli< ?']
# Base unit missing # Base unit missing
with pytest.warns(RuntimeWarning, match=r'This D-SI unit seems to be missing the base unit! \"\\milli\\tothe\{2\}\"'): with pytest.warns(RuntimeWarning, match=r'This D-SI unit seems to be missing the base unit! >\\milli\\tothe\{2\}<'):
tree = p.parse(r'\milli\tothe{2}') tree = p.parse(r'\milli\tothe{2}')
print(tree.toLatex()) print(tree.toLatex())
assert tree.toLatex() == r'$${\color{red}\mathrm{m}{\color{red}\mathrm{}}^{2}}$$' assert tree.toLatex() == r'$${\color{red}\mathrm{m}{\color{red}\mathrm{}}^{2}}$$'
assert not tree.valid assert not tree.valid
assert len(tree.warnings) == 1 assert len(tree.warnings) == 1
assert tree.warnings == ['This D-SI unit seems to be missing the base unit! \"\\milli\\tothe{2}\"'] assert tree.warnings == ['This D-SI unit seems to be missing the base unit! >\\milli\\tothe{2}<']
def test_power(): def test_power():
...@@ -58,10 +58,10 @@ def test_power(): ...@@ -58,10 +58,10 @@ def test_power():
assert p.parse(r'\metre\tothe{1337}').toLatex() == r'$$\mathrm{m}^{1337}$$' assert p.parse(r'\metre\tothe{1337}').toLatex() == r'$$\mathrm{m}^{1337}$$'
# Non-numerical power # Non-numerical power
with pytest.warns(RuntimeWarning, match='The exponent \"foo\" is not a number!'): with pytest.warns(RuntimeWarning, match='The exponent >foo< is not a number!'):
abcPowerTree = p.parse(r'\metre\tothe{foo}') abcPowerTree = p.parse(r'\metre\tothe{foo}')
assert abcPowerTree.toLatex() == r'$$\mathrm{m}^{{\color{red}\mathrm{foo}}}$$' assert abcPowerTree.toLatex() == r'$$\mathrm{m}^{{\color{red}\mathrm{foo}}}$$'
assert abcPowerTree.warnings == ['The exponent "foo" is not a number!'] assert abcPowerTree.warnings == ['The exponent >foo< is not a number!']
def test_prefix(): def test_prefix():
# D-SI prefix # D-SI prefix
...@@ -104,9 +104,9 @@ def test_wrappers(): ...@@ -104,9 +104,9 @@ def test_wrappers():
assert parserFull.parse(r'\metre').toLatex() == r'@\mathrm{Prefix}\mathrm{m}\mathrm{Suffix}@' assert parserFull.parse(r'\metre').toLatex() == r'@\mathrm{Prefix}\mathrm{m}\mathrm{Suffix}@'
def test_getClosestMatch(): def test_getClosestMatch():
closestMatch = _getClosestStrAndType('\kiilo') closestMatch = _getClosestStr('\kiilo')
assert closestMatch == ('kilo','prefix') assert closestMatch == (['kilo'])
closestMatch = _getClosestStrAndType('\mettre') closestMatch = _getClosestStr('\mettre')
assert closestMatch == ('metre','unit') assert closestMatch == (['metre'])
closestMatch = _getClosestStrAndType(r'\ttothe') closestMatch = _getClosestStr(r'\ttothe')
assert closestMatch == ('tothe', 'keyWord') assert closestMatch == (['tothe'])
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment