@@ -213,6 +213,39 @@ def pre_encoded_url(url_str: str) -> "URL":
213
213
return self
214
214
215
215
216
+ @lru_cache
217
+ def build_pre_encoded_url (
218
+ scheme : str ,
219
+ authority : str ,
220
+ user : Union [str , None ],
221
+ password : Union [str , None ],
222
+ host : str ,
223
+ port : Union [int , None ],
224
+ path : str ,
225
+ query_string : str ,
226
+ fragment : str ,
227
+ ) -> "URL" :
228
+ """Build a pre-encoded URL from parts."""
229
+ self = object .__new__ (URL )
230
+ self ._scheme = scheme
231
+ if authority :
232
+ self ._netloc = authority
233
+ elif host :
234
+ if port is not None :
235
+ port = None if port == DEFAULT_PORTS .get (scheme ) else port
236
+ if user is None and password is None :
237
+ self ._netloc = host if port is None else f"{ host } :{ port } "
238
+ else :
239
+ self ._netloc = make_netloc (user , password , host , port )
240
+ else :
241
+ self ._netloc = ""
242
+ self ._path = path
243
+ self ._query = query_string
244
+ self ._fragment = fragment
245
+ self ._cache = {}
246
+ return self
247
+
248
+
216
249
@lru_cache
217
250
def from_parts (scheme : str , netloc : str , path : str , query : str , fragment : str ) -> "URL" :
218
251
"""Create a new URL from parts."""
@@ -375,61 +408,59 @@ def build(
375
408
'"query_string", and "fragment" args, use empty string instead.'
376
409
)
377
410
411
+ if query :
412
+ query_string = get_str_query (query ) or ""
413
+
378
414
if encoded :
379
- if authority :
380
- netloc = authority
381
- elif host :
382
- if port is not None :
383
- port = None if port == DEFAULT_PORTS .get (scheme ) else port
384
- if user is None and password is None :
385
- netloc = host if port is None else f"{ host } :{ port } "
386
- else :
387
- netloc = make_netloc (user , password , host , port )
388
- else :
389
- netloc = ""
390
- else : # not encoded
391
- _host : Union [str , None ] = None
392
- if authority :
393
- user , password , _host , port = split_netloc (authority )
394
- _host = _encode_host (_host , validate_host = False ) if _host else ""
395
- elif host :
396
- _host = _encode_host (host , validate_host = True )
415
+ return build_pre_encoded_url (
416
+ scheme ,
417
+ authority ,
418
+ user ,
419
+ password ,
420
+ host ,
421
+ port ,
422
+ path ,
423
+ query_string ,
424
+ fragment ,
425
+ )
426
+
427
+ self = object .__new__ (URL )
428
+ self ._scheme = scheme
429
+ _host : Union [str , None ] = None
430
+ if authority :
431
+ user , password , _host , port = split_netloc (authority )
432
+ _host = _encode_host (_host , validate_host = False ) if _host else ""
433
+ elif host :
434
+ _host = _encode_host (host , validate_host = True )
435
+ else :
436
+ self ._netloc = ""
437
+
438
+ if _host is not None :
439
+ if port is not None :
440
+ port = None if port == DEFAULT_PORTS .get (scheme ) else port
441
+ if user is None and password is None :
442
+ self ._netloc = _host if port is None else f"{ _host } :{ port } "
397
443
else :
398
- netloc = ""
399
-
400
- if _host is not None :
401
- if port is not None :
402
- port = None if port == DEFAULT_PORTS .get (scheme ) else port
403
- if user is None and password is None :
404
- netloc = _host if port is None else f"{ _host } :{ port } "
405
- else :
406
- netloc = make_netloc (user , password , _host , port , True )
407
-
408
- path = PATH_QUOTER (path ) if path else path
409
- if path and netloc :
410
- if "." in path :
411
- path = normalize_path (path )
412
- if path [0 ] != "/" :
413
- msg = (
414
- "Path in a URL with authority should "
415
- "start with a slash ('/') if set"
416
- )
417
- raise ValueError (msg )
418
-
419
- query_string = QUERY_QUOTER (query_string ) if query_string else query_string
420
- fragment = FRAGMENT_QUOTER (fragment ) if fragment else fragment
444
+ self ._netloc = make_netloc (user , password , _host , port , True )
421
445
422
- if query :
423
- query_string = get_str_query (query ) or ""
446
+ path = PATH_QUOTER (path ) if path else path
447
+ if path and self ._netloc :
448
+ if "." in path :
449
+ path = normalize_path (path )
450
+ if path [0 ] != "/" :
451
+ msg = (
452
+ "Path in a URL with authority should "
453
+ "start with a slash ('/') if set"
454
+ )
455
+ raise ValueError (msg )
424
456
425
- url = object .__new__ (cls )
426
- url ._scheme = scheme
427
- url ._netloc = netloc
428
- url ._path = path
429
- url ._query = query_string
430
- url ._fragment = fragment
431
- url ._cache = {}
432
- return url
457
+ self ._path = path
458
+ if not query and query_string :
459
+ query_string = QUERY_QUOTER (query_string )
460
+ self ._query = query_string
461
+ self ._fragment = FRAGMENT_QUOTER (fragment ) if fragment else fragment
462
+ self ._cache = {}
463
+ return self
433
464
434
465
def __init_subclass__ (cls ):
435
466
raise TypeError (f"Inheriting a class { cls !r} from URL is forbidden" )
0 commit comments