Coding 2024-03-30

Tags:
By Max Woerner Chase

I'm looking at the code in MOTR to try to get a sense of how it all fits together, and naturally this means I've got a niggling voice in my head going, "You know, you could remove a lot of this boilerplate by writing something like..."

def delegate(
    method: typing.Callable[typing.Concatenate[T1, P], T1]
) -> typing.Callable[typing.Concatenate[T2, P], T2]:
    wrapped_class: type[T1] = # Some horrible nonsense I don't want to go into.
    @functools.wraps(method)
    def wrapper(self: T2, /, *args: P.args, **kwargs: P.kwargs) -> T2:
        for name, attr in attrs.asdict(self, recurse=False).items():
            if isinstance(attr, wrapped_class):
                return attrs.evolve(
                    self, **{name: method(attr, *args, **kwargs)}
                )
        raise TypeError(f"Did not find a field of type {wrapped_class}")
    return wrapper

I'm pretty skeptical that mypy will, accept this nonsense.

...

I just got it to accept broadly equivalent dataclasses code.

Oh dear, this could work.

And the other boilerplate! I could write a class decorator to convert a smattering of metadata into a standardized method.

:)

No! Back away from the edge! Mypy still doesn't handle class decorators that change the type of the class. To get it to typecheck, you'd probably need to write metaclass or something.

Also, this idea is completely deranged.

Ultimately, while I could try to golf things down a little, it makes more sense to get things documented and try to improve the names. Annoyingly, this stuff is calling for some pretty intense precision in names, and I feel like the pre-existing concepts I'm trying to track tend to be referred to a bit more flexibly. I'll have to come back to this when I'm a bit better rested.

And I should get to work on getting rested.

Good night.