# passerelle - uniform access to multiple data sources and services # Copyright (C) 2019 Entr'ouvert # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import io import json import uuid import zipfile import pytest from passerelle.utils.zip import ( ZipTemplate, ZipTemplateDoesNotExist, ZipTemplateError, ZipTemplateSyntaxError, ) @pytest.fixture def templates_path(tmpdir, settings): path = tmpdir.mkdir('templates') settings.TEMPLATES = settings.TEMPLATES[:] settings.TEMPLATES[0] = settings.TEMPLATES[0].copy() settings.TEMPLATES[0].setdefault('DIRS', []) settings.TEMPLATES[0]['DIRS'].insert(0, str(path)) zip_templates_path = path.mkdir('zip_templates') return zip_templates_path @pytest.fixture def tpl_builder(templates_path): def make(name_template, template_parts=(), content_parts=()): manifest_name = '%s.json' % uuid.uuid4().hex manifest_path = templates_path / manifest_name d = { 'name_template': name_template, } if template_parts or content_parts: d['part_templates'] = [] for name_template, content in template_parts: name = '%s.xml' % uuid.uuid4().hex with (templates_path / name).open('w') as fd: fd.write(content) d['part_templates'].append( { 'name_template': name_template, 'template_path': name, } ) for name_template, content in content_parts: d['part_templates'].append( { 'name_template': name_template, 'content_expression': content, } ) with manifest_path.open('w') as fd: json.dump(d, fd) return '%s/%s' % (templates_path.basename, manifest_name) return make @pytest.fixture def dest(tmpdir): return tmpdir.mkdir('dest') def test_missing(): with pytest.raises(ZipTemplateDoesNotExist): ZipTemplate('zip_templates/manifest1.json') def test_invalid(templates_path): path = templates_path / 'invalid-manifest.json' with path.open(mode='w') as fd: fd.write('{') with pytest.raises(ZipTemplateError) as exc_info: ZipTemplate(str(path)) assert 'invalid' in exc_info.value.args[0] with path.open(mode='w') as fd: fd.write('{}') with pytest.raises(ZipTemplateError): ZipTemplate(str(path)) assert 'invalid' in exc_info.value.args[0] def test_syntax_error(tpl_builder, dest): zip_template = ZipTemplate( tpl_builder('{{ name -{{ counter }}.zip'), ctx={'name': 'coucou', 'counter': 10} ) with pytest.raises(ZipTemplateSyntaxError): zip_template.render_to_path(dest) zip_template = ZipTemplate( tpl_builder('{{ name }}-{{ counter }}.zip', template_parts=[('part1.xml', '{{ name {{ }}')]), ctx={'name': 'coucou', 'counter': 10}, ) with pytest.raises(ZipTemplateSyntaxError): zip_template.render_to_path(dest) def test_no_parts(tpl_builder, dest): z = ZipTemplate(tpl_builder('{{ name }}-{{ counter }}.zip'), ctx={'name': 'coucou', 'counter': 10}) z.render_to_path(dest) full_path = dest / 'coucou-10.zip' with full_path.open('rb') as fd: with zipfile.ZipFile(fd) as zi: assert zi.namelist() == [] def test_with_parts(tpl_builder, dest): z = ZipTemplate( tpl_builder( '{{ name }}-{{ counter }}.zip', template_parts=[ ('{{ name }}-{{ counter }}-part1.xml', '{{ bo_dy|lower }}') ], content_parts=[('{{ name }}-{{ counter }}-dôc.xml', 'doc-content')], ), ctx={'name': 'coucou', 'counter': 10, 'bo_dy': 'blabla', 'doc-content': 'Héllo World!'}, ) z.render_to_path(dest) for part in z.parts: str(part) full_path = dest / 'coucou-10.zip' with full_path.open('rb') as fd: with zipfile.ZipFile(fd) as zi: assert zi.namelist() == ['coucou-10-part1.xml', 'coucou-10-dôc.xml'] with zi.open('coucou-10-part1.xml') as zfd: assert zfd.read().decode('utf-8') == 'blabla' with zi.open('coucou-10-dôc.xml') as zfd: assert zfd.read().decode('utf-8') == 'Héllo World!' with io.BytesIO(z.render_to_bytes()) as fd: with zipfile.ZipFile(fd) as zi: assert zi.namelist() == ['coucou-10-part1.xml', 'coucou-10-dôc.xml'] with zi.open('coucou-10-part1.xml') as zfd: assert zfd.read().decode('utf-8') == 'blabla' with zi.open('coucou-10-dôc.xml') as zfd: assert zfd.read().decode('utf-8') == 'Héllo World!' def test_xml_error(tpl_builder, dest): z = ZipTemplate( tpl_builder( 'rien.zip', content_parts=[('rien.xml', 'doc-content')], ), ctx={'doc-content': 'Héllo World!'}, ) with pytest.raises(ZipTemplateSyntaxError) as exc_info: z.render_to_bytes() assert 'XML syntax error' in exc_info.value.args[0]