-
Notifications
You must be signed in to change notification settings - Fork 3
/
urlutils.py
125 lines (93 loc) · 3.63 KB
/
urlutils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import urllib
import sublime
import sublime_plugin
import urllib.request
from urllib.parse import urlparse, urlunparse, parse_qsl, urlencode
def selections(view):
# get selected text regions or all text region if none selected
# from: https://github.com/mastahyeti/URLEncode/blob/master/urlencode.py#L24
regions = [r for r in view.sel() if not r.empty()]
if not regions:
regions = [sublime.Region(0, view.size())]
return regions
class ReplaceCommandBase(sublime_plugin.TextCommand):
@staticmethod
def process(s):
raise Exception('`process` method is missing.')
def run(self, edit):
view = self.view
drift = 0
for region in selections(view):
region.a += drift
region.b += drift
original_str = view.substr(region)
processed_str = self.process(original_str)
drift += len(processed_str) - len(original_str)
view.replace(edit, region, processed_str)
class UrlencodeCommand(ReplaceCommandBase):
process = staticmethod(lambda s: urllib.parse.quote(s, safe='\r\n'))
class UrldecodeCommand(ReplaceCommandBase):
process = staticmethod(lambda s: urllib.parse.unquote(s.replace('+', ' ')))
class ParseCommandBase(ReplaceCommandBase):
url_parts = ['scheme', 'netloc', 'path', 'params', 'query', 'fragment']
def header_format(f):
return '\n' + (' ' + f + ' ').center(75, '-') + '\n'
class UrlparseCommand(ParseCommandBase):
@staticmethod
def _query_parse(val):
lines = []
query = dict(parse_qsl(val, keep_blank_values=True))
max_key_len = max(map(len, query.keys())) + 3
for k, v in sorted(query.items()):
lines.append('{key} : {val}'.format(key=k.rjust(max_key_len, ' '), val=v))
return lines
@staticmethod
def _parse(s):
parsed = urlparse(s)
lines = []
for f in ParseCommandBase.url_parts:
# skip empty vals
val = getattr(parsed, f)
if not val:
continue
# header
lines.append(ParseCommandBase.header_format(f))
# key-vals
if f == 'query':
lines.extend(UrlparseCommand._query_parse(val))
else:
lines.append(val)
lines = [UrldecodeCommand.process(x) for x in lines]
return '\n'.join(lines).strip()
@staticmethod
def process(s):
return UrlparseCommand._parse(s)
class UrlunparseCommand(ParseCommandBase):
@staticmethod
def _query_unparse(parsed_val):
return urlencode(
[(kv.split(' : ')[0].strip(), kv.split(' : ')[1])
for kv in parsed_val.split('\n')]
)
@staticmethod
def _unparse(s):
found_parts = []
found_values = [s]
for url_part in ParseCommandBase.url_parts:
header = ParseCommandBase.header_format(url_part).strip()
if header in s:
found_parts.append(url_part)
found_values = found_values[0:-1] + found_values[-1].split(header)
parsed_kv = dict(zip(found_parts, [val.strip('\n\r') for val in found_values[1:]]))
parsed_kv['query'] = UrlunparseCommand._query_unparse(parsed_kv['query'])
return urlunparse([parsed_kv.get(url_part, '')
for url_part in ParseCommandBase.url_parts])
@staticmethod
def process(s):
return UrlunparseCommand._unparse(s)
class UrlresponseCommand(ReplaceCommandBase):
@staticmethod
def process(s):
with urllib.request.urlopen(s) as response:
resp = response.read()
return resp.decode('utf8')