Projet

Général

Profil

0001-utils-handle-foo.bar-dot-syntax-in-templated_url-192.patch

Thomas Noël, 06 octobre 2017 19:13

Télécharger (8,24 ko)

Voir les différences:

Subject: [PATCH] utils: handle foo.bar dot syntax in templated_url (#19261)

 combo/utils.py      | 27 +++++++++++++++++---
 tests/test_cells.py | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test_utils.py | 24 +++++++++++++++++-
 3 files changed, 120 insertions(+), 4 deletions(-)
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
-