Major updates to the argument model. Merged all "Classes" of args
("Shape", "Positional") etc into a single `Arg` class. This class can be
customized to match any of the previous arg types through appropriate
setting of parameters. This greatly simplifies the arg parsing model
and should allow much more freedom of design later.
The parser is essentially split into two layers:
- The core layer consists of the arg object and the core parse logic.
This is meant to be very simple and transparent: list of args goes in,
list of args with updated values comes out. Strict typing is enforced
throughout to maintain transparency.
- In addition to basic parsing, this layer also handles basic
validation, including validation errors and mandatory arg errors.
These can be elevated using the same mechanisms previously
available.
- This layer will still search for a "help" argument and print help if
provided. This is a vestigial function that should be moved the
second layer at some point
- The second layer is the "convenience" layer. This contains convenience
functions to cover most use cases, greatly reducing the amount of
boilerplate code needed.
- As before, a model is defined for each cli command. The model is
defined using an attrs wrapped class. Instead of Arg subclasses,
functions are used to quickly specialize Arg into the necessary
forms.
- The logic for each cli command is contained in a function wrapped
with a `@command` decorator. The function may take a number of type
annotated
arguments (all are optional):
- One argument annotated with a model, described above. It can also
be a union of a model and any number of errors, allowing custom
error handling in model validators.
- One annotated as list[str]. This will take any unparsed args (the
"tail" from the previous version).
- One annotated as the typevar `ParsedArgs` (importable from
`kslurm.args`). This will be a dict of key -> Arg objects for full
exposure to the underlying models.
- One annotated as str, which will be the name or path used to call
the function
- A typing cheat is used in model definition: instead of annotating
attributes as `Arg[...]`, the desired value type is used directly
(e.g. `str`, `Path`). `@command` will read these annotations and
automatically set the `format` function for each arg. After parsing,
the `value` or `values` will be extracted from each `Arg` and
inserted back into the model. This saves needing to type
`model.arg.value`, providing the more natural `model.arg`. The full
model is still available via function argument, as described above.
- The help system is redone, relying now on Templates that can be
assigned to each arg. Each template carries a title, a way of defining
rows, and optionally a way of defining tables. This should grant
greater flexibility in the future.