|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
3 | | -from pydantic import ConfigDict |
4 | | -from pydantic_xml import BaseXmlModel, attr, element, wrapped |
5 | | - |
6 | | -from .const import XML_NS |
| 3 | +from pydantic import BaseModel, ConfigDict, Field |
| 4 | +from xmltodict import parse as xml_parse |
7 | 5 |
|
8 | 6 | # Example Filter Diagnostics XML: |
9 | 7 | # |
|
32 | 30 | # </Response> |
33 | 31 |
|
34 | 32 |
|
35 | | -class FilterDiagnosticsParameter(BaseXmlModel, tag="Parameter", ns="api", nsmap=XML_NS): |
36 | | - """Individual diagnostic parameter with name, type, and value.""" |
37 | | - |
| 33 | +class FilterDiagnosticsParameter(BaseModel): |
38 | 34 | model_config = ConfigDict(from_attributes=True) |
39 | 35 |
|
40 | | - name: str = attr() |
41 | | - data_type: str = attr(name="dataType") |
42 | | - value: int |
43 | | - |
| 36 | + name: str = Field(alias="@name") |
| 37 | + dataType: str = Field(alias="@dataType") |
| 38 | + value: int = Field(alias="#text") |
44 | 39 |
|
45 | | -class FilterDiagnostics(BaseXmlModel, tag="Response", ns="api", nsmap=XML_NS): |
46 | | - """Filter diagnostics response containing diagnostic parameters. |
47 | | -
|
48 | | - The XML structure has a Parameters wrapper element containing Parameter children: |
49 | | - <Response> |
50 | | - <Name>FilterDiagnostics</Name> |
51 | | - <Parameters> |
52 | | - <Parameter name="..." dataType="...">value</Parameter> |
53 | | - ... |
54 | | - </Parameters> |
55 | | - </Response> |
56 | | - """ |
57 | 40 |
|
| 41 | +class FilterDiagnosticsParameters(BaseModel): |
58 | 42 | model_config = ConfigDict(from_attributes=True) |
59 | 43 |
|
60 | | - name: str = element(tag="Name") |
61 | | - parameters: list[FilterDiagnosticsParameter] = wrapped("Parameters", element(tag="Parameter", default_factory=list)) |
| 44 | + parameter: list[FilterDiagnosticsParameter] = Field(alias="Parameter") |
62 | 45 |
|
63 | | - def get_param_by_name(self, name: str) -> int: |
64 | | - """Get parameter value by name. |
65 | 46 |
|
66 | | - Args: |
67 | | - name: Name of the parameter to retrieve |
| 47 | +class FilterDiagnostics(BaseModel): |
| 48 | + model_config = ConfigDict(from_attributes=True) |
68 | 49 |
|
69 | | - Returns: |
70 | | - The integer value of the parameter |
| 50 | + name: str = Field(alias="Name") |
| 51 | + # parameters: FilterDiagnosticsParameters = Field(alias="Parameters") |
| 52 | + parameters: list[FilterDiagnosticsParameter] = Field(alias="Parameters") |
71 | 53 |
|
72 | | - Raises: |
73 | | - IndexError: If parameter name not found |
74 | | - """ |
| 54 | + def get_param_by_name(self, name: str) -> int: |
75 | 55 | return [param.value for param in self.parameters if param.name == name][0] |
76 | 56 |
|
77 | 57 | @staticmethod |
78 | 58 | def load_xml(xml: str) -> FilterDiagnostics: |
79 | | - """Load filter diagnostics from XML string. |
80 | | -
|
81 | | - Args: |
82 | | - xml: XML string containing filter diagnostics data |
83 | | -
|
84 | | - Returns: |
85 | | - Parsed FilterDiagnostics instance |
86 | | - """ |
87 | | - return FilterDiagnostics.from_xml(xml) |
| 59 | + data = xml_parse( |
| 60 | + xml, |
| 61 | + # Some things will be lists or not depending on if a pool has more than one of that piece of equipment. Here we are coercing |
| 62 | + # everything that *could* be a list into a list to make the parsing more consistent. |
| 63 | + force_list=("Parameter"), |
| 64 | + ) |
| 65 | + # The XML nests the Parameter entries under a Parameters entry, this is annoying to work with. Here we are adjusting the data to |
| 66 | + # remove that extra level in the data |
| 67 | + data["Response"]["Parameters"] = data["Response"]["Parameters"]["Parameter"] |
| 68 | + return FilterDiagnostics.model_validate(data["Response"]) |
0 commit comments