Proxy: Support for collections

Whenever we have a _links entry which is a list of dictionaries (rather
than just a dictionary), treat that as a collection. The Proxy class
doesn't use the cbase or sbase CURIEs to make this determination, but
instead relies on this more general method to determine the nature of
the link(s).

For scalars (1:1), we do the same thing we did before, which is to add a
LinkInfo object to the link map. An attribute access to object.attr
causes the LinkInfo object to be inspected and fetched if necessary.

For collections (1:N), we add a LinkCollection object to the link map,
which inherits from collections.Mapping, and is thus able to simulate a
dict. When an attribute access of the form object.attr[name] occurs,
Proxy's __getattr__ method first returns the LinkCollection object, and
then the __getitem__ method of LinkCollection is called, which in turn
finds the LinkInfo object associated with that entry in the collection.
This LinkInfo is then used in the same way as scalars above; a fetch is
performed if necessary, and then either a Proxy object or None is
returned, depending on whether the corresponding resource exists.
Caching also behaves the same as for scalars.

From an external perspective, Proxy can be used in exactly the same way
as Navigator for the purposes of collection access. The only difference
between test_nav03_collections.py and test_proxy03_collections.py is the
type of object (Navigator or Proxy) they create before carrying out
their actions.