def parse_uri(config_uri):
    """
    Parse the ``config_uri`` into a :class:`plaster.PlasterURL` object.

    ``config_uri`` can be a relative or absolute file path such as
    ``development.ini`` or ``/path/to/development.ini``. The file must have
    an extension that can be handled by a :class:`plaster.ILoader`
    registered with the system.

    Alternatively, ``config_uri`` may be a :rfc:`1738`-style string.

    """
    if isinstance(config_uri, PlasterURL):
        return config_uri

    # force absolute paths to look like a uri for more accurate parsing
    # we throw away the dummy scheme later and parse it from the resolved
    # path extension
    isabs = os.path.isabs(config_uri)
    if isabs:
        config_uri = 'dummy://' + config_uri

    # check if the uri is actually a url
    parts = urlparse.urlparse(config_uri)

    # reconstruct the path without the scheme and fragment
    path = urlparse.ParseResult(
        scheme='',
        netloc=parts.netloc,
        path=parts.path,
        params='',
        query='',
        fragment='',
    ).geturl()
    # strip off leading //
    if path.startswith('//'):
        path = path[2:]

    if parts.scheme and not isabs:
        scheme = parts.scheme

    else:
        scheme = os.path.splitext(path)[1]
        if scheme.startswith('.'):
            scheme = scheme[1:]

        # tag uris coming from file extension as file+scheme
        if scheme:
            scheme = 'file+' + scheme

    query = parts.query if parts.query else None
    options = OrderedDict()
    if query:
        options.update(urlparse.parse_qsl(query))
    fragment = parts.fragment if parts.fragment else None

    if not scheme:
        raise InvalidURI(config_uri, (
            'Could not determine the loader scheme for the supplied '
            'config_uri "{0}"'.format(config_uri)))

    return PlasterURL(
        scheme=scheme,
        path=path,
        options=options,
        fragment=fragment,
    )