Coding 2023-04-26

Tags:
By Max Woerner Chase

Okay, here we go... I've got a bit to catch up on.

Let's get right into it.

Code:

def saltate(typ: type[T], inst: Any, **changes: Any) -> T:
    return attrs.evolve(inst, **changes)

Plugin: ... like the new attrs plugin code, but unfortunately, more complicated. Basically, it needs to do all of the legwork of the builtin plugin, but also check that the underlying types of typ and inst "match", but need not unify, derive all arguments from typ, and mark any that are a different type from the attributes on inst as mandatory.

The basic concept here is that, because what I want is a kind of "discontinuous evolution", it's "saltation", and it needs to provide a specific target, as if it's a cast. This addresses some of the problems uncovered in the feature request discussion, and also hopefully makes it obvious that, hey, if you don't need to specify a type, probably just use evolve.

Unfortunately, it is too late at night for me to puzzle out plugin code right now, so I'm going to go over what else I did today.

However, the more I think about it, the more I think "No, there has to be a way to make Mypy make sense here." So I guess I'm going to be bouncing off of that for a bit.

...

Okay, that's weird. I managed to get rid of one instance of the error by just annotating stuff until Mypy admitted there wasn't actually a problem, but it's not working a second time.

Okay, that's... not the greatest solution, but I can't find fault with it from a simple inspection perspective.

facts: _requirements.Requirements[_cmd.EnvVar[_cmd.CmdArg]]
facts = value.map_facts(map_func)
facts = typing.cast(
    "_requirements.Requirements[_cmd.EnvVar[_cmd.CmdArg]]", facts
)

"What does the cast accomplish?"

It makes type-checking pass.

Anyway, now I've got a clean basis for working on saltate, but before that, I should probably try to extend the code some. It's possible I've forgotten some more improvements that I want to make. But for now, it's late.

Good night.