datalad-next
's Constraint System
datalad_next.constraints
implements a system to perform data validation, coercion, and parameter documentation for commands via a flexible set of "Constraints".
You can find an overview of available Constraints in the respective module overview of the Python tooling.
Adding parameter validation to a command
In order to equip an existing or new command with the constraint system, the following steps are required:
Set the commands base class to
ValidatedInterface
:
from datalad_next.commands import ValidatedInterface
@build_doc
class MyCommand(ValidatedInterface):
"""Download from URLs"""
Declare a
_validator_
class member:
from datalad_next.commands import (
EnsureCommandParameterization,
ValidatedInterface,
)
@build_doc
class MyCommand(ValidatedInterface):
"""Download from URLs"""
_validator_ = EnsureCommandParameterization(dict(
[...]
))
Determine for each parameter of the command whether it has constraints, and what those constraints are. If you're transitioning an existing command, remove any
constraints=
declaration in the_parameter_
class member.Add a fitting Constraint declaration for each parameter into the
_validator_
as a key-value pair where the key is the parameter and its value is a Constraint. There does not need to be a Constraint per parameter; only add entries for parameters that need validation.
from datalad_next.commands import (
EnsureCommandParameterization,
ValidatedInterface,
)
from datalad_next.constraints import EnsureChoice
from datalad_next.constraints import EnsureDataset
@build_doc
class Download(ValidatedInterface):
"""Download from URLs"""
_validator_ = EnsureCommandParameterization(dict(
dataset=EnsureDataset(installed=True),
force=EnsureChoice('yes','no','maybe'),
))
Combining constraints
Constraints can be combined in different ways.
The |
, &
, and ()
operators allow AND
, OR
, and grouping of Constraints.
The following example from the download
command defines a chain of possible Constraints:
spec_item_constraint = url2path_constraint | (
(
EnsureJSON() | EnsureURLFilenamePairFromURL()
) & url2path_constraint)
Constrains can also be combined using AnyOf
or AllOf
MultiConstraints, which correspond almost entirely to |
and &
.
Here's another example from the download
command:
spec_constraint = AnyOf(
spec_item_constraint,
EnsureListOf(spec_item_constraint),
EnsureGeneratorFromFileLike(
spec_item_constraint,
exc_mode='yield',
),
One can combine an arbitrary number of Constraints. They are evaluated in the order in which they were specified. Logical OR constraints will return the value from the first constraint that does not raise an exception, and logical AND constraints pass the return values of each constraint into the next.
Implementing additional constraints
TODO
Parameter Documentation
TODO