Parse a URL into 5 components: :// / ? # The result is a named 5-tuple with fields corresponding to the above. It is either a SplitResult or SplitResultBytes object, depending on the type of the url parameter. The username, password, h
(url, scheme='', allow_fragments=True)
| 451 | # comparison since this API supports both bytes and str input. |
| 452 | @functools.lru_cache(typed=True) |
| 453 | def urlsplit(url, scheme='', allow_fragments=True): |
| 454 | """Parse a URL into 5 components: |
| 455 | <scheme>://<netloc>/<path>?<query>#<fragment> |
| 456 | |
| 457 | The result is a named 5-tuple with fields corresponding to the |
| 458 | above. It is either a SplitResult or SplitResultBytes object, |
| 459 | depending on the type of the url parameter. |
| 460 | |
| 461 | The username, password, hostname, and port sub-components of netloc |
| 462 | can also be accessed as attributes of the returned object. |
| 463 | |
| 464 | The scheme argument provides the default value of the scheme |
| 465 | component when no scheme is found in url. |
| 466 | |
| 467 | If allow_fragments is False, no attempt is made to separate the |
| 468 | fragment component from the previous component, which can be either |
| 469 | path or query. |
| 470 | |
| 471 | Note that % escapes are not expanded. |
| 472 | """ |
| 473 | |
| 474 | url, scheme, _coerce_result = _coerce_args(url, scheme) |
| 475 | # Only lstrip url as some applications rely on preserving trailing space. |
| 476 | # (https://url.spec.whatwg.org/#concept-basic-url-parser would strip both) |
| 477 | url = url.lstrip(_WHATWG_C0_CONTROL_OR_SPACE) |
| 478 | scheme = scheme.strip(_WHATWG_C0_CONTROL_OR_SPACE) |
| 479 | |
| 480 | for b in _UNSAFE_URL_BYTES_TO_REMOVE: |
| 481 | url = url.replace(b, "") |
| 482 | scheme = scheme.replace(b, "") |
| 483 | |
| 484 | allow_fragments = bool(allow_fragments) |
| 485 | netloc = query = fragment = '' |
| 486 | i = url.find(':') |
| 487 | if i > 0 and url[0].isascii() and url[0].isalpha(): |
| 488 | for c in url[:i]: |
| 489 | if c not in scheme_chars: |
| 490 | break |
| 491 | else: |
| 492 | scheme, url = url[:i].lower(), url[i+1:] |
| 493 | if url[:2] == '//': |
| 494 | netloc, url = _splitnetloc(url, 2) |
| 495 | if (('[' in netloc and ']' not in netloc) or |
| 496 | (']' in netloc and '[' not in netloc)): |
| 497 | raise ValueError("Invalid IPv6 URL") |
| 498 | if '[' in netloc and ']' in netloc: |
| 499 | bracketed_host = netloc.partition('[')[2].partition(']')[0] |
| 500 | _check_bracketed_host(bracketed_host) |
| 501 | if allow_fragments and '#' in url: |
| 502 | url, fragment = url.split('#', 1) |
| 503 | if '?' in url: |
| 504 | url, query = url.split('?', 1) |
| 505 | _checknetloc(netloc) |
| 506 | v = SplitResult(scheme, netloc, url, query, fragment) |
| 507 | return _coerce_result(v) |
| 508 | |
| 509 | def urlunparse(components): |
| 510 | """Put a parsed URL back together again. This may result in a |
no test coverage detected