diff --git a/account_financial_report_webkit/report/webkit_parser_header_fix.py b/account_financial_report_webkit/report/webkit_parser_header_fix.py index 9f8b9fb8..4e97736e 100644 --- a/account_financial_report_webkit/report/webkit_parser_header_fix.py +++ b/account_financial_report_webkit/report/webkit_parser_header_fix.py @@ -30,8 +30,8 @@ import os import subprocess import tempfile -import time import logging +from functools import partial from mako import exceptions @@ -48,11 +48,12 @@ _logger = logging.getLogger('financial.reports.webkit') # Class used only as a workaround to bug: # http://code.google.com/p/wkhtmltopdf/issues/detail?id=656 -# html headers and footers do not work on big files (hundreds of pages) so we replace them by -# text headers and footers passed as arguments to wkhtmltopdf +# html headers and footers do not work on big files (hundreds of pages) so we +# replace them by text headers and footers passed as arguments to wkhtmltopdf # this class has to be removed once the bug is fixed -# in your report class, to print headers and footers as text, you have to add them in the localcontext with a key 'additional_args' +# in your report class, to print headers and footers as text, you have to add +# them in the localcontext with a key 'additional_args' # for instance: # header_report_name = _('PARTNER LEDGER') # footer_date_time = self.formatLang(str(datetime.today()), date_time=True) @@ -75,23 +76,25 @@ _logger = logging.getLogger('financial.reports.webkit') from mako.template import Template from mako.lookup import TemplateLookup + def mako_template(text): """Build a Mako template. This template uses UTF-8 encoding """ - tmp_lookup = TemplateLookup() #we need it in order to allow inclusion and inheritance + tmp_lookup = TemplateLookup() # we need it in order to allow inclusion and inheritance return Template(text, input_encoding='utf-8', output_encoding='utf-8', lookup=tmp_lookup) class HeaderFooterTextWebKitParser(webkit_report.WebKitParser): - def generate_pdf(self, comm_path, report_xml, header, footer, html_list, webkit_header=False): + def generate_pdf(self, comm_path, report_xml, header, footer, html_list, + webkit_header=False, parser_instance=False): """Call webkit in order to generate pdf""" if not webkit_header: webkit_header = report_xml.webkit_header - tmp_dir = tempfile.gettempdir() - out_filename = tempfile.mktemp(suffix=".pdf", prefix="webkit.tmp.") + fd, out_filename = tempfile.mkstemp(suffix=".pdf", + prefix="webkit.tmp.") file_to_del = [out_filename] if comm_path: command = [comm_path] @@ -115,16 +118,16 @@ class HeaderFooterTextWebKitParser(webkit_report.WebKitParser): if webkit_header.format: command.extend(['--page-size', str(webkit_header.format).replace(',', '.')]) - if self.parser_instance.localcontext.get('additional_args', False): - for arg in self.parser_instance.localcontext['additional_args']: + if parser_instance.localcontext.get('additional_args', False): + for arg in parser_instance.localcontext['additional_args']: command.extend(arg) count = 0 for html in html_list: - html_file = file(os.path.join(tmp_dir, str(time.time()) + str(count) +'.body.html'), 'w') - count += 1 - html_file.write(html) - html_file.close() + with tempfile.NamedTemporaryFile(suffix="%d.body.html" % count, + delete=False) as html_file: + count += 1 + html_file.write(self._sanitize_html(html)) file_to_del.append(html_file.name) command.append(html_file.name) command.append(out_filename) @@ -132,8 +135,8 @@ class HeaderFooterTextWebKitParser(webkit_report.WebKitParser): file_to_del.append(stderr_path) try: status = subprocess.call(command, stderr=stderr_fd) - os.close(stderr_fd) # ensure flush before reading - stderr_fd = None # avoid closing again in finally block + os.close(stderr_fd) # ensure flush before reading + stderr_fd = None # avoid closing again in finally block fobj = open(stderr_path, 'r') error_message = fobj.read() fobj.close() @@ -142,11 +145,11 @@ class HeaderFooterTextWebKitParser(webkit_report.WebKitParser): else: error_message = _('The following diagnosis message was provided:\n') + error_message if status: - raise except_osv(_('Webkit error' ), + raise except_osv(_('Webkit error'), _("The command 'wkhtmltopdf' failed with error code = %s. Message: %s") % (status, error_message)) - pdf_file = open(out_filename, 'rb') - pdf = pdf_file.read() - pdf_file.close() + with open(out_filename, 'rb') as pdf_file: + pdf = pdf_file.read() + os.close(fd) finally: if stderr_fd is not None: os.close(stderr_fd) @@ -160,57 +163,60 @@ class HeaderFooterTextWebKitParser(webkit_report.WebKitParser): # override needed to keep the attachments' storing procedure def create_single_pdf(self, cursor, uid, ids, data, report_xml, context=None): """generate the PDF""" + if context is None: - context={} + context = {} htmls = [] if report_xml.report_type != 'webkit': - return super(HeaderFooterTextWebKitParser,self).create_single_pdf(cursor, uid, ids, data, report_xml, context=context) + return super(HeaderFooterTextWebKitParser, self + ).create_single_pdf(cursor, uid, ids, data, + report_xml, context=context) - self.parser_instance = self.parser(cursor, - uid, - self.name2, - context=context) + parser_instance = self.parser(cursor, + uid, + self.name2, + context=context) self.pool = pooler.get_pool(cursor.dbname) objs = self.getObjects(cursor, uid, ids, context) - self.parser_instance.set_context(objs, data, ids, report_xml.report_type) + parser_instance.set_context(objs, data, ids, report_xml.report_type) - template = False + template = False if report_xml.report_file: path = addons.get_module_resource(*report_xml.report_file.split(os.path.sep)) if os.path.exists(path): template = file(path).read() if not template and report_xml.report_webkit_data: - template = report_xml.report_webkit_data + template = report_xml.report_webkit_data if not template: raise except_osv(_('Error!'), _('Webkit Report template not found !')) header = report_xml.webkit_header.html - footer = report_xml.webkit_header.footer_html + if not header and report_xml.header: raise except_osv( _('No header defined for this Webkit report!'), - _('Please set a header in company settings') + _('Please set a header in company settings.') ) css = report_xml.webkit_header.css if not css: css = '' - user = self.pool.get('res.users').browse(cursor, uid, uid) + translate_call = partial(self.translate_call, parser_instance) #default_filters=['unicode', 'entity'] can be used to set global filter body_mako_tpl = mako_template(template) helper = WebKitHelper(cursor, uid, report_xml.id, context) if report_xml.precise_mode: for obj in objs: - self.parser_instance.localcontext['objects'] = [obj] + parser_instance.localcontext['objects'] = [obj] try: html = body_mako_tpl.render(helper=helper, css=css, - _=self.translate_call, - **self.parser_instance.localcontext) + _=translate_call, + **parser_instance.localcontext) htmls.append(html) - except Exception, e: + except Exception: msg = exceptions.text_error_template().render() _logger.error(msg) raise except_osv(_('Webkit render'), msg) @@ -218,15 +224,16 @@ class HeaderFooterTextWebKitParser(webkit_report.WebKitParser): try: html = body_mako_tpl.render(helper=helper, css=css, - _=self.translate_call, - **self.parser_instance.localcontext) + _=translate_call, + **parser_instance.localcontext) htmls.append(html) - except Exception, e: + except Exception: msg = exceptions.text_error_template().render() _logger.error(msg) raise except_osv(_('Webkit render'), msg) - # NO html footer and header because we write them as text with wkhtmltopdf + # NO html footer and header because we write them as text with + # wkhtmltopdf head = foot = False if report_xml.webkit_debug: @@ -234,13 +241,14 @@ class HeaderFooterTextWebKitParser(webkit_report.WebKitParser): deb = body_mako_tpl.render(helper=helper, css=css, _debug=tools.ustr("\n".join(htmls)), - _=self.translate_call, - **self.parser_instance.localcontext) - except Exception, e: + _=translate_call, + **parser_instance.localcontext) + except Exception: msg = exceptions.text_error_template().render() _logger.error(msg) raise except_osv(_('Webkit render'), msg) return (deb, 'html') bin = self.get_lib(cursor, uid) - pdf = self.generate_pdf(bin, report_xml, head, foot, htmls) + pdf = self.generate_pdf(bin, report_xml, head, foot, htmls, + parser_instance=parser_instance) return (pdf, 'pdf')