|
- """Module containing the implementation of the URIReference class."""
- # -*- coding: utf-8 -*-
- # Copyright (c) 2014 Rackspace
- # Copyright (c) 2015 Ian Stapleton Cordasco
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- # implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- from collections import namedtuple
-
- from . import compat
- from . import misc
- from . import normalizers
- from ._mixin import URIMixin
-
-
- class URIReference(namedtuple('URIReference', misc.URI_COMPONENTS), URIMixin):
- """Immutable object representing a parsed URI Reference.
-
- .. note::
-
- This class is not intended to be directly instantiated by the user.
-
- This object exposes attributes for the following components of a
- URI:
-
- - scheme
- - authority
- - path
- - query
- - fragment
-
- .. attribute:: scheme
-
- The scheme that was parsed for the URI Reference. For example,
- ``http``, ``https``, ``smtp``, ``imap``, etc.
-
- .. attribute:: authority
-
- Component of the URI that contains the user information, host,
- and port sub-components. For example,
- ``google.com``, ``127.0.0.1:5000``, ``username@[::1]``,
- ``username:password@example.com:443``, etc.
-
- .. attribute:: path
-
- The path that was parsed for the given URI Reference. For example,
- ``/``, ``/index.php``, etc.
-
- .. attribute:: query
-
- The query component for a given URI Reference. For example, ``a=b``,
- ``a=b%20c``, ``a=b+c``, ``a=b,c=d,e=%20f``, etc.
-
- .. attribute:: fragment
-
- The fragment component of a URI. For example, ``section-3.1``.
-
- This class also provides extra attributes for easier access to information
- like the subcomponents of the authority component.
-
- .. attribute:: userinfo
-
- The user information parsed from the authority.
-
- .. attribute:: host
-
- The hostname, IPv4, or IPv6 adddres parsed from the authority.
-
- .. attribute:: port
-
- The port parsed from the authority.
- """
-
- slots = ()
-
- def __new__(cls, scheme, authority, path, query, fragment,
- encoding='utf-8'):
- """Create a new URIReference."""
- ref = super(URIReference, cls).__new__(
- cls,
- scheme or None,
- authority or None,
- path or None,
- query,
- fragment)
- ref.encoding = encoding
- return ref
-
- __hash__ = tuple.__hash__
-
- def __eq__(self, other):
- """Compare this reference to another."""
- other_ref = other
- if isinstance(other, tuple):
- other_ref = URIReference(*other)
- elif not isinstance(other, URIReference):
- try:
- other_ref = URIReference.from_string(other)
- except TypeError:
- raise TypeError(
- 'Unable to compare URIReference() to {0}()'.format(
- type(other).__name__))
-
- # See http://tools.ietf.org/html/rfc3986#section-6.2
- naive_equality = tuple(self) == tuple(other_ref)
- return naive_equality or self.normalized_equality(other_ref)
-
- def normalize(self):
- """Normalize this reference as described in Section 6.2.2.
-
- This is not an in-place normalization. Instead this creates a new
- URIReference.
-
- :returns: A new reference object with normalized components.
- :rtype: URIReference
- """
- # See http://tools.ietf.org/html/rfc3986#section-6.2.2 for logic in
- # this method.
- return URIReference(normalizers.normalize_scheme(self.scheme or ''),
- normalizers.normalize_authority(
- (self.userinfo, self.host, self.port)),
- normalizers.normalize_path(self.path or ''),
- normalizers.normalize_query(self.query),
- normalizers.normalize_fragment(self.fragment),
- self.encoding)
-
- @classmethod
- def from_string(cls, uri_string, encoding='utf-8'):
- """Parse a URI reference from the given unicode URI string.
-
- :param str uri_string: Unicode URI to be parsed into a reference.
- :param str encoding: The encoding of the string provided
- :returns: :class:`URIReference` or subclass thereof
- """
- uri_string = compat.to_str(uri_string, encoding)
-
- split_uri = misc.URI_MATCHER.match(uri_string).groupdict()
- return cls(
- split_uri['scheme'], split_uri['authority'],
- normalizers.encode_component(split_uri['path'], encoding),
- normalizers.encode_component(split_uri['query'], encoding),
- normalizers.encode_component(split_uri['fragment'], encoding),
- encoding,
- )
|