Replies: 6 comments
-
@saskiad We can rename the field or refactor the structure of the Device class and the subclasses. The main issue is that when a user converts the pydantic model into json, the information about the class it comes from vanishes. This is a problem when a user is allowed to select from a list of classes (usually wrapped inside as a |
Beta Was this translation helpful? Give feedback.
-
No, I understand that. That's not my question. There's a comment saying "# Needs to be set by child classes that inherits" but Device isn't always used via a subclass. I want to make sure that when Device is used by itself that a device_type can still be provided. I assume it can, but the comment and the fact that this line doesn't have Field(..., etc etc) makes me unsure. |
Beta Was this translation helpful? Give feedback.
-
We can change it to
The drawback is that people will have to remember to modify it in the child classes. We can add some extra logic to automatically create the field using the class name, but we can hard-code it for now. |
Beta Was this translation helpful? Give feedback.
-
I don't think we want that. Largely because I want people to say what kind of device it is when they use it in additional device. `class Device(AindModel):
` |
Beta Was this translation helpful? Give feedback.
-
If in a different model, we want a user to be select from the generic device or a specific device, such as
Then
|
Beta Was this translation helpful? Give feedback.
-
I think you are missing my question. We can discuss when I get back
…On Fri, Oct 20, 2023 at 1:03 AM jtyoung84 ***@***.***> wrote:
If in a different model, we want a user to be select from the generic
device or a specific device, such as
device: List[Union[Device, DeviceA, DeviceB]] = Field(...)
Then Device, DeviceA, and DeviceB all need to have a common field that's
a fixed constant for each of those classes. We can call it something other
than device type, and there might be some redundancy, but that's the only
way how to distinguish between the classes when they get stored as json
files. I'll post a small example showing what it could look like:
class Device(BaseModel):
# We can call this whatever we want
discriminator_field: Literal["device"] = Field("device", const=True, readOnly=True)
device_type: str = Field(..., title="Device Type")
name: str = Field(..., title="Device Name")
price: Optional[float] = Field(None, title="Price")
class DeviceA(Device):
discriminator_field: Literal["device_a"] = Field("device_a", const=True, readOnly=True)
device_type: str = Field("DeviceA", title="Device Type")
class DeviceB(Device):
discriminator_field: Literal["device_b"] = Field("device_a", const=True, readOnly=True)
device_type: str = Field("DeviceA", title="Device Type")
price: float = Field(100.0, title="Price")
class MyDevices(BaseModel):
devices: List[Annotated[Union[Device, DeviceA, DeviceB], Field(discriminator="discriminator_field")]]
MyDevice.schema_json()
{
"title": "MyDevices",
"type": "object",
"properties": {
"devices": {
"title": "Devices", "type": "array", "items": {"discriminator": {"propertyName": "discriminator_field", "mapping": {"device": "#/definitions/Device", "device_a": "#/definitions/DeviceA", "device_b": "#/definitions/DeviceB"}},
"oneOf": [{"$ref": "#/definitions/Device"}, {"$ref": "#/definitions/DeviceA"}, {"$ref": "#/definitions/DeviceB"}]}}
},
"required": ["devices"],
"definitions": {
"Device": {"title": "Device", "type": "object", "properties": {"discriminator_field": {"title": "Discriminator Field", "default": "device", "const": "device", "readOnly": true, "enum": ["device"], "type": "string"}, "device_type": {"title": "Device Type", "type": "string"}, "name": {"title": "Device Name", "type": "string"}, "price": {"title": "Price", "type": "number"}}, "required": ["device_type", "name"]},
"DeviceA": {"title": "DeviceA", "type": "object", "properties": {"discriminator_field": {"title": "Discriminator Field", "default": "device_a", "const": "device_a", "readOnly": true, "enum": ["device_a"], "type": "string"}, "device_type": {"title": "Device Type", "default": "DeviceA", "type": "string"}, "name": {"title": "Device Name", "type": "string"}, "price": {"title": "Price", "type": "number"}}, "required": ["name"]},
"DeviceB": {"title": "DeviceB", "type": "object", "properties": {"discriminator_field": {"title": "Discriminator Field", "default": "device_a", "const": "device_a", "readOnly": true, "enum": ["device_b"], "type": "string"}, "device_type": {"title": "Device Type", "default": "DeviceA", "type": "string"}, "name": {"title": "Device Name", "type": "string"}, "price": {"title": "Price", "default": 100.0, "type": "number"}}, "required": ["name"]}
}
}
# Since there's no restriction on device_type in the generic Device model, we can potentially call it DeviceA or DeviceB if someone wanted.
my_devices = MyDevices(devices=[Device(device_type="DeviceA", name="my device c"), DeviceA(name="my device a", price=50.0)])
my_devices.json()
{"devices": [{"discriminator_field": "device", "device_type": "DeviceA", "name": "my device c", "price": null}, {"discriminator_field": "device_a", "device_type": "DeviceA", "name": "my device a", "price": 50.0}]}
# Since we have a discriminator field though, we can get the original class back from the raw json
MyDevices.parse_raw(my_devices.json())
MyDevices(devices=[Device(discriminator_field='device', device_type='DeviceA', name='my device c', price=None), DeviceA(discriminator_field='device_a', device_type='DeviceA', name='my device a', price=50.0)])
—
Reply to this email directly, view it on GitHub
<#543 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA5N4JXKPDEDCTNIORIVRJLYAFMOPAVCNFSM6AAAAAA6FKZTLKVHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM3TGMZQGY3DE>
.
You are receiving this because you were mentioned.Message ID:
<AllenNeuralDynamics/aind-data-schema/repo-discussions/543/comments/7330662
@github.com>
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
In the rig class, we use additional device to list Device objects where the basic model is sufficient. I assume users can define the device type when they implement this? The structure of the device_type line in the Device class is different from normal so I want to be sure. @dyf @jtyoung84
Beta Was this translation helpful? Give feedback.
All reactions