diff --git a/openerp/report/__init__.py b/openerp/report/__init__.py index 801a7fb6eb9..b8dbb745208 100644 --- a/openerp/report/__init__.py +++ b/openerp/report/__init__.py @@ -1,18 +1,15 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import openerp from openerp import api -import interface -import print_xml -import print_fnc -import custom -import render -import int_to_text - -import report_sxw - -import printscreen +from . import custom +from . import int_to_text +from . import interface +from . import print_fnc +from . import print_xml +from . import printscreen +from . import render +from . import report_sxw def render_report(cr, uid, ids, name, data, context=None): """ diff --git a/openerp/report/custom.py b/openerp/report/custom.py index 4cc3a92cf0a..97d2a184cae 100644 --- a/openerp/report/custom.py +++ b/openerp/report/custom.py @@ -1,23 +1,25 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +import cStringIO import os import time +from lxml import etree +from pychart import area, arrow, axis, bar_plot, canvas, category_coord, \ + fill_style, legend, line_plot, line_style, pie_plot, theme + import openerp import openerp.tools as tools -from openerp.tools.safe_eval import safe_eval -import print_xml -import render -from interface import report_int -import common -from openerp.osv.orm import BaseModel -from pychart import * -import misc -import cStringIO -from lxml import etree -from openerp.tools.translate import _ from openerp.exceptions import UserError +from openerp.models import BaseModel +from openerp.tools.safe_eval import safe_eval +from openerp.tools.translate import _ +from . import common +from . import misc +from . import render +from .interface import report_int + class external_pdf(render.render): def __init__(self, pdf): @@ -37,6 +39,7 @@ theme.use_color = 1 class report_custom(report_int): def __init__(self, name): report_int.__init__(self, name) + # # PRE: # fields = [['address','city'],['name'], ['zip']] @@ -104,26 +107,18 @@ class report_custom(report_int): result.append(row) return result - def create(self, cr, uid, ids, datas, context=None): - if not context: - context={} - self.pool = openerp.registry(cr.dbname) - report = self.pool['ir.report.custom'].browse(cr, uid, [datas['report_id']])[0] + env = openerp.api.Environment(cr, uid, context or {}) + report = env['ir.report.custom'].browse([datas['report_id']]) datas['model'] = report.model_id.model if report.menu_id: - ids = self.pool[report.model_id.model].search(cr, uid, []) + ids = env[report.model_id.model].search([]).ids datas['ids'] = ids - report_id = datas['report_id'] - report = self.pool['ir.report.custom'].read(cr, uid, [report_id], context=context)[0] - fields = self.pool['ir.report.custom.fields'].read(cr, uid, report['fields_child0'], context=context) - - fields.sort(lambda x,y : x['sequence'] - y['sequence']) - - if report['field_parent']: - parent_field = self.pool['ir.model.fields'].read(cr, uid, [report['field_parent'][0]], ['model']) - model_name = self.pool['ir.model'].read(cr, uid, [report['model_id'][0]], ['model'], context=context)[0]['model'] + report = report.read()[0] + fields = env['ir.report.custom.fields'].browse(report['fields_child0']).read() + fields.sort(key=lambda x: x['sequence']) + model_name = env['ir.model'].browse(report['model_id'][0]).model fct = { 'id': lambda x: x, @@ -139,7 +134,7 @@ class report_custom(report_int): field_child = f['field_child'+str(i)] if field_child: row.append( - self.pool['ir.model.fields'].read(cr, uid, [field_child[0]], ['name'], context=context)[0]['name'] + env['ir.model.fields'].browse(field_child[0]).name ) if f['fc'+str(i)+'_operande']: fct_name = 'id' @@ -152,7 +147,7 @@ class report_custom(report_int): cond.append(None) new_fields.append(row) new_cond.append(cond) - objs = self.pool[model_name].browse(cr, uid, ids) + objs = env[model_name].browse(ids) # Group by groupby = None @@ -167,9 +162,9 @@ class report_custom(report_int): if report['field_parent']: level = [] def build_tree(obj, level, depth): - res = self._row_get(cr, uid,[obj], new_fields, new_cond) + res = self._row_get(cr, uid, [obj], new_fields, new_cond) level.append(depth) - new_obj = safe_eval('obj.'+report['field_parent'][1],{'obj': obj}) + new_obj = safe_eval('obj.'+report['field_parent'][1], {'obj': obj}) if not isinstance(new_obj, list) : new_obj = [new_obj] for o in new_obj: @@ -180,7 +175,7 @@ class report_custom(report_int): for obj in objs: results += build_tree(obj, level, 0) else: - results = self._row_get(cr, uid,objs, new_fields, new_cond, group_by=groupby) + results = self._row_get(cr, uid, objs, new_fields, new_cond, group_by=groupby) fct = { 'calc_sum': lambda l: reduce(lambda x,y: float(x)+float(y), filter(None, l), 0), @@ -214,7 +209,7 @@ class report_custom(report_int): row.append(fct[str(fields[col]['operation'])](map(lambda x: x[col], res_dic[key]))) new_res.append(row) results = new_res - + if report['type']=='table': if report['field_parent']: res = self._create_tree(uid, ids, report, fields, level, results, context) @@ -225,12 +220,13 @@ class report_custom(report_int): sort_idx = idx break try : - results.sort(lambda x,y : cmp(float(x[sort_idx]),float(y[sort_idx]))) + results.sort(key=lambda x: float(x[sort_idx])) except : - results.sort(lambda x,y : cmp(x[sort_idx],y[sort_idx])) + results.sort(key=lambda x: x[sort_idx]) if report['limitt']: results = results[:int(report['limitt'])] res = self._create_table(uid, ids, report, fields, None, results, context) + elif report['type'] in ('pie','bar', 'line'): results2 = [] prev = False @@ -254,6 +250,7 @@ class report_custom(report_int): res = self._create_bars(cr,uid, ids, report, fields, results2, context) elif report['type']=='line': res = self._create_lines(cr,uid, ids, report, fields, results2, context) + return self.obj.get(), 'pdf' def _create_tree(self, uid, ids, report, fields, level, results, context): @@ -262,7 +259,7 @@ class report_custom(report_int): pageSize=[pageSize[1],pageSize[0]] new_doc = etree.Element('report') - + config = etree.SubElement(new_doc, 'config') def _append_node(name, text): @@ -319,41 +316,34 @@ class report_custom(report_int): self.obj.render() return True - def _create_lines(self, cr, uid, ids, report, fields, results, context): - pool = openerp.registry(cr.dbname) + env = openerp.api.Environment(cr, uid, context or {}) pdf_string = cStringIO.StringIO() + can = canvas.init(fname=pdf_string, format='pdf') - can.show(80,380,'/16/H'+report['title']) - + ar = area.T(size=(350,350), - #x_coord = category_coord.T(['2005-09-01','2005-10-22'],0), - x_axis = axis.X(label = fields[0]['name'], format="/a-30{}%s"), - y_axis = axis.Y(label = ', '.join(map(lambda x : x['name'], fields[1:])))) - + #x_coord = category_coord.T(['2005-09-01','2005-10-22'],0), + x_axis=axis.X(label = fields[0]['name'], format="/a-30{}%s"), + y_axis=axis.Y(label = ', '.join(map(lambda x : x['name'], fields[1:])))) + process_date = { 'D': lambda x: reduce(lambda xx, yy: xx + '-' + yy, x.split('-')[1:3]), 'M': lambda x: x.split('-')[1], 'Y': lambda x: x.split('-')[0] } - order_date = { - 'D': lambda x: time.mktime((2005, int(x.split('-')[0]), int(x.split('-')[1]), 0, 0, 0, 0, 0, 0)), - 'M': lambda x: x, - 'Y': lambda x: x - } - abscissa = [] - + idx = 0 date_idx = None fct = {} for f in fields: field_id = (f['field_child3'] and f['field_child3'][0]) or (f['field_child2'] and f['field_child2'][0]) or (f['field_child1'] and f['field_child1'][0]) or (f['field_child0'] and f['field_child0'][0]) if field_id: - type = pool['ir.model.fields'].read(cr, uid, [field_id],['ttype']) - if type[0]['ttype'] == 'date': + ttype = env['ir.model.fields'].browse(field_id).ttype + if ttype == 'date': date_idx = idx fct[idx] = process_date[report['frequency']] else: @@ -411,7 +401,7 @@ class report_custom(report_int): ar.add_plot(plot) abscissa.update(fields_bar[idx]) idx0 += 1 - + abscissa = map(lambda x : [x, None], abscissa) ar.x_coord = category_coord.T(abscissa,0) ar.draw(can) @@ -422,30 +412,22 @@ class report_custom(report_int): pdf_string.close() return True - - def _create_bars(self, cr, uid, ids, report, fields, results, context): - pool = openerp.registry(cr.dbname) + env = openerp.api.Environment(cr, uid, context or {}) pdf_string = cStringIO.StringIO() + can = canvas.init(fname=pdf_string, format='pdf') - can.show(80,380,'/16/H'+report['title']) - + process_date = { 'D': lambda x: reduce(lambda xx, yy: xx + '-' + yy, x.split('-')[1:3]), 'M': lambda x: x.split('-')[1], 'Y': lambda x: x.split('-')[0] } - order_date = { - 'D': lambda x: time.mktime((2005, int(x.split('-')[0]), int(x.split('-')[1]), 0, 0, 0, 0, 0, 0)), - 'M': lambda x: x, - 'Y': lambda x: x - } - ar = area.T(size=(350,350), - x_axis = axis.X(label = fields[0]['name'], format="/a-30{}%s"), - y_axis = axis.Y(label = ', '.join(map(lambda x : x['name'], fields[1:])))) + x_axis=axis.X(label = fields[0]['name'], format="/a-30{}%s"), + y_axis=axis.Y(label = ', '.join(map(lambda x : x['name'], fields[1:])))) idx = 0 date_idx = None @@ -453,8 +435,8 @@ class report_custom(report_int): for f in fields: field_id = (f['field_child3'] and f['field_child3'][0]) or (f['field_child2'] and f['field_child2'][0]) or (f['field_child1'] and f['field_child1'][0]) or (f['field_child0'] and f['field_child0'][0]) if field_id: - type = pool['ir.model.fields'].read(cr, uid, [field_id],['ttype']) - if type[0]['ttype'] == 'date': + ttype = env['ir.model.fields'].browse(field_id).ttype + if ttype == 'date': date_idx = idx fct[idx] = process_date[report['frequency']] else: @@ -462,7 +444,7 @@ class report_custom(report_int): else: fct[idx] = lambda x : x idx+=1 - + # plot are usually displayed year by year # so we do so if the first field is a date data_by_year = {} @@ -480,7 +462,7 @@ class report_custom(report_int): nb_bar = len(data_by_year)*(len(fields)-1) colors = map(lambda x:fill_style.Plain(bgcolor=x), misc.choice_colors(nb_bar)) - + abscissa = {} for line in data_by_year.keys(): fields_bar = [] @@ -508,7 +490,7 @@ class report_custom(report_int): data_cum.append([k, float(data[k])+float(prev)]) if fields[idx+1]['cumulate']: prev += data[k] - + idx0 = 0 plot = bar_plot.T(label=fields[idx+1]['name']+' '+str(line), data = data_cum, cluster=(idx0*(len(fields)-1)+idx,nb_bar), fill_style=colors[idx0*(len(fields)-1)+idx]) ar.add_plot(plot) @@ -601,4 +583,5 @@ class report_custom(report_int): self.obj = render.rml(rml) self.obj.render() return True + report_custom('report.custom') diff --git a/openerp/report/interface.py b/openerp/report/interface.py index e93ba5a77e0..947ad489af6 100644 --- a/openerp/report/interface.py +++ b/openerp/report/interface.py @@ -3,18 +3,15 @@ import os import re +import urllib from lxml import etree import openerp import openerp.tools as tools -import openerp.modules -import print_xml -import render -import urllib - -from openerp import SUPERUSER_ID -from openerp.report.render.rml2pdf import customfonts +from . import print_xml +from . import render +from openerp.modules import get_module_resource # # coerce any type to a unicode string (to preserve non-ascii characters) @@ -24,6 +21,7 @@ def toxml(value): unicode_value = tools.ustr(value) return unicode_value.replace('&', '&').replace('<','<').replace('>','>') + class report_int(object): _reports = {} @@ -49,6 +47,7 @@ class report_int(object): def create(self, cr, uid, ids, datas, context=None): return False + class report_rml(report_int): """ Automatically builds a document using the transformation process: @@ -73,27 +72,24 @@ class report_rml(report_int): 'makohtml2html' :self.create_makohtml2html, } - def create(self, cr, uid, ids, datas, context): - registry = openerp.registry(cr.dbname) + def create(self, cr, uid, ids, datas, context=None): + env = openerp.api.Environment(cr, uid, context or {}) xml = self.create_xml(cr, uid, ids, datas, context) xml = tools.ustr(xml).encode('utf8') report_type = datas.get('report_type', 'pdf') if report_type == 'raw': return xml, report_type - registry['res.font'].font_scan(cr, SUPERUSER_ID, lazy=True, context=context) + env['res.font'].sudo().font_scan(lazy=True) rml = self.create_rml(cr, xml, uid, context) - ir_actions_report_xml_obj = registry['ir.actions.report.xml'] - report_xml_ids = ir_actions_report_xml_obj.search(cr, uid, [('report_name', '=', self.name[7:])], context=context) - self.title = report_xml_ids and ir_actions_report_xml_obj.browse(cr,uid,report_xml_ids)[0].name or 'OpenERP Report' + reports = env['ir.actions.report.xml'].search([('report_name', '=', self.name[7:])]) + self.title = reports[0].name if reports else 'Odoo Report' create_doc = self.generators[report_type] pdf = create_doc(rml, title=self.title) return pdf, report_type def create_xml(self, cr, uid, ids, datas, context=None): - if not context: - context={} doc = print_xml.document(cr, uid, datas, {}) self.bin_datas.update( doc.bin_datas or {}) doc.parse(self.tmpl, ids, self.table, context) @@ -102,9 +98,6 @@ class report_rml(report_int): return self.post_process_xml_data(cr, uid, xml, context) def post_process_xml_data(self, cr, uid, xml, context=None): - - if not context: - context={} # find the position of the 3rd tag # (skip the and the "root" tag) iter = re.finditer('<[^>]*>', xml) @@ -113,7 +106,7 @@ class report_rml(report_int): pos_xml = i.end() doc = print_xml.document(cr, uid, {}, {}) - tmpl_path = openerp.modules.get_module_resource('base', 'report', 'corporate_defaults.xml') + tmpl_path = get_module_resource('base', 'report', 'corporate_defaults.xml') doc.parse(tmpl_path, [uid], 'res.users', context) corporate_header = doc.xml_get() doc.close() @@ -131,10 +124,8 @@ class report_rml(report_int): def create_rml(self, cr, xml, uid, context=None): if self.tmpl=='' and not self.internal_header: self.internal_header=True - if not context: - context={} - registry = openerp.registry(cr.dbname) - ir_translation_obj = registry['ir.translation'] + env = openerp.api.Environment(cr, uid, context or {}) + Translation = env['ir.translation'] # In some case we might not use xsl ... if not self.xsl: @@ -172,17 +163,17 @@ class report_rml(report_int): if node.tail: tail = node.tail.strip().replace('\n',' ') if text: - translation1 = ir_translation_obj._get_source(cr, uid, self.name2, 'xsl', lang, text) - if translation1: - node.text = node.text.replace(text, translation1) + text1 = Translation._get_source(self.name2, 'xsl', lang, text) + if text1: + node.text = node.text.replace(text, text1) if tail: - translation2 = ir_translation_obj._get_source(cr, uid, self.name2, 'xsl', lang, tail) - if translation2: - node.tail = node.tail.replace(tail, translation2) + tail1 = Translation._get_source(self.name2, 'xsl', lang, tail) + if tail1: + node.tail = node.tail.replace(tail, tail1) translate_aux(node, lang, t) - if context.get('lang', False): - translate(stylesheet.iter(), context['lang']) + if env.lang: + translate(stylesheet.iter(), env.lang) transform = etree.XSLT(stylesheet) xml = etree.tostring( @@ -190,7 +181,7 @@ class report_rml(report_int): return xml - def create_pdf(self, rml, localcontext = None, logo=None, title=None): + def create_pdf(self, rml, localcontext=None, logo=None, title=None): if not localcontext: localcontext = {} localcontext.update({'internal_header':self.internal_header}) @@ -203,7 +194,7 @@ class report_rml(report_int): obj.render() return obj.get() - def create_html(self, rml, localcontext = None, logo=None, title=None): + def create_html(self, rml, localcontext=None, logo=None, title=None): obj = render.rml2html(rml, localcontext, self.bin_datas) obj.render() return obj.get() @@ -213,28 +204,28 @@ class report_rml(report_int): obj.render() return obj.get().encode('utf-8') - def create_html2html(self, rml, localcontext = None, logo=None, title=None): + def create_html2html(self, rml, localcontext=None, logo=None, title=None): obj = render.html2html(rml, localcontext, self.bin_datas) obj.render() return obj.get() - def create_raw(self,rml, localcontext = None, logo=None, title=None): + def create_raw(self,rml, localcontext=None, logo=None, title=None): obj = render.odt2odt(etree.XML(rml),localcontext) obj.render() return etree.tostring(obj.get()) - def create_sxw(self,rml,localcontext = None): + def create_sxw(self,rml,localcontext=None): obj = render.odt2odt(rml,localcontext) obj.render() return obj.get() - def create_odt(self,rml,localcontext = None): + def create_odt(self,rml,localcontext=None): obj = render.odt2odt(rml,localcontext) obj.render() return obj.get() - def create_makohtml2html(self,html,localcontext = None): + def create_makohtml2html(self,html,localcontext=None): obj = render.makohtml2html(html,localcontext) obj.render() return obj.get() diff --git a/openerp/report/misc.py b/openerp/report/misc.py index 676a401c124..0b735abca7c 100644 --- a/openerp/report/misc.py +++ b/openerp/report/misc.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from pychart import * +from pychart import color colorline = [color.T(r=((r+3) % 11)/10.0, g=((g+6) % 11)/10.0, diff --git a/openerp/report/preprocess.py b/openerp/report/preprocess.py index d61740e1a7c..16f35e1f49a 100644 --- a/openerp/report/preprocess.py +++ b/openerp/report/preprocess.py @@ -1,13 +1,16 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from lxml import etree import re + +from lxml import etree + rml_parents = ['tr','story','section'] html_parents = ['tr','body','div'] sxw_parents = ['{http://openoffice.org/2000/table}table-row','{http://openoffice.org/2000/office}body','{http://openoffice.org/2000/text}section'] odt_parents = ['{urn:oasis:names:tc:opendocument:xmlns:office:1.0}body','{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table-row','{urn:oasis:names:tc:opendocument:xmlns:text:1.0}section'] + class report(object): def preprocess_rml(self, root_node,type='pdf'): _regex1 = re.compile("\[\[(.*?)(repeatIn\(.*?\s*,\s*[\'\"].*?[\'\"]\s*(?:,\s*(.*?)\s*)?\s*\))(.*?)\]\]") diff --git a/openerp/report/print_xml.py b/openerp/report/print_xml.py index 588fb77dd9d..a39782f7999 100644 --- a/openerp/report/print_xml.py +++ b/openerp/report/print_xml.py @@ -2,15 +2,16 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from lxml import etree + import openerp import openerp.tools as tools +from . import print_fnc +from openerp.models import BaseModel from openerp.tools.safe_eval import safe_eval -import print_fnc -from openerp.osv.orm import BaseModel + class InheritDict(dict): - # Might be usefull when we're doing name lookup for call or eval. - + # Might be useful when we're doing name lookup for call or eval. def __init__(self, parent=None): self.parent = parent @@ -23,6 +24,7 @@ class InheritDict(dict): else: return self.parent[name] + def tounicode(val): if isinstance(val, str): unicode_val = unicode(val, 'utf-8') @@ -32,14 +34,14 @@ def tounicode(val): unicode_val = unicode(val) return unicode_val + class document(object): def __init__(self, cr, uid, datas, func=False): # create a new document self.cr = cr - self.pool = openerp.registry(cr.dbname) - self.func = func or {} - self.datas = datas self.uid = uid + self.datas = datas + self.func = func or {} self.bin_datas = {} def node_attrs_get(self, node): @@ -86,162 +88,159 @@ class document(object): return safe_eval(expr, {}, {'obj': record}) def parse_node(self, node, parent, browser, datas=None): - attrs = self.node_attrs_get(node) - if 'type' in attrs: - if attrs['type']=='field': - value = self.get_value(browser, attrs['name']) -#TODO: test this - if value == '' and 'default' in attrs: - value = attrs['default'] + env = openerp.api.Environment(self.cr, self.uid, {}) + attrs = self.node_attrs_get(node) + if 'type' in attrs: + if attrs['type']=='field': + value = self.get_value(browser, attrs['name']) + #TODO: test this + if value == '' and 'default' in attrs: + value = attrs['default'] + el = etree.SubElement(parent, node.tag) + el.text = tounicode(value) + #TODO: test this + for key, value in attrs.iteritems(): + if key not in ('type', 'name', 'default'): + el.set(key, value) + + elif attrs['type']=='attachment': + model = browser._name + value = self.get_value(browser, attrs['name']) + + atts = env['ir.attachment'].search([('res_model','=',model),('res_id','=',int(value))]) + datas = atts.read() + + if len(datas): + # if there are several, pick first + datas = datas[0] + fname = str(datas['datas_fname']) + ext = fname.split('.')[-1].lower() + if ext in ('jpg','jpeg', 'png'): + import base64 + from StringIO import StringIO + dt = base64.decodestring(datas['datas']) + fp = StringIO() + fp.write(dt) + i = str(len(self.bin_datas)) + self.bin_datas[i] = fp + el = etree.SubElement(parent, node.tag) + el.text = i + + elif attrs['type']=='data': + #TODO: test this + txt = self.datas.get('form', {}).get(attrs['name'], '') + el = etree.SubElement(parent, node.tag) + el.text = txt + + elif attrs['type']=='function': + if attrs['name'] in self.func: + txt = self.func[attrs['name']](node) + else: + txt = print_fnc.print_fnc(attrs['name'], node) + el = etree.SubElement(parent, node.tag) + el.text = txt + + elif attrs['type']=='eval': + value = self.eval(browser, attrs['expr']) + el = etree.SubElement(parent, node.tag) + el.text = str(value) + + elif attrs['type']=='fields': + fields = attrs['name'].split(',') + vals = {} + for b in browser: + value = tuple([self.get_value2(b, f) for f in fields]) + if not value in vals: + vals[value]=[] + vals[value].append(b) + keys = vals.keys() + keys.sort() + + if 'order' in attrs and attrs['order']=='desc': + keys.reverse() + + v_list = [vals[k] for k in keys] + for v in v_list: el = etree.SubElement(parent, node.tag) - el.text = tounicode(value) -#TODO: test this - for key, value in attrs.iteritems(): - if key not in ('type', 'name', 'default'): - el.set(key, value) + for el_cld in node: + self.parse_node(el_cld, el, v) - elif attrs['type']=='attachment': - model = browser._name - value = self.get_value(browser, attrs['name']) + elif attrs['type']=='call': + if len(attrs['args']): + #TODO: test this + # fetches the values of the variables which names where passed in the args attribute + args = [self.eval(browser, arg) for arg in attrs['args'].split(',')] + else: + args = [] + # get the object + if 'model' in attrs: + obj = env[attrs['model']] + else: + obj = browser # the record(set) is an instance of the model - ids = self.pool['ir.attachment'].search(self.cr, self.uid, [('res_model','=',model),('res_id','=',int(value))]) - datas = self.pool['ir.attachment'].read(self.cr, self.uid, ids) + # get the ids + if 'ids' in attrs: + ids = self.eval(browser, attrs['ids']) + else: + ids = browser.ids - if len(datas): - # if there are several, pick first - datas = datas[0] - fname = str(datas['datas_fname']) - ext = fname.split('.')[-1].lower() - if ext in ('jpg','jpeg', 'png'): - import base64 - from StringIO import StringIO - dt = base64.decodestring(datas['datas']) - fp = StringIO() - fp.write(dt) - i = str(len(self.bin_datas)) - self.bin_datas[i] = fp - el = etree.SubElement(parent, node.tag) - el.text = i + # call the method itself + newdatas = getattr(obj, attrs['name'])(*args) - elif attrs['type']=='data': -#TODO: test this - txt = self.datas.get('form', {}).get(attrs['name'], '') - el = etree.SubElement(parent, node.tag) - el.text = txt + def parse_result_tree(node, parent, datas): + if not node.tag == etree.Comment: + el = etree.SubElement(parent, node.tag) + atr = self.node_attrs_get(node) + if 'value' in atr: + if not isinstance(datas[atr['value']], (str, unicode)): + txt = str(datas[atr['value']]) + else: + txt = datas[atr['value']] + el.text = txt + else: + for el_cld in node: + parse_result_tree(el_cld, el, datas) + if not isinstance(newdatas, (BaseModel, list)): + newdatas = [newdatas] + for newdata in newdatas: + parse_result_tree(node, parent, newdata) - elif attrs['type']=='function': - if attrs['name'] in self.func: - txt = self.func[attrs['name']](node) + elif attrs['type']=='zoom': + value = self.get_value(browser, attrs['name']) + if value: + if not isinstance(value, (BaseModel, list)): + v_list = [value] else: - txt = print_fnc.print_fnc(attrs['name'], node) - el = etree.SubElement(parent, node.tag) - el.text = txt - - elif attrs['type']=='eval': - value = self.eval(browser, attrs['expr']) - el = etree.SubElement(parent, node.tag) - el.text = str(value) - - elif attrs['type']=='fields': - fields = attrs['name'].split(',') - vals = {} - for b in browser: - value = tuple([self.get_value2(b, f) for f in fields]) - if not value in vals: - vals[value]=[] - vals[value].append(b) - keys = vals.keys() - keys.sort() - - if 'order' in attrs and attrs['order']=='desc': - keys.reverse() - - v_list = [vals[k] for k in keys] + v_list = value for v in v_list: el = etree.SubElement(parent, node.tag) for el_cld in node: self.parse_node(el_cld, el, v) + else: + # if there is no "type" attribute in the node, copy it to the xml data and parse its children + if not node.tag == etree.Comment: + if node.tag == parent.tag: + el = parent + else: + el = etree.SubElement(parent, node.tag) + for el_cld in node: + self.parse_node(el_cld,el, browser) - elif attrs['type']=='call': - if len(attrs['args']): -#TODO: test this - # fetches the values of the variables which names where passed in the args attribute - args = [self.eval(browser, arg) for arg in attrs['args'].split(',')] - else: - args = [] - # get the object - if 'model' in attrs: - obj = self.pool[attrs['model']] - else: - obj = browser # the record(set) is an instance of the model - - # get the ids - if 'ids' in attrs: - ids = self.eval(browser, attrs['ids']) - else: - ids = browse.ids - - # call the method itself - newdatas = getattr(obj, attrs['name'])(self.cr, self.uid, ids, *args) - - def parse_result_tree(node, parent, datas): - if not node.tag == etree.Comment: - el = etree.SubElement(parent, node.tag) - atr = self.node_attrs_get(node) - if 'value' in atr: - if not isinstance(datas[atr['value']], (str, unicode)): - txt = str(datas[atr['value']]) - else: - txt = datas[atr['value']] - el.text = txt - else: - for el_cld in node: - parse_result_tree(el_cld, el, datas) - if not isinstance(newdatas, (BaseModel, list)): - newdatas = [newdatas] - for newdata in newdatas: - parse_result_tree(node, parent, newdata) - - elif attrs['type']=='zoom': - value = self.get_value(browser, attrs['name']) - if value: - if not isinstance(value, (BaseModel, list)): - v_list = [value] - else: - v_list = value - for v in v_list: - el = etree.SubElement(parent, node.tag) - for el_cld in node: - self.parse_node(el_cld, el, v) - else: - # if there is no "type" attribute in the node, copy it to the xml data and parse its children - if not node.tag == etree.Comment: - if node.tag == parent.tag: - el = parent - else: - el = etree.SubElement(parent, node.tag) - for el_cld in node: - self.parse_node(el_cld,el, browser) def xml_get(self): return etree.tostring(self.doc,encoding="utf-8",xml_declaration=True,pretty_print=True) def parse_tree(self, ids, model, context=None): - if not context: - context={} - browser = self.pool[model].browse(self.cr, self.uid, ids, context) + env = openerp.api.Environment(self.cr, self.uid, context or {}) + browser = env[model].browse(ids) self.parse_node(self.dom, self.doc, browser) def parse_string(self, xml, ids, model, context=None): - if not context: - context={} # parses the xml template to memory self.dom = etree.XML(xml) # create the xml data from the xml template self.parse_tree(ids, model, context) def parse(self, filename, ids, model, context=None): - if not context: - context={} # parses the xml template to memory src_file = tools.file_open(filename) try: diff --git a/openerp/report/printscreen/__init__.py b/openerp/report/printscreen/__init__.py index 25015ffd64c..5c442c68695 100644 --- a/openerp/report/printscreen/__init__.py +++ b/openerp/report/printscreen/__init__.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import ps_list -import ps_form +from . import ps_list +from . import ps_form """ A special report, that is automatically formatted to look like the diff --git a/openerp/report/printscreen/ps_form.py b/openerp/report/printscreen/ps_form.py index fa3ad47bb32..df9766ba898 100644 --- a/openerp/report/printscreen/ps_form.py +++ b/openerp/report/printscreen/ps_form.py @@ -1,20 +1,18 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import openerp -from openerp.report.interface import report_int -import openerp.tools as tools +import os +import time -from openerp.report import render from lxml import etree -import time, os +import openerp +import openerp.tools as tools +from openerp.report import render +from openerp.report.interface import report_int class report_printscreen_list(report_int): - def __init__(self, name): - report_int.__init__(self, name) - def _parse_node(self, root_node): result = [] for node in root_node: @@ -36,19 +34,18 @@ class report_printscreen_list(report_int): def create(self, cr, uid, ids, datas, context=None): if not context: context={} + env = openerp.api.Environment(cr, uid, context) datas['ids'] = ids - registry = openerp.registry(cr.dbname) - model = registry[datas['model']] + records = env[datas['model']].browse(ids) # title come from description of model which are specified in py file. - self.title = model._description - result = model.fields_view_get(cr, uid, view_type='form', context=context) + self.title = records._description + result = records.fields_view_get(view_type='form') fields_order = self._parse_string(result['arch']) - rows = model.read(cr, uid, datas['ids'], result['fields'].keys() ) - self._create_table(uid, datas['ids'], result['fields'], fields_order, rows, context, model._description) + rows = records.read(list(result['fields'])) + self._create_table(uid, datas['ids'], result['fields'], fields_order, rows, context, records._description) return self.obj.get(), 'pdf' - def _create_table(self, uid, ids, fields, fields_order, results, context, title=''): pageSize=[297.0,210.0] @@ -113,4 +110,5 @@ class report_printscreen_list(report_int): self.obj = render.rml(rml, self.title) self.obj.render() return True + report_printscreen_list('report.printscreen.form') diff --git a/openerp/report/printscreen/ps_list.py b/openerp/report/printscreen/ps_list.py index b14f8f36766..78de721cb6c 100644 --- a/openerp/report/printscreen/ps_list.py +++ b/openerp/report/printscreen/ps_list.py @@ -1,25 +1,26 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import openerp -from openerp.report.interface import report_int -import openerp.tools as tools -from openerp.tools.safe_eval import safe_eval -from lxml import etree -from openerp.report import render, report_sxw import locale - -import time, os -from operator import itemgetter +import os +import time from datetime import datetime +from lxml import etree + +import openerp +import openerp.tools as tools +from openerp.report import render, report_sxw +from openerp.report.interface import report_int +from openerp.tools.safe_eval import safe_eval + class report_printscreen_list(report_int): def __init__(self, name): - report_int.__init__(self, name) + super(report_printscreen_list, self).__init__(name) self.context = {} self.groupby = [] - self.cr='' + self.cr = '' def _parse_node(self, root_node): result = [] @@ -43,25 +44,23 @@ class report_printscreen_list(report_int): def create(self, cr, uid, ids, datas, context=None): if not context: - context={} - self.cr=cr + context = {} + self.cr = cr self.context = context self.groupby = context.get('group_by',[]) - self.groupby_no_leaf = context.get('group_by_no_leaf',False) - registry = openerp.registry(cr.dbname) - model = registry[datas['model']] - model_id = registry['ir.model'].search(cr, uid, [('model','=',model._name)]) - model_desc = model._description - if model_id: - model_desc = registry['ir.model'].browse(cr, uid, model_id[0], context).name + self.groupby_no_leaf = context.get('group_by_no_leaf', False) + env = openerp.api.Environment(cr, uid, context) + Model = env[datas['model']] + model = env['ir.model'].search([('model', '=', Model._name)]) + model_desc = model.name or Model._description self.title = model_desc datas['ids'] = ids - result = model.fields_view_get(cr, uid, view_type='tree', context=context) + result = Model.fields_view_get(view_type='tree') fields_order = self.groupby + self._parse_string(result['arch']) if self.groupby: rows = [] def get_groupby_data(groupby = [], domain = []): - records = model.read_group(cr, uid, domain, fields_order, groupby , 0, None, context) + records = Model.read_group(domain, fields_order, groupby, 0, None) for rec in records: rec['__group'] = True rec['__no_leaf'] = self.groupby_no_leaf @@ -79,18 +78,17 @@ class report_printscreen_list(report_int): else: if self.groupby_no_leaf: continue - child_ids = model.search(cr, uid, inner_domain) - res = model.read(cr, uid, child_ids, result['fields'].keys(), context) - res.sort(lambda x,y: cmp(ids.index(x['id']), ids.index(y['id']))) + children = Model.search(inner_domain) + res = children.read(list(result['fields'])) + res.sort(key=lambda x: ids.index(x['id'])) rows.extend(res) dom = [('id','in',ids)] if self.groupby_no_leaf and len(ids) and not ids[0]: dom = datas.get('_domain',[]) get_groupby_data(self.groupby, dom) else: - rows = model.read(cr, uid, datas['ids'], result['fields'].keys(), context) - ids2 = map(itemgetter('id'), rows) # getting the ids from read result - if datas['ids'] != ids2: # sorted ids were not taken into consideration for print screen + rows = Model.browse(ids).read(list(result['fields'])) + if datas['ids'] != rows.ids: # sorted ids were not taken into consideration for print screen rows_new = [] for id in datas['ids']: rows_new += [elem for elem in rows if elem['id'] == id] @@ -98,7 +96,6 @@ class report_printscreen_list(report_int): res = self._create_table(uid, datas['ids'], result['fields'], fields_order, rows, context, model_desc) return self.obj.get(), 'pdf' - def _create_table(self, uid, ids, fields, fields_order, results, context, title=''): pageSize=[297.0, 210.0] @@ -116,10 +113,10 @@ class report_printscreen_list(report_int): _append_node('PageHeight', '%.2f' %(pageSize[1] * 2.8346,)) _append_node('report-header', title) - registry = openerp.registry(self.cr.dbname) - _append_node('company', registry['res.users'].browse(self.cr,uid,uid).company_id.name) - rpt_obj = registry['res.users'] - rml_obj=report_sxw.rml_parse(self.cr, uid, rpt_obj._name,context) + env = openerp.api.Environment(self.cr, uid, {}) + Users = env['res.users'] + _append_node('company', Users.browse(uid).company_id.name) + rml_obj = report_sxw.rml_parse(self.cr, uid, Users._name, context) _append_node('header-date', str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M"))) l = [] t = 0 @@ -249,4 +246,5 @@ class report_printscreen_list(report_int): self.obj = render.rml(rml, title=self.title) self.obj.render() return True + report_printscreen_list('report.printscreen.list') diff --git a/openerp/report/render/__init__.py b/openerp/report/render/__init__.py index 1038c06e82f..228de009bd1 100644 --- a/openerp/report/render/__init__.py +++ b/openerp/report/render/__init__.py @@ -1,10 +1,9 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from simple import simple -from rml import rml, rml2html, rml2txt, odt2odt , html2html, makohtml2html -from render import render - +from .simple import simple +from .rml import rml, rml2html, rml2txt, odt2odt , html2html, makohtml2html +from .render import render try: from PIL import Image diff --git a/openerp/report/render/html2html/__init__.py b/openerp/report/render/html2html/__init__.py index ade973224e5..41fa95cf4a0 100644 --- a/openerp/report/render/html2html/__init__.py +++ b/openerp/report/render/html2html/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from html2html import parseString +from .html2html import parseString diff --git a/openerp/report/render/html2html/html2html.py b/openerp/report/render/html2html/html2html.py index 8f1156fc4ef..b66d44a5a5f 100644 --- a/openerp/report/render/html2html/html2html.py +++ b/openerp/report/render/html2html/html2html.py @@ -1,13 +1,15 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from openerp.report.render.rml2pdf import utils -import copy import base64 +import copy import cStringIO import re + from reportlab.lib.utils import ImageReader +from openerp.report.render.rml2pdf import utils + _regex = re.compile('\[\[(.+?)\]\]') utils._regex = re.compile('\[\[\s*(.+?)\s*\]\]',re.DOTALL) class html2html(object): diff --git a/openerp/report/render/makohtml2html/__init__.py b/openerp/report/render/makohtml2html/__init__.py index 93088cda05d..ad0404301ae 100644 --- a/openerp/report/render/makohtml2html/__init__.py +++ b/openerp/report/render/makohtml2html/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from makohtml2html import parseNode +from .makohtml2html import parseNode diff --git a/openerp/report/render/makohtml2html/makohtml2html.py b/openerp/report/render/makohtml2html/makohtml2html.py index be65f46d1cc..f044d1d8f36 100644 --- a/openerp/report/render/makohtml2html/makohtml2html.py +++ b/openerp/report/render/makohtml2html/makohtml2html.py @@ -1,12 +1,14 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. + import logging -import mako -from lxml import etree -from mako.template import Template -from mako.lookup import TemplateLookup import os +import mako +from mako.lookup import TemplateLookup +from mako.template import Template +from lxml import etree + _logger = logging.getLogger(__name__) class makohtml2html(object): diff --git a/openerp/report/render/odt2odt/__init__.py b/openerp/report/render/odt2odt/__init__.py index 45bb7297886..b1d94607dab 100644 --- a/openerp/report/render/odt2odt/__init__.py +++ b/openerp/report/render/odt2odt/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odt2odt import parseNode +from .odt2odt import parseNode diff --git a/openerp/report/render/odt2odt/odt2odt.py b/openerp/report/render/odt2odt/odt2odt.py index fc6a01212bd..350e3565c6c 100644 --- a/openerp/report/render/odt2odt/odt2odt.py +++ b/openerp/report/render/odt2odt/odt2odt.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from openerp.report.render.rml2pdf import utils import copy +from openerp.report.render.rml2pdf import utils + class odt2odt(object): def __init__(self, odt, localcontext): self.localcontext = localcontext diff --git a/openerp/report/render/rml.py b/openerp/report/render/rml.py index a71d519c476..d87a3a54ae2 100644 --- a/openerp/report/render/rml.py +++ b/openerp/report/render/rml.py @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import render -import rml2pdf -import rml2html as htmlizer -import rml2txt as txtizer -import odt2odt as odt -import html2html as html -import makohtml2html as makohtml +from . import render +from . import rml2pdf +from . import rml2html as htmlizer +from . import rml2txt as txtizer +from . import odt2odt as odt +from . import html2html as html +from . import makohtml2html as makohtml class rml(render.render): @@ -18,10 +18,10 @@ class rml(render.render): self.output_type = 'pdf' self.title=title - def _render(self): return rml2pdf.parseNode(self.rml, self.localcontext, images=self.bin_datas, path=self.path,title=self.title) + class rml2html(render.render): def __init__(self, rml,localcontext = None, datas=None): super(rml2html, self).__init__(datas) @@ -32,6 +32,7 @@ class rml2html(render.render): def _render(self): return htmlizer.parseString(self.rml,self.localcontext) + class rml2txt(render.render): def __init__(self, rml, localcontext= None, datas=None): super(rml2txt, self).__init__(datas) @@ -42,6 +43,7 @@ class rml2txt(render.render): def _render(self): return txtizer.parseString(self.rml, self.localcontext) + class odt2odt(render.render): def __init__(self, rml, localcontext=None, datas=None): render.render.__init__(self, datas) @@ -52,6 +54,7 @@ class odt2odt(render.render): def _render(self): return odt.parseNode(self.rml_dom,self.localcontext) + class html2html(render.render): def __init__(self, rml, localcontext=None, datas=None): render.render.__init__(self, datas) @@ -62,6 +65,7 @@ class html2html(render.render): def _render(self): return html.parseString(self.rml_dom,self.localcontext) + class makohtml2html(render.render): def __init__(self, html, localcontext = None): render.render.__init__(self) diff --git a/openerp/report/render/rml2html/__init__.py b/openerp/report/render/rml2html/__init__.py index d83321dc847..5f27854c99f 100644 --- a/openerp/report/render/rml2html/__init__.py +++ b/openerp/report/render/rml2html/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from rml2html import parseString +from .rml2html import parseString diff --git a/openerp/report/render/rml2html/rml2html.py b/openerp/report/render/rml2html/rml2html.py index dc2f8df6012..cdcecb45399 100644 --- a/openerp/report/render/rml2html/rml2html.py +++ b/openerp/report/render/rml2html/rml2html.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import sys -import cStringIO -from lxml import etree import copy +import cStringIO +import sys + +from lxml import etree from openerp.report.render.rml2pdf import utils diff --git a/openerp/report/render/rml2pdf/__init__.py b/openerp/report/render/rml2pdf/__init__.py index cb2fd352a1a..166e0f2d9a2 100644 --- a/openerp/report/render/rml2pdf/__init__.py +++ b/openerp/report/render/rml2pdf/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from trml2pdf import parseString, parseNode +from .trml2pdf import parseString, parseNode diff --git a/openerp/report/render/rml2pdf/color.py b/openerp/report/render/rml2pdf/color.py index 399b5ebd132..60767cdf8ab 100644 --- a/openerp/report/render/rml2pdf/color.py +++ b/openerp/report/render/rml2pdf/color.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from reportlab.lib import colors import re +from reportlab.lib import colors + allcols = colors.getAllNamedColors() regex_t = re.compile('\(([0-9\.]*),([0-9\.]*),([0-9\.]*)\)') diff --git a/openerp/report/render/rml2pdf/customfonts.py b/openerp/report/render/rml2pdf/customfonts.py index fe6c0d6a4f1..c34088ab085 100644 --- a/openerp/report/render/rml2pdf/customfonts.py +++ b/openerp/report/render/rml2pdf/customfonts.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from reportlab import rl_config -import logging import glob +import logging import os +from reportlab import rl_config + # .apidoc title: TTF Font Table """This module allows the mapping of some system-available TTF fonts to diff --git a/openerp/report/render/rml2pdf/trml2pdf.py b/openerp/report/render/rml2pdf/trml2pdf.py index 40925be549e..9690ecb5e70 100644 --- a/openerp/report/render/rml2pdf/trml2pdf.py +++ b/openerp/report/render/rml2pdf/trml2pdf.py @@ -1,27 +1,14 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. - -import sys -import copy -import reportlab -import re -from reportlab.pdfgen import canvas -from reportlab import platypus -import utils -import color -import os -import logging -import traceback -from lxml import etree import base64 +import copy +import logging +import os +import re +import sys +import traceback from distutils.version import LooseVersion -from reportlab.platypus.doctemplate import ActionFlowable -from openerp.tools.safe_eval import safe_eval -from reportlab.lib.units import inch,cm,mm -from openerp.tools.misc import file_open -from reportlab.pdfbase import pdfmetrics -from reportlab.lib.pagesizes import A4, letter try: from cStringIO import StringIO @@ -29,8 +16,21 @@ try: except ImportError: from StringIO import StringIO +import reportlab +from reportlab import platypus +from reportlab.lib.pagesizes import A4, letter +from reportlab.pdfbase import pdfmetrics +from reportlab.pdfgen import canvas +from reportlab.platypus.doctemplate import ActionFlowable +from lxml import etree + +from openerp.tools.misc import file_open +from openerp.tools.safe_eval import safe_eval +from . import color +from . import utils + try: - from customfonts import SetCustomFonts + from .customfonts import SetCustomFonts except ImportError: SetCustomFonts=lambda x:None @@ -271,7 +271,6 @@ class _rml_doc(object): def setTTFontMapping(self,face, fontname, filename, mode='all'): from reportlab.lib.fonts import addMapping - from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont if mode: diff --git a/openerp/report/render/rml2pdf/utils.py b/openerp/report/render/rml2pdf/utils.py index 2250bb50026..a213befa1ee 100644 --- a/openerp/report/render/rml2pdf/utils.py +++ b/openerp/report/render/rml2pdf/utils.py @@ -3,9 +3,9 @@ import copy import locale - import logging import re + import reportlab import openerp.tools as tools diff --git a/openerp/report/render/rml2txt/__init__.py b/openerp/report/render/rml2txt/__init__.py index f4ef971bd78..0eccc056111 100644 --- a/openerp/report/render/rml2txt/__init__.py +++ b/openerp/report/render/rml2txt/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from rml2txt import parseString, parseNode +from .rml2txt import parseString, parseNode """ This engine is the minimalistic renderer of RML documents into text files, diff --git a/openerp/report/render/rml2txt/rml2txt.py b/openerp/report/render/rml2txt/rml2txt.py index eaf4d10e2f2..3a401918ea3 100755 --- a/openerp/report/render/rml2txt/rml2txt.py +++ b/openerp/report/render/rml2txt/rml2txt.py @@ -4,9 +4,10 @@ import sys import StringIO + from lxml import etree -import utils +from . import utils Font_size= 10.0 diff --git a/openerp/report/render/rml2txt/utils.py b/openerp/report/render/rml2txt/utils.py index 79f8927ea03..17952e6356a 100644 --- a/openerp/report/render/rml2txt/utils.py +++ b/openerp/report/render/rml2txt/utils.py @@ -3,8 +3,10 @@ import copy import re + import reportlab import reportlab.lib.units + from openerp.tools.safe_eval import safe_eval _regex = re.compile('\[\[(.+?)\]\]') diff --git a/openerp/report/render/simple.py b/openerp/report/render/simple.py index 67a8fd9f80c..07584f11914 100644 --- a/openerp/report/render/simple.py +++ b/openerp/report/render/simple.py @@ -1,17 +1,17 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import render - -from cStringIO import StringIO +import copy import xml.dom.minidom +from cStringIO import StringIO -from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table +import reportlab.lib +from reportlab.platypus import SimpleDocTemplate, Paragraph from reportlab.lib.units import mm from reportlab.lib.pagesizes import A4 -import reportlab.lib -import copy +from . import render + class simple(render.render): def _render(self): diff --git a/openerp/report/report_sxw.py b/openerp/report/report_sxw.py index 0dbefe704f3..7f2c35110a3 100644 --- a/openerp/report/report_sxw.py +++ b/openerp/report/report_sxw.py @@ -1,27 +1,29 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from lxml import etree -import StringIO -import cStringIO + import base64 -from datetime import datetime +import cStringIO +import logging import os import re +import StringIO import time -from interface import report_rml -import preprocess -import logging -import openerp.tools as tools import zipfile -import common -from openerp.exceptions import AccessError +from datetime import datetime + +from lxml import etree import openerp -from openerp import SUPERUSER_ID +import openerp.tools as tools +from . import common +from . import preprocess +from .interface import report_rml +from openerp.exceptions import AccessError from openerp.osv.fields import float as float_field, function as function_field, datetime as datetime_field -from openerp.tools.translate import _ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT from openerp.tools.safe_eval import safe_eval +from openerp.tools.translate import _ + _logger = logging.getLogger(__name__) @@ -59,11 +61,11 @@ def get_date_length(date_format=DEFAULT_SERVER_DATE_FORMAT): class rml_parse(object): def __init__(self, cr, uid, name, parents=rml_parents, tag=rml_tag, context=None): if not context: - context={} + context = {} self.cr = cr self.uid = uid - self.pool = openerp.registry(cr.dbname) - user = self.pool['res.users'].browse(cr, uid, uid, context=context) + env = openerp.api.Environment(cr, uid, context) + user = env['res.users'].browse(uid) self.localcontext = { 'user': user, 'setCompany': self.setCompany, @@ -93,7 +95,7 @@ class rml_parse(object): self.lang_dict = {} self.default_lang = {} self.lang_dict_called = False - self._transl_regex = re.compile('(\[\[.+?\]\])') + self._transl_regex = re.compile(r'(\[\[.+?\]\])') def setTag(self, oldtag, newtag, attrs=None): return newtag, attrs @@ -123,19 +125,19 @@ class rml_parse(object): def removeParentNode(self, tag=None): raise GeneratorExit('Skip') - def set_html_image(self,id,model=None,field=None,context=None): - if not id : + def set_html_image(self, id, model=None, field=None, context=None): + if not id: return '' if not model: model = 'ir.attachment' - try : - id = int(id) - res = self.pool[model].read(self.cr,self.uid,id) - if field : + try: + env = openerp.api.Environment(self.cr, self.uid, {}) + res = env[model].browse(int(id)).read()[0] + if field: return res[field] - elif model =='ir.attachment' : + elif model =='ir.attachment': return res['datas'] - else : + else: return '' except Exception: return '' @@ -148,13 +150,14 @@ class rml_parse(object): self.objects = self.objects.with_env(env) def _get_lang_dict(self): - pool_lang = self.pool['res.lang'] + env = openerp.api.Environment(self.cr, self.uid, {}) + Lang = env['res.lang'] lang = self.localcontext.get('lang', 'en_US') or 'en_US' - lang_ids = pool_lang.search(self.cr,self.uid,[('code','=',lang)]) - if not lang_ids: - lang_ids = pool_lang.search(self.cr,self.uid,[('code','=','en_US')]) - lang_obj = pool_lang.browse(self.cr,self.uid,lang_ids[0]) - self.lang_dict.update({'lang_obj':lang_obj,'date_format':lang_obj.date_format,'time_format':lang_obj.time_format}) + lang_obj = Lang.search([('code', '=', lang)], limit=1) or \ + Lang.search([('code', '=', 'en_US')]) + self.lang_dict.update({'lang_obj': lang_obj, + 'date_format': lang_obj.date_format, + 'time_format':lang_obj.time_format}) self.default_lang[lang] = self.lang_dict.copy() return True @@ -165,10 +168,10 @@ class rml_parse(object): def get_digits(self, obj=None, f=None, dp=None): d = DEFAULT_DIGITS = 2 if dp: - decimal_precision_obj = self.pool['decimal.precision'] - d = decimal_precision_obj.precision_get(self.cr, self.uid, dp) + env = openerp.api.Environment(self.cr, self.uid, {}) + d = env['decimal.precision'].precision_get(dp) elif obj and f: - res_digits = getattr(obj._columns[f], 'digits', lambda x: ((16, DEFAULT_DIGITS))) + res_digits = getattr(obj._fields[f], 'digits', lambda x: ((16, DEFAULT_DIGITS))) if isinstance(res_digits, tuple): d = res_digits[1] else: @@ -243,13 +246,14 @@ class rml_parse(object): def _translate(self,text): lang = self.localcontext['lang'] if lang and text and not text.isspace(): - transl_obj = self.pool['ir.translation'] + env = openerp.api.Environment(self.cr, self.uid, {}) + Translation = env['ir.translation'] piece_list = self._transl_regex.split(text) for pn in range(len(piece_list)): if not self._transl_regex.match(piece_list[pn]): source_string = piece_list[pn].replace('\n', ' ').strip() if len(source_string): - translated_string = transl_obj._get_source(self.cr, self.uid, self.name, ('report', 'rml'), lang, source_string) + translated_string = Translation._get_source(self.name, ('report', 'rml'), lang, source_string) if translated_string: piece_list[pn] = piece_list[pn].replace(source_string, translated_string) text = ''.join(piece_list) @@ -273,7 +277,7 @@ class rml_parse(object): found.getparent().replace(found,tag) return True - def set_context(self, objects, data, ids, report_type = None): + def set_context(self, objects, data, ids, report_type=None): self.localcontext['data'] = data self.localcontext['objects'] = objects self.localcontext['digits_fmt'] = self.digits_fmt @@ -296,6 +300,7 @@ class rml_parse(object): # will have to call setCompany() inside the main repeatIn loop. self.setCompany(objects[0].company_id) + class report_sxw(report_rml, preprocess.report): """ The register=True kwarg has been added to help remove the @@ -319,8 +324,8 @@ class report_sxw(report_rml, preprocess.report): self.internal_header=True def getObjects(self, cr, uid, ids, context): - table_obj = openerp.registry(cr.dbname)[self.table] - return table_obj.browse(cr, uid, ids, context=context) + env = openerp.api.Environment(cr, uid, context or {}) + return env[self.table].browse(ids) def create(self, cr, uid, ids, data, context=None): context = dict(context or {}) @@ -329,15 +334,12 @@ class report_sxw(report_rml, preprocess.report): # skip osv.fields.sanitize_binary_value() because we want the raw bytes in all cases context.update(bin_raw=True) - registry = openerp.registry(cr.dbname) - ir_obj = registry['ir.actions.report.xml'] - registry['res.font'].font_scan(cr, SUPERUSER_ID, lazy=True, context=context) + env = openerp.api.Environment(cr, uid, context) + env['res.font'].sudo().font_scan(lazy=True) + ir_obj = env['ir.actions.report.xml'] - report_xml_ids = ir_obj.search(cr, uid, - [('report_name', '=', self.name[7:])], context=context) - if report_xml_ids: - report_xml = ir_obj.browse(cr, uid, report_xml_ids[0], context=context) - else: + report_xml = ir_obj.search([('report_name', '=', self.name[7:])], limit=1) + if not report_xml: title = '' report_file = tools.file_open(self.tmpl, subdir=None) try: @@ -384,8 +386,8 @@ class report_sxw(report_rml, preprocess.report): def create_source_pdf(self, cr, uid, ids, data, report_xml, context=None): if not context: - context={} - registry = openerp.registry(cr.dbname) + context = {} + env = openerp.api.Environment(cr, uid, context) attach = report_xml.attachment if attach: objs = self.getObjects(cr, uid, ids, context) @@ -394,12 +396,11 @@ class report_sxw(report_rml, preprocess.report): aname = safe_eval(attach, {'object':obj, 'time':time}) result = False if report_xml.attachment_use and aname and context.get('attachment_use', True): - aids = registry['ir.attachment'].search(cr, uid, [('datas_fname','=',aname+'.pdf'),('res_model','=',self.table),('res_id','=',obj.id)]) - if aids: - brow_rec = registry['ir.attachment'].browse(cr, uid, aids[0]) - if not brow_rec.datas: + att = env['ir.attachment'].search([('datas_fname','=',aname+'.pdf'),('res_model','=',self.table),('res_id','=',obj.id)], limit=1) + if att: + if not att.datas: continue - d = base64.decodestring(brow_rec.datas) + d = base64.decodestring(att.datas) results.append((d,'pdf')) continue result = self.create_single_pdf(cr, uid, [obj.id], data, report_xml, context) @@ -414,14 +415,13 @@ class report_sxw(report_rml, preprocess.report): # field. ctx = dict(context) ctx.pop('default_type', None) - registry['ir.attachment'].create(cr, uid, { + env['ir.attachment'].with_context(ctx).create({ 'name': aname, 'datas': base64.encodestring(result[0]), 'datas_fname': name, 'res_model': self.table, 'res_id': obj.id, - }, context=ctx - ) + }) except AccessError: #TODO: should probably raise a proper osv_except instead, shouldn't we? see LP bug #325632 _logger.info('Could not create saved report attachment', exc_info=True)