Form Validation

The form classes are the building blocks for the Settings Configuration Form.

Fields

This module defines specializations of the general tools in abstract_form, mostly useful field types.

class cascade_at.core.form.fields.BoolField(*args, **kwargs)[source]
class cascade_at.core.form.fields.IntField(*args, **kwargs)[source]
class cascade_at.core.form.fields.FloatField(*args, **kwargs)[source]
class cascade_at.core.form.fields.StrField(*args, **kwargs)[source]
class cascade_at.core.form.fields.NativeListField(*args, **kwargs)[source]

Because we already have a ListField for space separated strings which become lists, this field type should be used when the .json config returns a native python list.

class cascade_at.core.form.fields.FormList(inner_form_constructor, *args, **kwargs)[source]

This represents a homogeneous list of forms. For example, it might be used to contain a list of priors within a smoothing grid.

Parameters
  • inner_form_constructor – A factory which produces an instance of a Form

  • Most often it will just be the Form subclass itself. (subclass.) –

class cascade_at.core.form.fields.Dummy(*args, **kwargs)[source]

A black hole which consumes all values without error. Use to mark sections of the configuration which have yet to be implemented and should be ignored.

validate_and_normalize(instance, root=None)[source]

Validates the data for this field on the given parent instance and transforms the data into it’s normalized form. The actual details of validating and transforming are delegated to subclasses except for checking for missing data which is handled here.

Parameters
  • instance (Form) – the instance of the form for which this field should be validated.

  • root (Form) – pointer back to the base of the form hierarchy.

Returns

a list of error messages with path strings

showing where in this object they occurred. For most fields the path will always be empty.

Return type

[(str, str, str)]

class cascade_at.core.form.fields.OptionField(options, *args, constructor=<class 'str'>, **kwargs)[source]

A field which will only accept values from a predefined set.

Parameters
  • options (list) – The list of options to choose from

  • constructor – A function which takes a string and returns the expected type. Behaves as the constructor for SimpleTypeField. Defaults to str

class cascade_at.core.form.fields.ListField(*args, constructor=<class 'str'>, separator=' ', **kwargs)[source]

A field which takes a string containing values demarcated by some separator and transforms them into a homogeneous list of items of an expected type.

Parameters
  • constructor – A function which takes a string and returns the expected type. Behaves as the constructor for SimpleTypeField. Defaults to str

  • separator (str) – The string to split by. Defaults to a single space.

class cascade_at.core.form.fields.StringListField(*args, constructor=<class 'str'>, separator=' ', **kwargs)[source]

Abstract Form

This module defines general tools for building validators for messy hierarchical parameter data. It provides a declarative API for creating form validators. It tries to follow conventions from form validation systems in the web application world since that is a very similar problem.

Example

Validators are defined as classes with attributes which correspond to the values they expect to receive. For example, consider this JSON blob:

{“field_a”: “10”, “field_b”: “22.4”, “nested”: {“field_c”: “Some Text”}}

A validator for that document would look like this:

class NestedValidator(Form):

field_c = SimpleTypeField(str)

class BlobValidator(Form):

field_a = SimpleTypeField(int) field_b = SimpleTypeField(int) nested = NestedValidator()

And could be used as follows:

>>> form = BlobValidator(json.loads(document))
>>> form.validate_and_normalize()
>>> form.field_a
10
>>> form.nested.field_c
"Some Text"
class cascade_at.core.form.abstract_form.NoValue[source]

Represents an unset value, which is distinct from None because None may actually appear in input data.

class cascade_at.core.form.abstract_form.FormComponent(nullable=False, default=None, display=None, validation_priority=100)[source]

Base class for all form components. It bundles up behavior shared by both (sub)Forms and Fields.

Note

FormComponent, Form and Field all make heavy use of the descriptor protocol (https://docs.python.org/3/howto/descriptor.html). That means that the relationship between objects and the data they operate on is more complex than usual. Read up on descriptors, if you aren’t familiar, and pay close attention to how __set__ and __get__ access data.

Parameters
  • nullable (bool) – If False then missing data for this node is considered an error. Defaults to False.

  • default – Default value to return if unset

  • display (str) – The name used in the EpiViz interface.

  • validation_priority (int) – Sort order for validation.

class cascade_at.core.form.abstract_form.Field(*args, **kwargs)[source]

A field within a form. Fields are responsible for validating the data they contain (without respect to data in other fields) and transforming it into a normalized form.

validate_and_normalize(instance, root=None)[source]

Validates the data for this field on the given parent instance and transforms the data into it’s normalized form. The actual details of validating and transforming are delegated to subclasses except for checking for missing data which is handled here.

Parameters
  • instance (Form) – the instance of the form for which this field should be validated.

  • root (Form) – pointer back to the base of the form hierarchy.

Returns

a list of error messages with path strings

showing where in this object they occurred. For most fields the path will always be empty.

Return type

[(str, str, str)]

class cascade_at.core.form.abstract_form.SimpleTypeField(constructor, *args, **kwargs)[source]

A field which transforms input data using a constructor function and emits errors if that transformation fails.

In general this is used to convert to simple types like int or float. Because it emits only very simple messages it is not appropriate for cases where the cause of any error isn’t obvious from knowing the name of the constructor function and a string representation of the input value.

Parameters

constructor – a function which takes one argument and returns a normalized version of that argument. It must raise ValueError, TypeError or OverflowError if transformation is not possible.

class cascade_at.core.form.abstract_form.Form(source=None, name_field=None, nullable=False, display=None, **kwargs)[source]

The parent class of all forms.

Validation for forms happens in two stages. First all the form’s fields and sub forms are validated. If none of those have errors, then the form is known to be in a consistent state and it’s _full_form_validation method is run to finalize validation. If any field or sub form is invalid then this form’s _full_form_validation method will not be run because the form may be in an inconsistent state.

Simple forms will be valid if all their fields are valid but more complex forms will require additional checks across multiple fields which are handled by _full_form_validation.

Note

A nested form may be marked nullable. It is considered null if all of it’s children are null. If a nullable form is null then it is not an error for non-nullable fields in it to be null. If any of the form’s fields are non-null then the whole form is considered non-null at which point missing data for non-nullable fields becomes an error again.

Parameters
  • source (dict) – The input data to parse. If None, it can be supplied later by calling process_source

  • name_field (str) – If supplied then a field of the same name must be present on the subclass. That field will always have the name of the attribute this class is assigned to in it’s parent rather than the value, if any, that the field had in the input data.