Skip to content

Commit 7a6ff7f

Browse files
committed
create annotations class for handling annotations
1 parent ecb3770 commit 7a6ff7f

File tree

6 files changed

+80
-57
lines changed

6 files changed

+80
-57
lines changed

waveform_editor/annotations.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import difflib
2+
3+
4+
class Annotations:
5+
def __init__(self):
6+
self.annotations = []
7+
8+
def get(self):
9+
return self.annotations
10+
11+
def add_annotations(self, annotations):
12+
return self.annotations.extend(annotations.get())
13+
14+
def add(self, line_number, error_msg, is_warning=False):
15+
"""Adds the error message to the list of annotations.
16+
17+
Args:
18+
annotations: The list of annotations the error message is added to.
19+
line_number: The line number at which the error occurs.
20+
error_msg: The error message the annotation should display.
21+
error_type: Whether the annotation is a warning. If set to False, it is
22+
treated as an error.
23+
"""
24+
error_type = "warning" if is_warning else "error"
25+
self.annotations.extend(
26+
[
27+
{
28+
"row": line_number,
29+
"column": 0,
30+
"text": error_msg,
31+
"type": error_type,
32+
}
33+
]
34+
)
35+
36+
def add_yaml_error(self, error):
37+
if hasattr(error, "problem_mark"):
38+
line = error.problem_mark.line
39+
# TODO: Is there a way to visualize the column into the annotation?
40+
# column = error.problem_mark.column
41+
message = error.problem
42+
43+
self.add(line, message)
44+
else:
45+
self.add(0, f"Unknown YAML error: {error}")
46+
47+
def create_suggestion(self, match, list):
48+
suggestion = ""
49+
close_matches = difflib.get_close_matches(match, list, n=1)
50+
if close_matches:
51+
suggestion = f"Did you mean {close_matches[0]!r}?"
52+
53+
return suggestion
54+
55+
def clear(self):
56+
self.annotations.clear()

waveform_editor/tendencies/base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import param
66
from param import depends
77

8+
from waveform_editor.annotations import Annotations
89
from waveform_editor.tendencies.util import (
910
InconsistentInputsError,
10-
add_annotation,
1111
solve_with_constraints,
1212
)
1313

@@ -81,7 +81,7 @@ class BaseTendency(param.Parameterized):
8181
)
8282

8383
def __init__(self, **kwargs):
84-
self.annotations = []
84+
self.annotations = Annotations()
8585
self._check_for_unknown_kwargs(kwargs)
8686
super().__init__(**kwargs)
8787

@@ -222,4 +222,4 @@ def _check_for_unknown_kwargs(self, kwargs):
222222
" they will be ignored.",
223223
)
224224

225-
add_annotation(self.annotations, line_number, error_msg, is_warning=True)
225+
self.annotations.add(line_number, error_msg, is_warning=True)

waveform_editor/tendencies/util.py

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,3 @@ def solve_with_constraints(inputs, constraint_matrix):
3333
raise InconsistentInputsError()
3434

3535
return tuple(inputs)
36-
37-
38-
def add_annotation(annotations, line_number, error_msg, is_warning=False):
39-
"""Adds the error message to the list of annotations.
40-
41-
Args:
42-
annotations: The list of annotations the error message is added to.
43-
line_number: The line number at which the error occurs.
44-
error_msg: The error message the annotation should display.
45-
error_type: Whether the annotation is a warning. If set to False, it is treated
46-
as an error.
47-
"""
48-
error_type = "warning" if is_warning else "error"
49-
annotations.extend(
50-
[
51-
{
52-
"row": line_number,
53-
"column": 0,
54-
"text": error_msg,
55-
"type": error_type,
56-
}
57-
]
58-
)

waveform_editor/waveform.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import numpy as np
55

6+
from waveform_editor.annotations import Annotations
67
from waveform_editor.tendencies.constant import ConstantTendency
78
from waveform_editor.tendencies.linear import LinearTendency
89
from waveform_editor.tendencies.periodic.sawtooth_wave import SawtoothWaveTendency
@@ -12,7 +13,6 @@
1213
from waveform_editor.tendencies.piecewise import PiecewiseLinearTendency
1314
from waveform_editor.tendencies.repeat import RepeatTendency
1415
from waveform_editor.tendencies.smooth import SmoothTendency
15-
from waveform_editor.tendencies.util import add_annotation
1616

