0004-workflows-report-all-missing-things-in-one-time-5775.patch
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 |
- |