0001-utils-handle-foo.bar-dot-syntax-in-templated_url-192.patch
combo/utils.py | ||
---|---|---|
177 | 177 |
class UnknownTemplateVariableError(KeyError): |
178 | 178 |
pass |
179 | 179 | |
180 |
def get_templated_url_part(part, obj, prefix=''): |
|
181 |
if not part: |
|
182 |
return unicode(obj) |
|
183 |
split = part.split('.', 1) |
|
184 |
part0, part1 = split[0], '.'.join(split[1:]) |
|
185 |
next_prefix = '%s.%s' % (prefix, part0) if prefix else part0 |
|
186 |
if (isinstance(obj, Context) or isinstance(obj, dict)) and part0 in obj: |
|
187 |
return get_templated_url_part(part1, obj[part0], next_prefix) |
|
188 |
elif isinstance(obj, list) or isinstance(obj, tuple): |
|
189 |
try: |
|
190 |
index = int(part0) |
|
191 |
except ValueError: |
|
192 |
raise UnknownTemplateVariableError('invalid index %s in %s' % (part0, next_prefix)) |
|
193 |
try: |
|
194 |
item = obj[index] |
|
195 |
except IndexError: |
|
196 |
raise UnknownTemplateVariableError('index %s out of range in %s' % (part0, next_prefix)) |
|
197 |
return get_templated_url_part(part1, item, next_prefix) |
|
198 |
elif prefix: |
|
199 |
raise UnknownTemplateVariableError('no key %s in %s' % (part, next_prefix)) |
|
200 |
else: |
|
201 |
raise UnknownTemplateVariableError('unknown variable %s' % part) |
|
202 | ||
180 | 203 |
def get_templated_url(url, context=None): |
181 | 204 |
template_vars = Context() |
182 | 205 |
if context: |
... | ... | |
193 | 216 |
varname = matchobj.group(0)[1:-1] |
194 | 217 |
if varname == '[': |
195 | 218 |
return '[' |
196 |
if varname not in template_vars: |
|
197 |
raise UnknownTemplateVariableError(varname) |
|
198 |
return unicode(template_vars[varname]) |
|
219 |
return get_templated_url_part(varname, template_vars) |
|
199 | 220 |
return re.sub(r'(\[.+?\])', repl, url) |
200 | 221 | |
201 | 222 |
tests/test_cells.py | ||
---|---|---|
494 | 494 |
assert context['plop_url'] == 'http://bar' |
495 | 495 |
assert context['plop_status'] == 200 |
496 | 496 |
assert 'plop_error' not in context |
497 | ||
498 |
# additional-data url depends on others results |
|
499 |
with override_settings(JSON_CELL_TYPES={ |
|
500 |
'test-config-json-cell-2': { |
|
501 |
'name': 'Foobar', |
|
502 |
'url': 'http://foo', |
|
503 |
'additional-data': [ |
|
504 |
{'key': 'plop', 'url': 'http://[json.data]', 'log_errors': False, 'timeout': 42}, |
|
505 |
{'key': 'plop2', 'url': 'http://[json.data]/[plop.data]', 'log_errors': False, |
|
506 |
'timeout': 10}, |
|
507 |
] |
|
508 |
}}, |
|
509 |
TEMPLATE_DIRS=['%s/templates-1' % os.path.abspath(os.path.dirname(__file__))]): |
|
510 |
cell = ConfigJsonCell() |
|
511 |
cell.key = 'test-config-json-cell-2' |
|
512 |
cell.page = page |
|
513 |
cell.title = 'Example Site' |
|
514 |
cell.order = 0 |
|
515 |
cell.save() |
|
516 | ||
517 |
data = {'data': 'bar'} |
|
518 | ||
519 |
with mock.patch('combo.utils.requests.get') as requests_get: |
|
520 |
requests_get.return_value = mock.Mock(content=json.dumps(data), status_code=200) |
|
521 |
url = reverse('combo-public-ajax-page-cell', |
|
522 |
kwargs={'page_pk': page.id, 'cell_reference': cell.get_reference()}) |
|
523 |
resp = app.get(url) |
|
524 |
assert resp.body.strip() == '/var1=bar/var2=bar/' |
|
525 |
assert len(requests_get.mock_calls) == 3 |
|
526 |
assert requests_get.mock_calls[0][1][0] == 'http://foo' |
|
527 |
assert requests_get.mock_calls[0][-1]['log_errors'] == True |
|
528 |
assert requests_get.mock_calls[0][-1]['timeout'] == 28 |
|
529 |
assert requests_get.mock_calls[1][1][0] == 'http://bar' |
|
530 |
assert requests_get.mock_calls[1][-1]['log_errors'] == False |
|
531 |
assert requests_get.mock_calls[1][-1]['timeout'] == 42 |
|
532 |
assert requests_get.mock_calls[2][1][0] == 'http://bar/bar' |
|
533 |
assert requests_get.mock_calls[2][-1]['log_errors'] == False |
|
534 |
assert requests_get.mock_calls[2][-1]['timeout'] == 10 |
|
535 |
context = cell.get_cell_extra_context({}) |
|
536 |
assert context['json'] == data |
|
537 |
assert context['json_url'] == 'http://foo' |
|
538 |
assert context['json_status'] == 200 |
|
539 |
assert context['plop'] == data |
|
540 |
assert context['plop_url'] == 'http://bar' |
|
541 |
assert context['plop_status'] == 200 |
|
542 |
assert context['plop2'] == data |
|
543 |
assert context['plop2_url'] == 'http://bar/bar' |
|
544 |
assert context['plop2_status'] == 200 |
|
545 | ||
546 |
with mock.patch('combo.utils.requests.get') as requests_get: |
|
547 |
requests_get.return_value = mock.Mock(content=json.dumps(data), status_code=404, |
|
548 |
headers={'content-type': 'application/json'}) |
|
549 |
url = reverse('combo-public-ajax-page-cell', |
|
550 |
kwargs={'page_pk': page.id, 'cell_reference': cell.get_reference()}) |
|
551 |
resp = app.get(url) |
|
552 |
assert resp.body.strip() == '/var1=/var2=/' |
|
553 |
# can not create plop and plop2 url: only one request for "json" |
|
554 |
assert len(requests_get.mock_calls) == 1 |
|
555 |
assert requests_get.mock_calls[0][1][0] == 'http://foo' |
|
556 |
context = cell.get_cell_extra_context({}) |
|
557 |
assert context['json'] == None |
|
558 |
assert context['json_url'] == 'http://foo' |
|
559 |
assert context['json_status'] == 404 |
|
560 |
assert context['json_error'] == data |
|
561 |
# can not create plop and plop2 url: None value, no status |
|
562 |
assert context['plop'] == None |
|
563 |
assert 'plop_url' not in context |
|
564 |
assert 'plop_status' not in context |
|
565 |
assert 'plop_error' not in context |
|
566 |
assert context['plop2'] == None |
|
567 |
assert 'plop2_url' not in context |
|
568 |
assert 'plop2_status' not in context |
|
569 |
assert 'plop2_error' not in context |
tests/test_utils.py | ||
---|---|---|
44 | 44 |
assert get_templated_url('foobar[[]]') == 'foobar[]' |
45 | 45 |
assert get_templated_url('foobar[[]test]') == 'foobar[test]' |
46 | 46 | |
47 |
with pytest.raises(UnknownTemplateVariableError): |
|
47 |
with pytest.raises(UnknownTemplateVariableError, match='unknown variable test_url'):
|
|
48 | 48 |
get_templated_url('[test_url]') |
49 | 49 |
with override_settings(TEMPLATE_VARS={'test_url': 'http://www.example.net'}): |
50 | 50 |
assert get_templated_url('[test_url]') == 'http://www.example.net' |
51 | 51 |
assert get_templated_url('[test_url]/hello') == 'http://www.example.net/hello' |
52 | 52 | |
53 |
with override_settings(TEMPLATE_VARS={ |
|
54 |
'str': 'blah', |
|
55 |
'dict': {'foo': 'bar'}, |
|
56 |
'list': ['l1', 'l2', {'item': 'l3'}], |
|
57 |
'dictlist': {'litem': ['dl1', 'dl2']}, |
|
58 |
'lint': [1, 2], |
|
59 |
}): |
|
60 |
assert get_templated_url('[str]') == 'blah' |
|
61 |
assert get_templated_url('[dict.foo]') == 'bar' |
|
62 |
assert get_templated_url('[list.0] [list.2.item] [list.-2]') == 'l1 l3 l2' |
|
63 |
assert get_templated_url('[dictlist.litem.1]') == 'dl2' |
|
64 |
assert get_templated_url('[lint.0][lint.1]') == '12' |
|
65 |
for test_template in ( |
|
66 |
('[list.badix]', 'invalid index badix in list.badix'), |
|
67 |
('[list.5]', 'index 5 out of range in list.5'), |
|
68 |
('[str.attr]', 'no key attr in str.attr'), |
|
69 |
('[list.1.k]', 'no key k in list.1.k'), |
|
70 |
('[list.1.2]', 'no key 2 in list.1.2'), |
|
71 |
('[vroum]', 'unknown variable vroum')): |
|
72 |
with pytest.raises(UnknownTemplateVariableError, match=test_template[1]): |
|
73 |
get_templated_url(test_template[0]) |
|
74 | ||
53 | 75 |
# contexts without users |
54 | 76 |
request = RequestFactory().get('/') |
55 | 77 |
request.user = None |
56 |
- |