Source code for plaster.uri

from collections import OrderedDict
import os.path
from urllib import parse

from .exceptions import InvalidURI


[docs]class PlasterURL: """ Represents the components of a URL used to locate a :class:`plaster.ILoader`. :ivar scheme: The name of the loader backend. :ivar path: The loader-specific path string. This is the entirety of the ``config_uri`` passed to :func:`plaster.parse_uri` without the scheme, fragment and options. If this value is falsey it is replaced with an empty string. :ivar options: A dictionary of options parsed from the query string as url-encoded key=value pairs. :ivar fragment: A loader-specific default section name. This parameter may be used by loaders in scenarios where they provide APIs that support a default name. For example, a loader that provides ``get_wsgi_app`` may use the fragment to determine the name of the section containing the WSGI app if none was explicitly defined. If this value is falsey it is replaced with an empty string. """ def __init__(self, scheme, path="", options=None, fragment=""): self.scheme = scheme if not path: path = "" self.path = path if options is None: options = {} self.options = options if not fragment: fragment = "" self.fragment = fragment def __str__(self): result = "{0.scheme}://{0.path}".format(self) if self.options: result += "?" + parse.urlencode(self.options) if self.fragment: result += "#" + self.fragment return result def __repr__(self): return f"PlasterURL('{self}')"
[docs]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 = parse.urlparse(config_uri) # reconstruct the path without the scheme and fragment path = parse.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(parse.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 "{}"'.format(config_uri) ), ) return PlasterURL(scheme=scheme, path=path, options=options, fragment=fragment)