Elements — flatland 0.8.1 documentation

# Elements

Elements describe the possible fields of a form; their names, structure, Python types and rules for validation. A typical schema consists of at least one container type and one or more scalar types:

    from flatland import Dict, String
    SearchSchema = Dict.named('search').of(String.named(u'keywords'))

Todo

FIXME UPDATE:

FieldSchemas are a bit like Python `class` definitions: they need be defined only once and don’t do much on their own. `FieldSchema.create_element()` produces `Elements`; closely related objects that hold and manipulate form data. Much like a Python `class`, a single `FieldSchema` may produce an unlimited number of `Element` instances.

    >>> form = SearchSchema({u'keywords': u'foo bar baz'})
    >>> form.value
    {u'keywords': u'foo bar baz'}

Todo

FIXME UPDATE:

FieldSchema instances may be freely composed and shared among many containers.

    >>> from flatland import List
    >>> ComposedSchema = Dict.of(SearchSchema,
    ...                          List.named(u'many_searches').of(SearchSchema))
    >>> form = ComposedSchema()
    >>> sorted(form.value.keys())
    [u'many_searches', u'search']

Todo

FIXME UPDATE:

Elements can be supplied to template environments and used to great effect there: elements contain all of the information needed to display or redisplay a HTML form field, including errors specific to a field.

The `u`, `x`, `xa` and `el()` members are especially useful in templates and have shortened names to help preserve your sanity when used in markup.

## `Element`

