Enhance BaseDevice initialization and error handling

- Updated the `BaseDevice` class constructor to accept an optional `name` parameter for better context in error messages.
- Improved the `_validate_contract` method to raise an `OxiAPIError` with a descriptive message if the node is not found.
- Modified the `_run_ttp` method to include a check for node existence, returning `None` if not found.
- Changed the test file name in the `Eltex` model to reflect a more descriptive context for testing node not found scenarios.
This commit is contained in:
IluaAir
2026-04-18 19:21:25 +03:00
parent 9fd0ce1516
commit 5fa56d46af
3 changed files with 19 additions and 3 deletions

View File

@@ -60,7 +60,7 @@ class NodeConfig:
self._device: type[BaseDevice] = device_registry.get(self._model.lower()) self._device: type[BaseDevice] = device_registry.get(self._model.lower())
if self._device is None: if self._device is None:
raise ValueError(f"Device model '{self._model}' not found in registry") raise ValueError(f"Device model '{self._model}' not found in registry")
self._parsed_data = self._device(self.text).parse() self._parsed_data = self._device(self.text, name=self._full_name).parse()
@cached_property @cached_property
def _response(self): def _response(self):

View File

@@ -1,6 +1,7 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from pathlib import Path from pathlib import Path
from ttp import ttp from ttp import ttp
from oxi.exception import OxiAPIError
from oxi.interfaces.contract import Device from oxi.interfaces.contract import Device
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from oxi.interfaces.contract import Interfaces, System, Vlans from oxi.interfaces.contract import Interfaces, System, Vlans
@@ -10,8 +11,9 @@ class BaseDevice(ABC):
_REQUIRED_SECTIONS: frozenset[str] = frozenset({"system", "interfaces"}) _REQUIRED_SECTIONS: frozenset[str] = frozenset({"system", "interfaces"})
_OPTIONAL_SECTIONS: frozenset[str] = frozenset({"vlans"}) _OPTIONAL_SECTIONS: frozenset[str] = frozenset({"vlans"})
def __init__(self, config: str): def __init__(self, config: str, name: str | None = None):
self.config: str = config self.config: str = config
self.name = name
self._loaded_template = self._load_template() self._loaded_template = self._load_template()
self._declared_sections = None self._declared_sections = None
@@ -69,6 +71,13 @@ class BaseDevice(ABC):
return self.raw.get("system", None) return self.raw.get("system", None)
def _validate_contract(self) -> dict: def _validate_contract(self) -> dict:
if self.raw is None:
msg = (
f"Node {self.name} not found"
if self.name
else "Node not found"
)
raise OxiAPIError(msg, status_code=404)
system_data = self.system() system_data = self.system()
interfaces_data = self.interfaces() or [] interfaces_data = self.interfaces() or []
result = { result = {
@@ -114,6 +123,13 @@ class BaseDevice(ABC):
def _run_ttp(self) -> dict: def _run_ttp(self) -> dict:
"""Основной парсер""" """Основной парсер"""
pattern = """node not {{found}}"""
parser = ttp(data=self.config, template=pattern)
parser.parse()
res = parser.result()
if res[0][0]:
# raise OxiAPIError(f"Node {self.name} not found", status_code=404)
return None
p = ttp(data=self.config, template=self._loaded_template) p = ttp(data=self.config, template=self._loaded_template)
p.parse() p.parse()
raw: dict = p.result()[0][0] raw: dict = p.result()[0][0]

View File

@@ -37,7 +37,7 @@ class Eltex(BaseDevice):
if __name__ == "__main__": if __name__ == "__main__":
with open("./test6.txt") as file: with open("./test_not_found.txt") as file:
data = file.read() data = file.read()
eltex = Eltex(data) eltex = Eltex(data)
print(eltex.parse()) print(eltex.parse())