Projet

Général

Profil

0001-wf-backoffice_fields-log-compute-errors-as-functiona.patch

Thomas Noël, 29 juin 2018 16:33

Télécharger (8,79 ko)

Voir les différences:

Subject: [PATCH] wf/backoffice_fields: log compute errors as functional errors
 only (#24645)

 tests/test_workflows.py     | 38 +++++++++++++++++++++++++++++++++++++
 wcs/wf/backoffice_fields.py | 23 ++++++++++++++++++----
 wcs/workflows.py            | 21 +++++++++++++++++---
 3 files changed, 75 insertions(+), 7 deletions(-)
tests/test_workflows.py
2972 2972
def test_set_backoffice_field(http_requests, two_pubs):
2973 2973
    Workflow.wipe()
2974 2974
    FormDef.wipe()
2975
    LoggedError.wipe()
2975 2976
    wf = Workflow(name='xxx')
2976 2977
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
2977 2978
    wf.backoffice_fields_formdef.fields = [
......
3017 3018
    formdata = formdef.data_class().get(formdata.id)
3018 3019
    assert formdata.data['bo1'] == 'HELLO GOODBYE'
3019 3020

  
3021
    assert LoggedError.count() == 0
3022

  
3023
    item.fields = [{'field_id': 'bo1', 'value': '= ~ invalid python ~'}]
3024
    item.perform(formdata)
3025
    formdata = formdef.data_class().get(formdata.id)
3026
    assert LoggedError.count() == 1
3027
    logged_error = LoggedError.select()[0]
3028
    assert logged_error.summary == 'Failed to compute Python expression (error SyntaxError)'
3029
    assert logged_error.formdata_id == str(formdata.id)
3030
    assert logged_error.expression == ' ~ invalid python ~'
3031
    assert logged_error.expression_type == 'python'
3032
    assert logged_error.error_message == 'SyntaxError: invalid syntax (<string>, line 1)'
3033

  
3034
    LoggedError.wipe()
3035
    item.fields = [{'field_id': 'bo1', 'value': '{% if bad django %}'}]
3036
    item.perform(formdata)
3037
    formdata = formdef.data_class().get(formdata.id)
3038
    assert LoggedError.count() == 1
3039
    logged_error = LoggedError.select()[0]
3040
    assert logged_error.summary == 'Failed to compute template (error TemplateError)'
3041
    assert logged_error.formdata_id == str(formdata.id)
3042
    assert logged_error.expression == '{% if bad django %}'
3043
    assert logged_error.expression_type == 'template'
3044
    assert logged_error.error_message.startswith('TemplateError: syntax error in Django template')
3045

  
3020 3046
def test_set_backoffice_field_file(http_requests, two_pubs):
3021 3047
    Workflow.wipe()
3022 3048
    FormDef.wipe()
......
3138 3164
        item = SetBackofficeFieldsWorkflowStatusItem()
3139 3165
        item.parent = st1
3140 3166
        item.fields = [{'field_id': 'bo1', 'value': value}]
3167

  
3168
        LoggedError.wipe()
3141 3169
        item.perform(formdata)
3142 3170

  
3143 3171
        formdata = formdef.data_class().get(formdata.id)
3144 3172
        if value is not None:  # wrong value : do nothing
3145 3173
            assert formdata.data['bo1'].base_filename == 'hello.txt'
3146 3174
            assert formdata.data['bo1'].get_content() == 'HELLO WORLD'
3175
            assert LoggedError.count() == 1
3176
            logged_error = LoggedError.select()[0]
3177
            assert logged_error.summary.startswith('Failed to convert')
3178
            assert logged_error.formdata_id == str(formdata.id)
3147 3179
        else:  # empty value : remove field
3148 3180
            assert formdata.data['bo1'] is None
3181
            assert LoggedError.count() == 0
3149 3182

  
3150 3183
    # check wrong field
3151 3184
    item = SetBackofficeFieldsWorkflowStatusItem()
......
3309 3342
def test_set_backoffice_field_date(two_pubs):
3310 3343
    Workflow.wipe()
3311 3344
    FormDef.wipe()
3345
    LoggedError.wipe()
3312 3346
    wf = Workflow(name='xxx')
3313 3347
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
3314 3348
    st1 = wf.add_status('Status1')
......
3356 3390
    assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date(2017, 3, 23)
3357 3391

  
3358 3392
    # invalid values => do nothing
3393
    assert LoggedError.count() == 0
3359 3394
    for value in ('plop', {}, []):
3360 3395
        item = SetBackofficeFieldsWorkflowStatusItem()
3361 3396
        item.parent = st1
3362 3397
        item.fields = [{'field_id': 'bo1', 'value': value}]
3363 3398

  
3399
        LoggedError.wipe()
3364 3400
        item.perform(formdata)
3365 3401
        formdata = formdef.data_class().get(formdata.id)
3366 3402
        assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date(2017, 3, 23)
3403
        assert LoggedError.count() == 1
3404
        assert LoggedError.select()[0].summary.startswith('Failed to convert')
3367 3405

  
3368 3406
    # None : empty date
3369 3407
    item = SetBackofficeFieldsWorkflowStatusItem()
wcs/wf/backoffice_fields.py
97 97
                continue
98 98

  
99 99
            try:
100
                new_value = self.compute(field['value'], raises=True)
100
                new_value = self.compute(field['value'], raises=True,
101
                                         formdata=formdata, status_item=self)
101 102
            except:
102
                get_publisher().notify_of_exception(sys.exc_info(), context='[BO_FIELDS]')
103 103
                continue
104 104

  
105 105
            if formdef_field.convert_value_from_anything:
106 106
                try:
107 107
                    new_value = formdef_field.convert_value_from_anything(new_value)
108
                except ValueError:
109
                    get_publisher().notify_of_exception(sys.exc_info(), context='[BO_FIELDS]')
108
                except ValueError as e:
109
                    from wcs.logged_errors import LoggedError
110
                    summary = _('Failed to convert %(class)s value to %(kind)s field (%(id)s)') % {
111
                                    'class': type(new_value),
112
                                    'kind': _(getattr(formdef_field, 'description', 'unknown')),
113
                                    'id': field['field_id'],
114
                                }
115
                    plain_msg = _('Computed result: %(computed)r\n'
116
                                  'Computed result class: %(class)s') % {
117
                                        'computed': new_value,
118
                                        'class': type(new_value)
119
                                  }
120
                    expression_dict = self.get_expression(field['value'])
121
                    LoggedError.record(summary, plain_msg, formdata=formdata, status_item=self,
122
                                       expression=expression_dict['value'],
123
                                       expression_type=expression_dict['type'],
124
                                       error_message='%s: %s' % (e.__class__.__name__, e))
110 125
                    continue
111 126

  
112 127
            formdata.data['%s' % field['field_id']] = new_value
wcs/workflows.py
1677 1677
        return {'type': expression_type, 'value': expression_value}
1678 1678

  
1679 1679
    @classmethod
1680
    def compute(cls, var, render=True, raises=False, context=None):
1680
    def compute(cls, var, render=True, raises=False, context=None, formdata=None, status_item=None):
1681 1681
        if not isinstance(var, basestring):
1682 1682
            return var
1683 1683

  
......
1692 1692
        vars = get_publisher().substitutions.get_context_variables()
1693 1693
        vars.update(context or {})
1694 1694

  
1695
        def log_exception(e):
1696
            from wcs.logged_errors import LoggedError
1697
            summary = _('Failed to compute %(type)s (error %(error)s)') % {
1698
                            'type': {'text': _('text'),
1699
                                     'template': _('template'),
1700
                                     'python': _('Python expression')}.get(expression['type']),
1701
                            'error': e.__class__.__name__
1702
                        }
1703
            LoggedError.record(summary, formdata=formdata, status_item=status_item,
1704
                               expression=expression['value'],
1705
                               expression_type=expression['type'],
1706
                               error_message='%s: %s' % (e.__class__.__name__, e))
1707

  
1695 1708
        if expression['type'] == 'template':
1696 1709
            try:
1697 1710
                return Template(expression['value'], raises=raises, autoescape=False).render(vars)
1698
            except TemplateError:
1711
            except TemplateError as e:
1712
                log_exception(e)
1699 1713
                if raises:
1700 1714
                    raise
1701 1715
                return var
1702 1716

  
1703 1717
        try:
1704 1718
            return eval(expression['value'], get_publisher().get_global_eval_dict(), vars)
1705
        except:
1719
        except Exception as e:
1720
            log_exception(e)
1706 1721
            if raises:
1707 1722
                raise
1708 1723
            return var
1709
-