Coding 2023-05-03
I don't feel like touching MOTR directly right now, so let's take a look at how Mypy supports attrs.evolve.
It expects two args (inst and **changes?). Then it mostly focuses on args[0][0]. Is Mypy's usage of nested lists documented anywhere? I don't remember understanding it with the last plugin I wrote, just figuring out what made the test cases pass.
Anyway, it gets the type of inst, and operates on that. There's a helper function I'm going to have to get access to, which determines the types of the fields. Once the fields are gotten, it does a bunch of stuff that's pretty straightforward for evolve, and will be less so for saltate.
Let's see what's different.
- saltate has two required positional arguments, typ and inst.
- It needs to determine the type of typ. That is, given "this expression is of type type[T]", it needs to get the representation of T.
- It needs to confirm that the base types of T and inst are the same; this should not fail if they aren't generic, because I'm pretty sure there's some way to make that case matter, even if it's not occurring to me just yet.
- It needs to go through the overall flow for both types, eventually generating two different lists of fields.
- The one from typ should be used, but it needs to be compared against the inst list, to determine which fields should be required instead of optional. Maybe this can be done with simple equality, or maybe I need to try to unify the types.
In any case, let's work through this in order.
- Probably look at ctx.args[0][0] and ctx.args[1][0], after checking that len(ctx.args) == 3, len(ctx.args[0]) == 1 and len(ctx.args[1]) == 1.
- typ should be a TypeType? The type we want is the item field?
- If both types are Instance, then compare by the type field, otherwise compare normally? If the comparison fails, do no further processing, otherwise proceed.
That gets us to fields, and the check we need to make is whether a given inst field is a subtype of the corresponding typ field. Ah, that's what mypy.subtypes.is_subtype is for.
I think that's all the information I need to write the hook for saltate. I'm going to hold off on writing it, because I still want to figure out stuff like where to put it. Judging by how I positioned other general-purpose stuff, it looks like it should go in a module right under the motr package. (At least, until and if it gets its own package.)
Let's see if I'm up for working on this properly tomorrow.
Good night.