I really want to make a good guide for myself of the near future work on MOTR, so let's take a look at a use case and see how it illuminates things.
The global information pertinent to running Python-based scripts is contained in an object called the ObjectRegistry. It maps keys of a parameterized Key[T] type to a value of type T, and has the expected ancillary operations. (Technically, this type is uninhabited at runtime, and the actual implementation is handled by some PMap objects from pyrsistent.)
The ObjectRegistry should contain information about which Python interpreters to invoke for a given command, but because this choice depends on the command being run, each command should get its own key.
So, in the case of running pytest under coverage, the coverage run -m pytest ... command should run under every interpreter associated with running tests, while the remainder of the commands should run under a single interpreter. As such, there should be a PYTEST_INTERPRETERS key of type Key[PVector[PythonInterpreter]], and a COVERAGE_INTERPRETER key of type Key[PythonInterpreter], where PythonInterpreter is probably just a NewType wrapper around str.
Now, some quick background:
I'm building up command line arguments using several helper classes. The relevant class for this discussion is called CmdMeta, and it contains most of the data that the other classes use. It has a field called installer_segments, because it was originally just meant to contain path segments for locating the installation directory associated with a virtual environment.
My intention is to make installer_segments into something fuller-featured. Its keys are Installer objects, the current definition of which is unimportant. Its values should be whatever data is required to generate an installation command, which includes the choice of key to use for retrieving interpreter data. In the interest of not hardcoding the installation command generation flow into the command concatenation logic, each installer should define a custom type that conforms to a Protocol.
The Protocol should include:
- A method for combining two instances of the same class.
- A method for generating an installation command, given the ObjectRegistry and ItemRegistry associated with the overall call. This method should produce a generator that generates lower-level Requirement objects, and returns an object that contains several bits of data: The last command it generated, and the script path for the generated environment. This can be bundled up into a class, there shouldn't be any harm in that. Call it Installation.
(An ItemRegistry is similar to an ObjectRegistry, but the keys are of type Key[PVector[T]] while the values are of type T.)
(It makes sense to roll the "requirements" information into this new class, so that other classes can define the data types they want.)
The various containers in the CmdMeta that can contain IO objects need to be modified to also allow Tuple[Installer, str], or some similar type. These pairs need to be post-processed out. This consists of having the Installation returned by a given Installer generating Requirement data in response to the string argument, and returning an Input[Path].
All of this represents a high-level overview that fits into the generic "core" code I'm working on. The specific programs I want to cover may end up requiring specialized helper functions, but I should be able to avoid thinking about that right now.
For the moment, I need to review those notes later and come up with answers to some of the stuff I glossed over above, like "where does some of this code go?"
Hopefully, after no more than a few more rounds of this, I'll be ready to touch the code again.
Anyway, it's late and I'm tired. I'm happy with how this is shaping up.