Source code for odoo_report_testing.reports

import os
import subprocess
from subprocess import call


[docs]class pdftools(object): """Utility class to generate pdf file from odoo record, compare 2 pdf files """
[docs] @staticmethod def imagediff(ref, compared, output_dir=None): """Test if two images are equals, if not, this generate a diff file and a animated gif file to highlight differences. It can be two single page pdf file. This delegate the work to ``compare`` application installed with **imagemagick** package which is required. :param ref: a ``path`` to the file used as reference, expected result :param compared: a ``path`` to the file to compare to the ref file. :output_dir: Directory to generate diff files return (Boolean equals, [String path to diff files,]): The result is a a tuple with bool value to tell if files are equals or not, and a list of diff files generated. """ if not os.path.isfile(ref): raise RuntimeError("ref file not found %r" % ref) if not os.path.isfile(compared): raise RuntimeError("Compared file not found %r" % compared) result = { 'reference': ref, 'compared': compared, } output_dir, filename = pdftools.outputs_env( compared, output_dir=output_dir ) png_output = os.path.join(output_dir, filename + '_diff.png') if pdftools.files_equals(ref, compared, png_output): result.update( { 'equal': True, 'diff_files': [png_output], } ) else: gif_output = os.path.join(output_dir, filename + '_diff.gif') call([ 'convert', '-delay', '50', ref, compared, '-loop', '0', 'animated', gif_output ]) result.update( { 'equal': False, 'diff_files': [png_output, gif_output] } ) return result
@staticmethod def files_equals(ref, compared, output): equal = False p = subprocess.Popen( ['compare', '-metric', 'AE', ref, compared, output], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) try: p.wait() _, err = p.communicate() if err.strip().split('\n')[-1] == '0': equal = True except Exception as err: p.kill() p.wait() raise RuntimeError("Something goes wrong while comparing file") return equal
[docs] @staticmethod def pdfdiff(ref, compared, output_dir=None): """Test if two pdf are equals This split the pdf and delegate to imagediff to compare each pages. To split the pdf ``pdftk`` application from **pdftk** package is required. """ if not os.path.isfile(ref): raise RuntimeError("ref file not found %r" % ref) if not os.path.isfile(compared): raise RuntimeError("Compared file not found %r" % compared) output_dir, filename = pdftools.outputs_env( compared, output_dir=output_dir ) # split documents call([ 'pdftk', ref, 'burst', 'output', os.path.join(output_dir, filename + '_ref_page_%02d.pdf') ]) call([ 'pdftk', compared, 'burst', 'output', os.path.join(output_dir, filename + '_compared_page_%02d.pdf') ]) ref_pages = pdftools.findPages(output_dir, filename + '_ref_page_') compared_pages = pdftools.findPages( output_dir, filename + '_compared_page_' ) result = { 'equal': len(ref_pages) == len(compared_pages), 'reference': ref, 'reference_count': len(ref_pages), 'compared': compared, 'compared_count': len(compared_pages), 'pages_compared': 0, 'pages_equals': 0, 'pages': [] } for ref_page, compared_page in zip(ref_pages, compared_pages): diff = pdftools.imagediff( os.path.join(output_dir, ref_page), os.path.join(output_dir, compared_page), output_dir=output_dir ) result['pages'].append(diff) result.update( {'pages_compared': result.get('pages_compared', 0) + 1} ) if diff.get('equal'): result.update( {'pages_equals': result.get('pages_equals', 0) + 1} ) else: result.update({'equal': False}) return result
[docs] @staticmethod def outputs_env(expected_file, output_dir=None): """Return tuple with directory and base file name to use from expected file """ return ( output_dir if output_dir else os.getenv( 'REPORT_TESTING_OUTPUT_DIR', os.path.dirname(expected_file) ), os.path.splitext(os.path.basename(expected_file))[0] )
@staticmethod def findPages(directory, filename_start_width, extension='.pdf'): pages = [ f for f in os.listdir(directory) if f.startswith(filename_start_width) and f.endswith(extension) ] pages.sort() return pages
[docs] @staticmethod def generateReport( cr, uid, model, report_service_name, ids, data=None, context=None, version7=False ): """Generate the report and return it as a tuple (result, format) where `result` is the report document and `format` is the file extension. """ if not data: data = {} data.update({'model': model}) if not version7: try: # version 10 and higher from odoo.report import render_report except: # version 8 to 9 from openerp.report import render_report return render_report( cr, uid, ids, report_service_name, data, context=context ) else: # version 7 from openerp import netsvc report_service = netsvc.LocalService( 'report.' + report_service_name ) return report_service.create(cr, uid, ids, data, context=context)