ara/ara/fields.py

84 lines
2.7 KiB
Python

# Copyright (c) 2017 Red Hat, Inc.
#
# This file is part of ARA: Ansible Run Analysis.
#
# ARA is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ARA 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ARA. If not, see <http://www.gnu.org/licenses/>.
import datetime
from ara.webapp import create_app
from flask import render_template_string
app = create_app()
implicit_templates = {
datetime.datetime: '{{ value|datefmt }}',
datetime.timedelta: '{{ value|timefmt }}',
}
class Field(object):
"""
A utility class for extracting a value from an object hierarchy and
formatting it using a Jinja2 template.
"""
def __init__(self, name, path=None, template=None, raise_on_err=False):
"""
Initialize a Field object.
- 'name' -- field label (used for display)
- 'path' -- a Jinja2 expression used to extract a value from
an object hierarchy. If not specified, this is derived from
'name' by setting 'name' to lower case and replacing ' ' with
'_'.
- 'template' -- a Jinja2 template that will be used to render
the value for display.
- 'raise_on_err' -- raise an AttributeError if the specified
'path' does not return a value.
"""
if path is None:
path = name.lower().replace(' ', '_')
self.name = name
self.template = template
self.raise_on_err = raise_on_err
self.path = path
self.expr = app.jinja_env.compile_expression(path)
def __call__(self, obj):
"""
Extract a value from `obj` and return the formatted value.
"""
# Extract value from the object.
value = self.expr(**{x: getattr(obj, x)
for x in dir(obj)
if not x.startswith('_')})
if value is None:
if self.raise_on_err:
raise AttributeError(self.path)
# Get a template, maybe
template = (self.template if self.template
else implicit_templates.get(type(value)))
if template:
return render_template_string(template, value=value)
else:
return value
def __str__(self):
return self.name