All right, I gave this some though, and I think I see the way forward to fixing the functionality of MetaBuilder, if not the name.
Currently, MetaBuilder is kind of split between a Protocol class and a decorator that returns a function that conforms to that Protocol. I kind of want to get rid of the weird indirection that results from "here is a protocol, and here is the only lexical part of the source code concerned with implementing it", but I'm not sure if that's strictly necessary. Regardless, the first thing I want to do is, convert the Protocol to a dataclass that wraps a Builder[InputPathStr], and inline the nested function definition from the decorator into the __call__ method. I probably shouldn't mess with that any further until I have tests for it, except to set up a mapping to hold the MetaBuilder data, and populate that either unconditionally, or only in the Output case. At that point, I can consider questions like "what should the code that consumes this look like" and "what kind of interface do I need to actually generate the MetaBuilder instances from pytest, coverage, etc?
Hm, one thing that occurs to me as a further step is to convert all of this to a method on Builder[Input[PathStr]], which removes the need to name a separate class. This idea feels nicer to me, because now the question is "how do I synthesize a Builder[Input[PathStr]] with the desired properties?" which is somewhat more meaningful than "how do I synthesize a MetaBuilder with the desired properties?"
Let's see how much of a pain it is to do the conversion...
Okay, that wasn't too bad. I still need to reconsider the inside of the function, which is a terrible mess of nested definitions, but now the broader organization is more sensible.
Important TODO: expose self in some way in the output case.
Now, to think a little about how this all works in the downstream interfaces. There are basically two kinds of thing that have to be properly combined:
- The full range of parameters
- The different kinds of output
Basically, we need the commands to track all of their relevant keys, and translate them into string values. The resulting strings then must be fed into a function that produces a Builder[Input[PathStr]] from the key values.
This is going to be awkward, because I know I'll want to pass in stuff like PythonPackage, so it's like I guess I need to pass in a callback or something to handle the conversions. This sounds like a job for "sleeping before I try to code any of this".
It's a little early now, but I have to get up early tomorrow and deal with a whole bunch of... just... stuff, so it makes sense to try to wrap up now.