Embed __tname__ in models, support using it in model_validate (#918)
Gel supports inheritance much more than pydantic does, and so when we have a link to a parent type, we need to be able to determine which of its potential children type to create. We do this by adding a `tname__` field to every generated class, renamed to `__tname__` via the alias system, and update `__gel_validate__` (which currently just directly calls `model_validate`) to discriminate on it. The hard part here is handling the case where there are linkprops, which are represented by per-link subclasses of ProxyModel. To deal with this, we dynamically generate subclasses of the link class. This mechanism also allows us to return correct types from the client for links with link properties that point to subtypes, which we previously weren't. The other potential option was to use pydantic's discriminated unions, either by directly generating them in the source or dynamically mocking them up when creating models. Getting this to play nicely with everything we do seemed pretty nasty. (The linkprop situation in particular scares me more.) The big potential advantage of doing it that way, instead of having our own custom callbacks, is that it might allow us to not lose track of the parameters of validation (like strict mode and whether we are in JSON mode). But it turns out we were already losing track of that due to various ways we were interposing ourselves in validation, so maybe it's fine. We can maybe fix this with contextvars later. (Though the json situation is rough.) Fixes #755.
M
Michael J. Sullivan committed
089d6dc2fd3adedbc63b357b85d2b6e46b02bdd8
Parent: 4b52b71
Committed by GitHub <noreply@github.com>
on 9/23/2025, 3:59:50 PM