Tests of builtins and extra builtins installed by the
``plib.stdlib.builtins.upgrade_builtins`` function. Note
that importing the module is sufficient, the function
doesn't have to be called explicitly.

    >>> import plib.stdlib.builtins

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(range(3))
    0
    >>> print(first([]))
    None
    >>> first([], 'default')
    'default'
    >>> last(range(3))
    2
    >>> print(last([]))
    None
    >>> last([], 'default')
    'default'

The ``inverted`` function inverts a mapping.

    >>> d1 = {'a': 1, 'b': 2}
    >>> i1 = inverted(d1)
    >>> i1 == {1: 'a', 2: 'b'}
    True

The ``inverted`` function preserves the actual class
of the object, even if it's a subclass of ``dict``.

    >>> d1.__class__.__name__
    'dict'
    >>> i1.__class__.__name__
    'dict'
    >>> class test1(dict):
    ...     pass
    ... 
    >>> d2 = test1(d1)
    >>> d2.__class__.__name__
    'test1'
    >>> d2 == d1
    True
    >>> i2 = inverted(d2)
    >>> i2.__class__.__name__
    'test1'
    >>> i2 == i1
    True

Test limiting the keys to be inverted with the ``keylist``
parameter.

    >>> keylist = ['a', 'b']
    >>> d3 = {'a': 1, 'b': 2, 'c': 3}
    >>> i3 = inverted(d3, keylist)
    >>> i3 == i1
    True
    >>> i4 = inverted(d3)
    >>> i3 == i4
    False

If multiple keys have the same value in a mapping, its
inverse is undefined (since the last key having that
value will be the only one appearing in the inverse, and the
order in which keys are iterated over depends on the
implementation). The only thing we can guarantee is that the
size of the inverse will be smaller.

    >>> d5 = {'a': 0, 'b': 0}
    >>> len(d5)
    2
    >>> i5 = inverted(d5)
    >>> len(i5)
    1
    >>> 

The ``prod`` function returns the product of all items in an iterable.

    >>> prod(range(1, 5))
    24
    >>> prod(range(1, 10))
    362880
    >>> prod(range(1, 25))
    620448401733239439360000
    >>> prod(range(1))
    0
    >>> prod([])
    1

The ``type_from_name`` function finds built-in types corresponding
to a given name.

    >>> type_from_name('list')
    <class 'list'>
    >>> type_from_name('not_there')
    Traceback (most recent call last):
     ...
    ValueError: no type corresponding to not_there
