diff --git a/dev/config/pyramid_oereb.yml.mako b/dev/config/pyramid_oereb.yml.mako index aace2f21ec..8dd0a58270 100644 --- a/dev/config/pyramid_oereb.yml.mako +++ b/dev/config/pyramid_oereb.yml.mako @@ -358,6 +358,9 @@ pyramid_oereb: db_connection: *main_db_connection # The model which maps the logo images database table. model: pyramid_oereb.contrib.data_sources.standard.models.main.Logo + hooks: + get_logo_ref: pyramid_oereb.core.hook_methods.get_logo_ref + get_qr_code_ref: pyramid_oereb.core.hook_methods.get_qr_code_ref # The processor of the oereb project joins the document type labels. In the standard configuration this # is assumed to be read from a database. Hint: If you want to read the values out of an existing database diff --git a/pyramid_oereb/core/config.py b/pyramid_oereb/core/config.py index 862e5f8120..e564e1ffed 100644 --- a/pyramid_oereb/core/config.py +++ b/pyramid_oereb/core/config.py @@ -729,6 +729,25 @@ def get_logo_lookup_confederation(): return Config.get_logo_lookup('confederation') + @staticmethod + def get_logo_hooks(): + """ + Returns the hook methods specified in config file. + + Returns: + list: list of hook methods provided in config in dotted names. + + Raises: + ConfigurationError + """ + + logo_config = Config.get_logo_config() + if logo_config is None: + raise ConfigurationError("Missing configuration for logos") + if logo_config.get('hooks') is None: + raise ConfigurationError("Missing configuration for logos hook methods") + return logo_config.get('hooks') + @staticmethod def init_document_types(): """ diff --git a/pyramid_oereb/core/hook_methods.py b/pyramid_oereb/core/hook_methods.py index d11de52279..a2993e4d43 100644 --- a/pyramid_oereb/core/hook_methods.py +++ b/pyramid_oereb/core/hook_methods.py @@ -5,6 +5,7 @@ from functools import cmp_to_key from pyramid_oereb import route_prefix +from pyramid_oereb.core import get_multilingual_element from pyramid_oereb.core.records.office import OfficeRecord @@ -48,6 +49,46 @@ def get_symbol_ref(request, record): ) +def get_logo_ref(request, logo_code, language, image_dict): + """ + Returns the link to the logos. + + Args: + request (pyramid.request.Request): The current request instance. + logo_code (str): Code of logo, eg. bs or ch. + language (str): language of extract. + image_dict (dict): dict of image + + Returns: + uri: the link to the logos. + """ + + return request.route_url( + '{0}/image/logo'.format(route_prefix), + logo=logo_code, + language=language, + extension=get_multilingual_element( + image_dict, + language + ).extension + ) + + +def get_qr_code_ref(request, qr_code_ref): + """ + Returns the link for the qr_code. + + Args: + request (pyramid.request.Request): The current request instance. + qr_code_ref (str): The string of qr-code url. + + Returns: + uri: the link to the qr_code. + """ + + return qr_code_ref + + def get_surveying_data_provider(real_estate): """ diff --git a/pyramid_oereb/core/renderer/__init__.py b/pyramid_oereb/core/renderer/__init__.py index 4b5d73e700..8ffb433d13 100644 --- a/pyramid_oereb/core/renderer/__init__.py +++ b/pyramid_oereb/core/renderer/__init__.py @@ -52,6 +52,46 @@ def get_symbol_ref(cls, request, record): log.error('No "get_symbol_ref" method found for theme {}'.format(record.theme.code)) raise HTTPServerError() + @classmethod + def get_logo_ref(cls, request, logo_code, language, image_dict): + """ + Returns the link to the symbol of the specified logo. + + Args: + request (pyramid.request.Request): The current request instance. + logo_code (str): Code of logo, eg. bs or ch. + language (str): language of extract. + image_dict (dict): dict of image + + Returns: + uri: The link to the symbol for the specified logo. + """ + method = None + method = DottedNameResolver().resolve(Config.get_logo_hooks().get('get_logo_ref')) + if callable(method): + return method(request, logo_code, language, image_dict) + log.error('No "get_logo_ref" method found for logos') + raise HTTPServerError() + + @classmethod + def get_qr_code_ref(cls, request, qr_code_ref): + """ + Returns the link for the qr_code. + + Args: + request (pyramid.request.Request): The current request instance. + qr_code_ref (str): The string of qr-code url. + + Returns: + uri: the link to the qr_code. + """ + method = None + method = DottedNameResolver().resolve(Config.get_logo_hooks().get('get_qr_code_ref')) + if callable(method): + return method(request, qr_code_ref) + log.error('No "get_qr_code_ref" method found for logos') + raise HTTPServerError() + @classmethod def get_response(cls, system): """ diff --git a/pyramid_oereb/core/renderer/extract/json_.py b/pyramid_oereb/core/renderer/extract/json_.py index 518a6e57fe..82e4331b18 100644 --- a/pyramid_oereb/core/renderer/extract/json_.py +++ b/pyramid_oereb/core/renderer/extract/json_.py @@ -7,7 +7,7 @@ from pyramid.response import Response from pyramid.testing import DummyRequest -from pyramid_oereb import Config, route_prefix +from pyramid_oereb import Config from pyramid_oereb.core import get_multilingual_element from pyramid_oereb.core.records.documents import DocumentRecord from pyramid_oereb.core.records.theme import ThemeRecord @@ -119,44 +119,35 @@ def _render(self, extract, param): }) else: extract_dict.update({ - 'LogoPLRCadastreRef': self._request.route_url( - '{0}/image/logo'.format(route_prefix), - logo='oereb', - language=self._language, - extension=get_multilingual_element( - extract.logo_plr_cadastre.image_dict, - self._language - ).extension - ), - 'FederalLogoRef': self._request.route_url( - '{0}/image/logo'.format(route_prefix), - logo='confederation', - language=self._language, - extension=get_multilingual_element( - extract.federal_logo.image_dict, - self._language - ).extension - ), - 'CantonalLogoRef': self._request.route_url( - '{0}/image/logo'.format(route_prefix), - logo='canton', - language=self._language, - extension=get_multilingual_element( - extract.cantonal_logo.image_dict, - self._language - ).extension - ), - 'MunicipalityLogoRef': self._request.route_url( - '{0}/image/logo'.format(route_prefix), - logo='municipality', - language=self._language, - extension=get_multilingual_element( - extract.municipality_logo.image_dict, - self._language - ).extension - ) + '?fosnr={}'.format(extract.real_estate.fosnr), - 'QRCodeRef': extract.qr_code_ref - }) + 'LogoPLRCadastreRef': self.get_logo_ref( + self._request, + 'oereb', + self._language, + extract.logo_plr_cadastre.image_dict + ), + 'FederalLogoRef': self.get_logo_ref( + self._request, + 'confederation', + self._language, + extract.federal_logo.image_dict + ), + 'CantonalLogoRef': self.get_logo_ref( + self._request, + 'canton', + self._language, + extract.cantonal_logo.image_dict + ), + 'MunicipalityLogoRef': self.get_logo_ref( + self._request, + 'municipality', + self._language, + extract.municipality_logo.image_dict + ) + '?fosnr={}'.format(extract.real_estate.fosnr), + 'QRCodeRef': self.get_qr_code_ref( + self._request, + extract.qr_code_ref + ) + }) if extract.electronic_signature is not None: extract_dict['ElectronicSignature'] = extract.electronic_signature diff --git a/pyramid_oereb/core/renderer/extract/templates/xml/extract.xml b/pyramid_oereb/core/renderer/extract/templates/xml/extract.xml index 7941212dcf..2b76efcb47 100644 --- a/pyramid_oereb/core/renderer/extract/templates/xml/extract.xml +++ b/pyramid_oereb/core/renderer/extract/templates/xml/extract.xml @@ -65,12 +65,12 @@ ${extract.extract_identifier} ${extract.qr_code.encode()} %else: - ${request.route_url('{0}/image/logo'.format(route_prefix), logo='oereb', language=language, extension=get_multilingual_element(extract.logo_plr_cadastre.image_dict, language).extension) | x} - ${request.route_url('{0}/image/logo'.format(route_prefix), logo='confederation', language=language, extension=get_multilingual_element(extract.federal_logo.image_dict, language).extension) | x} - ${request.route_url('{0}/image/logo'.format(route_prefix), logo='canton', language=language, extension=get_multilingual_element(extract.cantonal_logo.image_dict, language).extension) | x} - ${request.route_url('{0}/image/logo'.format(route_prefix), logo='municipality', language=language, extension=get_multilingual_element(extract.municipality_logo.image_dict, language).extension) + '?fosnr={}'.format(extract.real_estate.fosnr) | x} + ${get_logo_ref(request=request, logo_code='oereb', language=language, image_dict=extract.logo_plr_cadastre.image_dict) | x} + ${get_logo_ref(request=request, logo_code='confederation', language=language, image_dict=extract.logo_plr_cadastre.image_dict) | x} + ${get_logo_ref(request=request, logo_code='canton', language=language, image_dict=extract.logo_plr_cadastre.image_dict) | x} + ${get_logo_ref(request=request, logo_code='municipality', language=language, image_dict=extract.logo_plr_cadastre.image_dict) + '?fosnr={}'.format(extract.real_estate.fosnr) | x} ${extract.extract_identifier} - ${extract.qr_code_ref} + ${get_qr_code_ref(request=request, qr_code_ref=extract.qr_code_ref) | x} %endif %for general_information in extract.general_information: <%include file="general_information.xml" args="general_information=general_information"/> diff --git a/pyramid_oereb/core/renderer/extract/xml_.py b/pyramid_oereb/core/renderer/extract/xml_.py index afa75bee93..83851c0b2a 100644 --- a/pyramid_oereb/core/renderer/extract/xml_.py +++ b/pyramid_oereb/core/renderer/extract/xml_.py @@ -83,6 +83,8 @@ def _render(self, extract, params): 'get_localized_image': self.get_localized_image, 'request': self._request, 'get_symbol_ref': self.get_symbol_ref, + 'get_logo_ref': self.get_logo_ref, + 'get_qr_code_ref': self.get_qr_code_ref, 'date_format': '%Y-%m-%dT%H:%M:%S' }) return content diff --git a/tests/contrib.print_proxy.mapfish_print/resources/test_config.yml b/tests/contrib.print_proxy.mapfish_print/resources/test_config.yml index b9b2134422..3b1dd144ee 100644 --- a/tests/contrib.print_proxy.mapfish_print/resources/test_config.yml +++ b/tests/contrib.print_proxy.mapfish_print/resources/test_config.yml @@ -22,6 +22,9 @@ pyramid_oereb: params: db_connection: postgresql://postgres:postgres@oereb-db:5432/pyramid_oereb_test model: pyramid_oereb.contrib.data_sources.standard.models.main.Logo + hooks: + get_logo_ref: pyramid_oereb.core.hook_methods.get_logo_ref + get_qr_code_ref: pyramid_oereb.core.hook_methods.get_qr_code_ref document_types: source: diff --git a/tests/contrib.print_proxy.mapfish_print/resources/test_custom_config.yml b/tests/contrib.print_proxy.mapfish_print/resources/test_custom_config.yml index a967257dd6..c253e36031 100644 --- a/tests/contrib.print_proxy.mapfish_print/resources/test_custom_config.yml +++ b/tests/contrib.print_proxy.mapfish_print/resources/test_custom_config.yml @@ -22,6 +22,9 @@ pyramid_oereb: params: db_connection: postgresql://postgres:postgres@oereb-db:5432/pyramid_oereb_test model: pyramid_oereb.standard.models.main.Logo + hooks: + get_logo_ref: pyramid_oereb.core.hook_methods.get_logo_ref + get_qr_code_ref: pyramid_oereb.core.hook_methods.get_qr_code_ref document_types: source: diff --git a/tests/contrib.print_proxy.mapfish_print/test_mapfish_print.py b/tests/contrib.print_proxy.mapfish_print/test_mapfish_print.py index c6c3c56c55..732f3cfafc 100644 --- a/tests/contrib.print_proxy.mapfish_print/test_mapfish_print.py +++ b/tests/contrib.print_proxy.mapfish_print/test_mapfish_print.py @@ -847,7 +847,6 @@ def dummy_pdf(): @patch.object(pyramid_oereb.core.views.webservice, 'route_prefix', 'oereb') -@patch.object(pyramid_oereb.core.renderer.extract.json_, 'route_prefix', 'oereb') @patch.object(pyramid_oereb.core.config.Config, 'municipalities', [MunicipalityRecord(1234, 'test', True)]) def test_mfp_service(mock_responses, pyramid_test_config, real_estate_data, diff --git a/tests/core/renderer/test_base.py b/tests/core/renderer/test_base.py index 9b5322eee5..e1f4bb9a7f 100644 --- a/tests/core/renderer/test_base.py +++ b/tests/core/renderer/test_base.py @@ -1,8 +1,11 @@ # -*- coding: utf-8 -*- +import io +from urllib.parse import urlparse import pytest from unittest.mock import patch import datetime +from PIL import Image from pyramid.httpexceptions import HTTPServerError, HTTPInternalServerError from pyramid.response import Response @@ -19,6 +22,18 @@ from tests.mockrequest import MockRequest +@pytest.fixture +def png_image(): + yield Image.new("RGB", (72, 36), (128, 128, 128)) + + +@pytest.fixture +def png_binary(png_image): + output = io.BytesIO() + png_image.save(output, format='PNG') + yield output.getvalue() + + def test_call(DummyRenderInfo, pyramid_oereb_test_config): renderer = Base(DummyRenderInfo()) assert isinstance(renderer.info, DummyRenderInfo) @@ -206,3 +221,69 @@ def test_get_symbol_ref(theme_code, pyramid_test_config, pyramid_oereb_test_conf assert ref == 'http://example.com/image/symbol/{}/legend_entry.svg?identifier=1'.format( theme_code ) + + +@pytest.mark.parametrize('test_value, expected_results', [ + ({ + 'logo_code': 'ch', + 'language': 'de', + }, '/image/logo/ch/de.png'), + ({ + 'logo_code': 'bs', + 'language': 'fr', + }, '/image/logo/bs/fr.png') + ]) +def test_get_logo_ref(test_value, expected_results, png_binary): + with patch.object(Config, 'get_logo_hooks', + return_value={"get_logo_ref": "pyramid_oereb.core.hook_methods.get_logo_ref"}): + request = DummyRequest() + url = urlparse(Base.get_logo_ref(request, + test_value.get('logo_code'), + test_value.get('language'), + {test_value.get('language'): ImageRecord(png_binary)})) + assert url.path == expected_results + + +@pytest.mark.parametrize('test_value, expected_results', [ + ({ + 'logo_code': 'ch', + 'language': 'de', + }, '/image/logo/ch/de.png'), + ({ + 'logo_code': 'bs', + 'language': 'fr', + }, '/image/logo/bs/fr.png') + ]) +def test_get_logo_ref_no_method(test_value, expected_results, png_binary): + with patch.object(Config, 'get_logo_hooks', + return_value={"get_logo_ref": "pyramid_oereb.core.hook_methods.get_logo_ref"}): + with patch.object(pyramid_oereb.core.hook_methods, 'get_logo_ref', {}): + with pytest.raises(HTTPServerError): + Base.get_logo_ref(DummyRequest(), + test_value.get('logo_code'), + test_value.get('language'), + {test_value.get('language'): ImageRecord(png_binary)}) + + +@pytest.mark.parametrize('test_value, expected_results', [ + ('', ''), + (None, None) + ]) +def test_get_qr_code_ref(test_value, expected_results): + with patch.object(Config, 'get_logo_hooks', + return_value={"get_qr_code_ref": "pyramid_oereb.core.hook_methods.get_qr_code_ref"}): + request = DummyRequest() + assert Base.get_qr_code_ref(request, test_value) == expected_results + + +@pytest.mark.parametrize('test_value, expected_results', [ + ('', '') + ]) +def test_get_qr_code_ref_no_method(test_value, expected_results): + with patch.object(Config, 'get_logo_hooks', + return_value={ + "get_qr_code_ref": "pyramid_oereb.core.hook_methods.get_qr_code_ref" + }): + with patch.object(pyramid_oereb.core.hook_methods, 'get_qr_code_ref', {}): + with pytest.raises(HTTPServerError): + Base.get_qr_code_ref(DummyRequest(), test_value) diff --git a/tests/core/renderer/test_json.py b/tests/core/renderer/test_json.py index 181d62f30f..790706f34c 100644 --- a/tests/core/renderer/test_json.py +++ b/tests/core/renderer/test_json.py @@ -3,7 +3,6 @@ import datetime import pytest -from unittest.mock import patch from shapely.geometry import MultiPolygon, Polygon, Point, LineString from pyramid.path import DottedNameResolver @@ -30,9 +29,6 @@ from tests.mockrequest import MockRequest from pyramid_oereb.core.views.webservice import Parameter -import pyramid_oereb.core.renderer.extract.json_ -import pyramid_oereb.core.hook_methods - def law_status(): return LawStatusRecord(u'inKraft', {u'de': u'Rechtskräftig'}) @@ -58,7 +54,6 @@ def glossary_expected(): }] -@patch.object(pyramid_oereb.core.renderer.extract.json_, 'route_prefix', 'oereb') @pytest.mark.parametrize('parameter, glossaries_input, glossaries_expected', [ (default_param(), glossary_input(), glossary_expected()), (default_param(), [], []), @@ -230,7 +225,6 @@ def test_format_real_estate(DummyRenderInfo, real_estate_test_data): } -@patch.object(pyramid_oereb.core.hook_methods, 'route_prefix', 'oereb') @pytest.mark.parametrize('parameter', [ default_param(), Parameter('json', False, True, False, 'BL0200002829', '1000', 'CH775979211712', 'de'), @@ -504,7 +498,6 @@ def test_format_theme(DummyRenderInfo, params): } -@patch.object(pyramid_oereb.core.hook_methods, 'route_prefix', 'oereb') @pytest.mark.parametrize('parameter', [ default_param(), Parameter('json', 'reduced', False, True, 'BL0200002829', '1000', 'CH775979211712', 'de') diff --git a/tests/core/test_config.py b/tests/core/test_config.py index 296c2fa814..afb1a2794b 100644 --- a/tests/core/test_config.py +++ b/tests/core/test_config.py @@ -96,6 +96,26 @@ def mock_read_logos(): assert Config.logos is None +@pytest.mark.run(order=-1) +def test_get_logo_hooks(): + with patch.object(Config, 'get_logo_config', return_value={"hooks": []}): + Config._config = None + assert Config.get_logo_hooks() == [] + + +@pytest.mark.parametrize('test_value', [ + ({"logos": [{"hooks": []}]}), + ({"logos": [{"not_expecting_key": []}]}), + (None) +]) +@pytest.mark.run(order=-1) +def test_get_logo_hooks_none(test_value): + with patch.object(Config, 'get_logo_config', return_value=test_value): + Config._config = None + with pytest.raises(ConfigurationError): + Config.get_logo_hooks() + + @pytest.mark.run(order=-1) def test_get_all_federal(config_path): Config._config = None diff --git a/tests/core/test_hook_methods.py b/tests/core/test_hook_methods.py index bdb75786a0..5dc317c733 100644 --- a/tests/core/test_hook_methods.py +++ b/tests/core/test_hook_methods.py @@ -1,3 +1,4 @@ +import io from pyramid_oereb.core.records.extract import ExtractRecord from pyramid_oereb.core.records.law_status import LawStatusRecord import pytest @@ -5,6 +6,7 @@ from shapely.wkt import loads from unittest.mock import patch +from PIL import Image from pyramid.testing import DummyRequest @@ -15,7 +17,8 @@ from pyramid_oereb.core.records.view_service import LegendEntryRecord from pyramid_oereb.core.records.real_estate import RealEstateRecord from pyramid_oereb.core.hook_methods import compare, get_symbol, get_symbol_ref, \ - get_surveying_data_update_date, plr_sort_within_themes + get_logo_ref, get_qr_code_ref, get_surveying_data_update_date,\ + plr_sort_within_themes from pyramid_oereb.contrib.data_sources.standard.sources.plr import StandardThemeConfigParser import pyramid_oereb.contrib.data_sources.standard.hook_methods from tests.core.records.test_extract import create_dummy_extract @@ -61,6 +64,18 @@ def legend_entry_data(pyramid_oereb_test_config, dbsession, transact, file_adapt yield legend_entries +@pytest.fixture +def png_image(): + yield Image.new("RGB", (72, 36), (128, 128, 128)) + + +@pytest.fixture +def png_binary(png_image): + output = io.BytesIO() + png_image.save(output, format='PNG') + yield output.getvalue() + + def test_get_symbol(): with pytest.raises(NotImplementedError): binary_image, content_type = get_symbol({'identifier': "1"}, {}) @@ -82,6 +97,36 @@ def test_get_symbol_ref(pyramid_test_config): assert url.path == '/image/symbol/ch.BelasteteStandorte/legend_entry.png' +@pytest.mark.parametrize('test_value, expected_results', [ + ({ + 'logo_code': 'ch', + 'language': 'de', + }, '/image/logo/ch/de.png'), + ({ + 'logo_code': 'bs', + 'language': 'fr', + }, '/image/logo/bs/fr.png') + ]) +def test_get_logo_ref(test_value, expected_results, png_binary): + request = DummyRequest() + url = urlparse(get_logo_ref(request, + test_value.get('logo_code'), + test_value.get('language'), + {test_value.get('language'): ImageRecord(png_binary)} + )) + assert url.path == expected_results + + +@pytest.mark.parametrize('test_value, expected_results', [ + ('', ''), + ({}, {}), + (None, None) + ]) +def test_get_qr_code_ref(test_value, expected_results): + request = DummyRequest() + assert get_qr_code_ref(request, test_value) == expected_results + + def test_get_surveying_data_date(): real_estate = RealEstateRecord('test_type', 'BL', 'Nusshof', 1, 100, loads('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')) diff --git a/tests/core/webservice/test_getextractbyid.py b/tests/core/webservice/test_getextractbyid.py index 54a5340a49..26f0199cb1 100644 --- a/tests/core/webservice/test_getextractbyid.py +++ b/tests/core/webservice/test_getextractbyid.py @@ -148,7 +148,6 @@ def test_return_no_content(): @patch.object(pyramid_oereb.core.hook_methods, 'route_prefix', 'oereb') -@patch.object(pyramid_oereb.core.renderer.extract.json_, 'route_prefix', 'oereb') @patch.object(pyramid_oereb.core.views.webservice, 'route_prefix', 'oereb') @patch.object(MockRequest, 'route_url', lambda *args, **kwargs: '') @pytest.mark.parametrize('egrid,topics', [ diff --git a/tests/resources/test_config.yml b/tests/resources/test_config.yml index af25f1937a..ad896d48a6 100644 --- a/tests/resources/test_config.yml +++ b/tests/resources/test_config.yml @@ -178,6 +178,9 @@ pyramid_oereb: params: db_connection: *main_db_connection model: pyramid_oereb.contrib.data_sources.standard.models.main.Logo + hooks: + get_logo_ref: pyramid_oereb.core.hook_methods.get_logo_ref + get_qr_code_ref: pyramid_oereb.core.hook_methods.get_qr_code_ref document_types: source: