[RFR] split off the fusion server to its own module

use libreoffice for conversions in the base version. Fixes #179
This commit is contained in:
Holger Brunn
2017-12-17 16:01:44 +01:00
committed by Elmeri Niemelä
parent 238b24877e
commit 0a706a660f
14 changed files with 108 additions and 308 deletions

View File

@@ -1,5 +1,4 @@
from . import ir_actions_report_xml
from . import py3o_template
from . import py3o_server
from . import report
from . import py3o_report

View File

@@ -31,19 +31,6 @@ class IrActionsReportXml(models.Model):
raise ValidationError(_(
"Field 'Output Format' is required for Py3O report"))
@api.multi
@api.constrains("py3o_is_local_fusion", "py3o_server_id",
"py3o_filetype")
def _check_py3o_server_id(self):
for report in self:
if report.report_type == "py3o":
is_native = Formats().get_format(report.py3o_filetype).native
if ((not is_native or not report.py3o_is_local_fusion) and
not report.py3o_server_id):
raise ValidationError(_(
"Can not use not native format in local fusion. "
"Please specify a Fusion Server"))
@api.model
def _get_py3o_filetypes(self):
formats = Formats()
@@ -62,15 +49,6 @@ class IrActionsReportXml(models.Model):
py3o_template_id = fields.Many2one(
'py3o.template',
"Template")
py3o_is_local_fusion = fields.Boolean(
"Local Fusion",
help="Native formats will be processed without a server. "
"You must use this mode if you call methods on your model into "
"the template.",
default=True)
py3o_server_id = fields.Many2one(
"py3o.server",
"Fusion Server")
module = fields.Char(
"Module",
help="The implementer module that provides this report")

View File

@@ -5,26 +5,23 @@
import base64
from base64 import b64decode
from cStringIO import StringIO
import json
import logging
import os
from contextlib import closing
import subprocess
import pkg_resources
import requests
import sys
import tempfile
from zipfile import ZipFile, ZIP_DEFLATED
from odoo.exceptions import AccessError
from odoo.exceptions import UserError
from odoo.report.report_sxw import rml_parse
from odoo import api, fields, models, tools, _
logger = logging.getLogger(__name__)
try:
from py3o.template.helpers import Py3oConvertor
from py3o.template import Template
from py3o import formats
from genshi.core import Markup
@@ -244,60 +241,63 @@ class Py3oReport(models.TransientModel):
""" This function to generate our py3o report
"""
self.ensure_one()
report_xml = self.ir_actions_report_xml_id
filetype = report_xml.py3o_filetype
result_fd, result_path = tempfile.mkstemp(
suffix='.' + filetype, prefix='p3o.report.tmp.')
suffix='.ods', prefix='p3o.report.tmp.')
tmpl_data = self.get_template(model_instance)
in_stream = StringIO(tmpl_data)
with closing(os.fdopen(result_fd, 'w+')) as out_stream:
template = Template(in_stream, out_stream, escape_false=True)
localcontext = self._get_parser_context(model_instance, data)
is_native = Formats().get_format(filetype).native
if report_xml.py3o_is_local_fusion:
template.render(localcontext)
out_stream.seek(0)
tmpl_data = out_stream.read()
datadict = {}
else:
expressions = template.get_all_user_python_expression()
py_expression = template.convert_py3o_to_python_ast(
expressions)
convertor = Py3oConvertor()
data_struct = convertor(py_expression)
datadict = data_struct.render(localcontext)
template.render(localcontext)
out_stream.seek(0)
tmpl_data = out_stream.read()
if not is_native or not report_xml.py3o_is_local_fusion:
# Call py3o.server to render the template in the desired format
files = {
'tmpl_file': tmpl_data,
}
fields = {
"targetformat": filetype,
"datadict": json.dumps(datadict),
"image_mapping": "{}",
"escape_false": "on",
}
if report_xml.py3o_is_local_fusion:
fields['skipfusion'] = '1'
r = requests.post(
report_xml.py3o_server_id.url, data=fields, files=files)
if r.status_code != 200:
# server says we have an issue... let's tell that to enduser
raise UserError(
_('Fusion server error %s') % r.text,
)
result_path = self._convert_single_report(
result_path, model_instance, data
)
chunk_size = 1024
with open(result_path, 'w+') as fd:
for chunk in r.iter_content(chunk_size):
fd.write(chunk)
if len(model_instance) == 1:
self._postprocess_report(
result_path, model_instance.id, save_in_attachment)
return result_path
@api.multi
def _convert_single_report(self, result_path, model_instance, data):
"""Run a command to convert to our target format"""
filetype = self.ir_actions_report_xml_id.py3o_filetype
if not Formats().get_format(filetype).native:
command = self._convert_single_report_cmd(
result_path, model_instance, data,
)
logger.debug('Running command %s', command)
output = subprocess.check_output(
command, cwd=os.path.dirname(result_path),
)
logger.debug('Output was %s', output)
self._cleanup_tempfiles([result_path])
result_path, result_filename = os.path.split(result_path)
result_path = os.path.join(
result_path, '%s.%s' % (
os.path.splitext(result_filename)[0], filetype
)
)
return result_path
@api.multi
def _convert_single_report_cmd(self, result_path, model_instance, data):
"""Return a command list suitable for use in subprocess.call"""
return [
self.env['ir.config_parameter'].get_param(
'py3o.conversion_command', 'libreoffice',
),
'--headless',
'--convert-to',
self.ir_actions_report_xml_id.py3o_filetype,
result_path,
]
@api.multi
def _get_or_create_single_report(self, model_instance, data,
save_in_attachment):

View File

@@ -1,15 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2013 XCG Consulting (http://odoo.consulting)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class Py3oServer(models.Model):
_name = 'py3o.server'
_rec_name = 'url'
url = fields.Char(
"Py3o Fusion Server URL", required=True,
help="If your Py3o Fusion server is on the same machine and runs "
"on the default port, the URL is http://localhost:8765/form")
is_active = fields.Boolean("Active", default=True)

View File

@@ -13,6 +13,10 @@ class Py3oTemplate(models.Model):
selection=[
('odt', "ODF Text Document"),
('ods', "ODF Spreadsheet"),
('odp', "ODF Presentation"),
('fodt', "ODF Text Document (Flat)"),
('fods', "ODF Spreadsheet (Flat)"),
('fodp', "ODF Presentation (Flat)"),
],
string="LibreOffice Template File Type",
required=True,