2009-10-20 10:52:23 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2006-12-07 13:41:40 +00:00
|
|
|
##############################################################################
|
2009-10-14 12:32:15 +00:00
|
|
|
#
|
2009-06-12 11:05:11 +00:00
|
|
|
# OpenERP, Open Source Management Solution
|
2009-10-14 12:32:15 +00:00
|
|
|
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
2006-12-07 13:41:40 +00:00
|
|
|
#
|
2008-11-03 18:27:16 +00:00
|
|
|
# This program is free software: you can redistribute it and/or modify
|
2009-10-14 12:32:15 +00:00
|
|
|
# it under the terms of the GNU Affero General Public License as
|
|
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
|
|
# License, or (at your option) any later version.
|
2006-12-07 13:41:40 +00:00
|
|
|
#
|
2008-11-03 18:27:16 +00:00
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2009-10-14 12:32:15 +00:00
|
|
|
# GNU Affero General Public License for more details.
|
2006-12-07 13:41:40 +00:00
|
|
|
#
|
2009-10-14 12:32:15 +00:00
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2006-12-07 13:41:40 +00:00
|
|
|
#
|
|
|
|
##############################################################################
|
|
|
|
|
2009-06-12 11:05:11 +00:00
|
|
|
from lxml import etree
|
2013-03-27 11:10:14 +00:00
|
|
|
import openerp
|
2011-02-07 12:57:23 +00:00
|
|
|
import openerp.tools as tools
|
|
|
|
from openerp.tools.safe_eval import safe_eval
|
2006-12-07 13:41:40 +00:00
|
|
|
import print_fnc
|
2011-02-07 12:57:23 +00:00
|
|
|
from openerp.osv.orm import browse_null, browse_record
|
2006-12-07 13:41:40 +00:00
|
|
|
|
|
|
|
class InheritDict(dict):
|
2008-07-22 14:24:36 +00:00
|
|
|
# Might be usefull when we're doing name lookup for call or eval.
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def __init__(self, parent=None):
|
|
|
|
self.parent = parent
|
2009-06-12 11:05:11 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def __getitem__(self, name):
|
|
|
|
if name in self:
|
|
|
|
return super(InheritDict, self).__getitem__(name)
|
|
|
|
else:
|
|
|
|
if not self.parent:
|
|
|
|
raise KeyError
|
|
|
|
else:
|
|
|
|
return self.parent[name]
|
2006-12-07 13:41:40 +00:00
|
|
|
|
|
|
|
def tounicode(val):
|
2008-07-22 14:24:36 +00:00
|
|
|
if isinstance(val, str):
|
|
|
|
unicode_val = unicode(val, 'utf-8')
|
|
|
|
elif isinstance(val, unicode):
|
|
|
|
unicode_val = val
|
|
|
|
else:
|
2009-06-12 11:05:11 +00:00
|
|
|
unicode_val = unicode(val)
|
2008-07-22 14:24:36 +00:00
|
|
|
return unicode_val
|
2006-12-07 13:41:40 +00:00
|
|
|
|
|
|
|
class document(object):
|
2008-07-22 14:24:36 +00:00
|
|
|
def __init__(self, cr, uid, datas, func=False):
|
|
|
|
# create a new document
|
2009-06-12 11:05:11 +00:00
|
|
|
self.cr = cr
|
2013-03-27 11:10:14 +00:00
|
|
|
self.pool = openerp.registry(cr.dbname)
|
2008-07-22 14:24:36 +00:00
|
|
|
self.func = func or {}
|
|
|
|
self.datas = datas
|
|
|
|
self.uid = uid
|
|
|
|
self.bin_datas = {}
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def node_attrs_get(self, node):
|
2009-06-12 11:05:11 +00:00
|
|
|
if len(node.attrib):
|
|
|
|
return node.attrib
|
|
|
|
return {}
|
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def get_value(self, browser, field_path):
|
|
|
|
fields = field_path.split('.')
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
if not len(fields):
|
|
|
|
return ''
|
2009-06-12 11:05:11 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
value = browser
|
2009-06-12 11:05:11 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
for f in fields:
|
|
|
|
if isinstance(value, list):
|
|
|
|
if len(value)==0:
|
|
|
|
return ''
|
|
|
|
value = value[0]
|
|
|
|
if isinstance(value, browse_null):
|
|
|
|
return ''
|
|
|
|
else:
|
|
|
|
value = value[f]
|
2009-06-12 11:05:11 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
if isinstance(value, browse_null) or (type(value)==bool and not value):
|
|
|
|
return ''
|
2009-06-12 11:05:11 +00:00
|
|
|
else:
|
2008-07-22 14:24:36 +00:00
|
|
|
return value
|
2009-06-12 11:05:11 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def get_value2(self, browser, field_path):
|
|
|
|
value = self.get_value(browser, field_path)
|
|
|
|
if isinstance(value, browse_record):
|
|
|
|
return value.id
|
|
|
|
elif isinstance(value, browse_null):
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return value
|
2009-06-12 11:05:11 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def eval(self, record, expr):
|
2006-12-07 13:41:40 +00:00
|
|
|
#TODO: support remote variables (eg address.title) in expr
|
2009-06-12 11:05:11 +00:00
|
|
|
# how to do that: parse the string, find dots, replace those dotted variables by temporary
|
2006-12-07 13:41:40 +00:00
|
|
|
# "simple ones", fetch the value of those variables and add them (temporarily) to the _data
|
|
|
|
# dictionary passed to eval
|
|
|
|
|
|
|
|
#FIXME: it wont work if the data hasn't been fetched yet... this could
|
|
|
|
# happen if the eval node is the first one using this browse_record
|
|
|
|
# the next line is a workaround for the problem: it causes the resource to be loaded
|
|
|
|
#Pinky: Why not this ? eval(expr, browser) ?
|
2008-07-22 14:24:36 +00:00
|
|
|
# name = browser.name
|
|
|
|
# data_dict = browser._data[self.get_value(browser, 'id')]
|
2010-05-03 23:49:53 +00:00
|
|
|
return safe_eval(expr, {}, {'obj': record})
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
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'])
|
2006-12-07 13:41:40 +00:00
|
|
|
#TODO: test this
|
2008-07-22 14:24:36 +00:00
|
|
|
if value == '' and 'default' in attrs:
|
|
|
|
value = attrs['default']
|
2009-11-28 10:48:10 +00:00
|
|
|
el = etree.SubElement(parent, node.tag)
|
2009-06-12 11:05:11 +00:00
|
|
|
el.text = tounicode(value)
|
2006-12-07 13:41:40 +00:00
|
|
|
#TODO: test this
|
2008-07-22 14:24:36 +00:00
|
|
|
for key, value in attrs.iteritems():
|
|
|
|
if key not in ('type', 'name', 'default'):
|
2009-06-12 11:05:11 +00:00
|
|
|
el.set(key, value)
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
elif attrs['type']=='attachment':
|
|
|
|
if isinstance(browser, list):
|
|
|
|
model = browser[0]._table_name
|
2009-06-12 11:05:11 +00:00
|
|
|
else:
|
2008-07-22 14:24:36 +00:00
|
|
|
model = browser._table_name
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
value = self.get_value(browser, attrs['name'])
|
2009-06-12 11:05:11 +00:00
|
|
|
|
2013-03-27 11:10:14 +00:00
|
|
|
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)
|
2009-06-12 11:05:11 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
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'):
|
2009-01-05 21:02:40 +00:00
|
|
|
import base64
|
2009-01-09 12:18:20 +00:00
|
|
|
from StringIO import StringIO
|
2008-07-22 14:24:36 +00:00
|
|
|
dt = base64.decodestring(datas['datas'])
|
2009-01-09 12:18:20 +00:00
|
|
|
fp = StringIO()
|
|
|
|
fp.write(dt)
|
2008-07-22 14:24:36 +00:00
|
|
|
i = str(len(self.bin_datas))
|
|
|
|
self.bin_datas[i] = fp
|
2009-11-28 10:48:10 +00:00
|
|
|
el = etree.SubElement(parent, node.tag)
|
2009-06-12 11:05:11 +00:00
|
|
|
el.text = i
|
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
elif attrs['type']=='data':
|
2006-12-07 13:41:40 +00:00
|
|
|
#TODO: test this
|
2008-07-22 14:24:36 +00:00
|
|
|
txt = self.datas.get('form', {}).get(attrs['name'], '')
|
2009-11-28 10:48:10 +00:00
|
|
|
el = etree.SubElement(parent, node.tag)
|
2009-06-12 11:05:11 +00:00
|
|
|
el.text = txt
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
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)
|
2009-11-28 10:48:10 +00:00
|
|
|
el = etree.SubElement(parent, node.tag)
|
2009-06-12 11:05:11 +00:00
|
|
|
el.text = txt
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
elif attrs['type']=='eval':
|
|
|
|
value = self.eval(browser, attrs['expr'])
|
2009-11-28 10:48:10 +00:00
|
|
|
el = etree.SubElement(parent, node.tag)
|
2009-06-12 11:05:11 +00:00
|
|
|
el.text = str(value)
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
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()
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
if 'order' in attrs and attrs['order']=='desc':
|
|
|
|
keys.reverse()
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
v_list = [vals[k] for k in keys]
|
2009-06-12 11:05:11 +00:00
|
|
|
for v in v_list:
|
2009-11-28 10:48:10 +00:00
|
|
|
el = etree.SubElement(parent, node.tag)
|
2009-06-12 11:05:11 +00:00
|
|
|
for el_cld in node:
|
2008-07-22 14:24:36 +00:00
|
|
|
self.parse_node(el_cld, el, v)
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
elif attrs['type']=='call':
|
|
|
|
if len(attrs['args']):
|
2009-06-12 11:05:11 +00:00
|
|
|
#TODO: test this
|
2008-07-22 14:24:36 +00:00
|
|
|
# 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
|
2012-02-08 17:03:51 +00:00
|
|
|
if 'model' in attrs:
|
2013-03-29 14:07:23 +00:00
|
|
|
obj = self.pool[attrs['model']]
|
2009-06-12 11:05:11 +00:00
|
|
|
else:
|
2008-07-22 14:24:36 +00:00
|
|
|
if isinstance(browser, list):
|
|
|
|
obj = browser[0]._table
|
|
|
|
else:
|
|
|
|
obj = browser._table
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
# get the ids
|
2012-02-08 17:03:51 +00:00
|
|
|
if 'ids' in attrs:
|
2008-07-22 14:24:36 +00:00
|
|
|
ids = self.eval(browser, attrs['ids'])
|
2009-06-12 11:05:11 +00:00
|
|
|
else:
|
2008-07-22 14:24:36 +00:00
|
|
|
if isinstance(browser, list):
|
2009-06-12 11:05:11 +00:00
|
|
|
ids = [b.id for b in browser]
|
2008-07-22 14:24:36 +00:00
|
|
|
else:
|
|
|
|
ids = [browser.id]
|
2009-06-12 11:05:11 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
# call the method itself
|
|
|
|
newdatas = getattr(obj, attrs['name'])(self.cr, self.uid, ids, *args)
|
2009-06-12 11:05:11 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def parse_result_tree(node, parent, datas):
|
2009-08-25 07:29:34 +00:00
|
|
|
if not node.tag == etree.Comment:
|
2009-11-28 10:48:10 +00:00
|
|
|
el = etree.SubElement(parent, node.tag)
|
2008-07-22 14:24:36 +00:00
|
|
|
atr = self.node_attrs_get(node)
|
|
|
|
if 'value' in atr:
|
|
|
|
if not isinstance(datas[atr['value']], (str, unicode)):
|
2009-06-12 11:05:11 +00:00
|
|
|
txt = str(datas[atr['value']])
|
2008-07-22 14:24:36 +00:00
|
|
|
else:
|
2012-02-08 17:04:56 +00:00
|
|
|
txt = datas[atr['value']]
|
2009-08-21 10:28:54 +00:00
|
|
|
el.text = txt
|
2008-07-22 14:24:36 +00:00
|
|
|
else:
|
2009-06-12 11:05:11 +00:00
|
|
|
for el_cld in node:
|
2008-07-22 14:24:36 +00:00
|
|
|
parse_result_tree(el_cld, el, datas)
|
|
|
|
if not isinstance(newdatas, list):
|
|
|
|
newdatas = [newdatas]
|
|
|
|
for newdata in newdatas:
|
|
|
|
parse_result_tree(node, parent, newdata)
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
elif attrs['type']=='zoom':
|
|
|
|
value = self.get_value(browser, attrs['name'])
|
|
|
|
if value:
|
|
|
|
if not isinstance(value, list):
|
|
|
|
v_list = [value]
|
|
|
|
else:
|
|
|
|
v_list = value
|
|
|
|
for v in v_list:
|
2009-11-28 10:48:10 +00:00
|
|
|
el = etree.SubElement(parent, node.tag)
|
2009-06-12 11:05:11 +00:00
|
|
|
for el_cld in node:
|
2008-07-22 14:24:36 +00:00
|
|
|
self.parse_node(el_cld, el, v)
|
|
|
|
else:
|
2010-03-24 16:32:22 +00:00
|
|
|
# if there is no "type" attribute in the node, copy it to the xml data and parse its children
|
2009-08-25 07:29:34 +00:00
|
|
|
if not node.tag == etree.Comment:
|
|
|
|
if node.tag == parent.tag:
|
|
|
|
el = parent
|
|
|
|
else:
|
2009-11-28 10:48:10 +00:00
|
|
|
el = etree.SubElement(parent, node.tag)
|
2009-08-25 07:29:34 +00:00
|
|
|
for el_cld in node:
|
|
|
|
self.parse_node(el_cld,el, browser)
|
2008-07-22 14:24:36 +00:00
|
|
|
def xml_get(self):
|
2009-08-25 07:29:34 +00:00
|
|
|
return etree.tostring(self.doc,encoding="utf-8",xml_declaration=True,pretty_print=True)
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def parse_tree(self, ids, model, context=None):
|
|
|
|
if not context:
|
|
|
|
context={}
|
2013-03-27 11:10:14 +00:00
|
|
|
browser = self.pool[model].browse(self.cr, self.uid, ids, context)
|
2009-06-12 11:05:11 +00:00
|
|
|
self.parse_node(self.dom, self.doc, browser)
|
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def parse_string(self, xml, ids, model, context=None):
|
|
|
|
if not context:
|
|
|
|
context={}
|
|
|
|
# parses the xml template to memory
|
2009-06-12 11:05:11 +00:00
|
|
|
self.dom = etree.XML(xml)
|
2008-07-22 14:24:36 +00:00
|
|
|
# create the xml data from the xml template
|
|
|
|
self.parse_tree(ids, model, context)
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def parse(self, filename, ids, model, context=None):
|
|
|
|
if not context:
|
|
|
|
context={}
|
|
|
|
# parses the xml template to memory
|
2011-01-04 10:13:35 +00:00
|
|
|
src_file = tools.file_open(filename)
|
|
|
|
try:
|
|
|
|
self.dom = etree.XML(src_file.read())
|
|
|
|
self.doc = etree.Element(self.dom.tag)
|
|
|
|
self.parse_tree(ids, model, context)
|
|
|
|
finally:
|
|
|
|
src_file.close()
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
def close(self):
|
|
|
|
self.doc = None
|
|
|
|
self.dom = None
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-07-23 15:01:27 +00:00
|
|
|
|
|
|
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
|
|
|