Tests of miscellaneous functions from ``plib.stdlib``.

    >>> from plib.stdlib import any, all, first, inrange, last, normalize, slice_len, strtobool, strtodate

The ``any`` and ``all`` functions should return a bool indicating whether
any or all of the items in an iterable satisfy a predicate (by default,
the predicate is ``bool``). First try with the default predicate.

    >>> any(range(2))
    True
    >>> any(range(1, 3))
    True
    >>> any(range(1))
    False
    >>> any([])
    False
    >>> all(range(2))
    False
    >>> all(range(1, 3))
    True
    >>> all(range(1))
    False
    >>> all([])
    True

Now define a test predicate which, for integers, gives identical truth
values to the default, to see if behavior remains the same.

    >>> def test(n):
    ...     return n > 0
    ... 
    >>> any(range(2), test)
    True
    >>> any(range(1, 3), test)
    True
    >>> any(range(1), test)
    False
    >>> any([], test)
    False
    >>> all(range(2), test)
    False
    >>> all(range(1, 3), test)
    True
    >>> all(range(1), test)
    False
    >>> all([], test)
    True

The ``first`` and ``last`` functions return the first or last items
in an iterable, without requiring that the entire iterable be realized
as a list. If the iterable is empty, they return a default value, or
``None`` if no default is provided.

    >>> first([0, 1, 2, 3])
    0
    >>> print first([])
    None
    >>> first([], "default")
    'default'
    >>> last([0, 1, 2, 3])
    3
    >>> print last([])
    None
    >>> last([], "default")
    'default'

The ``inrange`` function forces its argument to be within the low and
high limits given, and returns the result. Its behavior with anything
other than integer arguments is undefined (no type checking is done).

    >>> inrange(0, 0, 2)
    0
    >>> inrange(1, 0, 2)
    1
    >>> inrange(2, 0, 2)
    2
    >>> inrange(-1, 0, 2)
    0
    >>> inrange(3, 0, 2)
    2
    >>> inrange(0, 2, 0)
    0
    >>> inrange(1, 2, 0)
    1
    >>> inrange(2, 2, 0)
    2
    >>> inrange(-1, 2, 0)
    0
    >>> inrange(3, 2, 0)
    2

The ``normalize`` function returns its second argument "normalized"
as if it were an index into a sequence of length given by its first
argument. "Normalized" means negative indexes are interpreted relative
to the end of the sequence. Indexes that are out of range after
normalization throw IndexError.

    >>> normalize(6, 0)
    0
    >>> normalize(6, 5)
    5
    >>> normalize(6, -1)
    5
    >>> normalize(6, -6)
    0
    >>> normalize(6, 6)
    Traceback (most recent call last):
    ...
    IndexError: sequence index out of range
    >>> normalize(6, -7)
    Traceback (most recent call last):
    ...
    IndexError: sequence index out of range

The ``slice_len`` argument returns the number of index values that are
"covered" by the given slice. Its behavior is undefined for anything
except slice arguments (no type checking is done). The only exception
it will throw is ValueError if the slice step is zero (to match the
semantics of the builtin containers).

    >>> slice_len(slice(1))
    1
    >>> slice_len(slice(2))
    2
    >>> slice_len(slice(1, 2))
    1
    >>> slice_len(slice(2, 4))
    2
    >>> slice_len(slice(0, 1, 1))
    1
    >>> slice_len(slice(0, 2, 1))
    2
    >>> slice_len(slice(0, 2, 2))
    1
    >>> slice_len(slice(1, 0, -1))
    1
    >>> slice_len(slice(2, 0, -1))
    2
    >>> slice_len(slice(2, 0, -2))
    1
    >>> slice_len(slice(0))
    0
    >>> slice_len(slice(0, 0))
    0
    >>> slice_len(slice(0, 0, 0))
    Traceback (most recent call last):
    ...
    ValueError: Slice step cannot be zero.

We need a slight hack to test that ``slice_len`` returns None when
given a slice whose length cannot be determined (because there is
no count argument to tell it how long the sequence is that it is
indexing into).

    >>> class SliceHack(object):
    ...     def __getitem__(self, index):
    ...         if slice_len(index) is None:
    ...             return "Indefinite slice!"
    ...
    >>> SliceHack()[:]
    'Indefinite slice!'
    >>> SliceHack()[:-1]
    'Indefinite slice!'
    >>> SliceHack()[-1:]
    'Indefinite slice!'
    >>> SliceHack()[-1:-1]
    'Indefinite slice!'

The ``strtobool`` function provides a quick and dirty way to convert
the strings ``'False'`` and ``'True'`` back into their boolean
equivalents. It returns ``None`` for any other string value.

    >>> for b in (True, False, None):
    ...     print strtobool(str(b)) is b
    ... 
    True
    True
    True

The ``strtodate`` function provides a quick and dirty way to convert
strings in canonical date format back into date objects. Its behavior
for strings not correctly formatted is undefined.

    >>> s = '2001-05-30'
    >>> str(strtodate(s)) == s
    True
