• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

collective / sphinxcontrib-httpexample / 7956692684

pending completion
7956692684

push

github

datakurre
ci: Install sphinxcontrib-httpexample in readthedocs

418 of 445 relevant lines covered (93.93%)

0.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.72
/src/sphinxcontrib/httpexample/builders.py
1
# -*- coding: utf-8 -*-
2
from sphinxcontrib.httpexample.utils import is_json
4✔
3
from sphinxcontrib.httpexample.utils import maybe_str
4✔
4

5
import ast
4✔
6
import json
4✔
7
import re
4✔
8
import string
4✔
9

10

11
try:
4✔
12
    from urllib.parse import parse_qs
4✔
13
except ImportError:
×
14
    from urlparse import parse_qs
×
15

16
try:
4✔
17
    from ast import unparse
4✔
18
except ImportError:
2✔
19
    from six.moves import StringIO
2✔
20

21
    import astunparse
2✔
22

23
    # Fix: https://github.com/simonpercivall/astunparse/issues/43
24
    # See: https://github.com/juanlao7/codeclose/commit/0f145f53a3253f9c593c537e1a25c9ef445f30d1  # noqa: E501
25
    class FixUnparser(astunparse.Unparser):
2✔
26
        def _Constant(self, t):  # noqa:  N802
2✔
27
            if not hasattr(t, 'kind'):
1✔
28
                setattr(t, 'kind', None)
1✔
29
            super()._Constant(t)
1✔
30

31
    def unparse(tree):
2✔
32
        v = StringIO()
2✔
33
        FixUnparser(tree, file=v)
2✔
34
        return v.getvalue()
2✔
35

36
try:
4✔
37
    from shlex import quote as shlex_quote
4✔
38
except ImportError:
×
39
    from pipes import quote as shlex_quote
×
40

41

42
_find_unsafe = re.compile(
4✔
43
    r'[^\w@%+=:,./-' + string.ascii_letters + string.digits + ']',
44
).search
45

46

47
def shlex_double_quote(s):
4✔
48
    """Return a shell-escaped version of the string *s*."""
49
    if not s:
4✔
50
        return '""'
×
51
    if _find_unsafe(s) is None:
4✔
52
        return s
4✔
53

54
    # use double quotes, and put double quotes into single quotes
55
    # the string $"b is then quoted as "$"'"'"b"
56
    return re.sub(r'^""|""$', '', ('"' + s.replace('"', "\"'\"'\"") + '"'))
4✔
57

58

59
EXCLUDE_HEADERS = [
4✔
60
    'Authorization',
61
    'Host',
62
]
63
EXCLUDE_HEADERS_HTTP = EXCLUDE_HEADERS + [
4✔
64
]
65
EXCLUDE_HEADERS_REQUESTS = EXCLUDE_HEADERS + [
4✔
66
]
67

68

69
def build_curl_command(request):
4✔
70
    parts = ['curl', '-i']
4✔
71

72
    # Method
73
    parts.append('-X {}'.format(request.command))
4✔
74

75
    # URL
76
    parts.append(shlex_quote(request.url()))
4✔
77

78
    # Authorization (prepare)
79
    method, token = request.auth()
4✔
80

81
    # Headers
82
    for header in sorted(request.headers):
4✔
83
        if header in EXCLUDE_HEADERS:
4✔
84
            continue
4✔
85
        header_line = shlex_double_quote('{}: {}'.format(
4✔
86
            header, request.headers[header]),
87
        )
88
        parts.append('-H {}'.format(header_line))
4✔
89

90
    if method != 'Basic' and 'Authorization' in request.headers:
4✔
91
        header = 'Authorization'
4✔
92
        header_line = shlex_double_quote(
4✔
93
            '{}: {}'.format(header, request.headers[header]),
94
        )
95
        parts.append('-H {}'.format(header_line))
4✔
96

97
    # JSON
98
    data = maybe_str(request.data())
4✔
99
    if data:
4✔
100
        if is_json(request.headers.get('Content-Type', '')):
4✔
101
            data = json.dumps(data)
4✔
102
        parts.append("--data-raw '{}'".format(data))
4✔
103

104
    # Authorization
105
    if method == 'Basic':
4✔
106
        parts.append('--user {}'.format(token))
