source: uri/rfc3986/uri.py@ 262

Last change on this file since 262 was 230, checked in by wouter, 4 years ago

#91 clone https://pypi.org/project/rfc3986/

File size: 5.1 KB
Line 
1"""Module containing the implementation of the URIReference class."""
2# -*- coding: utf-8 -*-
3# Copyright (c) 2014 Rackspace
4# Copyright (c) 2015 Ian Stapleton Cordasco
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14# implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17from collections import namedtuple
18
19from . import compat
20from . import misc
21from . import normalizers
22from ._mixin import URIMixin
23
24
25class URIReference(namedtuple("URIReference", misc.URI_COMPONENTS), URIMixin):
26 """Immutable object representing a parsed URI Reference.
27
28 .. note::
29
30 This class is not intended to be directly instantiated by the user.
31
32 This object exposes attributes for the following components of a
33 URI:
34
35 - scheme
36 - authority
37 - path
38 - query
39 - fragment
40
41 .. attribute:: scheme
42
43 The scheme that was parsed for the URI Reference. For example,
44 ``http``, ``https``, ``smtp``, ``imap``, etc.
45
46 .. attribute:: authority
47
48 Component of the URI that contains the user information, host,
49 and port sub-components. For example,
50 ``google.com``, ``127.0.0.1:5000``, ``username@[::1]``,
51 ``username:password@example.com:443``, etc.
52
53 .. attribute:: path
54
55 The path that was parsed for the given URI Reference. For example,
56 ``/``, ``/index.php``, etc.
57
58 .. attribute:: query
59
60 The query component for a given URI Reference. For example, ``a=b``,
61 ``a=b%20c``, ``a=b+c``, ``a=b,c=d,e=%20f``, etc.
62
63 .. attribute:: fragment
64
65 The fragment component of a URI. For example, ``section-3.1``.
66
67 This class also provides extra attributes for easier access to information
68 like the subcomponents of the authority component.
69
70 .. attribute:: userinfo
71
72 The user information parsed from the authority.
73
74 .. attribute:: host
75
76 The hostname, IPv4, or IPv6 address parsed from the authority.
77
78 .. attribute:: port
79
80 The port parsed from the authority.
81 """
82
83 slots = ()
84
85 def __new__(
86 cls, scheme, authority, path, query, fragment, encoding="utf-8"
87 ):
88 """Create a new URIReference."""
89 ref = super(URIReference, cls).__new__(
90 cls,
91 scheme or None,
92 authority or None,
93 path or None,
94 query,
95 fragment,
96 )
97 ref.encoding = encoding
98 return ref
99
100 __hash__ = tuple.__hash__
101
102 def __eq__(self, other):
103 """Compare this reference to another."""
104 other_ref = other
105 if isinstance(other, tuple):
106 other_ref = URIReference(*other)
107 elif not isinstance(other, URIReference):
108 try:
109 other_ref = URIReference.from_string(other)
110 except TypeError:
111 raise TypeError(
112 "Unable to compare URIReference() to {0}()".format(
113 type(other).__name__
114 )
115 )
116
117 # See http://tools.ietf.org/html/rfc3986#section-6.2
118 naive_equality = tuple(self) == tuple(other_ref)
119 return naive_equality or self.normalized_equality(other_ref)
120
121 def normalize(self):
122 """Normalize this reference as described in Section 6.2.2.
123
124 This is not an in-place normalization. Instead this creates a new
125 URIReference.
126
127 :returns: A new reference object with normalized components.
128 :rtype: URIReference
129 """
130 # See http://tools.ietf.org/html/rfc3986#section-6.2.2 for logic in
131 # this method.
132 return URIReference(
133 normalizers.normalize_scheme(self.scheme or ""),
134 normalizers.normalize_authority(
135 (self.userinfo, self.host, self.port)
136 ),
137 normalizers.normalize_path(self.path or ""),
138 normalizers.normalize_query(self.query),
139 normalizers.normalize_fragment(self.fragment),
140 self.encoding,
141 )
142
143 @classmethod
144 def from_string(cls, uri_string, encoding="utf-8"):
145 """Parse a URI reference from the given unicode URI string.
146
147 :param str uri_string: Unicode URI to be parsed into a reference.
148 :param str encoding: The encoding of the string provided
149 :returns: :class:`URIReference` or subclass thereof
150 """
151 uri_string = compat.to_str(uri_string, encoding)
152
153 split_uri = misc.URI_MATCHER.match(uri_string).groupdict()
154 return cls(
155 split_uri["scheme"],
156 split_uri["authority"],
157 normalizers.encode_component(split_uri["path"], encoding),
158 normalizers.encode_component(split_uri["query"], encoding),
159 normalizers.encode_component(split_uri["fragment"], encoding),
160 encoding,
161 )
Note: See TracBrowser for help on using the repository browser.