/usr/lib/python2.7/dist-packages/relatorio/reporting.py is in python-relatorio 0.6.4-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | ###############################################################################
#
# Copyright (c) 2007, 2008 OpenHex SPRL. (http://openhex.com) All Rights
# Reserved.
#
# This program 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.
#
# 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 General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
__metaclass__ = type
import os
import sys
from genshi.template import TemplateLoader
def _absolute(path):
"Compute the absolute path of path relative to the caller file"
if os.path.isabs(path):
return path
caller_fname = sys._getframe(2).f_globals['__file__']
caller_dir = os.path.dirname(caller_fname)
return os.path.abspath(os.path.join(caller_dir, path))
def _guess_type(mime):
"""
Returns the codename used by relatorio to identify which template plugin
it should use to render a mimetype
"""
mime = mime.lower()
major, stype = mime.split('/', 1)
if major == 'application':
if 'opendocument' in stype:
return 'oo.org'
else:
return stype
elif major == 'text':
if stype in ('xml', 'html', 'xhtml'):
return 'markup'
else:
return 'text'
class MIMETemplateLoader(TemplateLoader):
"""This subclass of TemplateLoader use mimetypes to search and find
templates to load.
"""
factories = {}
mime_func = [_guess_type]
def get_type(self, mime):
"finds the codename used by relatorio to work on a mimetype"
for func in reversed(self.mime_func):
codename = func(mime)
if codename is not None:
return codename
def load(self, path, mime=None, relative_to=None, cls=None):
"returns a template object based on path"
assert mime is not None or cls is not None
if mime is not None:
cls = self.factories[self.get_type(mime)]
return super(MIMETemplateLoader, self).load(
path, cls=cls, relative_to=relative_to)
@classmethod
def add_factory(cls, abbr_mimetype, template_factory, id_function=None):
"""adds a template factory to the already known factories"""
cls.factories[abbr_mimetype] = template_factory
if id_function is not None:
cls.mime_func.append(id_function)
default_loader = MIMETemplateLoader(auto_reload=True)
class DefaultFactory:
"""This is the default factory used by relatorio.
It just returns a copy of the data it receives"""
def __init__(self, *args, **kwargs):
pass
def __call__(self, **kwargs):
data = kwargs.copy()
return data
default_factory = DefaultFactory()
class Report:
"""Report is a simple interface on top of a rendering template.
"""
def __init__(self, path, mimetype,
factory=default_factory, loader=default_loader):
self.fpath = path
self.mimetype = mimetype
self.data_factory = factory
self.tmpl_loader = loader
self.filters = []
def __call__(self, **kwargs):
template = self.tmpl_loader.load(self.fpath, self.mimetype)
data = self.data_factory(**kwargs)
return template.generate(**data).filter(*self.filters)
def __repr__(self):
return '<relatorio report on %s>' % self.fpath
class ReportDict:
def __init__(self, *args, **kwargs):
self.mimetypes = {}
self.ids = {}
class ReportRepository:
"""ReportRepository stores the report definition associated to objects.
The report are indexed in this object by the object class they are working
on and the name given to it by the user.
"""
def __init__(self, datafactory=DefaultFactory):
self.classes = {}
self.default_factory = datafactory
self.loader = default_loader
def add_report(self, klass, mimetype, template_path, data_factory=None,
report_name='default', description=''):
"""adds a report to the repository.
You will be able to find the report via
- the class it is working on
- the mimetype it outputs
- the name of the report
You also have the opportunity to define a specific data_factory.
"""
if data_factory is None:
data_factory = self.default_factory
reports = self.classes.setdefault(klass, ReportDict())
report = Report(_absolute(template_path), mimetype,
data_factory(klass, mimetype), self.loader)
reports.ids[report_name] = report, mimetype, description
reports.mimetypes.setdefault(mimetype, []) \
.append((report, report_name))
def by_mime(self, klass, mimetype):
"""gets a list of report related to a class by specifying the mimetype
"""
return self.classes[klass].mimetypes[mimetype]
def by_id(self, klass, id):
"""get a report related to a class by its id
"""
return self.classes[klass].ids[id]
|