I was thinking about my proposed changes to punq earlier today, and suddenly realized that, in thinking about this, I'd somehow managed to be everyone in this xkcd comic, several times. I was trying to design an over-complicated workaround for the fact that my desired usage of punq was sort of adjacent to the bug I found.
So, today, I decided to do two quick things, since I've been really tired recently. One was, I slightly rewrote the test I wrote against punq, so that it was a little more consistent with punq's other tests. The other was, I replaced the "horrifying" part of my workflow with something that makes enough sense at runtime, I think, and sort of makes sense from a static analysis perspective. Basically, instead of aliases, I'm differentiating types with NewTypes. From a typing perspective, this is technically backward, because I'm using the NewType as some kind of phantom superclass. If this really bothers me, I can define an adaptor function something like
# I didn't test this. def constructor(new_typ: Type[T], constructor: Any) -> Callable[..., T]: return constructor
Anyway, tomorrow I'll try to work on the more restricted ideas I came up with for punq today.