passerelle/tests/test_utils_zip.py

172 lines
5.8 KiB
Python

# 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 <http://www.gnu.org/licenses/>.
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', '<?xml version="1.0"?><body>{{ bo_dy|lower }}</body>')
],
content_parts=[('{{ name }}-{{ counter }}-dôc.xml', 'doc-content')],
),
ctx={'name': 'coucou', 'counter': 10, 'bo_dy': 'blabla', 'doc-content': '<a>Héllo World!</a>'},
)
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') == '<?xml version="1.0"?><body>blabla</body>'
with zi.open('coucou-10-dôc.xml') as zfd:
assert zfd.read().decode('utf-8') == '<a>Héllo World!</a>'
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') == '<?xml version="1.0"?><body>blabla</body>'
with zi.open('coucou-10-dôc.xml') as zfd:
assert zfd.read().decode('utf-8') == '<a>Héllo World!</a>'
def test_xml_error(tpl_builder, dest):
z = ZipTemplate(
tpl_builder(
'rien.zip',
content_parts=[('rien.xml', 'doc-content')],
),
ctx={'doc-content': '<a>Héllo World!'},
)
with pytest.raises(ZipTemplateSyntaxError) as exc_info:
z.render_to_bytes()
assert 'XML syntax error' in exc_info.value.args[0]