Source code for pyramid_oereb.core.readers.extract
# -*- coding: utf-8 -*-
import logging
from operator import attrgetter
from pyramid.path import DottedNameResolver
from shapely.geometry import box
from timeit import default_timer as timer
from pyramid_oereb.core.config import Config
from pyramid_oereb.core.records.extract import ExtractRecord
from pyramid_oereb.core.records.image import ImageRecord
from pyramid_oereb.core.records.plr import PlrRecord, EmptyPlrRecord
log = logging.getLogger(__name__)
[docs]
class ExtractReader(object):
"""
The class which generates *the extract* as a record
(:ref:`api-pyramid_oereb-core-records-extract-extractrecord`). This is the point where all necessary
and extract related components are bound together.
Attributes:
extract (pyramid_oereb.lib.records.extract.ExtractRecord or None): The extract as a record
representation. On initialisation this is None. It will be set by calling the read method of the
instance.
"""
[docs]
def __init__(self, plr_sources, plr_cadastre_authority):
"""
Args:
plr_sources (list of pyramid_oereb.lib.sources.plr.PlrBaseSource): The list of PLR source
instances which the achieved extract should be about.
plr_cadastre_authority (pyramid_oereb.lib.records.office.OfficeRecord): The authority responsible
for the PLR cadastre.
"""
self.extract = None
self._plr_sources_ = plr_sources
self._plr_cadastre_authority_ = plr_cadastre_authority
self.law_status = Config.get_law_status_codes()
@property
def plr_cadastre_authority(self):
"""
Returns:
pyramid_oereb.lib.records.office.OfficeRecord: The authority responsible for the PLR
cadastre.
"""
return self._plr_cadastre_authority_
[docs]
def read(self, params, real_estate, municipality):
"""
This method finally creates the extract.
Note:
If you subclass this class your implementation needs to offer this method in the same
signature. Means the parameters must be the same and the return must be a
:ref:`api-pyramid_oereb-core-records-extract-extractrecord`. Otherwise the API like way the server
works would be broken.
Args:
params (pyramid_oereb.views.webservice.Parameter): The parameters of the extract request.
real_estate (pyramid_oereb.lib.records.real_estate.RealEstateRecord): The real
estate for which the report should be generated
municipality (pyramid_oereb.lib.records.municipality.MunicipalityRecord): The municipality
record.
Returns:
pyramid_oereb.lib.records.extract.ExtractRecord:
The extract record containing all gathered data.
"""
log.debug("read() start")
bbox = Config.get_bbox(real_estate.limit)
bbox = box(bbox[0], bbox[1], bbox[2], bbox[3])
concerned_themes = list()
not_concerned_themes = list()
themes_without_data = list()
if municipality.published:
for plr_source in self._plr_sources_:
if not params.skip_topic(plr_source.info.get('code')):
plr_source.read(params, real_estate, bbox)
real_estate.public_law_restrictions.extend(plr_source.records)
for plr in real_estate.public_law_restrictions:
# Filter topics due to topics parameter
if not params.skip_topic(plr.theme.code):
if isinstance(plr, PlrRecord):
if plr.theme.code not in [theme.code for theme in concerned_themes]:
concerned_themes.append(plr.theme)
elif isinstance(plr, EmptyPlrRecord):
if plr.has_data:
not_concerned_themes.append(plr.theme)
else:
themes_without_data.append(plr.theme)
else:
for plr_source in self._plr_sources_:
themes_without_data.append(Config.get_theme_by_code_sub_code(plr_source.info.get('code')))
# sort theme lists
concerned_themes.sort(key=attrgetter('extract_index'))
not_concerned_themes.sort(key=attrgetter('extract_index'))
themes_without_data.sort(key=attrgetter('extract_index'))
# sort plr according to theme, sub-theme and law-status
start_time = timer()
log.debug("sort plrs by theme and law status start")
real_estate.public_law_restrictions.sort(key=lambda element: (
self._sort_plr_theme(element), self._sort_plr_law_status(element)
))
end_time = timer()
log.debug(f"DONE with sort plrs by theme and law status, time spent: {end_time-start_time} seconds")
# Load base data form configuration
resolver = DottedNameResolver()
date_method_string = Config.get('extract').get('base_data').get('methods').get('date')
date_method = resolver.resolve(date_method_string)
update_date_os = date_method(real_estate)
general_information = Config.get_general_information()
oereb_logo = Config.get_oereb_logo()
confederation_logo = Config.get_conferderation_logo()
canton_logo = Config.get_canton_logo()
municipality_logo = Config.get_municipality_logo(municipality.fosnr)
qr_code_image = ImageRecord(params.qr_code)
self.extract = ExtractRecord(
real_estate,
oereb_logo,
confederation_logo,
canton_logo,
municipality_logo,
self.plr_cadastre_authority,
update_date_os,
concerned_theme=concerned_themes,
not_concerned_theme=not_concerned_themes,
theme_without_data=themes_without_data,
general_information=general_information,
qr_code=qr_code_image,
qr_code_ref=params.qr_code_ref
)
log.debug("read() done")
return self.extract
def _sort_plr_law_status(self, plr_element):
"""
This method generates the sorting key for plr_elements according to their law_status code.
The value is generated from the index the plr_element.law_status.code has in the law_status
list. The law_status list corresponds to the law status taken from the DB
If the argument is not a PlrRecord or its law_status.code is not contained in the law_status list,
the method will return the length of the law_status list so it can be sorted at the end of the list.
Args:
plr_element (PlrRecord or EmptyPlrRecord) a plr record element.
Returns:
int: Value which can be used to sort the record depending on its law_status.code.
"""
if (isinstance(plr_element, PlrRecord) and plr_element.law_status.code in self.law_status):
return self.law_status.index(plr_element.law_status.code)
else:
return len(self.law_status)
@staticmethod
def _sort_plr_theme(plr_element):
"""
This method generates a sorting key to sort PLRs in to themes and sub-themes.
The value is generated using the extract_index given for each theme.
Currently it is assumed that the extract_index for a sub-theme is in accord to
its theme so that the order will be correct.
If the plr_element is not a PlrRecord 10 000 will be returned so that it is
added at the end of the list
Args:
plr_element (PlrRecord or EmptyPlrRecord) a plr record element.
Returns:
int: Value which can be used to sort the record depending on its theme/sub-theme.
"""
if (isinstance(plr_element, PlrRecord)):
index = plr_element.sub_theme.extract_index \
if (plr_element.sub_theme is not None) \
else plr_element.theme.extract_index
return index
return 10000