Today, I ended up just trying to do more with MOTR. It was mainly focused on planning. I was figuring out what the functionality related to running tests under coverage would look like (there are some weird subtleties), and I think I'm going to need to work things out from the "how are environments created?" perspective.
So, first off, there's some awkward stuff going on that means that things aren't quite right, because I've got this idea that it should be possible to dispatch commands to things besides a Python virtualenv with all of this, but I don't know if it should be possible to run disparate installers for a single command. The data types support specifying the information, but right now the shape of the code forces a very specific flow that prevents actually using more than one binary directory. Thinking about this, I think the solution is to create a pair of (installer, command) objects, and allow that type anywhere in a CmdMeta. Then, after the installers run, the pairs can be processed into Input and Output. Actually, since the path can be pre-calculated, it would mean less changes to the rest of the stack if the Output data were calculated before the installers run, and injected into their commands.
I think this will help out the structure in general, even if I'm not currently taking advantage of the flexibility this provides. (It allows my to process the data based on its contents rather than its location, which feels nicer to me.)
Anyway, there are a few related improvements required to get this to work. The smaller improvement required is for there to be a key for python interpreters (NewType around string with some minor validation, wrapped in an Optional), and then each Fragment type gets an associated key, to allow for stuff like "processing coverage data under one interpreter, but generating coverage data under multiple interpreters". The bigger improvement, by my estimation, is to set up something like the Key system, but for installer names.
Let's put that aside for a moment and consider what the "run a Script Fragment code" has to look like now.
- The Fragment contains a mapping from installers to "segments", which can be processed into a mapping from installers to virtualenv directories.
- Somewhere there has to be a mapping from installers to keys; I think I skipped over this... I think this has to live on the Fragment or the CmdMeta. It shouldn't live in the data type I'm talking about above, Maybe it should be in the values of the segments mapping. Let's go with that for now.
- So anyway, let's say it retrieves additional argument data for the installer from the segments. (Combining this data should probably be delegated to a custom class per installer.)
- So, that's all the information it needs to run the installer, but before we can run the command, we need to process the CmdMeta to extract the dependencies.
- So, we inject the dependencies into the cmd_ factory, and probably also do some Mkdir stuff so the directory parents exist.
- The installer command is ready to generate, and the CmdMeta is processed, so now we can generate the installer commands, then generate the main command.
The big change this needs is to create a "combiner" protocol, and to create another registry-type object to house segments and metadata, complete with a utility function to combine these registries.
- Combining metadata protocol
- Rework Installer type, fix type errors (including by creating a Pip installer type)
- Switch to registry-style type.
- Potentially fold req_set and installer_segments together
- Rework CmdMeta. This may involve threading a type parameter through the library that unions onto the data types in the CmdMeta, and it can either be the new type I was describing above, or Union[()].
Around that point, I can step back and reorient.
I think for the next few days, I should take a break from this.
Anyway, I want to get to bed.