* make NoSuchAsset subclass IOError?...

* add support for "file://" paths so that asset() can be used
  agnostically to whether the asset is on the filesystem or
  in a python package...

* add shortcuts...
    asset.read(*) == asset.load(*).read()

* make .load() optimize for no-wildcards specs by returning an Asset.
  ==> Asset's must behave like AssetGroups though! (i.e. listable)

* make import errors better, e.g. an
    asset.symbol('asset.badmodule.BadClass')

  fails with:
    ImportError: No module named badmodule

  or if badmodule exists, but not BadClass, then:
    ImportError: No module named BadClass

  it should:
    ImportError: No module named asset.badmodule

  for the former, and:
    ImportError: No module or attribute named asset.badmodule.BadClass

  for the latter.

  ==> perhaps return an AssetError which is subclass of both ImportError
      and AttributeError?
      no. just ImportError
      unless the asset-spec specifies an attribute...

* make asset.load() complain on unknown keywords, such as `transformer`

* convert the `peek()` method into a .load(lazy=True) parameter.

* add helpers:
  * `isspec`
  * `isresource`
  * `issymbol`

  base it on::

    import re
    isResourceSpec = re.compile('^[a-z][a-z0-9_]*:', re.IGNORECASE)
    def isresource(spec):
      return isstr(spec) and bool(isResourceSpec.match(spec))

* make the stream returned by asset.load(SPEC).stream() behave like a stream...
  not whatever this is:

    Traceback (most recent call last):
      File "/media/raspi-local/raspi-door.git/raspi_door/trap.py", line 59, in trigger
        target[2](*args, topic=topic, event=event, **kw)
      File "/media/raspi-local/raspi-door.git/raspi_door/sensor.py", line 120, in onSense
        self.sounds[evt] = pygame.mixer.Sound(play)
    error: OGG bitstream is not valid Vorbis stream!