1717
tendency_map = {
1818
"linear": LinearTendency,
@@ -34,7 +34,7 @@
3434
class Waveform:
3535
def __init__(self, waveform):
3636
self.tendencies = []
37-
self.annotations = []
37+
self.annotations = Annotations()
3838
self._process_waveform(waveform)
3939

4040
def get_value(
@@ -114,8 +114,8 @@ def _process_waveform(self, waveform):
114114
self.tendencies[i].set_previous_tendency(self.tendencies[i - 1])
115115

116116
for tendency in self.tendencies:
117-
if tendency.annotations != []:
118-
self.annotations.extend(tendency.annotations)
117+
if tendency.annotations.get() != []:
118+
self.annotations.add_annotations(tendency.annotations)
119119

120120
def _handle_tendency(self, entry):
121121
"""Creates a tendency instance based on the entry in the YAML file.
@@ -137,9 +137,17 @@ def _handle_tendency(self, entry):
137137
return tendency
138138
else:
139139
line_number = entry.pop("line_number")
140+
141+
suggestions = ""
142+
close_matches = difflib.get_close_matches(
143+
tendency_type, tendency_map.keys(), n=1
144+
)
145+
if close_matches:
146+
suggestions = f"Did you mean {close_matches[0]!r}?"
147+
140148
error_msg = (
141-
f"Unsupported tendency type: {tendency_type}. "
149+
f"Unsupported tendency type: {tendency_type}, {suggestions} \n"
142150
"This tendency will be ignored.",
143151
)
144-
add_annotation(self.annotations, line_number, error_msg, is_warning=True)
152+
self.annotations.add(line_number, error_msg, is_warning=True)
145153
return None

waveform_editor/waveform_editor_gui.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
yaml_parser = YamlParser()
2828

2929
alert_pane = pn.pane.Alert(
30-
"### The YAML did not parse correctly (see editor)!",
30+
"### The YAML did not parse correctly! (see editor)",
3131
alert_type="danger",
3232
visible=False,
3333
)
@@ -36,7 +36,7 @@
3636
def update_plot(value):
3737
yaml_parser.parse_waveforms_from_string(value)
3838

39-
code_editor.annotations = yaml_parser.annotations
39+
code_editor.annotations = yaml_parser.annotations.get()
4040
code_editor.param.trigger("annotations")
4141

4242
if yaml_parser.waveform is None:

waveform_editor/yaml_parser.py

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import param
33
import yaml
44

5-
from waveform_editor.tendencies.util import add_annotation
5+
from waveform_editor.annotations import Annotations
66
from waveform_editor.waveform import Waveform
77

88

@@ -15,12 +15,9 @@ def construct_mapping(self, node, deep=False):
1515

1616

1717
class YamlParser(param.Parameterized):
18-
waveform = param.ClassSelector(
19-
class_=Waveform,
20-
default=None,
21-
doc="Waveform that contains the tendencies.",
22-
)
23-
annotations = param.List(doc="List of error messages")
18+
def __init__(self):
19+
# self.waveform = None
20+
self.annotations = Annotations()
2421

2522
def parse_waveforms_from_file(self, file_path):
2623
"""Loads a YAML file from a file path and stores its tendencies into a list.
@@ -46,24 +43,9 @@ def parse_waveforms_from_string(self, yaml_str):
4643
self.waveform = Waveform(waveform)
4744
self.annotations = self.waveform.annotations
4845
except yaml.YAMLError as e:
49-
self.annotations = self.yaml_error_to_annotation(e)
46+
self.annotations.add_yaml_error(e)
5047
self.waveform = None
5148

52-
def yaml_error_to_annotation(self, error):
53-
annotations = []
54-
55-
if hasattr(error, "problem_mark"):
56-
line = error.problem_mark.line
57-
# TODO: Is there a way to visualize the column into the annotation?
58-
# column = error.problem_mark.column
59-
message = error.problem
60-
61-
add_annotation(annotations, line, message)
62-
else:
63-
add_annotation(0, 0, f"Unknown YAML error: {error}")
64-
65-
return annotations
66-
6749
def plot_empty(self):
6850
overlay = hv.Overlay()
6951

0 commit comments

Comments
 (0)