@@ -140,6 +140,27 @@ def _coerce_args(*args):
140140 return args + (_noop ,)
141141 return _decode_args (args ) + (_encode_result ,)
142142
143+ def _parse_hostinfo (netloc ):
144+ _ , _ , hostinfo = netloc .rpartition ('@' )
145+ _ , have_open_br , bracketed = hostinfo .partition ('[' )
146+ if have_open_br :
147+ hostname , _ , port = bracketed .partition (']' )
148+ _ , _ , port = port .partition (':' )
149+ else :
150+ hostname , _ , port = hostinfo .partition (':' )
151+ if not port :
152+ port = None
153+ return hostname , port
154+
155+ def _validate_port (port ):
156+ if port .isdigit () and port .isascii ():
157+ port = int (port )
158+ else :
159+ raise ValueError (f"Port could not be cast to integer value as { port !r} " )
160+ if not (0 <= port <= 65535 ):
161+ raise ValueError ("Port out of range 0-65535" )
162+ return port
163+
143164# Result objects are more helpful than simple tuples
144165class _ResultMixinStr (object ):
145166 """Standard approach to encoding parsed results from str to bytes"""
@@ -198,12 +219,7 @@ def hostname(self):
198219 def port (self ):
199220 port = self ._hostinfo [1 ]
200221 if port is not None :
201- if port .isdigit () and port .isascii ():
202- port = int (port )
203- else :
204- raise ValueError (f"Port could not be cast to integer value as { port !r} " )
205- if not (0 <= port <= 65535 ):
206- raise ValueError ("Port out of range 0-65535" )
222+ port = _validate_port (port )
207223 return port
208224
209225 __class_getitem__ = classmethod (types .GenericAlias )
@@ -231,16 +247,7 @@ def _hostinfo(self):
231247 netloc = self .netloc
232248 if netloc is None :
233249 return None , None
234- _ , _ , hostinfo = netloc .rpartition ('@' )
235- _ , have_open_br , bracketed = hostinfo .partition ('[' )
236- if have_open_br :
237- hostname , _ , port = bracketed .partition (']' )
238- _ , _ , port = port .partition (':' )
239- else :
240- hostname , _ , port = hostinfo .partition (':' )
241- if not port :
242- port = None
243- return hostname , port
250+ return _parse_hostinfo (netloc )
244251
245252
246253class _NetlocResultMixinBytes (_NetlocResultMixinBase , _ResultMixinBytes ):
@@ -506,9 +513,7 @@ def _splitnetloc(url, start=0):
506513 delim = min (delim , wdelim ) # use earliest delim position
507514 return url [start :delim ], url [delim :] # return (domain, rest)
508515
509- def _checknetloc (netloc ):
510- if not netloc or netloc .isascii ():
511- return
516+ def _checknetloc_nfkc (netloc ):
512517 # looking for characters like \u2100 that expand to 'a/c'
513518 # IDNA uses NFKC equivalence, so normalize for this check
514519 import unicodedata
@@ -524,6 +529,16 @@ def _checknetloc(netloc):
524529 raise ValueError ("netloc '" + netloc + "' contains invalid " +
525530 "characters under NFKC normalization" )
526531
532+ def _checknetloc (netloc ):
533+ if not netloc :
534+ return
535+ if not netloc .isascii ():
536+ _checknetloc_nfkc (netloc )
537+
538+ _ , port = _parse_hostinfo (netloc )
539+ if port is not None :
540+ _validate_port (port )
541+
527542def _check_bracketed_netloc (netloc ):
528543 # Note that this function must mirror the splitting
529544 # done in NetlocResultMixins._hostinfo().
0 commit comments