Here's an example that highlights a problem. If the deserialization and validation fails, smpclient makes a final effort to deserialize as an Error. In this case, that makes the trace misleading. I suppose that if the Error deserialization fails, it can then point out that both deserialization attempts have failed. But maybe pydantic has some better approach?
related:
│ │
│ ╭─────────────────────────────────────────────────────────────────────── locals ───────────────────────────────────────────────────────────────────────╮ │
│ │ data = { │ │
│ │ │ 'header': Header( │ │
│ │ │ │ op=<OP.READ_RSP: 1>, │ │
│ │ │ │ version=<Version.V2: 1>, │ │
│ │ │ │ flags=<Flag.UNUSED: 0>, │ │
│ │ │ │ length=38, │ │
│ │ │ │ group_id=10, │ │
│ │ │ │ sequence=1, │ │
│ │ │ │ command_id=3 │ │
│ │ │ ), │ │
│ │ │ 'groups': [{'group': 100, 'name': '', 'handlers': 40}], │ │
│ │ │ 'smp_data': bytearray(b'\t\x00\x00&\x00\n\x01\x03\xbffgroups\x9f\xbfegroup\x18ddname`hhandlers\x18(\xff\xff\xff') │ │
│ │ } │ │
│ │ self = EnumManagementErrorV2() │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
ValidationError: 2 validation errors for EnumManagementErrorV2
err
Field required [type=missing, input_value={'header': Header(op=<OP....lers\x18(\xff\xff\xff')}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.11/v/missing
groups
Extra inputs are not permitted [type=extra_forbidden, input_value=[{'group': 100, 'name': '', 'handlers': 40}], input_type=list]
For further information visit https://errors.pydantic.dev/2.11/v/extra_forbidden
Originally posted by @sgfeniex in #71 (comment)
Here's the code block causing this suppression and coercion:
|
try: |
|
return request._Response.loads(frame) # type: ignore |
|
except ValidationError: |
|
pass |
|
try: |
|
return request._ErrorV1.loads(frame) |
|
except ValidationError: |
|
pass |
|
try: |
|
return request._ErrorV2.loads(frame) |
|
except ValidationError: |
|
error_message = ( |
|
f"Response could not by parsed as one of {request._Response}, " |
|
f"{request._ErrorV1}, or {request._ErrorV2}. {header=} {frame=}" |
|
) |
|
logger.error(error_message) |
|
raise ValidationError(error_message) |
Here's an example that highlights a problem. If the deserialization and validation fails, smpclient makes a final effort to deserialize as an Error. In this case, that makes the trace misleading. I suppose that if the Error deserialization fails, it can then point out that both deserialization attempts have failed. But maybe pydantic has some better approach?
related:
Originally posted by @sgfeniex in #71 (comment)
Here's the code block causing this suppression and coercion:
smpclient/smpclient/__init__.py
Lines 180 to 196 in dcace1a