Join a base URL and a possibly relative URL to form an absolute interpretation of the latter.
(base, url, allow_fragments=True)
| 578 | return url |
| 579 | |
| 580 | def urljoin(base, url, allow_fragments=True): |
| 581 | """Join a base URL and a possibly relative URL to form an absolute |
| 582 | interpretation of the latter.""" |
| 583 | if not base: |
| 584 | return url |
| 585 | if not url: |
| 586 | return base |
| 587 | |
| 588 | base, url, _coerce_result = _coerce_args(base, url) |
| 589 | bscheme, bnetloc, bpath, bquery, bfragment = \ |
| 590 | _urlsplit(base, None, allow_fragments) |
| 591 | scheme, netloc, path, query, fragment = \ |
| 592 | _urlsplit(url, None, allow_fragments) |
| 593 | |
| 594 | if scheme is None: |
| 595 | scheme = bscheme |
| 596 | if scheme != bscheme or (scheme and scheme not in uses_relative): |
| 597 | return _coerce_result(url) |
| 598 | if not scheme or scheme in uses_netloc: |
| 599 | if netloc: |
| 600 | return _coerce_result(_urlunsplit(scheme, netloc, path, |
| 601 | query, fragment)) |
| 602 | netloc = bnetloc |
| 603 | |
| 604 | if not path: |
| 605 | path = bpath |
| 606 | if query is None: |
| 607 | query = bquery |
| 608 | if fragment is None: |
| 609 | fragment = bfragment |
| 610 | return _coerce_result(_urlunsplit(scheme, netloc, path, |
| 611 | query, fragment)) |
| 612 | |
| 613 | base_parts = bpath.split('/') |
| 614 | if base_parts[-1] != '': |
| 615 | # the last item is not a directory, so will not be taken into account |
| 616 | # in resolving the relative path |
| 617 | del base_parts[-1] |
| 618 | |
| 619 | # for rfc3986, ignore all base path should the first character be root. |
| 620 | if path[:1] == '/': |
| 621 | segments = path.split('/') |
| 622 | else: |
| 623 | segments = base_parts + path.split('/') |
| 624 | # filter out elements that would cause redundant slashes on re-joining |
| 625 | # the resolved_path |
| 626 | segments[1:-1] = filter(None, segments[1:-1]) |
| 627 | |
| 628 | resolved_path = [] |
| 629 | |
| 630 | for seg in segments: |
| 631 | if seg == '..': |
| 632 | try: |
| 633 | resolved_path.pop() |
| 634 | except IndexError: |
| 635 | # ignore any .. segments that would otherwise cause an IndexError |
| 636 | # when popped from resolved_path if resolving for rfc3986 |
| 637 | pass |
no test coverage detected