Skip to content

Commit 90dad07

Browse files
Pepa Hajekrjarry
authored andcommitted
data: add structured error in exception
Refactor LibyangError exception handling with structured details Signed-off-by: Pepa Hajek <hajekpepa@gmail.com>
1 parent d3dd5f0 commit 90dad07

File tree

3 files changed

+63
-13
lines changed

3 files changed

+63
-13
lines changed

libyang/context.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@
1616
validation_flags,
1717
)
1818
from .schema import Module, SNode, schema_in_format
19-
from .util import DataType, IOType, LibyangError, c2str, data_load, str2c
19+
from .util import (
20+
DataType,
21+
IOType,
22+
LibyangError,
23+
LibyangErrorItem,
24+
c2str,
25+
data_load,
26+
str2c,
27+
)
2028

2129

2230
# -------------------------------------------------------------------------------------
@@ -284,23 +292,35 @@ def __exit__(self, *args, **kwargs):
284292
self.destroy()
285293

286294
def error(self, msg: str, *args) -> LibyangError:
287-
msg %= args
295+
if args:
296+
msg = msg % args
297+
298+
parts = [msg]
299+
errors = []
288300

289301
if self.cdata:
290302
err = lib.ly_err_first(self.cdata)
291303
while err:
292-
if err.msg:
293-
msg += ": %s" % c2str(err.msg)
294-
if err.data_path:
295-
msg += ": Data path: %s" % c2str(err.data_path)
296-
if err.schema_path:
297-
msg += ": Schema path: %s" % c2str(err.schema_path)
298-
if err.line != 0:
299-
msg += " (line %u)" % err.line
304+
m = c2str(err.msg) if err.msg else None
305+
dp = c2str(err.data_path) if err.data_path else None
306+
sp = c2str(err.schema_path) if err.schema_path else None
307+
ln = int(err.line) if err.line else None
308+
parts.extend(
309+
tmpl.format(val)
310+
for val, tmpl in [
311+
(m, ": {}"),
312+
(dp, ": Data path: {}"),
313+
(sp, ": Schema path: {}"),
314+
(ln, " (line {})"),
315+
]
316+
if val is not None
317+
)
318+
errors.append(LibyangErrorItem(m, dp, sp, ln))
300319
err = err.next
301320
lib.ly_err_clean(self.cdata, ffi.NULL)
302321

303-
return LibyangError(msg)
322+
msg = "".join(parts)
323+
return LibyangError(msg, errors=errors)
304324

305325
def parse_module(
306326
self,

libyang/util.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,34 @@
22
# Copyright (c) 2021 RACOM s.r.o.
33
# SPDX-License-Identifier: MIT
44

5+
from dataclasses import dataclass
56
import enum
6-
from typing import Optional
7+
from typing import Iterable, Optional
78
import warnings
89

910
from _libyang import ffi, lib
1011

1112

13+
# -------------------------------------------------------------------------------------
14+
@dataclass(frozen=True)
15+
class LibyangErrorItem:
16+
msg: Optional[str]
17+
data_path: Optional[str]
18+
schema_path: Optional[str]
19+
line: Optional[int]
20+
21+
1222
# -------------------------------------------------------------------------------------
1323
class LibyangError(Exception):
14-
pass
24+
def __init__(
25+
self, message: str, *args, errors: Optional[Iterable[LibyangErrorItem]] = None
26+
):
27+
super().__init__(message, *args)
28+
self.message = message
29+
self.errors = tuple(errors or ())
30+
31+
def __str__(self):
32+
return self.message
1533

1634

1735
# -------------------------------------------------------------------------------------

tests/test_data.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,18 @@ def test_data_parse_config_xml_multi_error(self):
289289
"Data path: /yolo-system:conf/url[proto='https'] (line 7)",
290290
)
291291

292+
first = cm.exception.errors[0]
293+
self.assertEqual(first.msg, 'Invalid boolean value "abcd".')
294+
self.assertEqual(
295+
first.data_path, "/yolo-system:conf/url[proto='https']/enabled"
296+
)
297+
self.assertEqual(first.line, 6)
298+
299+
second = cm.exception.errors[1]
300+
self.assertEqual(second.msg, 'List instance is missing its key "host".')
301+
self.assertEqual(second.data_path, "/yolo-system:conf/url[proto='https']")
302+
self.assertEqual(second.line, 7)
303+
292304
XML_STATE = """<state xmlns="urn:yang:yolo:system">
293305
<hostname>foo</hostname>
294306
<url>

0 commit comments

Comments
 (0)