11"""Module containing the implementation of the URIMixin class."""
2+
3+ import typing as t
24import warnings
35
46from . import exceptions as exc
57from . import misc
68from . import normalizers
9+ from . import uri
710from . import validators
11+ from ._typing_compat import Self as _Self
12+
13+
14+ class _AuthorityInfo (t .TypedDict ):
15+ """A typed dict for the authority info triple: userinfo, host, and port."""
16+
17+ userinfo : t .Optional [str ]
18+ host : t .Optional [str ]
19+ port : t .Optional [str ]
820
921
1022class URIMixin :
1123 """Mixin with all shared methods for URIs and IRIs."""
1224
13- __hash__ = tuple .__hash__
25+ if t .TYPE_CHECKING :
26+ scheme : t .Optional [str ]
27+ authority : t .Optional [str ]
28+ path : t .Optional [str ]
29+ query : t .Optional [str ]
30+ fragment : t .Optional [str ]
31+ encoding : str
1432
15- def authority_info (self ):
33+ def authority_info (self ) -> _AuthorityInfo :
1634 """Return a dictionary with the ``userinfo``, ``host``, and ``port``.
1735
1836 If the authority is not valid, it will raise a
@@ -53,11 +71,11 @@ def authority_info(self):
5371
5472 return matches
5573
56- def _match_subauthority (self ):
74+ def _match_subauthority (self ) -> t . Optional [ t . Match [ str ]] :
5775 return misc .SUBAUTHORITY_MATCHER .match (self .authority )
5876
5977 @property
60- def _validator (self ):
78+ def _validator (self ) -> validators . Validator :
6179 v = getattr (self , "_cached_validator" , None )
6280 if v is not None :
6381 return v
@@ -67,7 +85,7 @@ def _validator(self):
6785 return self ._cached_validator
6886
6987 @property
70- def host (self ):
88+ def host (self ) -> t . Optional [ str ] :
7189 """If present, a string representing the host."""
7290 try :
7391 authority = self .authority_info ()
@@ -76,7 +94,7 @@ def host(self):
7694 return authority ["host" ]
7795
7896 @property
79- def port (self ):
97+ def port (self ) -> t . Optional [ str ] :
8098 """If present, the port extracted from the authority."""
8199 try :
82100 authority = self .authority_info ()
@@ -85,15 +103,15 @@ def port(self):
85103 return authority ["port" ]
86104
87105 @property
88- def userinfo (self ):
106+ def userinfo (self ) -> t . Optional [ str ] :
89107 """If present, the userinfo extracted from the authority."""
90108 try :
91109 authority = self .authority_info ()
92110 except exc .InvalidAuthority :
93111 return None
94112 return authority ["userinfo" ]
95113
96- def is_absolute (self ):
114+ def is_absolute (self ) -> bool :
97115 """Determine if this URI Reference is an absolute URI.
98116
99117 See http://tools.ietf.org/html/rfc3986#section-4.3 for explanation.
@@ -103,7 +121,7 @@ def is_absolute(self):
103121 """
104122 return bool (misc .ABSOLUTE_URI_MATCHER .match (self .unsplit ()))
105123
106- def is_valid (self , ** kwargs ) :
124+ def is_valid (self , ** kwargs : bool ) -> bool :
107125 """Determine if the URI is valid.
108126
109127 .. deprecated:: 1.1.0
@@ -137,7 +155,7 @@ def is_valid(self, **kwargs):
137155 ]
138156 return all (v (r ) for v , r in validators )
139157
140- def authority_is_valid (self , require = False ):
158+ def authority_is_valid (self , require : bool = False ) -> bool :
141159 """Determine if the authority component is valid.
142160
143161 .. deprecated:: 1.1.0
@@ -167,7 +185,7 @@ def authority_is_valid(self, require=False):
167185 require = require ,
168186 )
169187
170- def scheme_is_valid (self , require = False ):
188+ def scheme_is_valid (self , require : bool = False ) -> bool :
171189 """Determine if the scheme component is valid.
172190
173191 .. deprecated:: 1.1.0
@@ -186,7 +204,7 @@ def scheme_is_valid(self, require=False):
186204 )
187205 return validators .scheme_is_valid (self .scheme , require )
188206
189- def path_is_valid (self , require = False ):
207+ def path_is_valid (self , require : bool = False ) -> bool :
190208 """Determine if the path component is valid.
191209
192210 .. deprecated:: 1.1.0
@@ -205,7 +223,7 @@ def path_is_valid(self, require=False):
205223 )
206224 return validators .path_is_valid (self .path , require )
207225
208- def query_is_valid (self , require = False ):
226+ def query_is_valid (self , require : bool = False ) -> bool :
209227 """Determine if the query component is valid.
210228
211229 .. deprecated:: 1.1.0
@@ -224,7 +242,7 @@ def query_is_valid(self, require=False):
224242 )
225243 return validators .query_is_valid (self .query , require )
226244
227- def fragment_is_valid (self , require = False ):
245+ def fragment_is_valid (self , require : bool = False ) -> bool :
228246 """Determine if the fragment component is valid.
229247
230248 .. deprecated:: 1.1.0
@@ -243,7 +261,7 @@ def fragment_is_valid(self, require=False):
243261 )
244262 return validators .fragment_is_valid (self .fragment , require )
245263
246- def normalized_equality (self , other_ref ) :
264+ def normalized_equality (self , other_ref : "uri.URIReference" ) -> bool :
247265 """Compare this URIReference to another URIReference.
248266
249267 :param URIReference other_ref: (required), The reference with which
@@ -253,7 +271,11 @@ def normalized_equality(self, other_ref):
253271 """
254272 return tuple (self .normalize ()) == tuple (other_ref .normalize ())
255273
256- def resolve_with (self , base_uri , strict = False ):
274+ def resolve_with ( # noqa: C901
275+ self ,
276+ base_uri : t .Union [str , "uri.URIReference" ],
277+ strict : bool = False ,
278+ ) -> _Self :
257279 """Use an absolute URI Reference to resolve this relative reference.
258280
259281 Assuming this is a relative reference that you would like to resolve,
@@ -272,6 +294,9 @@ def resolve_with(self, base_uri, strict=False):
272294 if not isinstance (base_uri , URIMixin ):
273295 base_uri = type (self ).from_string (base_uri )
274296
297+ if t .TYPE_CHECKING :
298+ base_uri = t .cast (uri .URIReference , base_uri )
299+
275300 try :
276301 self ._validator .validate (base_uri )
277302 except exc .ValidationError :
@@ -325,14 +350,14 @@ def resolve_with(self, base_uri, strict=False):
325350 )
326351 return target
327352
328- def unsplit (self ):
353+ def unsplit (self ) -> str :
329354 """Create a URI string from the components.
330355
331356 :returns: The URI Reference reconstituted as a string.
332357 :rtype: str
333358 """
334359 # See http://tools.ietf.org/html/rfc3986#section-5.3
335- result_list = []
360+ result_list : list [ str ] = []
336361 if self .scheme :
337362 result_list .extend ([self .scheme , ":" ])
338363 if self .authority :
@@ -347,12 +372,12 @@ def unsplit(self):
347372
348373 def copy_with (
349374 self ,
350- scheme = misc .UseExisting ,
351- authority = misc .UseExisting ,
352- path = misc .UseExisting ,
353- query = misc .UseExisting ,
354- fragment = misc .UseExisting ,
355- ):
375+ scheme : t . Optional [ str ] = misc .UseExisting ,
376+ authority : t . Optional [ str ] = misc .UseExisting ,
377+ path : t . Optional [ str ] = misc .UseExisting ,
378+ query : t . Optional [ str ] = misc .UseExisting ,
379+ fragment : t . Optional [ str ] = misc .UseExisting ,
380+ ) -> _Self :
356381 """Create a copy of this reference with the new components.
357382
358383 :param str scheme:
@@ -380,6 +405,6 @@ def copy_with(
380405 for key , value in list (attributes .items ()):
381406 if value is misc .UseExisting :
382407 del attributes [key ]
383- uri = self ._replace (** attributes )
408+ uri : _Self = self ._replace (** attributes )
384409 uri .encoding = self .encoding
385410 return uri
0 commit comments