From cb29af71adb6743d6faafece65a206ad5403f792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 12 Jan 2018 16:25:20 +0100 Subject: [PATCH] Replace unoconv by calling soffice directly issue5907 review34341002 --- CHANGELOG | 1 + doc/topics/configuration.rst | 10 ---------- doc/topics/install.rst | 1 - doc/topics/reports/index.rst | 4 +++- setup.py | 1 - trytond/config.py | 3 --- trytond/ir/action.py | 2 +- trytond/report/report.py | 37 ++++++++++++++++++++++++------------ 8 files changed, 30 insertions(+), 29 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 9cdbab976c..7c9030b8b6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Remove unoconv and call soffice directly * Allow to include mixin to pool objects * Improve validation of PYSON domain * Use JSON canonical form for Dict value diff --git a/doc/topics/configuration.rst b/doc/topics/configuration.rst index 0b2698be80..d91c35da73 100644 --- a/doc/topics/configuration.rst +++ b/doc/topics/configuration.rst @@ -277,16 +277,6 @@ The ratio of non repeated characters for the user password. Default: `0.75` -report ------- - -unoconv -~~~~~~~ - -The parameters for `unoconv`. - -Default: `pipe,name=trytond;urp;StarOffice.ComponentContext` - attachment ---------- diff --git a/doc/topics/install.rst b/doc/topics/install.rst index e95d80be7c..fc47716348 100644 --- a/doc/topics/install.rst +++ b/doc/topics/install.rst @@ -21,7 +21,6 @@ Prerequisites (http://github.com/chtd/psycopg2cffi) * Optional: MySQL-python (http://sourceforge.net/projects/mysql-python/) * Optional: pydot (http://code.google.com/p/pydot/) - * Optional: unoconv http://dag.wieers.com/home-made/unoconv/) * Optional: sphinx (http://sphinx.pocoo.org/) * Optional: cdecimal (http://www.bytereef.org/mpdecimal/index.html) * Optional: python-Levenshtein diff --git a/doc/topics/reports/index.rst b/doc/topics/reports/index.rst index a164239169..5a6a612e2c 100644 --- a/doc/topics/reports/index.rst +++ b/doc/topics/reports/index.rst @@ -10,7 +10,9 @@ format, explained later, is interpolated with dynamic data and placed into a document of the same file format. Tryton's ability to generate documents in this way allows documents to be generated for any editor that supports the Open Document Format which can be converted to third party formats, such as PDF. -Extra libraries are required for this, see INSTALL for more information. +`LibreOffice`_ must be installed on the server host for format conversion. + +.. _LibreOffice: https://www.libreoffice.org/ Report Templates ================ diff --git a/setup.py b/setup.py index cfcb93d805..2c7837975e 100644 --- a/setup.py +++ b/setup.py @@ -105,7 +105,6 @@ setup(name=name, extras_require={ 'PostgreSQL': pg_require, 'MySQL': ['MySQL-python'], - 'unoconv': ['unoconv'], 'graphviz': ['pydot'], 'cdecimal': ['cdecimal'], 'Levenshtein': ['python-Levenshtein'], diff --git a/trytond/config.py b/trytond/config.py index 1206a5839b..2c2a72a228 100644 --- a/trytond/config.py +++ b/trytond/config.py @@ -69,9 +69,6 @@ class TrytonConfigParser(ConfigParser.RawConfigParser): self.add_section('password') self.set('password', 'length', 8) self.set('password', 'entropy', 0.75) - self.add_section('report') - self.set('report', 'unoconv', - 'pipe,name=trytond;urp;StarOffice.ComponentContext') self.update_etc() def update_etc(self, configfile=os.environ.get('TRYTOND_CONFIG')): diff --git a/trytond/ir/action.py b/trytond/ir/action.py index 90e3004a40..3177c05f6f 100644 --- a/trytond/ir/action.py +++ b/trytond/ir/action.py @@ -488,7 +488,7 @@ class ActionReport(ActionMixin, ModelSQL, ModelView): ('xpm', 'X PixMap'), ], translate=False, string='Extension', help='Leave empty for the same as template, ' - 'see unoconv documentation for compatible format') + 'see LibreOffice documentation for compatible format') module = fields.Char('Module', readonly=True, select=True) email = fields.Char('Email', help='Python dictonary where keys define "to" "cc" "subject"\n' diff --git a/trytond/report/report.py b/trytond/report/report.py index 471351c1f1..3a95ed8ffc 100644 --- a/trytond/report/report.py +++ b/trytond/report/report.py @@ -2,6 +2,7 @@ # this repository contains the full copyright notices and license terms. import datetime import os +import logging import subprocess import tempfile import warnings @@ -23,13 +24,14 @@ try: except ImportError: Manifest, MANIFEST = None, None from genshi.filters import Translator -from trytond.config import config from trytond.pool import Pool, PoolBase from trytond.transaction import Transaction from trytond.url import URLMixin from trytond.rpc import RPC from trytond.exceptions import UserError +logger = logging.getLogger(__name__) + MIMETYPES = { 'odt': 'application/vnd.oasis.opendocument.text', 'odp': 'application/vnd.oasis.opendocument.presentation', @@ -289,21 +291,32 @@ class Report(URLMixin, PoolBase): if output_format in MIMETYPES: return output_format, data - fd, path = tempfile.mkstemp(suffix=(os.extsep + input_format), - prefix='trytond_') + dtemp = tempfile.mkdtemp(prefix='trytond_') + path = os.path.join( + dtemp, report.report_name + os.extsep + input_format) oext = FORMAT2EXT.get(output_format, output_format) - with os.fdopen(fd, 'wb+') as fp: + with open(path, 'wb+') as fp: fp.write(data) - cmd = ['unoconv', '--connection=%s' % config.get('report', 'unoconv'), - '-f', oext, '--stdout', path] try: - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - stdoutdata, stderrdata = proc.communicate() - if proc.wait() != 0: - raise Exception(stderrdata) - return oext, stdoutdata + cmd = ['soffice', + '--headless', '--nolockcheck', '--nodefault', '--norestore', + '--convert-to', oext, '--outdir', dtemp, path] + output = os.path.splitext(path)[0] + os.extsep + oext + subprocess.check_call(cmd) + if os.path.exists(output): + with open(output, 'rb') as fp: + return oext, fp.read() + else: + logger.error( + 'fail to convert %s to %s', report.report_name, oext) + return input_format, data finally: - os.remove(path) + try: + os.remove(path) + os.remove(output) + os.rmdir(dtemp) + except OSError: + pass @classmethod def format_date(cls, value, lang=None):