0001-wf-backoffice_fields-log-compute-errors-as-functiona.patch
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 |
- |