X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/7ef55860a7a563f5218a91a4396a793fb127d43c..af77776a9ff93ac89cfe941c8a97e3e4cac1bd2e:/apps/reporting/utils.py diff --git a/apps/reporting/utils.py b/apps/reporting/utils.py new file mode 100755 index 000000000..919e2edc1 --- /dev/null +++ b/apps/reporting/utils.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +import os +import os.path +import shutil +import subprocess +from tempfile import mkdtemp +from StringIO import StringIO +from django.conf import settings +import logging +from django.http import HttpResponse +from django.template.loader import render_to_string + +logger = logging.getLogger(__name__) + + +def render_to_pdf(output_path, template, context=None, add_files=None): + """Renders a TeXML document into a PDF file. + + :param str output_path: is where the PDF file should go + :param str template: is a TeXML template path + :param context: is context for rendering the template + :param dict add_files: a dictionary of additional files XeTeX will need + """ + + import Texml.processor + rendered = render_to_string(template, context) + texml = StringIO(rendered.encode('utf-8')) + tempdir = mkdtemp(prefix = "render_to_pdf-") + tex_path = os.path.join(tempdir, "doc.tex") + with open(tex_path, 'w') as tex_file: + Texml.processor.process(texml, tex_file, encoding="utf-8") + + if add_files: + for add_name, src_file in add_files.items(): + add_path = os.path.join(tempdir, add_name) + if hasattr(src_file, "read"): + with open(add_path, 'w') as add_file: + add_file.write(add_file.read()) + else: + shutil.copy(src_file, add_path) + + cwd = os.getcwd() + os.chdir(tempdir) + try: + subprocess.check_call(['xelatex', '-interaction=batchmode', tex_path], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + try: + os.makedirs(os.path.dirname(output_path)) + except: + pass + shutil.move(os.path.join(tempdir, "doc.pdf"), output_path) + finally: + os.chdir(cwd) + shutil.rmtree(tempdir) + + +def read_chunks(f, size=8192): + chunk = f.read(size) + while chunk: + yield chunk + chunk = f.read(size) + + +def generated_file_view(file_name, mime_type, send_name=None, signals=None): + file_path = os.path.join(settings.MEDIA_ROOT, file_name) + file_url = os.path.join(settings.MEDIA_URL, file_name) + if send_name is None: + send_name = os.path.basename(file_name) + + def signal_handler(*args, **kwargs): + os.unlink(file_path) + + if signals: + for signal in signals: + signal.connect(signal_handler, weak=False) + + def decorator(func): + def view(request, *args, **kwargs): + if not os.path.exists(file_path) or True: + func(file_path, *args, **kwargs) + + if hasattr(send_name, "__call__"): + name = send_name() + else: + name = send_name + + response = HttpResponse(mimetype=mime_type) + response['Content-Disposition'] = 'attachment; filename=%s' % name + with open(file_path) as f: + for chunk in read_chunks(f): + response.write(chunk) + return response + return view + return decorator