Source code for kvalikirstu2.template_generator

""" A module for generating html files using Jinja2.

Attributes
----------
    ENV(Environment): A jinja2 enviroment for generating templates.

"""

import json
import logging
import os
import shutil
import jinja2
from kvalikirstu2 import utils
from kvalikirstu2 import study
from kvalikirstu2 import paragraph_analyzer
from kvalikirstu2 import argument_parser
from kvalikirstu2 import localization

ENV = jinja2.Environment(
    loader=jinja2.PackageLoader('kvalikirstu2', 'templates'),
    autoescape=jinja2.select_autoescape(['html', 'xml'])
)
logger = logging.getLogger(__name__)


[docs]def relpath_with_fwd_slash(path: str, start=None): """Produces a relative path with forward slashes :param str path: The path for which the relative path should be determined. :param str start: The path to which the path is relative to. If no argument is given, the current working directory is used. """ return os.path.relpath(path, start).replace(os.sep, '/')
[docs]def get_html_path(output_path: str): """ Gets the folder for all the "under the hood" files for the index document. :param str output_path: The path where the index file goes to. """ args = argument_parser.get_args() data_path = os.path.join(output_path, args.study_data_folder, args.index_data_folder) return data_path
def _move_deps(output_path: str): """Moves the dependencies to the data folder in the output directory. :param str output_path: The path the index is being generated in. """ logger.info('Moving dependencies to %s', output_path) data_path = get_html_path(output_path) kvalikirstu2_dir = os.path.dirname(__file__) deps_dir = os.path.join(kvalikirstu2_dir, "index deps") if os.path.exists(data_path): shutil.rmtree(data_path) shutil.copytree(deps_dir, data_path) def _get_digits_for_filename(subject_count): """Gets how characters should be in a filename for the subject html files. """ return utils.number_of_digits(subject_count) def _get_padded_number(index, digits): """Get zero padded number with 'digits' digits. """ return ("%s" % (index+1)).zfill(digits) def _get_html_filepath(data_path, index, digits, metadata, language_code): """Gets the html filepath for the subject with the given index. """ args = argument_parser.get_args() padded_number = _get_padded_number(index, digits) if language_code: filename = "%s_%s" % (padded_number, language_code) else: filename = padded_number subject_path = os.path.join(data_path, args.html_file_name.format(study_number=metadata.extract_study_number(), name=filename)) return subject_path def _get_all_subjects_filepath(data_path, metadata, language_code): """Gets the html filepath for the all subjects file. """ args = argument_parser.get_args() _ = localization._ if language_code: filename = "%s_%s" % (_("all_subjects"), language_code) else: filename = _("all_subjects") subject_path = os.path.join(data_path, args.html_file_name.format(study_number=metadata.extract_study_number(), name=filename)) return subject_path def _generate_subject_files(mapping, template_study: study.Study, translation_func): """Creates .html documents for individual subjects. :param dict mapping: File mapping. :param Study template_study: The study to be saved. :param translation_func: Function used for translating messages from English to other languages. """ output_path = mapping.get_path('output') logger.info('Generating subjects to path %s', output_path) template = ENV.get_template("subject_template.xml") for index in range(len(template_study.subjects)): subject_path = mapping.get_path(str(index)) with open(subject_path, "w", encoding="utf-8") as file_stream: file_stream.write(template.render(subject=template_study.subjects[index], is_image=utils.is_image_file, relpath=relpath_with_fwd_slash, output_path=output_path, ParagraphType=paragraph_analyzer.ParagraphType, index=index, _=translation_func)) def _generate_all_subjects_file(mapping, template_study: study.Study, translation_func): """Creates .html documents for all subjects. :param dict: The file mapping. :param Study template_study: The study to be saved. :param translation_func: Function used for translating messages from English to other languages. """ subject_path = mapping.get_path('all') output_path = mapping.get_path('output') logger.debug('Generating all subjects page to %s', subject_path) template = ENV.get_template("all_subjects_template.xml") with open(subject_path, "w", encoding="utf-8") as file_stream: file_stream.write(template.render(study=template_study, is_image=utils.is_image_file, relpath=relpath_with_fwd_slash, output_path=output_path, ParagraphType=paragraph_analyzer.ParagraphType, _=translation_func)) def _get_table_localization(_): """Gets the table localization. :param _: The translation function. """ kvalikirstu2_dir = os.path.dirname(__file__) path = os.path.join(kvalikirstu2_dir, "locale", "table_localization", _("English.json")) with open(path, mode='r', encoding='utf-8') as file_stream: table_localization = json.load(file_stream) return table_localization def _ellipsis_value(value, max_chars): """Shortens a value if necessary. :param value: Value that may be shortened. :param max_chars: The maximum number of characters before the string gets shortened. :return: The shortened string with a tooltip or the original. """ if len(value) > max_chars: shortened = value[0:max_chars] return '<span class="ellipsis" title="%s">%s&#8230;</span>' % (jinja2.escape(value), jinja2.escape(shortened)) return value
[docs]def get_index_path(output_path): """ :param output_path: The path of the output folder. :return: The path of the index file. """ return os.path.join(output_path, "index.html")
[docs]def generate_index(output_path: str, template_study: study.Study, header_info, metadata): """ Generates an index file for the study. :param str output_path: The output path for the generated html index file. :param Study template_study: The study from which the template is generated from. :param header_info: Contains information about the study's headers. :param metadata: The metadata of the study. """ logger.info('Generating index to path %s', output_path) headers = header_info.get_index_headers() alignments = header_info.get_header_alignments() args = argument_parser.get_args() # Delete old html folder to remove any old files html_path = get_html_path(output_path) if os.path.exists(html_path): shutil.rmtree(html_path) os.makedirs(html_path) _move_deps(output_path) mapping = _get_file_mapping(html_path, output_path, metadata, template_study) translation_func = localization.get_translation_func(args.index_lang) _generate_subject_files(mapping, template_study, translation_func) _generate_all_subjects_file(mapping, template_study, translation_func) index_path = get_index_path(output_path) template = ENV.get_template("index_template.xml") with open(index_path, "w", encoding="utf-8") as file: file.write(template.render(headers=headers, study=template_study, basename=os.path.basename, relpath=relpath_with_fwd_slash, dirname=os.path.dirname, _=translation_func, ParagraphType=paragraph_analyzer.ParagraphType, file_mapping=mapping, header_info=header_info, _get_padded_number=_get_padded_number, digits=utils.number_of_digits(len(template_study.subjects)), utils=utils, args=args, os=os, metadata=metadata, ellipsis=_ellipsis_value, alignments=alignments, table_localization=_get_table_localization(translation_func)))
[docs]class HTMLFileMapping: """A class that handles the file mapping for HTML files. """ def __init__(self): self.mapping = {}
[docs] def add_path(self, key, path): """Add a path with a key. :param key: The key of the file. :param path: The path of the file. """ self.mapping[key] = path
[docs] def get_path(self, key): """Returns the output path for the given key. :param key: The key of the file. """ return self.mapping[key]
def _get_file_mapping(data_path, output_path, metadata, template_study): """Returns an instance of HTMLFileMapping that contains information about HTML files. :param data_path: The path of the html folder. :param output_path: The study path. :param metadata: The study metadata. :param template_study: A study for which the index is being generated. """ language_codes = argument_parser.get_languages() mapping = HTMLFileMapping() subject_count = len(template_study.subjects) digits = utils.number_of_digits(subject_count) for index in range(subject_count): lang_code = template_study.get_subject_language_code(index, language_codes) mapping.add_path(str(index), _get_html_filepath(data_path, index, digits, metadata, lang_code)) mapping.add_path('all', _get_all_subjects_filepath(data_path, metadata, template_study.get_language_code(language_codes))) mapping.add_path('data', data_path) mapping.add_path('output', output_path) return mapping