#!/usr/bin/python
# Copyright (C) 2015 Christopher M. Biwer
#
# 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 Generals
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import os.path, types
import codecs
from six.moves.configparser import ConfigParser
from jinja2 import Environment, FileSystemLoader
from xml.sax.saxutils import unescape
import pycbc.results
from pycbc.results import unescape_table
from pycbc.results.metadata import save_html_with_metadata
from pycbc.workflow.core import SegFile, makedir
[docs]def render_workflow_html_template(filename, subtemplate, filelists, **kwargs):
""" Writes a template given inputs from the workflow generator. Takes
a list of tuples. Each tuple is a pycbc File object. Also the name of the
subtemplate to render and the filename of the output.
"""
dirnam = os.path.dirname(filename)
makedir(dirnam)
try:
filenames = [f.name for filelist in filelists for f in filelist if f is not None]
except TypeError:
filenames = []
# render subtemplate
subtemplate_dir = pycbc.results.__path__[0] + '/templates/wells'
env = Environment(loader=FileSystemLoader(subtemplate_dir))
env.globals.update(get_embedded_config=get_embedded_config)
env.globals.update(path_exists=os.path.exists)
env.globals.update(len=len)
subtemplate = env.get_template(subtemplate)
context = {'filelists' : filelists,
'dir' : dirnam}
context.update(kwargs)
output = subtemplate.render(context)
# save as html page
kwds = {'render-function' : 'render_tmplt',
'filenames' : ','.join(filenames)}
kwds.update(kwargs)
for key in kwds:
kwds[key] = str(kwds[key])
save_html_with_metadata(str(output), filename, None, kwds)
[docs]def get_embedded_config(filename):
""" Attempt to load config data attached to file
"""
def check_option(self, section, name):
return (self.has_section(section) and
(self.has_option(section, name) or (name in self.defaults())))
try:
cp = pycbc.results.load_metadata_from_file(filename)
except TypeError:
cp = ConfigParser()
cp.check_option = types.MethodType(check_option, cp)
return cp
[docs]def setup_template_render(path, config_path):
""" This function is the gateway for rendering a template for a file.
"""
# initialization
cp = get_embedded_config(path)
output = ''
filename = os.path.basename(path)
# use meta-data if not empty for rendering
if cp.has_option(filename, 'render-function'):
render_function_name = cp.get(filename, 'render-function')
render_function = eval(render_function_name)
output = render_function(path, cp)
# read configuration file for rendering
elif os.path.exists(config_path):
cp.read(config_path)
# render template
if cp.has_option(filename, 'render-function'):
render_function_name = cp.get(filename, 'render-function')
render_function = eval(render_function_name)
output = render_function(path, cp)
else:
output = render_default(path, cp)
# if no configuration file is present
# then render the default template
else:
output = render_default(path, cp)
return output
[docs]def render_default(path, cp):
""" This is the default function that will render a template to a string of HTML. The
string will be for a drop-down tab that contains a link to the file.
If the file extension requires information to be read, then that is passed to the
content variable (eg. a segmentlistdict).
"""
# define filename and slug from path
filename = os.path.basename(path)
slug = filename.replace('.', '_')
# initializations
content = None
if path.endswith('.xml') or path.endswith('.xml.gz'):
# segment or veto file return a segmentslistdict instance
try:
wf_file = SegFile.from_segment_xml(path)
# FIXME: This is a dictionary, but the code wants a segmentlist
# for now I just coalesce.
wf_file.return_union_seglist()
except Exception as e:
print('No segment table found in %s : %s' % (path, e))
# render template
template_dir = pycbc.results.__path__[0] + '/templates/files'
env = Environment(loader=FileSystemLoader(template_dir))
env.globals.update(abs=abs)
env.globals.update(open=open)
env.globals.update(path_exists=os.path.exists)
template = env.get_template('file_default.html')
context = {'path' : path,
'filename' : filename,
'slug' : slug,
'cp' : cp,
'content' : content}
output = template.render(context)
return output
[docs]def render_glitchgram(path, cp):
""" Render a glitchgram file template.
"""
# define filename and slug from path
filename = os.path.basename(path)
slug = filename.replace('.', '_')
# render template
template_dir = pycbc.results.__path__[0] + '/templates/files'
env = Environment(loader=FileSystemLoader(template_dir))
env.globals.update(abs=abs)
template = env.get_template(cp.get(filename, 'template'))
context = {'filename' : filename,
'slug' : slug,
'cp' : cp}
output = template.render(context)
return output
[docs]def render_text(path, cp):
""" Render a file as text.
"""
# define filename and slug from path
filename = os.path.basename(path)
slug = filename.replace('.', '_')
# initializations
content = None
# read file as a string
with codecs.open(path, 'r', encoding='utf-8', errors='replace') as fp:
content = fp.read()
# replace all the escaped characters
content = unescape(content, unescape_table)
# render template
template_dir = pycbc.results.__path__[0] + '/templates/files'
env = Environment(loader=FileSystemLoader(template_dir))
env.globals.update(abs=abs)
env.globals.update(path_exists=os.path.exists)
template = env.get_template('file_pre.html')
context = {'filename' : filename,
'slug' : slug,
'cp' : cp,
'content' : content}
output = template.render(context)
return output
[docs]def render_ignore(path, cp):
""" Does not render anything.
"""
return ''
[docs]def render_tmplt(path, cp):
""" Render a file as text.
"""
# define filename and slug from path
filename = os.path.basename(path)
slug = filename.replace('.', '_')
# initializations
content = None
# read file as a string
with open(path, 'r') as fp:
content = fp.read()
# replace all the escaped characters
content = unescape(content, unescape_table)
# render template
template_dir = '/'.join(path.split('/')[:-1])
env = Environment(loader=FileSystemLoader(template_dir))
env.globals.update(setup_template_render=setup_template_render)
env.globals.update(get_embedded_config=get_embedded_config)
env.globals.update(path_exists=os.path.exists)
template = env.get_template(filename)
context = {'filename' : filename,
'slug' : slug,
'cp' : cp,
'content' : content}
output = template.render(context)
return output