Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/rfc3986/uri.py: 69%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

32 statements  

1"""Module containing the implementation of the URIReference class.""" 

2 

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. 

17import typing as t 

18 

19from . import compat 

20from . import misc 

21from . import normalizers 

22from ._mixin import URIMixin 

23from ._typing_compat import Self as _Self 

24 

25 

26class URIReference(misc.URIReferenceBase, URIMixin): 

27 """Immutable object representing a parsed URI Reference. 

28 

29 .. note:: 

30 

31 This class is not intended to be directly instantiated by the user. 

32 

33 This object exposes attributes for the following components of a 

34 URI: 

35 

36 - scheme 

37 - authority 

38 - path 

39 - query 

40 - fragment 

41 

42 .. attribute:: scheme 

43 

44 The scheme that was parsed for the URI Reference. For example, 

45 ``http``, ``https``, ``smtp``, ``imap``, etc. 

46 

47 .. attribute:: authority 

48 

49 Component of the URI that contains the user information, host, 

50 and port sub-components. For example, 

51 ``google.com``, ``127.0.0.1:5000``, ``username@[::1]``, 

52 ``username:password@example.com:443``, etc. 

53 

54 .. attribute:: path 

55 

56 The path that was parsed for the given URI Reference. For example, 

57 ``/``, ``/index.php``, etc. 

58 

59 .. attribute:: query 

60 

61 The query component for a given URI Reference. For example, ``a=b``, 

62 ``a=b%20c``, ``a=b+c``, ``a=b,c=d,e=%20f``, etc. 

63 

64 .. attribute:: fragment 

65 

66 The fragment component of a URI. For example, ``section-3.1``. 

67 

68 This class also provides extra attributes for easier access to information 

69 like the subcomponents of the authority component. 

70 

71 .. attribute:: userinfo 

72 

73 The user information parsed from the authority. 

74 

75 .. attribute:: host 

76 

77 The hostname, IPv4, or IPv6 address parsed from the authority. 

78 

79 .. attribute:: port 

80 

81 The port parsed from the authority. 

82 """ 

83 

84 encoding: str 

85 

86 def __new__( 

87 cls, 

88 scheme: t.Optional[str], 

89 authority: t.Optional[str], 

90 path: t.Optional[str], 

91 query: t.Optional[str], 

92 fragment: t.Optional[str], 

93 encoding: str = "utf-8", 

94 ) -> _Self: 

95 """Create a new URIReference.""" 

96 ref = super().__new__( 

97 cls, 

98 scheme or None, 

99 authority or None, 

100 path or None, 

101 query, 

102 fragment, 

103 ) 

104 ref.encoding = encoding 

105 return ref 

106 

107 __hash__ = tuple.__hash__ 

108 

109 def __eq__(self, other: object) -> bool: 

110 """Compare this reference to another.""" 

111 other_ref = other 

112 if isinstance(other, tuple): 

113 other_ref = type(self)(*other) 

114 elif not isinstance(other, URIReference): 

115 try: 

116 other_ref = self.from_string(other) 

117 except TypeError: 

118 raise TypeError( 

119 "Unable to compare {}() to {}()".format( 

120 type(self).__name__, type(other).__name__ 

121 ) 

122 ) 

123 

124 # See http://tools.ietf.org/html/rfc3986#section-6.2 

125 naive_equality = tuple(self) == tuple(other_ref) 

126 return naive_equality or self.normalized_equality(other_ref) 

127 

128 def normalize(self) -> "URIReference": 

129 """Normalize this reference as described in Section 6.2.2. 

130 

131 This is not an in-place normalization. Instead this creates a new 

132 URIReference. 

133 

134 :returns: A new reference object with normalized components. 

135 :rtype: URIReference 

136 """ 

137 # See http://tools.ietf.org/html/rfc3986#section-6.2.2 for logic in 

138 # this method. 

139 return URIReference( 

140 normalizers.normalize_scheme(self.scheme or ""), 

141 normalizers.normalize_authority( 

142 (self.userinfo, self.host, self.port) 

143 ), 

144 normalizers.normalize_path(self.path or ""), 

145 normalizers.normalize_query(self.query), 

146 normalizers.normalize_fragment(self.fragment), 

147 self.encoding, 

148 ) 

149 

150 @classmethod 

151 def from_string( 

152 cls, 

153 uri_string: t.Union[str, bytes], 

154 encoding: str = "utf-8", 

155 ) -> _Self: 

156 """Parse a URI reference from the given unicode URI string. 

157 

158 :param str uri_string: Unicode URI to be parsed into a reference. 

159 :param str encoding: The encoding of the string provided 

160 :returns: :class:`URIReference` or subclass thereof 

161 """ 

162 uri_string = compat.to_str(uri_string, encoding) 

163 

164 split_uri = misc.URI_MATCHER.match(uri_string).groupdict() 

165 return cls( 

166 split_uri["scheme"], 

167 split_uri["authority"], 

168 normalizers.encode_component(split_uri["path"], encoding), 

169 normalizers.encode_component(split_uri["query"], encoding), 

170 normalizers.encode_component(split_uri["fragment"], encoding), 

171 encoding, 

172 )