Projet

Général

Profil

0001-workflows-only-log-condition-errors-as-functional-er.patch

Thomas Noël, 12 juin 2018 16:51

Télécharger (7,94 ko)

Voir les différences:

Subject: [PATCH] workflows: only log condition errors as functional errors
 (#24472)

 tests/test_form_pages.py |  3 ++-
 tests/test_workflows.py  | 50 +++++++++++++++++++++++++++++++++++++++-
 wcs/conditions.py        | 13 +++++++++--
 wcs/logged_errors.py     |  2 +-
 wcs/wf/jump.py           |  3 ++-
 wcs/workflows.py         |  3 ++-
 6 files changed, 67 insertions(+), 7 deletions(-)
tests/test_form_pages.py
4492 4492
    assert LoggedError.count() == 1
4493 4493

  
4494 4494
    error = LoggedError.get_on_index(
4495
            '34-12-None-None-zerodivisionerror-integer-division-or-modulo-by-zero', 'tech_id')
4495
        '34-12-just_submitted-_jump-failed-to-evaluate-condition-10-python-integer-division-or-modulo-by-zero-zerodivisionerror',
4496
        'tech_id')
4496 4497
    assert error.occurences_count == 2
4497 4498

  
4498 4499
    assert len(LoggedError.get_ids_with_indexed_value('formdef_id', '34')) == 1
tests/test_workflows.py
19 19
from wcs import sessions
20 20
from wcs.fields import (StringField, DateField, MapField, FileField, ItemField,
21 21
        ItemsField, CommentField)
22
from wcs.logged_errors import LoggedError
22 23
from wcs.roles import Role
23 24
from wcs.workflows import (Workflow, WorkflowStatusItem,
24 25
        SendmailWorkflowStatusItem, SendSMSWorkflowStatusItem,
......
258 259
            'value': 'utils.time_delta(utils.time.localtime(), "2015-01-04").days > 0'}
259 260
    assert item.must_jump(formdata) is True
260 261

  
261

  
262 262
def test_jump_count_condition(pub):
263 263
    FormDef.wipe()
264 264
    formdef = FormDef()
......
278 278
    item.condition = {'type': 'python', 'value': 'form_objects.count < 2'}
279 279
    assert item.must_jump(formdata) is False
280 280

  
281
def test_jump_bad_python_condition(pub):
282
    FormDef.wipe()
283
    formdef = FormDef()
284
    formdef.name = 'foobar'
285
    formdef.store()
286
    pub.substitutions.feed(formdef)
287
    formdef.data_class().wipe()
288
    formdata = formdef.data_class()()
289
    item = JumpWorkflowStatusItem()
290

  
291
    LoggedError.wipe()
292
    item.condition = {'type': 'python', 'value': 'form_var_foobar == 0'}
293
    assert item.must_jump(formdata) is False
294
    assert LoggedError.count() == 1
295
    logged_error = LoggedError.select()[0]
296
    assert logged_error.summary.startswith('Failed to evaluate condition')
297
    assert 'form_var_foobar == 0' in logged_error.summary
298
    assert "name 'form_var_foobar' is not defined" in logged_error.summary
299

  
300
    LoggedError.wipe()
301
    item.condition = {'type': 'python', 'value': '~ invalid ~'}
302
    assert item.must_jump(formdata) is False
303
    assert LoggedError.count() == 1
304
    logged_error = LoggedError.select()[0]
305
    assert logged_error.summary.startswith('Failed to evaluate condition')
306
    assert '~ invalid ~' in logged_error.summary
307
    assert 'unexpected EOF while parsing' in logged_error.summary
308

  
281 309
def test_jump_django_conditions(pub):
282 310
    FormDef.wipe()
283 311
    formdef = FormDef()
......
289 317
    pub.substitutions.feed(formdata)
290 318
    item = JumpWorkflowStatusItem()
291 319

  
320
    LoggedError.wipe()
292 321
    item.condition = {'type': 'django', 'value': '1 < 2'}
293 322
    assert item.must_jump(formdata) is True
294 323

  
......
301 330
    item.condition = {'type': 'django', 'value': 'form_var_foo|first|upper == "X"'}
302 331
    assert item.must_jump(formdata) is False
303 332

  
333
    assert LoggedError.count() == 0
334

  
304 335
    item.condition = {'type': 'django', 'value': '~ invalid ~'}
305 336
    assert item.must_jump(formdata) is False
337
    assert LoggedError.count() == 1
338
    logged_error = LoggedError.select()[0]
339
    assert logged_error.summary.startswith('Failed to evaluate condition')
340
    assert '~ invalid ~' in logged_error.summary
341
    assert "Could not parse the remainder: '~' from '~'" in logged_error.summary
306 342

  
307 343
def test_check_auth(pub):
308 344
    user = pub.user_class(name='foo')
......
3504 3540
    choice.condition = {'type': 'python', 'value': 'form_name == "baz"'}
3505 3541
    workflow.store()
3506 3542
    assert len(FormDef.get(formdef.id).data_class().get_actionable_ids([role.id])) == 2
3543

  
3544
    # bad condition
3545
    LoggedError.wipe()
3546
    choice.condition = {'type': 'python', 'value': 'foobar == barfoo'}
3547
    workflow.store()
3548
    assert len(FormDef.get(formdef.id).data_class().get_actionable_ids([role.id])) == 0
3549
    assert LoggedError.count() == 1
3550
    logged_error = LoggedError.select()[0]
3551
    assert logged_error.occurences_count > 1  # should be 2... == 12 with pickle, 4 with sql
3552
    assert logged_error.summary.startswith('Failed to evaluate condition')
3553
    assert 'foobar == barfoo' in logged_error.summary
3554
    assert "name 'foobar' is not defined" in logged_error.summary
wcs/conditions.py
30 30
    record_errors = True
31 31
    log_errors = False
32 32

  
33
    def __init__(self, condition, context=None):
33
    def __init__(self, condition, context={}):
34 34
        if not condition:
35 35
            condition = {}
36 36
        self.type = condition.get('type')
......
53 53
            if self.log_errors:
54 54
                get_logger().warn('failed to evaluate %r (%r)', self, e)
55 55
            if self.record_errors:
56
                get_publisher().notify_of_exception(sys.exc_info())
56
                from wcs.logged_errors import LoggedError
57
                message = '%s (%s)' % (e, e.__class__.__name__)
58
                summary = _('Failed to evaluate condition "%(value)s" (%(type)s): %(message)s') % {
59
                    'value': self.value,
60
                    'type': self.type,
61
                    'message': message,
62
                }
63
                LoggedError.record(summary,
64
                                   formdata=self.context.get('formdata'),
65
                                   status_item=self.context.get('status_item'))
57 66
            raise RuntimeError()
58 67

  
59 68
    def evaluate_python(self, local_variables):
wcs/logged_errors.py
74 74

  
75 75
        if status_item:
76 76
            error.status_item_id = status_item.id
77
            if status_item.parent:
77
            if getattr(status_item, 'parent', None):
78 78
                error.status_id = status_item.parent.id
79 79
        if status:
80 80
            error.status_id = status.id
wcs/wf/jump.py
218 218
        must_jump = True
219 219

  
220 220
        if self.condition:
221
            context = {'formdata': formdata, 'status_item': self}
221 222
            try:
222
                must_jump = Condition(self.condition).evaluate()
223
                must_jump = Condition(self.condition, context).evaluate()
223 224
            except RuntimeError:
224 225
                must_jump = False
225 226

  
wcs/workflows.py
1583 1583
        return False
1584 1584

  
1585 1585
    def check_condition(self, formdata):
1586
        context = {'formdata': formdata, 'status_item': self}
1586 1587
        try:
1587
            return Condition(self.condition).evaluate()
1588
            return Condition(self.condition, context).evaluate()
1588 1589
        except RuntimeError:
1589 1590
            return False
1590 1591

  
1591
-