Coding 2022-12-24
I had a look at the missing coverage in command_builder.py, and I concluded that, while it should be relatively straightforward to throw together a test at some level of abstraction, I feel like there should be some way to encode the checks that aren't being hit into the type system and remove them from the runtime code.
So, what would that look like:
- Create a new typevar for representing the module_args value.
- This propagates to the usages of the CommandBuilder in parametric_command, and secondarily to the client-style modules.
- The immediate change would be through the addition of a new parameter to ParametricCommandMeta.
- One question this raises is whether commands that accept a module argument should be required to be passed one, but it should be safe to err on the side of strictness to start with.
- The key point is that the module_or_adaptor field would also need to become parameterized, and I haven't yet thought of anything that seems like a good way to do that. A way to do that is to create a parameterized protocol, and two classes that implement it, somehow scoping the implementation of each to a different value of the variable (probably by using self annotations of the protocol? Does that even work?), which should then localize the with_module calls to the paths where it's statically asserted to succeed.
Thinking about what would improve the codebase, I think the thing to do is to try to eliminate the isinstance checks that have test coverage. That makes the typing a bit easier to reason about, and also eliminates some conditionals, so the behavior of the code should be less squirrelly. If all of that works, then I can look into propagating the type information like I was talking about.
For now, I'm going to wind down, and I'll see what I can do in the next few days.
Good night.