Skip to content

Commit a0863f7

Browse files
adamnschFlorentinD
andcommitted
Improve from_dfs error messages
Co-Authored-By: Florentin Dörre <florentin.dorre@neotechnology.com>
1 parent 7562fba commit a0863f7

2 files changed

Lines changed: 80 additions & 2 deletions

File tree

python-wrapper/src/neo4j_viz/pandas.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import Optional, Union
55

66
from pandas import DataFrame
7+
from pydantic import BaseModel, ValidationError
78

89
from .node import Node
910
from .relationship import Relationship
@@ -12,6 +13,17 @@
1213
DFS_TYPE = Union[DataFrame, Iterable[DataFrame]]
1314

1415

16+
def _parse_validation_error(e: ValidationError, entity_type: type[BaseModel]) -> None:
17+
for err in e.errors():
18+
loc = err["loc"][0]
19+
if err["type"] == "missing":
20+
raise ValueError(
21+
f"Mandatory column '{loc}' is missing. Expected one of {entity_type.model_fields[loc].validation_alias.choices} to be present" # type: ignore
22+
)
23+
else:
24+
raise ValueError(f"Error for column '{loc}' with provided input '{err['input']}'. Reason: {err['msg']}")
25+
26+
1527
def _from_dfs(
1628
node_dfs: DFS_TYPE,
1729
rel_dfs: DFS_TYPE,
@@ -41,7 +53,10 @@ def _from_dfs(
4153
key = rename_properties[key]
4254
properties[key] = value
4355

44-
nodes.append(Node(**top_level, properties=properties))
56+
try:
57+
nodes.append(Node(**top_level, properties=properties))
58+
except ValidationError as e:
59+
_parse_validation_error(e, Node)
4560

4661
if isinstance(rel_dfs, DataFrame):
4762
rel_dfs_iter: Iterable[DataFrame] = [rel_dfs]
@@ -61,7 +76,10 @@ def _from_dfs(
6176
key = rename_properties[key]
6277
properties[key] = value
6378

64-
relationships.append(Relationship(**top_level, properties=properties))
79+
try:
80+
relationships.append(Relationship(**top_level, properties=properties))
81+
except ValidationError as e:
82+
_parse_validation_error(e, Relationship)
6583

6684
VG = VisualizationGraph(nodes=nodes, relationships=relationships)
6785

python-wrapper/tests/test_pandas.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import pytest
12
from pandas import DataFrame
23
from pydantic_extra_types.color import Color
34

@@ -104,3 +105,62 @@ def test_from_dfs() -> None:
104105
assert VG.relationships[1].source == 1
105106
assert VG.relationships[1].target == 0
106107
assert VG.relationships[1].caption == "REL2"
108+
109+
110+
def test_node_errors() -> None:
111+
nodes = DataFrame(
112+
{"caption": ["A", "B"], "size": [1337, 42], "color": "#FF0000", "instrument": ["piano", "guitar"]}
113+
)
114+
with pytest.raises(
115+
ValueError,
116+
match=r"Mandatory column 'id' is missing. Expected one of \['id', 'ID', 'id', 'nodeid', 'NODEID', 'nodeid', 'node_id', 'NODE_ID', 'nodeId'\] to be present",
117+
):
118+
from_dfs(nodes, [])
119+
120+
nodes = DataFrame(
121+
{
122+
"id": [0, 1],
123+
"caption": ["A", "B"],
124+
"size": ["aaa", 42],
125+
"color": "#FF0000",
126+
"instrument": ["piano", "guitar"],
127+
}
128+
)
129+
with pytest.raises(
130+
ValueError,
131+
match=r"Error for column 'size' with provided input 'aaa'. Reason: Input should be a valid integer, unable to parse string as an integer",
132+
):
133+
from_dfs(nodes, [])
134+
135+
136+
def test_rel_errors() -> None:
137+
nodes = DataFrame(
138+
{"id": [0, 1], "caption": ["A", "B"], "size": [1337, 42], "color": "#FF0000", "instrument": ["piano", "guitar"]}
139+
)
140+
relationships = DataFrame(
141+
{
142+
"target": [1, 0],
143+
"caption": ["REL", "REL2"],
144+
"weight": [1.0, 2.0],
145+
}
146+
)
147+
with pytest.raises(
148+
ValueError,
149+
match=r"Mandatory column 'source' is missing. Expected one of \['source', 'SOURCE', 'source', 'sourcenodeid', 'SOURCENODEID', 'sourcenodeid', 'source_node_id', 'SOURCE_NODE_ID', 'sourceNodeId', 'from', 'FROM', 'from'\] to be present",
150+
):
151+
from_dfs(nodes, relationships)
152+
153+
relationships = DataFrame(
154+
{
155+
"source": [0, 1],
156+
"target": [1, 0],
157+
"caption": ["REL", "REL2"],
158+
"caption_size": [1.0, -300],
159+
"weight": [1.0, 2.0],
160+
}
161+
)
162+
with pytest.raises(
163+
ValueError,
164+
match=r"Error for column 'caption_size' with provided input '-300.0'. Reason: Input should be greater than 0",
165+
):
166+
from_dfs(nodes, relationships)

0 commit comments

Comments
 (0)