0001-wf-export_to_model-support-XML-templates-56537.patch
tests/test_workflows.py | ||
---|---|---|
45 | 45 |
from wcs.formdata import Evolution |
46 | 46 |
from wcs.formdef import FormDef |
47 | 47 |
from wcs.qommon.errors import ConnectionError |
48 |
from wcs.qommon.form import Form, UploadedFile |
|
48 |
from wcs.qommon.form import Form, UploadedFile, UploadValidationError
|
|
49 | 49 |
from wcs.qommon.http_request import HTTPRequest |
50 | 50 |
from wcs.qommon.upload_storage import PicklableUpload |
51 | 51 |
from wcs.wf.aggregation_email import ( |
... | ... | |
60 | 60 |
from wcs.wf.criticality import MODE_DEC, MODE_INC, MODE_SET, ModifyCriticalityWorkflowStatusItem |
61 | 61 |
from wcs.wf.dispatch import DispatchWorkflowStatusItem |
62 | 62 |
from wcs.wf.edit_carddata import EditCarddataWorkflowStatusItem |
63 |
from wcs.wf.export_to_model import ExportToModel, transform_to_pdf |
|
63 |
from wcs.wf.export_to_model import ExportToModel, TemplatingError, transform_to_pdf
|
|
64 | 64 |
from wcs.wf.form import FormWorkflowStatusItem, WorkflowFormFieldsFormDef |
65 | 65 |
from wcs.wf.geolocate import GeolocateWorkflowStatusItem |
66 | 66 |
from wcs.wf.jump import JumpWorkflowStatusItem, _apply_timeouts |
... | ... | |
3987 | 3987 |
assert b'>A <> name<' in new_content |
3988 | 3988 | |
3989 | 3989 | |
3990 |
def test_export_to_model_xml(pub): |
|
3991 |
formdef = FormDef() |
|
3992 |
formdef.name = 'foo-export-to-template-with-django' |
|
3993 |
formdef.fields = [ |
|
3994 |
StringField(id='1', label='String', type='string', varname='string'), |
|
3995 |
] |
|
3996 |
formdef.store() |
|
3997 |
formdata = formdef.data_class()() |
|
3998 |
formdata.data = {'1': 'écho'} |
|
3999 |
formdata.just_created() |
|
4000 |
formdata.store() |
|
4001 | ||
4002 |
# good XML |
|
4003 |
item = ExportToModel() |
|
4004 |
item.method = 'non-interactive' |
|
4005 |
item.attach_to_history = True |
|
4006 | ||
4007 |
def run(template, filename='/foo/template.xml', content_type='application/xml'): |
|
4008 |
upload = QuixoteUpload(filename, content_type=content_type) |
|
4009 |
upload.fp = io.BytesIO() |
|
4010 |
upload.fp.write(template.encode()) |
|
4011 |
upload.fp.seek(0) |
|
4012 |
item.model_file = UploadedFile(pub.app_dir, None, upload) |
|
4013 |
item.convert_to_pdf = False |
|
4014 |
pub.substitutions.reset() |
|
4015 |
pub.substitutions.feed(formdata) |
|
4016 |
item.perform(formdata) |
|
4017 |
with open(formdata.evolution[0].parts[0].filename) as fd: |
|
4018 |
return fd.read() |
|
4019 | ||
4020 |
# unknown file format |
|
4021 |
with pytest.raises(UploadValidationError): |
|
4022 |
run( |
|
4023 |
template='<a>{{ form_var_string }}</a>', |
|
4024 |
filename='/foo/template.txt', |
|
4025 |
content_type='application/octet-stream', |
|
4026 |
) |
|
4027 | ||
4028 |
# good XML |
|
4029 |
assert run(template='<a>{{ form_var_string }}</a>') == '<a>écho</a>' |
|
4030 | ||
4031 |
# malformed XML |
|
4032 |
with pytest.raises(TemplatingError): |
|
4033 |
run(template='<a>{{ form_var_string }}<a>') |
|
4034 | ||
4035 | ||
3990 | 4036 |
@pytest.mark.parametrize('filename', ['template-form-details.odt', 'template-form-details-no-styles.odt']) |
3991 | 4037 |
def test_export_to_model_form_details_section(pub, filename): |
3992 | 4038 |
BlockDef.wipe() |
wcs/wf/export_to_model.py | ||
---|---|---|
282 | 282 |
fp = upload.get_file() |
283 | 283 |
else: |
284 | 284 |
raise UploadValidationError('unknown upload object %r' % upload) |
285 | ||
286 |
# RTF |
|
285 | 287 |
if upload.content_type and upload.content_type == 'application/rtf': |
286 | 288 |
return 'rtf' |
287 | 289 |
if ( |
... | ... | |
292 | 294 |
if fp.read(10).startswith(b'{\\rtf'): |
293 | 295 |
fp.seek(0) |
294 | 296 |
return 'rtf' |
297 | ||
298 |
# OpenDocument |
|
295 | 299 |
fp.seek(0) |
296 | 300 |
if upload.content_type and upload.content_type.startswith('application/vnd.oasis.opendocument.'): |
297 | 301 |
return 'opendocument' |
... | ... | |
302 | 306 |
return 'opendocument' |
303 | 307 |
if is_opendocument(fp): |
304 | 308 |
return 'opendocument' |
309 | ||
310 |
# XML |
|
311 |
if (upload.content_type and upload.content_type in ('text/xml', 'application/xml')) or ( |
|
312 |
upload.content_type is None and upload.base_filename and upload.base_filename.endswith('.rtf') |
|
313 |
): |
|
314 |
return 'xml' |
|
305 | 315 |
raise UploadValidationError(_('Only RTF and OpenDocument files can be used')) |
306 | 316 | |
307 | 317 |
def get_parameters(self): |
... | ... | |
486 | 496 |
outstream = self.apply_rtf_template_to_formdata(formdata) |
487 | 497 |
elif kind == 'opendocument': |
488 | 498 |
outstream = self.apply_od_template_to_formdata(formdata) |
499 |
elif kind == 'xml': |
|
500 |
outstream = self.apply_text_template_to_formdata(formdata) |
|
489 | 501 |
else: |
490 | 502 |
raise Exception('unsupported model kind %r' % kind) |
491 |
if self.convert_to_pdf: |
|
492 |
if transform_to_pdf is None: |
|
493 |
raise Exception('libreoffice is missing') |
|
494 |
return transform_to_pdf(outstream) |
|
503 |
if kind == 'xml': |
|
504 |
outstream.seek(0) |
|
505 |
try: |
|
506 |
ET.parse(outstream) |
|
507 |
except ET.ParseError as e: |
|
508 |
get_publisher().record_error( |
|
509 |
_('Error in template for export to model'), formdata=formdata, exception=e |
|
510 |
) |
|
511 |
raise TemplatingError(_('Error in template: output is not valid XML (%s)') % str(e)) |
|
512 |
finally: |
|
513 |
outstream.seek(0) |
|
514 |
else: |
|
515 |
if self.convert_to_pdf: |
|
516 |
if transform_to_pdf is None: |
|
517 |
raise Exception('libreoffice is missing') |
|
518 |
return transform_to_pdf(outstream) |
|
495 | 519 |
return outstream |
496 | 520 | |
521 |
def apply_text_template_to_formdata(self, formdata): |
|
522 |
try: |
|
523 |
# force ezt_only=True because an RTF file may contain {{ characters |
|
524 |
# and would be seen as a Django template |
|
525 |
return io.BytesIO( |
|
526 |
force_bytes( |
|
527 |
template_on_formdata( |
|
528 |
formdata, |
|
529 |
self.model_file.get_file().read().decode(errors='surrogateescape'), |
|
530 |
) |
|
531 |
) |
|
532 |
) |
|
533 |
except TemplateError as e: |
|
534 |
get_publisher().record_error( |
|
535 |
_('Error in template for export to model'), formdata=formdata, exception=e |
|
536 |
) |
|
537 |
raise TemplatingError(_('Error in template: %s') % str(e)) |
|
538 | ||
497 | 539 |
def apply_rtf_template_to_formdata(self, formdata): |
498 | 540 |
try: |
499 | 541 |
# force ezt_only=True because an RTF file may contain {{ characters |
500 |
- |