diff --git a/tests/test_yaml_parser.py b/tests/test_yaml_parser.py index 8866cd71..a0a6a9f2 100644 --- a/tests/test_yaml_parser.py +++ b/tests/test_yaml_parser.py @@ -91,3 +91,30 @@ def assert_tendencies_correct(tendencies): assert tendencies[6].duration == approx(2) assert tendencies[6].from_ == approx(8) assert tendencies[6].to == approx(0) + + +def test_scientific_notation(): + """Test if scientific notation is parsed correctly.""" + waveforms = { + "waveform:\n- {type: linear, to: 1.5e5}": 1.5e5, + "waveform:\n- {type: linear, to: 1.5e+5}": 1.5e5, + "waveform:\n- {type: linear, to: 1.5E+5}": 1.5e5, + "waveform:\n- {type: linear, to: 1.5e-5}": 1.5e-5, + "waveform:\n- {type: linear, to: 1.5E-5}": 1.5e-5, + "waveform:\n- {type: linear, to: 1e5}": 1e5, + "waveform:\n- {type: linear, to: 1e+5}": 1e5, + "waveform:\n- {type: linear, to: 1E+5}": 1e5, + "waveform:\n- {type: linear, to: 1e-5}": 1e-5, + "waveform:\n- {type: linear, to: 1E-5}": 1e-5, + "waveform:\n- {type: linear, to: 0e5}": 0.0, + "waveform:\n- {type: linear, to: 0E0}": 0.0, + "waveform:\n- {type: linear, to: -1.5e5}": -1.5e5, + "waveform:\n- {type: linear, to: -1E+5}": -1e5, + "waveform:\n- {type: linear, to: -1.5e-5}": -1.5e-5, + } + + yaml_parser = YamlParser() + + for waveform, expected_value in waveforms.items(): + yaml_parser.parse_waveforms(waveform) + assert yaml_parser.waveform.tendencies[0].to == expected_value diff --git a/waveform_editor/yaml_parser.py b/waveform_editor/yaml_parser.py index b6a798c8..41f8771b 100644 --- a/waveform_editor/yaml_parser.py +++ b/waveform_editor/yaml_parser.py @@ -1,3 +1,5 @@ +import re + import holoviews as hv import yaml @@ -48,7 +50,24 @@ def parse_waveforms(self, yaml_str): """ self.has_yaml_error = False try: - waveform_yaml = yaml.load(yaml_str, Loader=LineNumberYamlLoader) + loader = LineNumberYamlLoader + # Parse scientific notation as a float, instead of a string. For + # more information see: https://stackoverflow.com/a/30462009/8196245 + loader.add_implicit_resolver( + "tag:yaml.org,2002:float", + re.compile( + """^(?: + [-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+]?[0-9]+)? + |[-+]?(?:[0-9][0-9_]*)(?:[eE][-+]?[0-9]+) + |\\.[0-9_]+(?:[eE][-+][0-9]+)? + |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]* + |[-+]?\\.(?:inf|Inf|INF) + |\\.(?:nan|NaN|NAN))$""", + re.X, + ), + list("-+0123456789."), + ) + waveform_yaml = yaml.load(yaml_str, Loader=loader) if not isinstance(waveform_yaml, dict): raise yaml.YAMLError(