class `Element`(value=Unspecified, **kw)

  Base class for form fields.

  A data node that stores a Python and a text value plus added state.

  Instance Attributes

  `parent`

    An owning element, or None if element is topmost or not a member of a hierarchy.

  `valid`
  `errors`

    A list of validation error messages.

  `warnings`

    A list of validation warning messages.

  Members

  `name` = None

    The string name of the element.

  `optional` = False

    If True, `validate()` will return True when no value has been set.

    `validators` are not called for optional, empty elements.

  `validators` = ()

    A sequence of validators, invoked by `validate()`.

    See Validation.

  `default` = None

    The default value of this element.

  `default_factory` = None

    A callable to generate default element values. Passed an element.

    default_factory will be used preferentially over `default`.

  `ugettext` = None

    If set, provides translation support to validation messages.

    See Message Internationalization.

  `ungettext` = None

    If set, provides translation support to validation messages.

    See Message Internationalization.

  `value` = None

    The element’s native Python value.

    Only validation routines should write this attribute directly: use `set()` to update the element’s value.

  `raw` = Unset

    The element’s raw, unadapted value from input.

  `u` = u''

    A string representation of the element’s value.

    As in `value`, writing directly to this attribute should be restricted to validation routines.

  `properties` = {}

    A mapping of arbitrary data associated with the element.

  `named`(name)

    Return a class with `name` = name

    Parameters: | name – a string or None.
    Returns: | a new class

  `using`(**overrides)

    Return a class with attributes set from **overrides.

    Parameters: | **overrides – new values for any attributes already present on the class. A `TypeError` is raised for unknown attributes.
    Returns: | a new class

  `validated_by`(*validators)

    Return a class with validators set to *validators.

    Parameters: | *validators – one or more validator functions, replacing any validators present on the class.
    Returns: | a new class

  `including_validators`(*validators, **kw)

    Return a class with additional *validators.

    Parameters: | *validators – one or more validator functions position – defaults to -1. By default, additional validators are placed after existing validators. Use 0 for before, or any other list index to splice in validators at that point.
    Returns: | a new class

  `with_properties`(*iterable, **properties)

    Return a class with **properties set.

    Param: | optional positional parameter, an iterable of property name / value pairs
    Parameters: | **properties – property names and values as keyword arguments
    Returns: | a new class

  classmethod `from_flat`(pairs, **kw)

    Return a new element with its value initialized from pairs.

    Parameters: | **kw – passed through to the `element_type`.

    This is a convenience constructor for:

        element = cls(**kw)
        element.set_flat(pairs)

  classmethod `from_defaults`(**kw)

    Return a new element with its value initialized from field defaults.

    Parameters: | **kw – passed through to the `element_type`.

    This is a convenience constructor for:

        element = cls(**kw)
        element.set_default()

  `all_valid`

    True if this element and all children are valid.

  `root`

    The top-most parent of the element.

  `parents`

    An iterator of all parent elements.

  `path`

    An iterator of all elements from root to the Element, inclusive.

  `children`

    An iterator of immediate child elements.

  `all_children`

    An iterator of all child elements, breadth-first.

  `fq_name`()

    Return the fully qualified path name of the element.

    Returns `find()` compatible element path string from the `Element.root` (`/`) down to the element.

        >>> from flatland import Dict, Integer
        >>> Point = Dict.named(u'point').of(Integer.named(u'x'),
        ...                                 Integer.named(u'y'))
        >>> p = Point(dict(x=10, y=20))
        >>> p.name
        u'point'
        >>> p.fq_name()
        u'/'
        >>> p['x'].name
        u'x'
        >>> p['x'].fq_name()
        u'/x'

    The index used in a path may not be the `name` of the element. For example, sequence members are referenced by their numeric index.

        >>> from flatland import List, String
        >>> Addresses = List.named('addresses').of(String.named('address'))
        >>> form = Addresses([u'uptown', u'downtown'])
        >>> form.name
        u'addresses'
        >>> form.fq_name()
        u'/'
        >>> form[0].name
        u'address'
        >>> form[0].fq_name()
        u'/0'

  `find`(path, single=False, strict=True)

    Find child elements by string path.

    Parameters: | path – a /-separated string specifying elements to select, such as ‘child/grandchild/great grandchild’. Relative & absolute paths are supported, as well as container expansion. See Path Lookups. single – if true, return a scalar result rather than a list of elements. If no elements match path, `None` is returned. If multiple elements match, a `LookupError` is raised. If multiple elements are found and strict is false, an unspecified element from the result set is returned. strict – defaults to True. If path specifies children or sequence indexes that do not exist, a `LookupError` is raised.
    Returns: | a list of `Element` instances, an `Element` if single is true, or raises `LookupError`.

        >>> cities = form.find('/contact/addresses[:]/city')
        >>> [el.value for el in cities]
        [u'Kingsport', u'Dunwich']
        >>> form.find('/contact/name', single=True)
        <String u'name'; value=u'Obed Marsh'>

  `find_one`(path)

    Find a single element at path.

    An alias for `find()`. Equivalent to `find(path, single=True, strict=True)`.

  `add_error`(message)

    Register an error message on this element, ignoring duplicates.

  `add_warning`(message)

    Register a warning message on this element, ignoring duplicates.

  `flattened_name`(sep=u'_')

    Return the element’s complete flattened name as a string.

    Joins this element’s `path` with sep and returns the fully qualified, flattened name. Encodes all `Container` and other structures into a single string.

    Example:

        >>> import flatland
        >>> form = flatland.List('addresses',
        ...                      flatland.String('address'))
        >>> element = form()
        >>> element.set([u'uptown', u'downtown'])
        >>> element[0].value
        u'uptown'
        >>> element['0'].flattened_name()
        u'addresses_0_address'

  `flatten`(sep=u'_', value=<operator.attrgetter object>)

    Export an element hierarchy as a flat sequence of key, value pairs.

    Parameters: | sep – a string, will join together element names. value – a 1-arg callable called once for each element. Defaults to a callable that returns the `u` of each element.

    Encodes the element hierarchy in a sep-separated name string, paired with any representation of the element you like. The default is the text value of the element, and the output of the default `flatten()` can be round-tripped with `set_flat()`.

    Given a simple form with a string field and a nested dictionary:

        >>> from flatland import Schema, Dict, String
        >>> class Nested(Schema):
        ...     contact = Dict.of(String.named(u'name'),
        ...                       Dict.named(u'address').
        ...                            of(String.named(u'email')))
        ...
        >>> element = Nested()
        >>> element.flatten()
        [(u'contact_name', u''), (u'contact_address_email', u'')]

    The value of each pair can be customized with the value callable:

        >>> element.flatten(value=operator.attrgetter('u'))
        [(u'contact_name', u''), (u'contact_address_email', u'')]
        >>> element.flatten(value=lambda el: el.value)
        [(u'contact_name', None), (u'contact_address_email', None)]

    Solo elements will return a sequence containing a single pair:

        >>> element['name'].flatten()
        [(u'contact_name', u'')]

  `set`(obj)

    Process obj and assign the native and text values.

    Attempts to adapt the given obj and assigns this element’s `value` and `u` attributes in tandem. Returns True if the adaptation was successful.

    If adaptation succeeds, `value` will contain the adapted native value and `u` will contain a text serialized version of it. A native value of None will be represented as u’’ in `u`.

    If adaptation fails, `value` will be `None` and `u` will contain `str(value)` (or unicode), or `u''` for None.

        >>> from flatland import Integer
        >>> el = Integer()
        >>> el.u, el.value
        (u'', None)

        >>> el.set('123')
        True
        >>> el.u, el.value
        (u'123', 123)

        >>> el.set(456)
        True
        >>> el.u, el.value
        (u'456', 456)

        >>> el.set('abc')
        False
        >>> el.u, el.value
        (u'abc', None)

        >>> el.set(None)
        True
        >>> el.u, el.value
        (u'', None)

  `set_flat`(pairs, sep=u'_')

    Set element values from pairs, expanding the element tree as needed.

    Given a sequence of name/value tuples or a dict, build out a structured tree of value elements.

  `set_default`()

    set() the element to the schema default.

  `is_empty`

    True if the element has no value.

  `validate`(state=None, recurse=True)

    Assess the validity of this element and its children.

    Parameters: | state – optional, will be passed unchanged to all validator callables. recurse – if False, do not validate children.
    Returns: | True or False.

    Iterates through this element and all of its children, invoking each validation on each. Each element will be visited twice: once heading down the tree, breadth-first, and again heading back up in reverse order.

    Returns True if all validations pass, False if one or more fail.

  `default_value`

    A calculated “default” value.

    If `default_factory` is present, it will be called with the element as a single positional argument. The result of the call will be returned.

    Otherwise, returns `default`.

    When comparing an element’s `value` to its default value, use this property in the comparison.

  `x`

    Sugar, the XML-escaped value of `u`.

  `xa`

    Sugar, the XML-attribute-escaped quoted value of `u`.