Fix up flake8 errors
This commit is contained in:
parent
2c4e606b35
commit
08335d75b5
|
@ -14,18 +14,19 @@
|
|||
# limitations under the License.
|
||||
|
||||
"""
|
||||
rfc3986
|
||||
=======
|
||||
An implementation of semantics and validations described in RFC 3986.
|
||||
|
||||
An implementation of semantics and validations described in RFC 3986. See
|
||||
http://rfc3986.rtfd.org/ for documentation.
|
||||
See http://rfc3986.readthedocs.io/ for detailed documentation.
|
||||
|
||||
:copyright: (c) 2014 Rackspace
|
||||
:license: Apache v2.0, see LICENSE for details
|
||||
"""
|
||||
|
||||
from .api import (URIReference, uri_reference, is_valid_uri, normalize_uri,
|
||||
urlparse)
|
||||
from .api import is_valid_uri
|
||||
from .api import normalize_uri
|
||||
from .api import uri_reference
|
||||
from .api import URIReference
|
||||
from .api import urlparse
|
||||
from .parseresult import ParseResult
|
||||
|
||||
__title__ = 'rfc3986'
|
||||
|
@ -33,7 +34,7 @@ __author__ = 'Ian Cordasco'
|
|||
__author_email__ = 'graffatcolmingov@gmail.com'
|
||||
__license__ = 'Apache v2.0'
|
||||
__copyright__ = 'Copyright 2014 Rackspace'
|
||||
__version__ = '0.4.1'
|
||||
__version__ = '1.0.0.0b0'
|
||||
|
||||
__all__ = (
|
||||
'ParseResult',
|
||||
|
|
|
@ -13,15 +13,14 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""
|
||||
rfc3986.api
|
||||
~~~~~~~~~~~
|
||||
Module containing the simple and functional API for rfc3986.
|
||||
|
||||
This defines the simple API to rfc3986. This module defines 3 functions and
|
||||
provides access to the class ``URIReference``.
|
||||
This module defines functions and provides access to the public attributes
|
||||
and classes of rfc3986.
|
||||
"""
|
||||
|
||||
from .uri import URIReference
|
||||
from .parseresult import ParseResult
|
||||
from .uri import URIReference
|
||||
|
||||
|
||||
def uri_reference(uri, encoding='utf-8'):
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""Compatibility module for Python 2 and 3 support."""
|
||||
import sys
|
||||
|
||||
|
||||
|
@ -20,12 +21,14 @@ if sys.version_info >= (3, 0):
|
|||
|
||||
|
||||
def to_str(b, encoding):
|
||||
"""Ensure that b is text in the specified encoding."""
|
||||
if hasattr(b, 'decode') and not isinstance(b, unicode):
|
||||
b = b.decode('utf-8')
|
||||
return b
|
||||
|
||||
|
||||
def to_bytes(s, encoding):
|
||||
"""Ensure that s is converted to bytes from the encoding."""
|
||||
if hasattr(s, 'encode') and not isinstance(s, bytes):
|
||||
s = s.encode('utf-8')
|
||||
return s
|
||||
|
|
|
@ -1,21 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Exceptions module for rfc3986."""
|
||||
|
||||
|
||||
class RFC3986Exception(Exception):
|
||||
"""Base class for all rfc3986 exception classes."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class InvalidAuthority(RFC3986Exception):
|
||||
"""Exception when the authority string is invalid."""
|
||||
|
||||
def __init__(self, authority):
|
||||
"""Initialize the exception with the invalid authority."""
|
||||
super(InvalidAuthority, self).__init__(
|
||||
"The authority ({0}) is not valid.".format(authority))
|
||||
|
||||
|
||||
class InvalidPort(RFC3986Exception):
|
||||
"""Exception when the port is invalid."""
|
||||
|
||||
def __init__(self, port):
|
||||
"""Initialize the exception with the invalid port."""
|
||||
super(InvalidPort, self).__init__(
|
||||
'The port ("{0}") is not valid.'.format(port))
|
||||
|
||||
|
||||
class ResolutionError(RFC3986Exception):
|
||||
"""Exception to indicate a failure to resolve a URI."""
|
||||
|
||||
def __init__(self, uri):
|
||||
"""Initialize the error with the failed URI."""
|
||||
super(ResolutionError, self).__init__(
|
||||
"{0} is not an absolute URI.".format(uri.unsplit()))
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""
|
||||
rfc3986.misc
|
||||
~~~~~~~~~~~~
|
||||
Module containing compiled regular expressions and constants.
|
||||
|
||||
This module contains important constants, patterns, and compiled regular
|
||||
expressions for parsing and validating URIs and their components.
|
||||
|
|
|
@ -12,17 +12,20 @@
|
|||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""Module with functions to normalize components."""
|
||||
import re
|
||||
|
||||
from .compat import to_bytes
|
||||
from .misc import NON_PCT_ENCODED
|
||||
from . import compat
|
||||
from . import misc
|
||||
|
||||
|
||||
def normalize_scheme(scheme):
|
||||
"""Normalize the scheme component."""
|
||||
return scheme.lower()
|
||||
|
||||
|
||||
def normalize_authority(authority):
|
||||
"""Normalize an authority tuple to a string."""
|
||||
userinfo, host, port = authority
|
||||
result = ''
|
||||
if userinfo:
|
||||
|
@ -35,6 +38,7 @@ def normalize_authority(authority):
|
|||
|
||||
|
||||
def normalize_path(path):
|
||||
"""Normalize the path string."""
|
||||
if not path:
|
||||
return path
|
||||
|
||||
|
@ -43,12 +47,14 @@ def normalize_path(path):
|
|||
|
||||
|
||||
def normalize_query(query):
|
||||
"""Normalize the query string."""
|
||||
if not query:
|
||||
return query
|
||||
return normalize_percent_characters(query)
|
||||
|
||||
|
||||
def normalize_fragment(fragment):
|
||||
"""Normalize the fragment string."""
|
||||
if not fragment:
|
||||
return fragment
|
||||
return normalize_percent_characters(fragment)
|
||||
|
@ -70,6 +76,10 @@ def normalize_percent_characters(s):
|
|||
|
||||
|
||||
def remove_dot_segments(s):
|
||||
"""Remove dot segments from the string.
|
||||
|
||||
See also Section 5.2.4 of :rfc:`3986`.
|
||||
"""
|
||||
# See http://tools.ietf.org/html/rfc3986#section-5.2.4 for pseudo-code
|
||||
segments = s.split('/') # Turn the path into a list of segments
|
||||
output = [] # Initialize the variable to use to store output
|
||||
|
@ -100,10 +110,11 @@ def remove_dot_segments(s):
|
|||
|
||||
|
||||
def encode_component(uri_component, encoding):
|
||||
"""Encode the specific component in the provided encoding."""
|
||||
if uri_component is None:
|
||||
return uri_component
|
||||
|
||||
uri_bytes = to_bytes(uri_component, encoding)
|
||||
uri_bytes = compat.to_bytes(uri_component, encoding)
|
||||
|
||||
encoded_uri = bytearray()
|
||||
|
||||
|
@ -111,7 +122,7 @@ def encode_component(uri_component, encoding):
|
|||
# Will return a single character bytestring on both Python 2 & 3
|
||||
byte = uri_bytes[i:i+1]
|
||||
byte_ord = ord(byte)
|
||||
if byte_ord < 128 and byte.decode() in NON_PCT_ENCODED:
|
||||
if byte_ord < 128 and byte.decode() in misc.NON_PCT_ENCODED:
|
||||
encoded_uri.extend(byte)
|
||||
continue
|
||||
encoded_uri.extend('%{0:02x}'.format(byte_ord).encode())
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""Module containing the urlparse compatibility logic."""
|
||||
from collections import namedtuple
|
||||
|
||||
from . import compat
|
||||
|
@ -65,10 +66,17 @@ class ParseResultMixin(object):
|
|||
|
||||
class ParseResult(namedtuple('ParseResult', PARSED_COMPONENTS),
|
||||
ParseResultMixin):
|
||||
"""Implementation of urlparse compatibility class.
|
||||
|
||||
This uses the URIReference logic to handle compatibility with the
|
||||
urlparse.ParseResult class.
|
||||
"""
|
||||
|
||||
slots = ()
|
||||
|
||||
def __new__(cls, scheme, userinfo, host, port, path, query, fragment,
|
||||
uri_ref, encoding='utf-8'):
|
||||
"""Create a new ParseResult."""
|
||||
parse_result = super(ParseResult, cls).__new__(
|
||||
cls,
|
||||
scheme or None,
|
||||
|
@ -144,6 +152,7 @@ class ParseResult(namedtuple('ParseResult', PARSED_COMPONENTS),
|
|||
|
||||
def copy_with(self, scheme=None, userinfo=None, host=None, port=None,
|
||||
path=None, query=None, fragment=None):
|
||||
"""Create a copy of this instance replacing with specified parts."""
|
||||
attributes = zip(PARSED_COMPONENTS,
|
||||
(scheme, userinfo, host, port, path, query, fragment))
|
||||
attrs_dict = {}
|
||||
|
@ -160,6 +169,7 @@ class ParseResult(namedtuple('ParseResult', PARSED_COMPONENTS),
|
|||
return ParseResult(uri_ref=ref, encoding=self.encoding, **attrs_dict)
|
||||
|
||||
def encode(self, encoding=None):
|
||||
"""Convert to an instance of ParseResultBytes."""
|
||||
encoding = encoding or self.encoding
|
||||
attrs = dict(
|
||||
zip(PARSED_COMPONENTS,
|
||||
|
@ -187,8 +197,11 @@ class ParseResult(namedtuple('ParseResult', PARSED_COMPONENTS),
|
|||
|
||||
class ParseResultBytes(namedtuple('ParseResultBytes', PARSED_COMPONENTS),
|
||||
ParseResultMixin):
|
||||
"""Compatibility shim for the urlparse.ParseResultBytes object."""
|
||||
|
||||
def __new__(cls, scheme, userinfo, host, port, path, query, fragment,
|
||||
uri_ref, encoding='utf-8', lazy_normalize=True):
|
||||
"""Create a new ParseResultBytes instance."""
|
||||
parse_result = super(ParseResultBytes, cls).__new__(
|
||||
cls,
|
||||
scheme or None,
|
||||
|
@ -272,6 +285,7 @@ class ParseResultBytes(namedtuple('ParseResultBytes', PARSED_COMPONENTS),
|
|||
|
||||
def copy_with(self, scheme=None, userinfo=None, host=None, port=None,
|
||||
path=None, query=None, fragment=None, lazy_normalize=True):
|
||||
"""Create a copy of this instance replacing with specified parts."""
|
||||
attributes = zip(PARSED_COMPONENTS,
|
||||
(scheme, userinfo, host, port, path, query, fragment))
|
||||
attrs_dict = {}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""Module containing the implementation of the URIReference class."""
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2014 Rackspace
|
||||
# Copyright (c) 2015 Ian Cordasco
|
||||
|
@ -15,24 +16,75 @@
|
|||
# limitations under the License.
|
||||
from collections import namedtuple
|
||||
|
||||
from .compat import to_str
|
||||
from .exceptions import InvalidAuthority, ResolutionError
|
||||
from .misc import (
|
||||
ABSOLUTE_URI_MATCHER, FRAGMENT_MATCHER, IPv4_MATCHER, PATH_MATCHER,
|
||||
QUERY_MATCHER, SCHEME_MATCHER, SUBAUTHORITY_MATCHER, URI_MATCHER,
|
||||
URI_COMPONENTS, merge_paths
|
||||
)
|
||||
from .normalizers import (
|
||||
encode_component, normalize_scheme, normalize_authority, normalize_path,
|
||||
normalize_query, normalize_fragment
|
||||
)
|
||||
from . import compat
|
||||
from . import exceptions as exc
|
||||
from . import misc
|
||||
from . import normalizers
|
||||
|
||||
|
||||
class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
||||
class URIReference(namedtuple('URIReference', misc.URI_COMPONENTS)):
|
||||
"""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,
|
||||
|
@ -44,6 +96,7 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
return ref
|
||||
|
||||
def __eq__(self, other):
|
||||
"""Compare this reference to another."""
|
||||
other_ref = other
|
||||
if isinstance(other, tuple):
|
||||
other_ref = URIReference(*other)
|
||||
|
@ -67,49 +120,52 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
:param str encoding: The encoding of the string provided
|
||||
:returns: :class:`URIReference` or subclass thereof
|
||||
"""
|
||||
uri_string = to_str(uri_string, encoding)
|
||||
uri_string = compat.to_str(uri_string, encoding)
|
||||
|
||||
split_uri = URI_MATCHER.match(uri_string).groupdict()
|
||||
return cls(split_uri['scheme'], split_uri['authority'],
|
||||
encode_component(split_uri['path'], encoding),
|
||||
encode_component(split_uri['query'], encoding),
|
||||
encode_component(split_uri['fragment'], encoding), 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,
|
||||
)
|
||||
|
||||
def authority_info(self):
|
||||
"""Returns a dictionary with the ``userinfo``, ``host``, and ``port``.
|
||||
"""Return a dictionary with the ``userinfo``, ``host``, and ``port``.
|
||||
|
||||
If the authority is not valid, it will raise a ``InvalidAuthority``
|
||||
Exception.
|
||||
If the authority is not valid, it will raise a
|
||||
:class:`~rfc3986.exceptions.InvalidAuthority` Exception.
|
||||
|
||||
:returns:
|
||||
``{'userinfo': 'username:password', 'host': 'www.example.com',
|
||||
'port': '80'}``
|
||||
:rtype: dict
|
||||
:raises InvalidAuthority: If the authority is not ``None`` and can not
|
||||
be parsed.
|
||||
:raises rfc3986.exceptions.InvalidAuthority:
|
||||
If the authority is not ``None`` and can not be parsed.
|
||||
"""
|
||||
if not self.authority:
|
||||
return {'userinfo': None, 'host': None, 'port': None}
|
||||
|
||||
match = SUBAUTHORITY_MATCHER.match(self.authority)
|
||||
match = misc.SUBAUTHORITY_MATCHER.match(self.authority)
|
||||
|
||||
if match is None:
|
||||
# In this case, we have an authority that was parsed from the URI
|
||||
# Reference, but it cannot be further parsed by our
|
||||
# SUBAUTHORITY_MATCHER. In this case it must not be a valid
|
||||
# misc.SUBAUTHORITY_MATCHER. In this case it must not be a valid
|
||||
# authority.
|
||||
raise InvalidAuthority(self.authority.encode(self.encoding))
|
||||
raise exc.InvalidAuthority(self.authority.encode(self.encoding))
|
||||
|
||||
# We had a match, now let's ensure that it is actually a valid host
|
||||
# address if it is IPv4
|
||||
matches = match.groupdict()
|
||||
host = matches.get('host')
|
||||
|
||||
if (host and IPv4_MATCHER.match(host) and not
|
||||
if (host and misc.IPv4_MATCHER.match(host) and not
|
||||
valid_ipv4_host_address(host)):
|
||||
# If we have a host, it appears to be IPv4 and it does not have
|
||||
# valid bytes, it is an InvalidAuthority.
|
||||
raise InvalidAuthority(self.authority.encode(self.encoding))
|
||||
raise exc.InvalidAuthority(self.authority.encode(self.encoding))
|
||||
|
||||
return matches
|
||||
|
||||
|
@ -118,16 +174,16 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
"""If present, a string representing the host."""
|
||||
try:
|
||||
authority = self.authority_info()
|
||||
except InvalidAuthority:
|
||||
except exc.InvalidAuthority:
|
||||
return None
|
||||
return authority['host']
|
||||
|
||||
@property
|
||||
def port(self):
|
||||
"""If present, the port (as a string) extracted from the authority."""
|
||||
"""If present, the port extracted from the authority."""
|
||||
try:
|
||||
authority = self.authority_info()
|
||||
except InvalidAuthority:
|
||||
except exc.InvalidAuthority:
|
||||
return None
|
||||
return authority['port']
|
||||
|
||||
|
@ -136,7 +192,7 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
"""If present, the userinfo extracted from the authority."""
|
||||
try:
|
||||
authority = self.authority_info()
|
||||
except InvalidAuthority:
|
||||
except exc.InvalidAuthority:
|
||||
return None
|
||||
return authority['userinfo']
|
||||
|
||||
|
@ -148,10 +204,10 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
:returns: ``True`` if it is an absolute URI, ``False`` otherwise.
|
||||
:rtype: bool
|
||||
"""
|
||||
return bool(ABSOLUTE_URI_MATCHER.match(self.unsplit()))
|
||||
return bool(misc.ABSOLUTE_URI_MATCHER.match(self.unsplit()))
|
||||
|
||||
def is_valid(self, **kwargs):
|
||||
"""Determines if the URI is valid.
|
||||
"""Determine if the URI is valid.
|
||||
|
||||
:param bool require_scheme: Set to ``True`` if you wish to require the
|
||||
presence of the scheme component.
|
||||
|
@ -184,7 +240,7 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
return value is None or matcher.match(value)
|
||||
|
||||
def authority_is_valid(self, require=False):
|
||||
"""Determines if the authority component is valid.
|
||||
"""Determine if the authority component is valid.
|
||||
|
||||
:param str require: Set to ``True`` to require the presence of this
|
||||
component.
|
||||
|
@ -193,15 +249,15 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
"""
|
||||
try:
|
||||
self.authority_info()
|
||||
except InvalidAuthority:
|
||||
except exc.InvalidAuthority:
|
||||
return False
|
||||
|
||||
is_valid = self._is_valid(self.authority,
|
||||
SUBAUTHORITY_MATCHER,
|
||||
misc.SUBAUTHORITY_MATCHER,
|
||||
require)
|
||||
|
||||
# Ensure that IPv4 addresses have valid bytes
|
||||
if is_valid and self.host and IPv4_MATCHER.match(self.host):
|
||||
if is_valid and self.host and misc.IPv4_MATCHER.match(self.host):
|
||||
return valid_ipv4_host_address(self.host)
|
||||
|
||||
# Perhaps the host didn't exist or if it did, it wasn't an IPv4-like
|
||||
|
@ -210,47 +266,47 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
return is_valid
|
||||
|
||||
def scheme_is_valid(self, require=False):
|
||||
"""Determines if the scheme component is valid.
|
||||
"""Determine if the scheme component is valid.
|
||||
|
||||
:param str require: Set to ``True`` to require the presence of this
|
||||
component.
|
||||
:returns: ``True`` if the scheme is valid. ``False`` otherwise.
|
||||
:rtype: bool
|
||||
"""
|
||||
return self._is_valid(self.scheme, SCHEME_MATCHER, require)
|
||||
return self._is_valid(self.scheme, misc.SCHEME_MATCHER, require)
|
||||
|
||||
def path_is_valid(self, require=False):
|
||||
"""Determines if the path component is valid.
|
||||
"""Determine if the path component is valid.
|
||||
|
||||
:param str require: Set to ``True`` to require the presence of this
|
||||
component.
|
||||
:returns: ``True`` if the path is valid. ``False`` otherwise.
|
||||
:rtype: bool
|
||||
"""
|
||||
return self._is_valid(self.path, PATH_MATCHER, require)
|
||||
return self._is_valid(self.path, misc.PATH_MATCHER, require)
|
||||
|
||||
def query_is_valid(self, require=False):
|
||||
"""Determines if the query component is valid.
|
||||
"""Determine if the query component is valid.
|
||||
|
||||
:param str require: Set to ``True`` to require the presence of this
|
||||
component.
|
||||
:returns: ``True`` if the query is valid. ``False`` otherwise.
|
||||
:rtype: bool
|
||||
"""
|
||||
return self._is_valid(self.query, QUERY_MATCHER, require)
|
||||
return self._is_valid(self.query, misc.QUERY_MATCHER, require)
|
||||
|
||||
def fragment_is_valid(self, require=False):
|
||||
"""Determines if the fragment component is valid.
|
||||
"""Determine if the fragment component is valid.
|
||||
|
||||
:param str require: Set to ``True`` to require the presence of this
|
||||
component.
|
||||
:returns: ``True`` if the fragment is valid. ``False`` otherwise.
|
||||
:rtype: bool
|
||||
"""
|
||||
return self._is_valid(self.fragment, FRAGMENT_MATCHER, require)
|
||||
return self._is_valid(self.fragment, misc.FRAGMENT_MATCHER, require)
|
||||
|
||||
def normalize(self):
|
||||
"""Normalize this reference as described in Section 6.2.2
|
||||
"""Normalize this reference as described in Section 6.2.2.
|
||||
|
||||
This is not an in-place normalization. Instead this creates a new
|
||||
URIReference.
|
||||
|
@ -260,12 +316,12 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
"""
|
||||
# See http://tools.ietf.org/html/rfc3986#section-6.2.2 for logic in
|
||||
# this method.
|
||||
return URIReference(normalize_scheme(self.scheme or ''),
|
||||
normalize_authority(
|
||||
return URIReference(normalizers.normalize_scheme(self.scheme or ''),
|
||||
normalizers.normalize_authority(
|
||||
(self.userinfo, self.host, self.port)),
|
||||
normalize_path(self.path or ''),
|
||||
normalize_query(self.query),
|
||||
normalize_fragment(self.fragment),
|
||||
normalizers.normalize_path(self.path or ''),
|
||||
normalizers.normalize_query(self.query),
|
||||
normalizers.normalize_fragment(self.fragment),
|
||||
self.encoding)
|
||||
|
||||
def normalized_equality(self, other_ref):
|
||||
|
@ -291,13 +347,14 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
:returns: A new URIReference which is the result of resolving this
|
||||
reference using ``base_uri``.
|
||||
:rtype: :class:`URIReference`
|
||||
:raises ResolutionError: If the ``base_uri`` is not an absolute URI.
|
||||
:raises rfc3986.exceptions.ResolutionError:
|
||||
If the ``base_uri`` is not an absolute URI.
|
||||
"""
|
||||
if not isinstance(base_uri, URIReference):
|
||||
base_uri = URIReference.from_string(base_uri)
|
||||
|
||||
if not base_uri.is_absolute():
|
||||
raise ResolutionError(base_uri)
|
||||
raise exc.ResolutionError(base_uri)
|
||||
|
||||
# This is optional per
|
||||
# http://tools.ietf.org/html/rfc3986#section-5.2.1
|
||||
|
@ -311,12 +368,14 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
|
||||
# http://tools.ietf.org/html/rfc3986#page-32
|
||||
if resolving.scheme is not None:
|
||||
target = resolving.copy_with(path=normalize_path(resolving.path))
|
||||
target = resolving.copy_with(
|
||||
path=normalizers.normalize_path(resolving.path)
|
||||
)
|
||||
else:
|
||||
if resolving.authority is not None:
|
||||
target = resolving.copy_with(
|
||||
scheme=base_uri.scheme,
|
||||
path=normalize_path(resolving.path)
|
||||
path=normalizers.normalize_path(resolving.path)
|
||||
)
|
||||
else:
|
||||
if resolving.path is None:
|
||||
|
@ -332,10 +391,10 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
)
|
||||
else:
|
||||
if resolving.path.startswith('/'):
|
||||
path = normalize_path(resolving.path)
|
||||
path = normalizers.normalize_path(resolving.path)
|
||||
else:
|
||||
path = normalize_path(
|
||||
merge_paths(base_uri, resolving.path)
|
||||
path = normalizers.normalize_path(
|
||||
misc.merge_paths(base_uri, resolving.path)
|
||||
)
|
||||
target = resolving.copy_with(
|
||||
scheme=base_uri.scheme,
|
||||
|
@ -367,6 +426,23 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
|
||||
def copy_with(self, scheme=None, authority=None, path=None, query=None,
|
||||
fragment=None):
|
||||
"""Create a copy of this reference with the new components.
|
||||
|
||||
:param str scheme:
|
||||
(optional) The scheme to use for the new reference.
|
||||
:param str authority:
|
||||
(optional) The authority to use for the new reference.
|
||||
:param str path:
|
||||
(optional) The path to use for the new reference.
|
||||
:param str query:
|
||||
(optional) The query to use for the new reference.
|
||||
:param str fragment:
|
||||
(optional) The fragment to use for the new reference.
|
||||
:returns:
|
||||
New URIReference with provided components.
|
||||
:rtype:
|
||||
URIReference
|
||||
"""
|
||||
attributes = {
|
||||
'scheme': scheme,
|
||||
'authority': authority,
|
||||
|
@ -383,6 +459,7 @@ class URIReference(namedtuple('URIReference', URI_COMPONENTS)):
|
|||
|
||||
|
||||
def valid_ipv4_host_address(host):
|
||||
"""Determine if the given host is a valid IPv4 address."""
|
||||
# If the host exists, and it might be IPv4, check each byte in the
|
||||
# address.
|
||||
return all([0 <= int(byte, base=10) <= 255 for byte in host.split('.')])
|
||||
|
|
Loading…
Reference in New Issue