4✔
107

108
    return ' '.join(parts)
4✔
109

110

111
def build_wget_command(request):
4✔
112
    parts = ['wget', '-S', '-O-']
4✔
113

114
    # Method
115
    if request.command not in ['GET', 'POST']:
4✔
116
        parts.append('--method={}'.format(request.command))
4✔
117

118
    # URL
119
    parts.append(shlex_quote(request.url()))
4✔
120

121
    # Authorization (prepare)
122
    method, token = request.auth()
4✔
123

124
    # Headers
125
    for header in sorted(request.headers):
4✔
126
        if header in EXCLUDE_HEADERS:
4✔
127
            continue
4✔
128
        header_line = shlex_double_quote(
4✔
129
            '{}: {}'.format(header, request.headers[header]),
130
        )
131
        parts.append('--header={}'.format(header_line))
4✔
132

133
    if method != 'Basic' and 'Authorization' in request.headers:
4✔
134
        header = 'Authorization'
4✔
135
        header_line = shlex_double_quote(
4✔
136
            '{}: {}'.format(header, request.headers[header])
137
        )
138
        parts.append('--header={}'.format(header_line))
4✔
139

140
    # JSON or raw data
141
    data = maybe_str(request.data())
4✔
142
    if data:
4✔
143
        if is_json(request.headers.get('Content-Type', '')):
4✔
144
            data = json.dumps(data)
4✔
145
        if request.command == 'POST':
4✔
146
            parts.append("--post-data='{}'".format(data))
4✔
147
        elif request.command != 'POST':
4✔
148
            parts.append("--body-data='{}'".format(data))
4✔
149

150
    # Authorization
151
    if method == 'Basic':
4✔
152
        user, password = token.split(':')
4✔
153
        parts.append('--auth-no-challenge')
4✔
154
        parts.append('--user={}'.format(user))
4✔
155
        parts.append('--password={}'.format(password))
4✔
156

157
    return ' '.join(parts)
4✔
158

159

160
def build_httpie_command(request):
4✔
161
    parts = ['http']
4✔
162
    redir_input = ''
4✔
163

164
    # Method
165
    if request.command != 'GET':
4✔
166
        parts.append(request.command)
4✔
167

168
    # URL
169
    parts.append(shlex_quote(request.url()))
4✔
170

171
    # Authorization (prepare)
172
    method, token = request.auth()
4✔
173

174
    # Headers
175
    for header in sorted(request.headers):
4✔
176
        if header in EXCLUDE_HEADERS_HTTP:
4✔
177
            continue
4✔
178
        parts.append('{}:{}'.format(
4✔
179
            header, shlex_double_quote(request.headers[header]),
180
        ))
181

182
    if method != 'Basic' and 'Authorization' in request.headers:
4✔
183
        header = 'Authorization'
4✔
184
        parts.append('{}:{}'.format(
4✔
185
            header, shlex_double_quote(request.headers[header]),
186
        ))
187

188
    # JSON or raw data
189
    data = maybe_str(request.data())
4✔
190
    if data:
4✔
191

192
        if is_json(request.headers.get('Content-Type', '')):
4✔
193
            # We need to explicitly set the separators to get consistent
194
            # whitespace handling across Python 2 and 3. See
195
            # https://bugs.python.org/issue16333 for details.
196
            redir_input = shlex_quote(
4✔
197
                json.dumps(data, indent=2, sort_keys=True,
198
                           separators=(',', ': ')))
199
        else:
200
            redir_input = shlex_quote(data)
4✔
201

202
    # Authorization
203
    if method == 'Basic':
4✔
204
        parts.append('-a {}'.format(token))
4✔
205

206
    cmd = ' '.join(parts)
4✔
207

208
    if not redir_input:
4✔
209
        return cmd
4✔
210

211
    else:
212
        return 'echo {} | {}'.format(redir_input, cmd)
4✔
213

214

215
def build_plone_javascript_command(request):
4✔
216
    javascript_code = 'createAliasesMutation'
4✔
217
    redir_input2 = ''
4✔
218

219
    # Request body
220
    data = maybe_str(request.data())
4✔
221
    if data:
4✔
222
        if is_json(request.headers.get('Content-Type', '')):
