/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/urlutils.py

  • Committer: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2020-02-14 03:16:54 UTC
  • mfrom: (7479.2.3 no-more-python2)
  • Revision ID: breezy.the.bot@gmail.com-20200214031654-bp1xtv2jr9nmhto3
Drop python2 support.

Merged from https://code.launchpad.net/~jelmer/brz/no-more-python2/+merge/378694

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
import re
23
23
import sys
24
24
 
25
 
try:
26
 
    import urlparse
27
 
except ImportError:
28
 
    from urllib import parse as urlparse
 
25
from urllib import parse as urlparse
29
26
 
30
27
from . import (
31
28
    errors,
37
34
from posixpath import split as _posix_split
38
35
""")
39
36
 
40
 
from .sixish import (
41
 
    int2byte,
42
 
    PY3,
43
 
    text_type,
44
 
    unichr,
45
 
    )
46
37
 
47
38
 
48
39
class InvalidURL(errors.PathError):
99
90
    return split(url, exclude_trailing_slash=exclude_trailing_slash)[0]
100
91
 
101
92
 
102
 
if PY3:
103
 
    quote_from_bytes = urlparse.quote_from_bytes
104
 
    quote = urlparse.quote
105
 
    unquote_to_bytes = urlparse.unquote_to_bytes
106
 
else:
107
 
    # Private copies of quote and unquote, copied from Python's urllib module
108
 
    # because urllib unconditionally imports socket, which imports ssl.
109
 
 
110
 
    always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'
111
 
                   'abcdefghijklmnopqrstuvwxyz'
112
 
                   '0123456789' '_.-')
113
 
    _safe_map = {}
114
 
    for i, c in zip(range(256), ''.join(map(chr, range(256)))):
115
 
        _safe_map[c] = c if (
116
 
            i < 128 and c in always_safe) else '%{0:02X}'.format(i)
117
 
    _safe_quoters = {}
118
 
 
119
 
    def quote_from_bytes(s, safe='/'):
120
 
        """quote('abc def') -> 'abc%20def'
121
 
 
122
 
        Each part of a URL, e.g. the path info, the query, etc., has a
123
 
        different set of reserved characters that must be quoted.
124
 
 
125
 
        RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists
126
 
        the following reserved characters.
127
 
 
128
 
        reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
129
 
                      "$" | ","
130
 
 
131
 
        Each of these characters is reserved in some component of a URL,
132
 
        but not necessarily in all of them.
133
 
 
134
 
        By default, the quote function is intended for quoting the path
135
 
        section of a URL.  Thus, it will not encode '/'.  This character
136
 
        is reserved, but in typical usage the quote function is being
137
 
        called on a path where the existing slash characters are used as
138
 
        reserved characters.
139
 
        """
140
 
        # fastpath
141
 
        if not s:
142
 
            if s is None:
143
 
                raise TypeError('None object cannot be quoted')
144
 
            return s
145
 
        cachekey = (safe, always_safe)
146
 
        try:
147
 
            (quoter, safe) = _safe_quoters[cachekey]
148
 
        except KeyError:
149
 
            safe_map = _safe_map.copy()
150
 
            safe_map.update([(c, c) for c in safe])
151
 
            quoter = safe_map.__getitem__
152
 
            safe = always_safe + safe
153
 
            _safe_quoters[cachekey] = (quoter, safe)
154
 
        if not s.rstrip(safe):
155
 
            return s
156
 
        return ''.join(map(quoter, s))
157
 
 
158
 
    quote = quote_from_bytes
159
 
    unquote_to_bytes = urlparse.unquote
160
 
 
161
 
 
 
93
quote_from_bytes = urlparse.quote_from_bytes
 
94
quote = urlparse.quote
 
95
unquote_to_bytes = urlparse.unquote_to_bytes
162
96
unquote = urlparse.unquote
163
97
 
164
98
 
165
99
def escape(relpath, safe='/~'):
166
100
    """Escape relpath to be a valid url."""
167
 
    if not isinstance(relpath, str) and sys.version_info[0] == 2:
168
 
        # GZ 2019-06-16: Should use _fs_enc instead here really?
169
 
        relpath = relpath.encode('utf-8')
170
101
    return quote(relpath, safe=safe)
171
102
 
172
103
 
411
342
        return local_path_to_url(url)
412
343
    prefix = url[:path_start]
413
344
    path = url[path_start:]
414
 
    if not isinstance(url, text_type):
 
345
    if not isinstance(url, str):
415
346
        for c in url:
416
347
            if c not in _url_safe_characters:
417
348
                raise InvalidURL(url, 'URLs can only contain specific'
691
622
    #       try to encode the UNICODE => ASCII, and then decode
692
623
    #       it into utf-8.
693
624
 
694
 
    if PY3:
695
 
        if isinstance(url, text_type):
696
 
            try:
697
 
                url.encode("ascii")
698
 
            except UnicodeError as e:
699
 
                raise InvalidURL(
700
 
                    url, 'URL was not a plain ASCII url: %s' % (e,))
701
 
        return urlparse.unquote(url)
702
 
    else:
703
 
        if isinstance(url, text_type):
704
 
            try:
705
 
                url = url.encode("ascii")
706
 
            except UnicodeError as e:
707
 
                raise InvalidURL(
708
 
                    url, 'URL was not a plain ASCII url: %s' % (e,))
709
 
        unquoted = unquote(url)
 
625
    if isinstance(url, str):
710
626
        try:
711
 
            unicode_path = unquoted.decode('utf-8')
 
627
            url.encode("ascii")
712
628
        except UnicodeError as e:
713
629
            raise InvalidURL(
714
 
                url, 'Unable to encode the URL as utf-8: %s' % (e,))
715
 
        return unicode_path
 
630
                url, 'URL was not a plain ASCII url: %s' % (e,))
 
631
    return urlparse.unquote(url)
716
632
 
717
633
 
718
634
# These are characters that if escaped, should stay that way
720
636
_no_decode_ords = [ord(c) for c in _no_decode_chars]
721
637
_no_decode_hex = (['%02x' % o for o in _no_decode_ords]
722
638
                  + ['%02X' % o for o in _no_decode_ords])
723
 
_hex_display_map = dict(([('%02x' % o, int2byte(o)) for o in range(256)]
724
 
                         + [('%02X' % o, int2byte(o)) for o in range(256)]))
 
639
_hex_display_map = dict(([('%02x' % o, bytes([o])) for o in range(256)]
 
640
                         + [('%02X' % o, bytes([o])) for o in range(256)]))
725
641
# These entries get mapped to themselves
726
642
_hex_display_map.update((hex, b'%' + hex.encode('ascii'))
727
643
                        for hex in _no_decode_hex)
765
681
            escaped_chunks[j] = _hex_display_map[item[:2]]
766
682
        except KeyError:
767
683
            # Put back the percent symbol
768
 
            escaped_chunks[j] = b'%' + \
769
 
                (item[:2].encode('utf-8') if PY3 else item[:2])
 
684
            escaped_chunks[j] = b'%' + (item[:2].encode('utf-8'))
770
685
        except UnicodeDecodeError:
771
 
            escaped_chunks[j] = unichr(int(item[:2], 16)).encode('utf-8')
772
 
        escaped_chunks[j] += (item[2:].encode('utf-8') if PY3 else item[2:])
 
686
            escaped_chunks[j] = chr(int(item[:2], 16)).encode('utf-8')
 
687
        escaped_chunks[j] += (item[2:].encode('utf-8'))
773
688
    unescaped = b''.join(escaped_chunks)
774
689
    try:
775
690
        decoded = unescaped.decode('utf-8')
933
848
        # unicode.
934
849
        if isinstance(url, str):
935
850
            pass
936
 
        elif isinstance(url, text_type):
 
851
        elif isinstance(url, str):
937
852
            try:
938
853
                url = url.encode()
939
854
            except UnicodeEncodeError:
1004
919
        # unicode.
1005
920
        if isinstance(relpath, str):
1006
921
            pass
1007
 
        elif isinstance(relpath, text_type):
 
922
        elif isinstance(relpath, str):
1008
923
            try:
1009
924
                relpath = relpath.encode()
1010
925
            except UnicodeEncodeError:
1042
957
        """
1043
958
        if offset is not None:
1044
959
            relative = unescape(offset)
1045
 
            if sys.version_info[0] == 2:
1046
 
                relative = relative.encode('utf-8')
1047
960
            path = self._combine_paths(self.path, relative)
1048
961
            path = quote(path, safe="/~")
1049
962
        else: