Projet

Général

Profil

0004-workflows-report-all-missing-things-in-one-time-5775.patch

Lauréline Guérin, 04 novembre 2021 14:51

Télécharger (13,6 ko)

Voir les différences:

Subject: [PATCH 4/4] workflows: report all missing things in one time (#57753)

 tests/test_workflow_import.py | 78 ++++++++++++++++++++++++++++++++++-
 wcs/formdef.py                | 25 +++++++++--
 wcs/workflows.py              | 74 ++++++++++++++++++++++++++++-----
 3 files changed, 161 insertions(+), 16 deletions(-)
tests/test_workflow_import.py
136 136
    pub.cfg['sp'] = {'idp-manage-roles': True}
137 137
    # now roles are managed: cannot create them
138 138
    dispatch.role_id = 'unknown'
139
    with pytest.raises(WorkflowImportError, match=r'.*Unknown referenced role.*'):
139
    with pytest.raises(WorkflowImportError) as excinfo:
140 140
        wf2 = assert_import_export_works(wf)
141
    assert excinfo.value.msg == 'Unknown referenced objects'
142
    assert excinfo.value.details == 'Unknown roles: unknown'
141 143
    # but allow computed roles
142 144
    dispatch.role_id = '=form_var_bar'
143 145
    wf2 = assert_import_export_works(wf)
......
895 897
    # import with non existing mail template
896 898
    MailTemplate.wipe()
897 899
    export = ET.tostring(wf.export_to_xml(include_id=True))
898
    with pytest.raises(WorkflowImportError, match='Unknown referenced mail template'):
900
    with pytest.raises(WorkflowImportError) as excinfo:
899 901
        Workflow.import_from_xml_tree(ET.fromstring(export), include_id=True)
902
    assert excinfo.value.msg == 'Unknown referenced objects'
903
    assert excinfo.value.details == 'Unknown mail templates: test-mail-template'
900 904

  
901 905

  
902 906
def test_workflow_with_unknown_data_source(pub):
......
1039 1043
    export = ET.tostring(wf.export_to_xml(include_id=True))
1040 1044
    wf3 = Workflow.import_from_xml_tree(ET.fromstring(export), include_id=True)
1041 1045
    assert wf3.category_id is None
1046

  
1047

  
1048
def test_import_workflow_multiple_errors(pub):
1049
    BlockDef.wipe()
1050
    pub.cfg['sp'] = {'idp-manage-roles': True}
1051

  
1052
    wf = Workflow(name='status')
1053
    st1 = wf.add_status('Status1', 'st1')
1054
    display_form = FormWorkflowStatusItem()
1055
    display_form.id = '_x'
1056
    display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
1057
    display_form.formdef.fields = [
1058
        BlockField(id='1', type='block:foobar1'),
1059
        BlockField(id='2', type='block:foobaz1'),
1060
        StringField(id='3', type='string', data_source={'type': 'foobar1'}),
1061
        StringField(id='4', type='string', data_source={'type': 'carddef:unknown1'}),
1062
    ]
1063
    st1.items.append(display_form)
1064
    display_form.parent = st1
1065

  
1066
    dispatch1 = DispatchWorkflowStatusItem()
1067
    dispatch1.id = '_x1'
1068
    dispatch1.role_id = 'unknown-role1'
1069
    dispatch1.role_key = 'plop'
1070
    st1.items.append(dispatch1)
1071
    dispatch1.parent = st1
1072
    dispatch2 = DispatchWorkflowStatusItem()
1073
    dispatch2.id = '_x2'
1074
    dispatch2.role_id = 'unknown-role2'
1075
    dispatch2.role_key = 'plop'
1076
    st1.items.append(dispatch2)
1077
    dispatch2.parent = st1
1078

  
1079
    item1 = SendmailWorkflowStatusItem()
1080
    item1.to = ['_receiver']
1081
    item1.mail_template = 'unknown-mt-1'
1082
    st1.items.append(item1)
1083
    item1.parent = st1
1084
    item2 = SendmailWorkflowStatusItem()
1085
    item2.to = ['_receiver']
1086
    item2.mail_template = 'unknown-mt-2'
1087
    st1.items.append(item2)
1088
    item2.parent = st1
1089

  
1090
    wf.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=wf)
1091
    wf.variables_formdef.fields = [
1092
        BlockField(id='1', type='block:foobar2'),
1093
        BlockField(id='2', type='block:foobaz2'),
1094
        StringField(id='3', type='string', data_source={'type': 'foobar2'}),
1095
        StringField(id='4', type='string', data_source={'type': 'carddef:unknown2'}),
1096
    ]
1097

  
1098
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
1099
    wf.backoffice_fields_formdef.fields = [
1100
        BlockField(id='1', type='block:foobar3'),
1101
        BlockField(id='2', type='block:foobaz3'),
1102
        StringField(id='3', type='string', data_source={'type': 'foobar3'}),
1103
        StringField(id='4', type='string', data_source={'type': 'carddef:unknown3'}),
1104
    ]
1105

  
1106
    export = ET.tostring(export_to_indented_xml(wf))
1107
    with pytest.raises(WorkflowImportError) as excinfo:
1108
        Workflow.import_from_xml(io.BytesIO(export))
1109
    assert excinfo.value.msg == 'Unknown referenced objects'
1110
    assert excinfo.value.details == (
1111
        'Unknown datasources: carddef:unknown1, carddef:unknown2, carddef:unknown3, foobar1, foobar2, foobar3; '
1112
        'Unknown field types: block:foobar1, block:foobar2, block:foobar3, block:foobaz1, block:foobaz2, block:foobaz3; '
1113
        'Unknown mail templates: unknown-mt-1, unknown-mt-2; '
1114
        'Unknown roles: unknown-role1, unknown-role2'
1115
    )
wcs/formdef.py
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import base64
18
import collections
18 19
import contextlib
19 20
import copy
20 21
import datetime
......
60 61
        self.details = details
61 62

  
62 63

  
64
class FormdefImportUnknownReferencedError(FormdefImportError):
65
    def __init__(self, msg, msg_args=None, details=None):
66
        self.msg = msg
67
        self.msg_args = msg_args or ()
68
        self._details = details
69

  
70
    @property
71
    def details(self):
72
        if not self._details:
73
            return None
74
        details = []
75
        for kind in self._details:
76
            details.append('%s: %s' % (kind, ', '.join(sorted(self._details[kind]))))
77
        return '; '.join(details)
78

  
79

  
63 80
class FormdefImportRecoverableError(FormdefImportError):
64 81
    pass
65 82

  
......
1357 1374
                            unknown_datasources.add(data_source_id)
1358 1375

  
1359 1376
        if unknown_field_types or unknown_datasources:
1360
            details = []
1377
            details = collections.defaultdict(set)
1361 1378
            if unknown_field_types:
1362
                details.append('%s: %s' % (_('Unknown field types'), ', '.join(sorted(unknown_field_types))))
1379
                details[_('Unknown field types')].update(unknown_field_types)
1363 1380
            if unknown_datasources:
1364
                details.append('%s: %s' % (_('Unknown datasources'), ', '.join(sorted(unknown_datasources))))
1365
            raise FormdefImportError(_('Unknown referenced objects'), details='; '.join(details))
1381
                details[_('Unknown datasources')].update(unknown_datasources)
1382
            raise FormdefImportUnknownReferencedError(_('Unknown referenced objects'), details=details)
1366 1383

  
1367 1384
        return formdef
1368 1385

  
wcs/workflows.py
34 34
from .conditions import Condition
35 35
from .fields import FileField
36 36
from .formdata import Evolution
37
from .formdef import FormDef, FormdefImportError
37
from .formdef import FormDef, FormdefImportError, FormdefImportUnknownReferencedError
38 38
from .mail_templates import MailTemplate
39 39
from .qommon import _, emails, errors, ezt, force_str, get_cfg, misc
40 40
from .qommon.form import (
......
122 122
        self.details = details
123 123

  
124 124

  
125
class WorkflowImportUnknownReferencedError(WorkflowImportError):
126
    def __init__(self, msg, msg_args=None, details=None):
127
        self.msg = msg
128
        self.msg_args = msg_args or ()
129
        self._details = details
130

  
131
    @property
132
    def details(self):
133
        if not self._details:
134
            return None
135
        details = []
136
        for kind in sorted(self._details.keys()):
137
            details.append('%s: %s' % (kind, ', '.join(sorted(self._details[kind]))))
138
        return '; '.join(details)
139

  
140

  
125 141
class AbortActionException(Exception):
126 142
    def __init__(self, url=None):
127 143
        self.url = url
......
803 819
            for role_node in tree.findall('roles/role'):
804 820
                workflow.roles[role_node.attrib['id']] = xml_node_text(role_node)
805 821

  
822
        unknown_referenced_objects_details = collections.defaultdict(set)
806 823
        workflow.possible_status = []
807 824
        for status in tree.find('possible_status'):
808 825
            status_o = WorkflowStatus()
......
815 832
                    snapshot=snapshot,
816 833
                    check_datasources=check_datasources,
817 834
                )
835
            except WorkflowImportUnknownReferencedError as e:
836
                for k, v in e._details.items():
837
                    unknown_referenced_objects_details[k].update(v)
818 838
            except FormdefImportError as e:
819 839
                raise WorkflowImportError(e.msg, details=e.details)
820
            workflow.possible_status.append(status_o)
840
            else:
841
                workflow.possible_status.append(status_o)
821 842

  
822 843
        workflow.global_actions = []
823 844
        global_actions = tree.find('global_actions')
......
843 864
                imported_formdef = FormDef.import_from_xml_tree(
844 865
                    formdef, include_id=True, snapshot=snapshot, check_datasources=check_datasources
845 866
                )
867
            except FormdefImportUnknownReferencedError as e:
868
                for k, v in e._details.items():
869
                    unknown_referenced_objects_details[k].update(v)
846 870
            except FormdefImportError as e:
847 871
                raise WorkflowImportError(e.msg, details=e.details)
848
            workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
849
            workflow.variables_formdef.fields = imported_formdef.fields
872
            else:
873
                workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
874
                workflow.variables_formdef.fields = imported_formdef.fields
850 875

  
851 876
        variables = tree.find('backoffice-fields')
852 877
        if variables is not None:
......
855 880
                imported_formdef = FormDef.import_from_xml_tree(
856 881
                    formdef, include_id=True, snapshot=snapshot, check_datasources=check_datasources
857 882
                )
883
            except FormdefImportUnknownReferencedError as e:
884
                for k, v in e._details.items():
885
                    unknown_referenced_objects_details[k].update(v)
858 886
            except FormdefImportError as e:
859 887
                raise WorkflowImportError(e.msg, details=e.details)
860
            workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow=workflow)
861
            workflow.backoffice_fields_formdef.fields = imported_formdef.fields
888
            else:
889
                workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow=workflow)
890
                workflow.backoffice_fields_formdef.fields = imported_formdef.fields
891

  
892
        if unknown_referenced_objects_details:
893
            raise WorkflowImportUnknownReferencedError(
894
                _('Unknown referenced objects'), details=unknown_referenced_objects_details
895
            )
862 896

  
863 897
        return workflow
864 898

  
......
1194 1228

  
1195 1229
        # if the roles are managed by the idp, don't try further.
1196 1230
        if get_publisher() and get_cfg('sp', {}).get('idp-manage-roles') is True:
1197
            raise WorkflowImportError(_('Unknown referenced role (%s)'), (value,))
1231
            raise WorkflowImportUnknownReferencedError(
1232
                _('Unknown referenced role (%s)'), details={_('Unknown roles'): {value}}
1233
            )
1198 1234

  
1199 1235
        # and if there's no match, create a new role
1200 1236
        role = get_publisher().role_class()
......
1996 2032
            self.visibility.append(visibility_role.text)
1997 2033

  
1998 2034
        self.items = []
2035
        unknown_referenced_objects_details = collections.defaultdict(set)
1999 2036
        for item in elem.find('items'):
2000 2037
            item_type = item.attrib['type']
2001 2038
            self.append_item(item_type)
2002 2039
            item_o = self.items[-1]
2003 2040
            item_o.parent = self
2004
            item_o.init_with_xml(
2005
                item, charset, include_id=include_id, snapshot=snapshot, check_datasources=check_datasources
2041
            try:
2042
                item_o.init_with_xml(
2043
                    item,
2044
                    charset,
2045
                    include_id=include_id,
2046
                    snapshot=snapshot,
2047
                    check_datasources=check_datasources,
2048
                )
2049
            except (WorkflowImportUnknownReferencedError, FormdefImportUnknownReferencedError) as e:
2050
                for k, v in e._details.items():
2051
                    unknown_referenced_objects_details[k].update(v)
2052
            except FormdefImportError as e:
2053
                raise WorkflowImportError(e.msg, details=e.details)
2054

  
2055
        if unknown_referenced_objects_details:
2056
            raise WorkflowImportUnknownReferencedError(
2057
                _('Unknown referenced objects'), details=unknown_referenced_objects_details
2006 2058
            )
2007 2059

  
2008 2060
    def __repr__(self):
......
2428 2480
        value = xml_node_text(elem)
2429 2481
        mail_template = MailTemplate.get_by_slug(value)
2430 2482
        if not mail_template:
2431
            raise WorkflowImportError(_('Unknown referenced mail template (%s)'), (value,))
2483
            raise WorkflowImportUnknownReferencedError(
2484
                _('Unknown referenced mail template (%s)'), details={_('Unknown mail templates'): {value}}
2485
            )
2432 2486
        self.mail_template = value
2433 2487
        return
2434 2488

  
2435
-