4✔
223
            redir_input2 = json.dumps(
4✔
224
                data, indent=2, sort_keys=True,
225
                separators=(',', ': '),
226
            ).encode('utf-8')
227
        else:
228
            redir_input2 = data
4✔
229

230
    # Output string
231
    output_string =\
4✔
232
        "{}\n|\nconst aliasesData = '{}';".format(
233
            maybe_str(javascript_code),
234
            maybe_str(redir_input2),
235
        )
236

237
    return output_string
4✔
238

239

240
def flatten_parsed_qs(data):
4✔
241
    """Flatten single value lists in parse_qs results."""
242
    for key, value in data.items():
4✔
243
        if isinstance(value, list) and len(value) == 1:
4✔
244
            data[key] = value[0]
4✔
245
    return data
4✔
246

247

248
def build_requests_command(request):
4✔
249
    # Method
250
    tree = ast.parse('requests.{}()'.format(request.command.lower()))
4✔
251
    call = tree.body[0].value
4✔
252
    call.keywords = []
4✔
253

254
    # URL
255
    call.args.append(ast.Str(request.url()))
4✔
256

257
    # Authorization (prepare)
258
    method, token = request.auth()
4✔
259

260
    # Headers
261
    header_keys = []
4✔
262
    header_values = []
4✔
263
    for header in sorted(request.headers):
4✔
264
        if header in EXCLUDE_HEADERS_REQUESTS:
4✔
265
            continue
4✔
266
        header_keys.append(ast.Str(header))
4✔
267
        header_values.append(ast.Str(request.headers[header]))
4✔
268
    if method != 'Basic' and 'Authorization' in request.headers:
4✔
269
        header_keys.append(ast.Str('Authorization'))
4✔
270
        header_values.append(ast.Str(request.headers['Authorization']))
4✔
271
    if header_keys and header_values:
4✔
272
        call.keywords.append(
4✔
273
            ast.keyword('headers', ast.Dict(header_keys, header_values)))
274

275
    # JSON or raw data
276
    data = maybe_str(request.data())
4✔
277

278
    # Form data
279
    content_type = request.headers.get('Content-Type')
4✔
280
    if content_type == 'application/x-www-form-urlencoded':
4✔
281
        if not isinstance(data, dict):
4✔
282
            data = flatten_parsed_qs(parse_qs(data))
4✔
283

284
    def astify_json_obj(obj):
4✔
285
        obj = maybe_str(obj)
4✔
286
        if isinstance(obj, str):
4✔
287
            return ast.Str(obj)
4✔
288
        elif isinstance(obj, bool):
4✔
289
            return ast.Name(str(obj), ast.Load())
4✔
290
        elif isinstance(obj, int):
4✔
291
            return ast.Name(str(obj), ast.Load())
4✔
292
        elif isinstance(obj, float):
4✔
293
            return ast.Name(str(obj), ast.Load())
4✔
294
        elif isinstance(obj, list):
4✔
295
            json_values = []
4✔
296
            for v in obj:
4✔
297
                json_values.append(astify_json_obj(v))
4✔
298
            return ast.List(json_values, ast.Load())
4✔
299
        elif isinstance(obj, dict):
4✔
300
            json_values = []
4✔
301
            json_keys = []
4✔
302
            for k, v in obj.items():
4✔
303
                json_keys.append(ast.Str(maybe_str(k)))
4✔
304
                json_values.append(astify_json_obj(v))
4✔
305
            return ast.Dict(json_keys, json_values)
4✔
306
        else:
307
            raise Exception('Cannot astify {0:s}'.format(str(obj)))
×
308

309
    if data:
4✔
310
        if is_json(request.headers.get('Content-Type', '')):
4✔
311
            call.keywords.append(ast.keyword('json', astify_json_obj(data)))
4✔
312
        else:
313
            call.keywords.append(ast.keyword('data', ast.Str(data)))
4✔
314

315
    # Authorization
316
    if method == 'Basic':
4✔
317
        token = maybe_str(token)
4✔
318
        call.keywords.append(
4✔
319
            ast.keyword('auth', ast.Tuple(
320
                tuple(map(ast.Str, token.split(':'))), None)))
321

322
    return unparse(tree).strip()
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc