Source code for ontocode.result_processor
# Copyright, 2018-2019, Deutsches Zentrum für Luft- und Raumfahrt e.V.
# Licensed under LGPLv3+, see LICENSE for details.
"""
Result processors convert the output of :ref:`queries<queries>`, a list of
dictionaries with variable names as keys and Owlready2_ objects as values, into
the form expected by :ref:`templates<templates>`.
A template :ref:`instantiation<instantiations>` is given a list of result
processors, a result processor chain. The first element of that chain is
applied to the result of the template :ref:`instantiation<instantiations>`\\´s
query result and subsequent elements of the chain are then applied to the
output of their predecessor.
A result processor is a callable_ with two parameters, ``input_`` and
``world``. ``input_`` is the query result or the output of their predecessor,
while ``world`` is the :class:`owlready2.namespace.World` object that the query
was run against.
It is the responsibility of the user, that a result processor chain is setup,
so that the output of a result processor meets the expectations of its
successor or, for the final result processor, of the :ref:`template<templates>`
for its input value.
Built-In Result Processors
~~~~~~~~~~~~~~~~~~~~~~~~~~
This module provides three result processors for commonly required
transformation tasks and a base class for result processors of a commonly
encountered transformation scheme.
.. _callable: https://docs.python.org/3/library/functions.html#callable
.. _Owlready2: https://pypi.org/project/Owlready2/
"""
import abc
__all__ = ['AbstractMapElementsProcessor', 'list_of_dicts_to_dict_of_lists',
'NoLabelError', 'NoNameError', 'ObjectNameProcessor',
'ObjectLabelProcessor']
[docs]class AbstractMapElementsProcessor(metaclass=abc.ABCMeta):
"""AbstractMapElementsProcessor is an abstract base class for result
processors that expect a list of dictionaries as their ``input_``
parameter and, when called, apply a function,
:func:`~ontocode.result_processor.AbstractMapElementsProcessor.process_value`,
to every value of those dictionaries.
"""
[docs] def __call__(self, input_, world):
"""Apply
:func:`~ontocode.result_processor.AbstractMapElementsProcessor.process_value`
to every value of dictionaries in ``input_``.
:param list input_: a list of dictionaries
:return: ``input_`` with
:func:`~ontocode.result_processor.AbstractMapElementsProcessor.process_value`
applied to every value
:rtype: a list of dictionaries
"""
return [self._process_row(row, world) for row in input_]
def _process_row(self, row, world):
return {key: self.process_value(row[key], world) for key in row}
[docs] @abc.abstractmethod
def process_value(self, value, world):
"""Returns a new value derived from ``value`` and ``world``.
:param value: some value
:param owlready2.namespace.World world: the world object, that is the
source of the currently processed query result"""
[docs]class ObjectNameProcessor(AbstractMapElementsProcessor):
"""Replaces Owlready2_ objects with their names."""
def process_value(self, value, world):
if not hasattr(value, 'name'):
raise NoNameError()
return value.name
[docs]class NoNameError(ValueError):
"""Raised when ObjectNameProcessor encounters an object without name."""
[docs]class ObjectLabelProcessor(AbstractMapElementsProcessor):
"""Replaces Owlready2_ objects with their English ('en') labels."""
def process_value(self, value, world):
if not hasattr(value, 'label'):
raise NoLabelError()
labels = value.label
if not labels.en:
raise NoLabelError()
return labels.en[0]
[docs]class NoLabelError(ValueError):
"""Raised when ObjectLabelProcessor encounters an object without an English
('en') label."""
[docs]def list_of_dicts_to_dict_of_lists(input_, _world):
"""Converts a list of dicts to a dict of lists.
Assumes that all dicts in the list of dicts have the same set of keys.
:param list input_: a list dictionaries
:return: a dictionary of lists
:rtype: dict
"""
if not input_:
return {}
return {k: [d[k] for d in input_] for k in input_[0]}