work around issue with discriminated typed unions (#939)

We're experiencing a bug where Unions of sub-models are getting downcast, which causes a loss of information.  

As an example, EventScalesetCreated was getting downcast to EventScalesetDeleted.  I have not figured out why, nor can I replicate it locally to minimize the bug send upstream, but I was able to reliably replicate it on the service.

While working through this issue, I noticed that deserialization of SignalR events was frequently wrong, leaving things like tasks as "init" in `status top`.

Both of these issues are Unions of models with a type field, so it's likely these are related.
This commit is contained in:
bmc-msft
2021-06-02 12:40:58 -04:00
committed by GitHub
parent 3d191c3c5d
commit a92c84d42a
7 changed files with 81 additions and 39 deletions

View File

@ -5,7 +5,7 @@
from datetime import datetime
from enum import Enum
from typing import List, Optional, Union
from typing import Any, Dict, List, Optional, Union
from uuid import UUID, uuid4
from pydantic import BaseModel, Field
@ -91,7 +91,7 @@ class EventTaskHeartbeat(BaseEvent):
config: TaskConfig
class EventPing(BaseResponse):
class EventPing(BaseEvent, BaseResponse):
ping_id: UUID
@ -300,3 +300,22 @@ class EventMessage(BaseEvent):
event: Event
instance_id: UUID
instance_name: str
# because Pydantic does not yet have discriminated union types yet, parse events
# by hand. https://github.com/samuelcolvin/pydantic/issues/619
def parse_event_message(data: Dict[str, Any]) -> EventMessage:
instance_id = UUID(data["instance_id"])
instance_name = data["instance_name"]
event_id = UUID(data["event_id"])
event_type = EventType[data["event_type"]]
# mypy incorrectly identifies this as having not supported parse_obj yet
event = EventTypeMap[event_type].parse_obj(data["event"]) # type: ignore
return EventMessage(
event_id=event_id,
event_type=event_type,
event=event,
instance_id=instance_id,
instance_name=instance_name,
)

View File

@ -1 +1 @@
pydantic~=1.8.1 --no-binary=pydantic
pydantic==1.8.2 --no-binary=pydantic