Merge commit 'origin/master' into mdv-gpl3-py26

Conflicts:
	bin/report/interface.py
	bin/report/printscreen/ps_list.py
	bin/report/render/__init__.py
	bin/report/render/rml.py
	bin/report/render/rml2pdf/trml2pdf.py
	bin/sql_db.py

bzr revid: p_christ@hol.gr-20090506201813-qb71ec85xr08obb1
This commit is contained in:
P. Christeas 2009-05-06 23:18:13 +03:00
commit 3814e4dc73
33 changed files with 1217 additions and 976 deletions

View File

@ -322,6 +322,7 @@ def upgrade_graph(graph, cr, module_list, force=None):
raise
if info.get('installable', True):
packages.append((module, info.get('depends', []), info))
dependencies = dict([(p, deps) for p, deps, data in packages])
current, later = set([p for p, dep, data in packages]), set()
@ -672,7 +673,8 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
pool = pooler.get_pool(cr.dbname)
try:
report = tools.assertion_report()
STATES_TO_LOAD = ['installed', 'to upgrade']
# NOTE: Try to also load the modules that have been marked as uninstallable previously...
STATES_TO_LOAD = ['installed', 'to upgrade', 'uninstallable']
graph = create_graph(cr, ['base'], force)
has_updates = False
if update_module:

View File

@ -145,6 +145,7 @@ CREATE TABLE res_users (
context_tz varchar(64) default null,
signature text,
-- action_id int references ir_act_window on delete set null,
context_lang varchar(64) default '',
action_id int,
primary key(id)
);

View File

@ -121,6 +121,7 @@ class report_xml(osv.osv):
('sxw', 'sxw'),
('txt', 'txt'),
('odt', 'odt'),
('html2html','Html from html'),
], string='Type', required=True),
'groups_id': fields.many2many('res.groups', 'res_groups_report_rel', 'uid', 'gid', 'Groups'),
'attachment': fields.char('Save As Attachment Prefix', size=128, help='This is the filename of the attachment used to store the printing result. Keep empty to not save the printed reports. You can use a python expression with the object and time variables.'),
@ -519,14 +520,15 @@ class actions_server(osv.osv):
result = self.pool.get(action.action_id.type).read(cr, uid, action.action_id.id, context=context)
return result
if action.state=='python':
if action.state=='code':
localdict = {
'self': self.pool.get(action.model_id.model),
'context': context,
'time': time,
'ids': ids,
'cr': cr,
'uid': uid
'uid': uid,
'obj':obj
}
exec action.code in localdict
if 'action' in localdict:

View File

@ -178,8 +178,8 @@ class maintenance_contract_wizard(osv.osv_memory):
is_ok = contract_info['status'] in ('partial', 'full')
if is_ok:
module_ids = []
if contract_info['modules_with_contract']:
module_ids = []
for name, version in contract_info['modules_with_contract']:
contract_module = self.pool.get('maintenance.contract.module')
res = contract_module.search(cr, uid, [('name', '=', name),('version', '=', version)])

View File

@ -244,7 +244,7 @@ class module(osv.osv):
m.state not in ('uninstalled','uninstallable','to remove')''', (module.name,))
res = cr.fetchall()
if res:
raise orm.except_orm(_('Error'), _('Some installed modules depends on the module you plan to desinstall :\n %s') % '\n'.join(map(lambda x: '\t%s: %s' % (x[0], x[1]), res)))
raise orm.except_orm(_('Error'), _('Some installed modules depend on the module you plan to Uninstall :\n %s') % '\n'.join(map(lambda x: '\t%s: %s' % (x[0], x[1]), res)))
self.write(cr, uid, ids, {'state': 'to remove'})
return True

View File

@ -200,6 +200,28 @@
</rng:element>
</rng:define>
<rng:define name="data">
<rng:element name="data">
<rng:zeroOrMore>
<rng:choice>
<rng:ref name="form"/>
<rng:ref name="tree"/>
<rng:ref name="field"/>
<rng:ref name="label"/>
<rng:ref name="separator"/>
<rng:ref name="notebook"/>
<rng:ref name="page"/>
<rng:ref name="xpath"/>
<rng:ref name="button"/>
<rng:ref name="group"/>
<rng:ref name="graph"/>
<rng:element name="newline"><rng:empty/></rng:element>
</rng:choice>
</rng:zeroOrMore>
</rng:element>
</rng:define>
<rng:define name="field">
<rng:element name="field">
<rng:attribute name="name" />
@ -366,6 +388,7 @@
<rng:ref name="notebook" />
<rng:ref name="graph" />
<rng:ref name="calendar" />
<rng:ref name="data" />
<rng:ref name="gantt" />
<rng:ref name="xpath" />
<rng:ref name="page" />

View File

@ -450,13 +450,11 @@ class one2many(_column):
elif act[0] == 5:
cr.execute('update '+_table+' set '+self._fields_id+'=null where '+self._fields_id+'=%s', (id,))
elif act[0] == 6:
if not act[2]:
ids2 = [0]
else:
ids2 = act[2]
cr.execute('update '+_table+' set '+self._fields_id+'=NULL where '+self._fields_id+'=%s and id not in ('+','.join(map(str, ids2))+')', (id,))
if act[2]:
cr.execute('update '+_table+' set '+self._fields_id+'=%s where id in ('+','.join(map(str, act[2]))+')', (id,))
obj.write(cr, user, act[2], {self._fields_id:id}, context=context or {})
ids2 = act[2] or [0]
cr.execute('select id from '+_table+' where '+self._fields_id+'=%s and id not in ('+','.join(map(str, ids2))+')', (id,))
ids3 = map(lambda x:x[0], cr.fetchall())
obj.write(cr, user, ids3, {self._fields_id:False}, context=context or {})
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like'):
return obj.pool.get(self._obj).name_search(cr, uid, value, self._domain, offset, limit)

View File

@ -811,13 +811,14 @@ class orm_template(object):
attrs = {}
try:
if node.getAttribute('name') in self._columns:
relation = self._columns[node.getAttribute('name')]._obj
column = self._columns[node.getAttribute('name')]
else:
relation = self._inherit_fields[node.getAttribute('name')][2]._obj
column = self._inherit_fields[node.getAttribute('name')][2]
except:
relation = False
column = False
if relation:
if column:
relation = column._obj
childs = False
views = {}
for f in node.childNodes:
@ -832,9 +833,12 @@ class orm_template(object):
}
attrs = {'views': views}
if node.hasAttribute('widget') and node.getAttribute('widget')=='selection':
# We can not use the domain has it is defined according to the record !
attrs['selection'] = self.pool.get(relation).name_search(cr, user, '', context=context)
if not attrs.get('required',False):
# We can not use the 'string' domain has it is defined according to the record !
dom = None
if column._domain and not isinstance(column._domain, (str, unicode)):
dom = column._domain
attrs['selection'] = self.pool.get(relation).name_search(cr, user, '', dom, context=context)
if (node.hasAttribute('required') and not int(node.getAttribute('required'))) or not column.required:
attrs['selection'].append((False,''))
fields[node.getAttribute('name')] = attrs
@ -2322,7 +2326,7 @@ class orm(orm_template):
# It's the first node of the parent: position = parent_left+1
if not position:
if not vals[self._parent_name]:
if not vals[self._parent_name]:
position = 1
else:
cr.execute('select parent_left from '+self._table+' where id=%s', (vals[self._parent_name],))
@ -2450,10 +2454,6 @@ class orm(orm_template):
upd2.append(user)
cr.execute('insert into "'+self._table+'" (id'+upd0+") values ("+str(id_new)+upd1+')', tuple(upd2))
upd_todo.sort(lambda x, y: self._columns[x].priority-self._columns[y].priority)
for field in upd_todo:
self._columns[field].set(cr, self, id_new, field, vals[field], user, context)
self._validate(cr, user, [id_new], context)
if self._parent_store:
if self.pool._init:
@ -2478,6 +2478,9 @@ class orm(orm_template):
cr.execute('update '+self._table+' set parent_left=parent_left+2 where parent_left>%s', (pleft,))
cr.execute('update '+self._table+' set parent_right=parent_right+2 where parent_right>%s', (pleft,))
cr.execute('update '+self._table+' set parent_left=%s,parent_right=%s where id=%s', (pleft+1,pleft+2,id_new))
for field in upd_todo:
self._columns[field].set(cr, self, id_new, field, vals[field], user, context)
self._validate(cr, user, [id_new], context)
result = self._store_get_values(cr, user, [id_new], vals.keys(), context)
for order, object, ids, fields in result:

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -25,5 +25,48 @@ pageSize = {
'A5': (148.5,105)
}
odt_namespace = {
"office":"{urn:oasis:names:tc:opendocument:xmlns:office:1.0}",
"style":"{urn:oasis:names:tc:opendocument:xmlns:style:1.0}",
"text":"{urn:oasis:names:tc:opendocument:xmlns:text:1.0}",
"table":"{urn:oasis:names:tc:opendocument:xmlns:table:1.0}",
"draw":"{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}",
"fo":"{urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0}",
"xlink":"{http://www.w3.org/1999/xlink}",
"dc":"{http://purl.org/dc/elements/1.1/}",
"meta":"{urn:oasis:names:tc:opendocument:xmlns:meta:1.0}",
"number":"{urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0}",
"svg":"{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}",
"chart":"{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}",
"dr3d":"{urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0}",
"math":"{http://www.w3.org/1998/Math/MathML}",
"form":"{urn:oasis:names:tc:opendocument:xmlns:form:1.0}",
"script":"{urn:oasis:names:tc:opendocument:xmlns:script:1.0}",
"ooo":"{http://openoffice.org/2004/office}",
"ooow":"{http://openoffice.org/2004/writer}",
"oooc":"{http://openoffice.org/2004/calc}",
"dom":"{http://www.w3.org/2001/xml-events}" }
sxw_namespace = {
"office":"{http://openoffice.org/2000/office}",
"style":"{http://openoffice.org/2000/style}",
"text":"{http://openoffice.org/2000/text}",
"table":"{http://openoffice.org/2000/table}",
"draw":"{http://openoffice.org/2000/drawing}",
"fo":"{http://www.w3.org/1999/XSL/Format}",
"xlink":"{http://www.w3.org/1999/xlink}",
"dc":"{http://purl.org/dc/elements/1.1/}",
"meta":"{http://openoffice.org/2000/meta}",
"number":"{http://openoffice.org/2000/datastyle}",
"svg":"{http://www.w3.org/2000/svg}",
"chart":"{http://openoffice.org/2000/chart}",
"dr3d":"{http://openoffice.org/2000/dr3d}",
"math":"{http://www.w3.org/1998/Math/MathML}",
"form":"{http://openoffice.org/2000/form}",
"script":"{http://openoffice.org/2000/script}",
"ooo":"{http://openoffice.org/2004/office}",
"ooow":"{http://openoffice.org/2004/writer}",
"oooc":"{http://openoffice.org/2004/calc}",
"dom":"{http://www.w3.org/2001/xml-events}"}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -23,10 +23,9 @@
import os
import re
#Ged> Why do we use libxml2 here instead of xml.dom like in other places of the code?
import libxml2
import libxslt
from lxml import etree
import netsvc
import pooler
@ -84,6 +83,7 @@ class report_rml(report_int):
'sxw': self.create_sxw,
'txt': self.create_txt,
'odt': self.create_odt,
'html2html' : self.create_html2html,
}
def create(self, cr, uid, ids, datas, context):
@ -190,18 +190,18 @@ class report_rml(report_int):
result.freeDoc()
return xml
def create_pdf(self, xml, logo=None, title=None):
def create_pdf(self, rml, localcontext = None, logo=None, title=None):
if logo:
self.bin_datas['logo'] = logo
else:
if 'logo' in self.bin_datas:
del self.bin_datas['logo']
obj = render.rml(xml, self.bin_datas, tools.config['root_path'],title)
obj = render.rml(rml, localcontext, self.bin_datas, tools.config['root_path'],title)
obj.render()
return obj.get()
def create_html(self, xml, logo=None, title=None):
obj = render.rml2html(xml, self.bin_datas)
def create_html(self, rml, localcontext = None, logo=None, title=None):
obj = render.rml2html(rml, localcontext, self.bin_datas)
obj.render()
return obj.get()
@ -210,15 +210,26 @@ class report_rml(report_int):
obj.render()
return obj.get().encode('utf-8')
def create_raw(self, xml, logo=None, title=None):
return xml
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_sxw(self, path, logo=None, title=None):
return path
def create_odt(self, data, logo=None, title=None):
return data
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):
obj = render.odt2odt(rml,localcontext)
obj.render()
return obj.get()
def create_odt(self,rml,localcontext = None):
obj = render.odt2odt(rml,localcontext)
obj.render()
return obj.get()
from report_sxw import report_sxw

74
bin/report/preprocess.py Normal file
View File

@ -0,0 +1,74 @@
from lxml import etree
import re
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']
class report(object):
def preprocess_rml(self, root_node,type='pdf'):
_regex1 = re.compile("\[\[(.*?)(repeatIn\(.*?\s*,\s*[\'\"].*?[\'\"]\s*(?:,\s*(.*?)\s*)?\s*\))(.*?)\]\]")
_regex11= re.compile("\[\[(.*?)(repeatIn\(.*?\s*\(.*?\s*[\'\"].*?[\'\"]\s*\),[\'\"].*?[\'\"](?:,\s*(.*?)\s*)?\s*\))(.*?)\]\]")
_regex2 = re.compile("\[\[(.*?)(removeParentNode\(\s*(?:['\"](.*?)['\"])\s*\))(.*?)\]\]")
_regex3 = re.compile("\[\[\s*(.*?setTag\(\s*['\"](.*?)['\"]\s*,\s*['\"].*?['\"]\s*(?:,.*?)?\).*?)\s*\]\]")
for node in root_node:
if node.text:
def _sub3(txt):
n = node
while n.tag != txt.group(2):
n = n.getparent()
n.set('rml_tag', txt.group(1))
return "[[ '' ]]"
def _sub2(txt):
if txt.group(3):
n = node
try:
while n.tag != txt.group(3):
n = n.getparent()
except:
n = node
else:
n = node.getparent()
n.set('rml_except', txt.group(0)[2:-2])
return txt.group(0)
def _sub1(txt):
if len(txt.group(4)) > 1:
return " "
match = rml_parents
if type in ['odt','sxw']:
match = sxw_parents
if type =='html2html':
match = html_parents
if txt.group(3):
match = [txt.group(3)]
n = node
while n.tag not in match:
n = n.getparent()
n.set('rml_loop', txt.group(2))
return '[['+txt.group(1)+"''"+txt.group(4)+']]'
t = _regex1.sub(_sub1, node.text)
if t == " ":
t = _regex11.sub(_sub1, node.text)
t = _regex3.sub(_sub3, t)
node.text = _regex2.sub(_sub2, t)
self.preprocess_rml(node,type)
return root_node
if __name__=='__main__':
node = etree.XML('''<story>
<para>This is a test[[ setTag('para','xpre') ]]</para>
<blockTable>
<tr>
<td><para>Row 1 [[ setTag('tr','tr',{'style':'TrLevel'+str(a['level']), 'paraStyle':('Level'+str(a['level']))}) ]] </para></td>
<td>Row 2 [[ True and removeParentNode('td') ]] </td>
</tr><tr>
<td>Row 1 [[repeatIn(o.order_line,'o')]] </td>
<td>Row 2</td>
</tr>
</blockTable>
<p>This isa test</p>
</story>''')
a = report()
result = a.preprocess_rml(node)
print etree.tostring(result)

View File

@ -262,7 +262,8 @@ class document(object):
if not isinstance(datas[atr['value']], (str, unicode)):
txt = self.doc.createTextNode(str(datas[atr['value']]))
else:
txt = self.doc.createTextNode(datas[atr['value']].decode('utf-8'))
# txt = self.doc.createTextNode(datas[atr['value']].decode('utf-8'))
txt = self.doc.createTextNode(datas[atr['value']])
el.appendChild(txt)
else:
el_cld = node.firstChild

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -25,7 +25,7 @@ import pooler
import tools
from report import render
from lxml import etree
from xml.dom import minidom
import libxml2
import libxslt
@ -38,20 +38,25 @@ class report_printscreen_list(report_int):
def _parse_node(self, root_node):
result = []
for node in root_node.childNodes:
if node.localName == 'field':
attrsa = node.attributes
for node in root_node.getchildren():
if node.tag == 'field':
#attrsa = node.attributes
attrsa = node.attrib
print "typppppp",type(attrsa),dir(attrsa)
attrs = {}
if not attrsa is None:
for i in range(attrsa.length):
attrs[attrsa.item(i).localName] = attrsa.item(i).nodeValue
for key,val in attrsa.items():
attrs[key] = val
#for i in range(attrsa.length):
# attrs[attrsa.item(i).localName] = attrsa.item(i).nodeValue
result.append(attrs['name'])
else:
result.extend(self._parse_node(node))
return result
def _parse_string(self, view):
dom = minidom.parseString(view)
#dom = minidom.parseString(view)
dom = etree.XML(view)
return self._parse_node(dom)
def create(self, cr, uid, ids, datas, context=None):

View File

@ -23,10 +23,8 @@
from report.interface import report_int
import pooler
import tools
from lxml import etree
from report import render
from xml.dom import minidom
import libxml2
import libxslt
@ -38,20 +36,20 @@ class report_printscreen_list(report_int):
def _parse_node(self, root_node):
result = []
for node in root_node.childNodes:
if node.localName == 'field':
attrsa = node.attributes
for node in root_node.getchildren():
if node.tag == 'field':
attrsa = node.attrib
attrs = {}
if not attrsa is None:
for i in range(attrsa.length):
attrs[attrsa.item(i).localName] = attrsa.item(i).nodeValue
for key,val in attrsa.items():
attrs[key] = val
result.append(attrs['name'])
else:
result.extend(self._parse_node(node))
return result
def _parse_string(self, view):
dom = minidom.parseString(unicode(view, 'utf-8').encode('utf-8'))
dom = etree.XML(unicode(view, 'utf-8').encode('utf-8'))
return self._parse_node(dom)
def create(self, cr, uid, ids, datas, context=None):
@ -79,18 +77,15 @@ class report_printscreen_list(report_int):
def _create_table(self, uid, ids, fields, fields_order, results, context, title=''):
pageSize=[297.0, 210.0]
impl = minidom.getDOMImplementation()
new_doc = impl.createDocument(None, "report", None)
new_doc = etree.Element("report")
config = etree.Element("config")
# build header
config = new_doc.createElement("config")
def _append_node(name, text):
n = new_doc.createElement(name)
t = new_doc.createTextNode(text)
n.appendChild(t)
config.appendChild(n)
n = etree.Element(name)
n.text = text
config.append(n)
_append_node('date', time.strftime('%d/%m/%Y'))
_append_node('PageSize', '%.2fmm,%.2fmm' % tuple(pageSize))
@ -126,19 +121,17 @@ class report_printscreen_list(report_int):
l[pos] = strmax * s / t
_append_node('tableSize', ','.join(map(str,l)) )
new_doc.childNodes[0].appendChild(config)
header = new_doc.createElement("header")
new_doc.append(config)
header=etree.Element("header")
for f in fields_order:
field = new_doc.createElement("field")
field_txt = new_doc.createTextNode(fields[f]['string'] or '')
field.appendChild(field_txt)
header.appendChild(field)
field = etree.Element("field")
field.text = fields[f]['string'] or ''
header.append(field)
new_doc.childNodes[0].appendChild(header)
lines = new_doc.createElement("lines")
new_doc.append(header)
lines = etree.Element("lines")
tsum = []
count = len(fields_order)
@ -147,7 +140,7 @@ class report_printscreen_list(report_int):
for line in results:
node_line = new_doc.createElement("row")
node_line = etree.Element("row")
count = -1
for f in fields_order:
@ -169,49 +162,46 @@ class report_printscreen_list(report_int):
precision=(('digits' in fields[f]) and fields[f]['digits'][1]) or 2
line[f]='%.2f'%(line[f])
col = new_doc.createElement("col")
col.setAttribute('para','yes')
col.setAttribute('tree','no')
col = etree.Element("col")
col.set('para','yes')
col.set('tree','no')
if line[f] != None:
txt = new_doc.createTextNode(tools.ustr(line[f] or ''))
col.text = tools.ustr(line[f] or '')
if temp[count] == 1:
tsum[count] = float(tsum[count]) + float(line[f]);
else:
txt = new_doc.createTextNode('/')
col.appendChild(txt)
node_line.appendChild(col)
lines.appendChild(node_line)
node_line = new_doc.createElement("row")
lines.appendChild(node_line)
node_line = new_doc.createElement("row")
count = len(tsum)
for f in range(0,count):
col = new_doc.createElement("col")
col.setAttribute('para','yes')
col.setAttribute('tree','no')
col.text = '/'
node_line.append(col)
lines.append(node_line)
node_line = etree.Element("row")
lines.append(node_line)
for f in range(0,count+1):
col = etree.Element("col")
col.set('para','yes')
col.set('tree','no')
if tsum[f] != None:
if tsum[f] >= 0.01 :
total = '%.2f'%(tsum[f])
txt = new_doc.createTextNode(str(total or ''))
txt = str(total or '')
else :
txt = new_doc.createTextNode(str(tsum[f] or ''))
txt = str(tsum[f] or '')
else:
txt = new_doc.createTextNode('/')
txt = '/'
if f == 0:
txt = new_doc.createTextNode('Total')
txt ='Total'
col.appendChild(txt)
node_line.appendChild(col)
col.text = txt
node_line.append(col)
lines.appendChild(node_line)
lines.append(node_line)
new_doc.childNodes[0].appendChild(lines)
new_doc.append(lines)
styledoc = libxml2.parseFile(os.path.join(tools.config['root_path'],'addons/base/report/custom_new.xsl'))
style = libxslt.parseStylesheetDoc(styledoc)
doc = libxml2.parseDoc(new_doc.toxml(encoding='utf-8'))
doc = libxml2.parseDoc(etree.tostring(new_doc))
rml_obj = style.applyStylesheet(doc, None)
rml = style.saveResultToString(rml_obj)
self.obj = render.rml(rml, title=self.title)

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -21,8 +21,7 @@
##############################################################################
from simple import simple
from rml import rml, rml2html, rml2txt
from rml import rml, rml2html, rml2txt, odt2odt , html2html
from render import render
try:

View File

@ -0,0 +1,26 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from html2html import parseString
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,62 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from report.render.rml2pdf import utils
from lxml import etree
import copy
import pooler
class html2html(object):
def __init__(self, html, localcontext):
self.localcontext = localcontext
self.etree = html
self._node = None
def render(self):
def process_text(node,new_node):
if new_node.tag in ['story','tr','section']:
new_node.attrib.clear()
for child in utils._child_get(node, self):
new_child = copy.deepcopy(child)
new_node.append(new_child)
if len(child):
for n in new_child:
new_child.remove(n)
process_text(child, new_child)
else:
if new_child.tag=='img' and new_child.get('name'):
src = utils._process_text(self, new_child.get('name'))
if src :
new_child.set('src','data:image/gif;base64,%s'%src)
new_child.text = utils._process_text(self, child.text)
self._node = copy.deepcopy(self.etree)
for n in self._node:
self._node.remove(n)
process_text(self.etree, self._node)
return self._node
def parseString(node, localcontext = {}):
r = html2html(node, localcontext)
return r.render()

View File

@ -0,0 +1,22 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odt2odt import parseNode

View File

@ -0,0 +1,67 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from report.render.rml2pdf import utils
from lxml import etree
import copy
class odt2odt(object):
def __init__(self, odt, localcontext):
self.localcontext = localcontext
self.etree = odt
self._node = None
def render(self):
def process_text(node,new_node):
if new_node.tag in ['story','tr','section']:
new_node.attrib.clear()
for child in utils._child_get(node, self):
new_child = copy.deepcopy(child)
new_node.append(new_child)
if len(child):
for n in new_child:
new_child.remove(n)
process_text(child, new_child)
else:
new_child.text = utils._process_text(self, child.text)
self._node = copy.deepcopy(self.etree)
for n in self._node:
self._node.remove(n)
process_text(self.etree, self._node)
return self._node
def parseNode(node, localcontext = {}):
body = node.getchildren()[-1]
elements = body.findall(localcontext['name_space']["text"]+"p")
for pe in elements:
e = pe.findall(localcontext['name_space']["text"]+"drop-down")
for de in e:
pp=de.getparent()
for cnd in de.getchildren():
if cnd.text:
pe.append(cnd)
pp.remove(de)
r = odt2odt(node, localcontext)
return r.render()

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -24,26 +24,32 @@ import render
import rml2pdf
import rml2html as htmlizer
import rml2txt as txtizer
import odt2odt as odt
import html2html as html
class rml(render.render):
def __init__(self, xml, datas={}, path='.',title=None):
def __init__(self, rml, localcontext = None, datas={}, path='.', title=None):
render.render.__init__(self, datas)
self.xml = xml
self.localcontext = localcontext
self.rml = rml
self.output_type = 'pdf'
self.path = path
self.title=title
def _render(self):
return rml2pdf.parseString(self.xml, images=self.bin_datas, path=self.path,title=self.title)
return rml2pdf.parseNode(self.rml, self.localcontext, images=self.bin_datas, path=self.path,title=self.title)
class rml2html(render.render):
def __init__(self, xml, datas={}):
def __init__(self, rml,localcontext = None, datas = {}):
super(rml2html, self).__init__(datas)
self.xml = xml
self.rml = rml
self.localcontext = localcontext
self.output_type = 'html'
def _render(self):
return htmlizer.parseString(self.xml)
return htmlizer.parseString(self.rml,self.localcontext)
class rml2txt(render.render):
def __init__(self, xml, datas={}):
@ -54,5 +60,26 @@ class rml2txt(render.render):
def _render(self):
return txtizer.parseString(self.xml)
class odt2odt(render.render):
def __init__(self, rml, localcontext = None, datas = {}):
render.render.__init__(self, datas)
self.rml_dom = rml
self.localcontext = localcontext
self.output_type = 'odt'
def _render(self):
return odt.parseNode(self.rml_dom,self.localcontext)
class html2html(render.render):
def __init__(self, rml, localcontext = None, datas = {}):
render.render.__init__(self, datas)
self.rml_dom = rml
self.localcontext = localcontext
self.output_type = 'html'
def _render(self):
return html.parseString(self.rml_dom,self.localcontext)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -38,17 +38,18 @@
import sys
import cStringIO
import xml.dom.minidom
from lxml import etree
import copy
import utils
from report.render.rml2pdf import utils
class _flowable(object):
def __init__(self, template, doc):
def __init__(self, template, doc, localcontext = None):
self._tags = {
'title': self._tag_title,
'spacer': self._tag_spacer,
'para': self._tag_para,
'section':self._section,
'nextFrame': self._tag_next_frame,
'blockTable': self._tag_table,
'pageBreak': self._tag_page_break,
@ -56,6 +57,8 @@ class _flowable(object):
}
self.template = template
self.doc = doc
self.localcontext = localcontext
self._cache = {}
def _tag_page_break(self, node):
return '<br/>'*3
@ -70,43 +73,72 @@ class _flowable(object):
return result
def _tag_title(self, node):
node.tagName='h1'
return node.toxml()
node.tag='h1'
return etree.tostring(node)
def _tag_spacer(self, node):
length = 1+int(utils.unit_get(node.getAttribute('length')))/35
length = 1+int(utils.unit_get(node.get('length')))/35
return "<br/>"*length
def _tag_table(self, node):
node.tagName='table'
if node.hasAttribute('colWidths'):
sizes = map(lambda x: utils.unit_get(x), node.getAttribute('colWidths').split(','))
tr = self.doc.createElement('tr')
new_node = copy.deepcopy(node)
for child in new_node:
new_node.remove(child)
new_node.tag = 'table'
def process(node,new_node):
for child in utils._child_get(node,self):
new_child = copy.deepcopy(child)
new_node.append(new_child)
if len(child):
for n in new_child:
new_child.remove(n)
process(child, new_child)
else:
new_child.text = utils._process_text(self, child.text)
new_child.tag = 'p'
try:
if new_child.get('style').find('terp_tblheader')!= -1:
new_node.tag = 'th'
except:
pass
process(node,new_node)
if new_node.get('colWidths',False):
sizes = map(lambda x: utils.unit_get(x), new_node.get('colWidths').split(','))
tr = etree.Element('tr')
for s in sizes:
td = self.doc.createElement('td')
td.setAttribute("width", str(s))
tr.appendChild(td)
node.appendChild(tr)
return node.toxml()
td = etree.Element('td')
td.set("width", str(s))
tr.append(td)
new_node.append(tr)
return etree.tostring(new_node)
def _tag_para(self, node):
node.tagName='p'
if node.hasAttribute('style'):
node.setAttribute('class', node.getAttribute('style'))
return node.toxml()
new_node = copy.deepcopy(node)
new_node.tag = 'p'
if new_node.attrib.get('style',False):
new_node.set('class', new_node.get('style'))
new_node.text = utils._process_text(self, node.text)
return etree.tostring(new_node)
def _section(self, node):
result = ''
for child in utils._child_get(node, self):
if child.tag in self._tags:
result += self._tags[child.tag](child)
return result
def render(self, node):
result = self.template.start()
result += self.template.frame_start()
for n in node.childNodes:
if n.nodeType==node.ELEMENT_NODE:
if n.localName in self._tags:
result += self._tags[n.localName](n)
else:
pass
#print 'tag', n.localName, 'not yet implemented!'
for n in utils._child_get(node, self):
if n.tag in self._tags:
result += self._tags[n.tag](n)
else:
pass
result += self.template.frame_stop()
result += self.template.end()
return result.encode('utf-8').replace('"',"\'").replace('°','&deg;')
class _rml_tmpl_tag(object):
def __init__(self, *args):
pass
@ -132,21 +164,22 @@ class _rml_tmpl_frame(_rml_tmpl_tag):
def tag_mergeable(self):
return False
# An awfull workaround since I don't really understand the semantic behind merge.
def merge(self, frame):
pass
class _rml_tmpl_draw_string(_rml_tmpl_tag):
def __init__(self, node, style):
self.posx = utils.unit_get(node.getAttribute('x'))
self.posy = utils.unit_get(node.getAttribute('y'))
def __init__(self, node, style,localcontext = {}):
self.localcontext = localcontext
self.posx = utils.unit_get(node.get('x'))
self.posy = utils.unit_get(node.get('y'))
aligns = {
'drawString': 'left',
'drawRightString': 'right',
'drawCentredString': 'center'
}
align = aligns[node.localName]
self.pos = [(self.posx, self.posy, align, utils.text_get(node), style.get('td'), style.font_size_get('td'))]
align = aligns[node.tag]
self.pos = [(self.posx, self.posy, align, utils._process_text(self, node.text), style.get('td'), style.font_size_get('td'))]
def tag_start(self):
self.pos.sort()
@ -171,8 +204,9 @@ class _rml_tmpl_draw_string(_rml_tmpl_tag):
self.pos+=ds.pos
class _rml_tmpl_draw_lines(_rml_tmpl_tag):
def __init__(self, node, style):
coord = [utils.unit_get(x) for x in utils.text_get(node).split(' ')]
def __init__(self, node, style, localcontext = {}):
self.localcontext = localcontext
coord = [utils.unit_get(x) for x in utils._process_text(self, node.text).split(' ')]
self.ok = False
self.posx = coord[0]
self.posy = coord[1]
@ -188,20 +222,20 @@ class _rml_tmpl_draw_lines(_rml_tmpl_tag):
return ''
class _rml_stylesheet(object):
def __init__(self, stylesheet, doc):
def __init__(self, localcontext, stylesheet, doc):
self.doc = doc
self.localcontext = localcontext
self.attrs = {}
self._tags = {
'fontSize': lambda x: ('font-size',str(utils.unit_get(x))+'px'),
'fontSize': lambda x: ('font-size',str(utils.unit_get(x)+5.0)+'px'),
'alignment': lambda x: ('text-align',str(x))
}
result = ''
for ps in stylesheet.getElementsByTagName('paraStyle'):
for ps in stylesheet.findall('paraStyle'):
attr = {}
attrs = ps.attributes
for i in range(attrs.length):
name = attrs.item(i).localName
attr[name] = ps.getAttribute(name)
attrs = ps.attrib
for key, val in attrs.items():
attr[key] = val
attrs = []
for a in attr:
if a in self._tags:
@ -217,13 +251,13 @@ class _rml_draw_style(object):
def __init__(self):
self.style = {}
self._styles = {
'fill': lambda x: {'td': {'color':x.getAttribute('color')}},
'setFont': lambda x: {'td': {'font-size':x.getAttribute('size')+'px'}},
'stroke': lambda x: {'hr': {'color':x.getAttribute('color')}},
'fill': lambda x: {'td': {'color':x.get('color')}},
'setFont': lambda x: {'td': {'font-size':x.get('size')+'px'}},
'stroke': lambda x: {'hr': {'color':x.get('color')}},
}
def update(self, node):
if node.localName in self._styles:
result = self._styles[node.localName](node)
if node.tag in self._styles:
result = self._styles[node.tag](node)
for key in result:
if key in self.style:
self.style[key].update(result[key])
@ -239,8 +273,9 @@ class _rml_draw_style(object):
return ';'.join(['%s:%s' % (x[0],x[1]) for x in self.style[tag].items()])
class _rml_template(object):
def __init__(self, template):
def __init__(self, template, localcontext=None):
self.frame_pos = -1
self.localcontext = localcontext
self.frames = []
self.template_order = []
self.page_template = {}
@ -252,20 +287,23 @@ class _rml_template(object):
'lines': _rml_tmpl_draw_lines
}
self.style = _rml_draw_style()
for pt in template.getElementsByTagName('pageTemplate'):
rc = 'data:image/png;base64,'
self.data = ''
for pt in template.findall('pageTemplate'):
frames = {}
id = pt.getAttribute('id')
id = pt.get('id')
self.template_order.append(id)
for tmpl in pt.getElementsByTagName('frame'):
posy = int(utils.unit_get(tmpl.getAttribute('y1'))) #+utils.unit_get(tmpl.getAttribute('height')))
posx = int(utils.unit_get(tmpl.getAttribute('x1')))
frames[(posy,posx,tmpl.getAttribute('id'))] = _rml_tmpl_frame(posx, utils.unit_get(tmpl.getAttribute('width')))
for tmpl in template.getElementsByTagName('pageGraphics'):
for n in tmpl.childNodes:
if n.nodeType==n.ELEMENT_NODE:
if n.localName in self._tags:
t = self._tags[n.localName](n, self.style)
frames[(t.posy,t.posx,n.localName)] = t
for tmpl in pt.findall('frame'):
posy = int(utils.unit_get(tmpl.get('y1')))
posx = int(utils.unit_get(tmpl.get('x1')))
frames[(posy,posx,tmpl.get('id'))] = _rml_tmpl_frame(posx, utils.unit_get(tmpl.get('width')))
for tmpl in pt.findall('pageGraphics'):
for n in tmpl.getchildren():
if n.tag == 'image':
self.data = rc + utils._process_text(self, n.text)
if n.tag in self._tags:
t = self._tags[n.tag](n, self.style,self.localcontext)
frames[(t.posy,t.posx,n.tag)] = t
else:
self.style.update(n)
keys = frames.keys()
@ -318,7 +356,7 @@ class _rml_template(object):
def start(self):
return ''
def end(self):
result = ''
while not self.loop:
@ -327,9 +365,10 @@ class _rml_template(object):
return result
class _rml_doc(object):
def __init__(self, data):
self.dom = xml.dom.minidom.parseString(data)
self.filename = self.dom.documentElement.getAttribute('filename')
def __init__(self, data, localcontext):
self.dom = etree.XML(data)
self.localcontext = localcontext
self.filename = self.dom.get('filename')
self.result = ''
def render(self, out):
@ -341,28 +380,28 @@ class _rml_doc(object):
p {margin:0px; font-size:12px;}
td {font-size:14px;}
'''
style = self.dom.documentElement.getElementsByTagName('stylesheet')[0]
s = _rml_stylesheet(style, self.dom)
style = self.dom.findall('stylesheet')[0]
s = _rml_stylesheet(self.localcontext, style, self.dom)
self.result += s.render()
self.result+='''
</style>
'''
# f = _flowable(template, self.dom)
list_story =[]
storys= self.dom.documentElement.getElementsByTagName('story')
for story in storys :
template = _rml_template(self.dom.documentElement.getElementsByTagName('template')[0])
f = _flowable(template, self.dom)
for story in utils._child_get(self.dom, self, 'story'):
template = _rml_template(self.dom.findall('template')[0], self.localcontext)
f = _flowable(template, self.dom, localcontext = self.localcontext)
story_text = f.render(story)
list_story.append(story_text)
del f
if template.data:
tag = '''<img src = '%s' width=80 height=72/>'''%(template.data)
else:
tag = ''
self.result +='''
<script type="text/javascript">
var indexer = 0;
var aryTest = %s ;
var aryTest = %s ;
function nextData()
{
if(indexer < aryTest.length -1)
@ -378,22 +417,23 @@ class _rml_doc(object):
indexer -= 1;
document.getElementById("tiny_data").innerHTML=aryTest[indexer];
}
}
</script>
}
</script>
</head>
<body>
%s
<div id="tiny_data">
%s
</div>
</div>
<br>
<input type="button" value="next" onclick="nextData();">
<input type="button" value="prev" onclick="prevData();">
</body></html>'''%(list_story,list_story[0])
</body></html>'''%(list_story,tag,list_story[0])
out.write( self.result)
def parseString(data, fout=None):
r = _rml_doc(data)
def parseString(data,localcontext = {}, fout=None):
r = _rml_doc(data, localcontext)
if fout:
fp = file(fout,'wb')
r.render(fp)
@ -404,7 +444,7 @@ def parseString(data, fout=None):
r.render(fp)
return fp.getvalue()
def trml2pdf_help():
def rml2html_help():
print 'Usage: rml2html input.rml >output.html'
print 'Render the standard input (RML) and output an HTML file'
sys.exit(0)
@ -412,7 +452,7 @@ def trml2pdf_help():
if __name__=="__main__":
if len(sys.argv)>1:
if sys.argv[1]=='--help':
trml2pdf_help()
rml2html_help()
print parseString(file(sys.argv[1], 'r').read()),
else:
print 'Usage: trml2pdf input.rml >output.pdf'

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -24,16 +24,9 @@ import re
import reportlab
import reportlab.lib.units
def text_get(node):
rc = ''
for node in node.childNodes:
if node.nodeType == node.TEXT_NODE:
rc = rc + node.data
return rc
units = [
(re.compile('^(-?[0-9\.]+)\s*in$'), reportlab.lib.units.inch),
(re.compile('^(-?[0-9\.]+)\s*cm$'), reportlab.lib.units.cm),
(re.compile('^(-?[0-9\.]+)\s*cm$'), reportlab.lib.units.cm),
(re.compile('^(-?[0-9\.]+)\s*mm$'), reportlab.lib.units.mm),
(re.compile('^(-?[0-9\.]+)\s*px$'), 0.7),
(re.compile('^(-?[0-9\.]+)\s*$'), 1)
@ -48,9 +41,9 @@ def unit_get(size):
return False
def tuple_int_get(node, attr_name, default=None):
if not node.hasAttribute(attr_name):
if not node.get(attr_name):
return default
res = [int(x) for x in node.getAttribute(attr_name).split(',')]
res = [int(x) for x in node.get(attr_name).split(',')]
return res
def bool_get(value):
@ -59,16 +52,16 @@ def bool_get(value):
def attr_get(node, attrs, dict={}):
res = {}
for name in attrs:
if node.hasAttribute(name):
res[name] = unit_get(node.getAttribute(name))
if node.get(name):
res[name] = unit_get(node.get(name))
for key in dict:
if node.hasAttribute(key):
if node.get(key):
if dict[key]=='str':
res[key] = str(node.getAttribute(key))
res[key] = str(node.get(key))
elif dict[key]=='bool':
res[key] = bool_get(node.getAttribute(key))
res[key] = bool_get(node.get(key))
elif dict[key]=='int':
res[key] = int(node.getAttribute(key))
res[key] = int(node.get(key))
return res
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -20,24 +20,5 @@
#
##############################################################################
# trml2pdf - An RML to PDF converter
# Copyright (C) 2003, Fabien Pinckaers, UCL, FSA
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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 GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from trml2pdf import parseString
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
from trml2pdf import parseString, parseNode

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -29,6 +29,8 @@ regex_t = re.compile('\(([0-9\.]*),([0-9\.]*),([0-9\.]*)\)')
regex_h = re.compile('#([0-9a-zA-Z][0-9a-zA-Z])([0-9a-zA-Z][0-9a-zA-Z])([0-9a-zA-Z][0-9a-zA-Z])')
def get(col_str):
if col_str == None:
col_str = ''
global allcols
if col_str in allcols.keys():
return allcols[col_str]

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -39,12 +39,68 @@
import re
import reportlab
from lxml import etree
_regex = re.compile('\[\[(.+?)\]\]')
def _child_get(node, self=None, tagname=None):
for n in node:
if self and self.localcontext and n.get('rml_loop', False):
oldctx = self.localcontext
for ctx in eval(n.get('rml_loop'),{}, self.localcontext):
self.localcontext.update(ctx)
if (tagname is None) or (n.tag==tagname):
if n.get('rml_except', False):
try:
eval(n.get('rml_except'), {}, self.localcontext)
except:
continue
if n.get('rml_tag'):
try:
(tag,attr) = eval(n.get('rml_tag'),{}, self.localcontext)
n2 = copy.copy(n)
n2.tag = tag
n2.attrib.update(attr)
yield n2
except:
yield n
else:
yield n
self.localcontext = oldctx
continue
if self and self.localcontext and n.get('rml_except', False):
try:
eval(n.get('rml_except'), {}, self.localcontext)
except:
continue
if (tagname is None) or (n.tag==tagname):
yield n
def _process_text(self, txt):
if not self.localcontext:
return txt
if not txt:
return ''
result = ''
sps = _regex.split(txt)
while sps:
# This is a simple text to translate
result += self.localcontext.get('translate', lambda x:x)(sps.pop(0))
if sps:
try:
txt2 = eval(sps.pop(0),self.localcontext)
except:
txt2 = ''
if type(txt2) == type(0) or type(txt2) == type(0.0):
txt2 = str(txt2)
if type(txt2)==type('') or type(txt2)==type(u''):
result += txt2
return result
def text_get(node):
rc = ''
for node in node.childNodes:
if node.nodeType == node.TEXT_NODE:
rc = rc + node.data
for node in node.getchildren():
rc = rc + node.text
return rc
units = [
@ -56,16 +112,17 @@ units = [
def unit_get(size):
global units
for unit in units:
res = unit[0].search(size, 0)
if res:
return unit[1]*float(res.group(1))
if size:
for unit in units:
res = unit[0].search(size, 0)
if res:
return unit[1]*float(res.group(1))
return False
def tuple_int_get(node, attr_name, default=None):
if not node.hasAttribute(attr_name):
if not node.get(attr_name):
return default
res = [int(x) for x in node.getAttribute(attr_name).split(',')]
res = [int(x) for x in node.get(attr_name).split(',')]
return res
def bool_get(value):
@ -74,19 +131,18 @@ def bool_get(value):
def attr_get(node, attrs, dict={}):
res = {}
for name in attrs:
if node.hasAttribute(name):
res[name] = unit_get(node.getAttribute(name))
if node.get(name):
res[name] = unit_get(node.get(name))
for key in dict:
if node.hasAttribute(key):
if node.get(key):
if dict[key]=='str':
res[key] = str(node.getAttribute(key))
res[key] = str(node.get(key))
elif dict[key]=='bool':
res[key] = bool_get(node.getAttribute(key))
res[key] = bool_get(node.get(key))
elif dict[key]=='int':
res[key] = int(node.getAttribute(key))
res[key] = int(node.get(key))
elif dict[key]=='unit':
res[key] = unit_get(node.getAttribute(key))
res[key] = unit_get(node.get(key))
return res
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -20,23 +20,26 @@
#
##############################################################################
from interface import report_rml
from lxml import etree
import StringIO
import cStringIO
import base64
import copy
import ir
import locale
import mx.DateTime
import netsvc
import os
import osv
import pooler
import re
import time
from interface import report_rml
import preprocess
import ir
import netsvc
import osv
import pooler
import tools
import warnings
import xml.dom.minidom
import zipfile
import common
DT_FORMAT = '%Y-%m-%d'
DHM_FORMAT = '%Y-%m-%d %H:%M:%S'
@ -58,15 +61,21 @@ sxw_parents = {
'section': 0,
}
html_parents = {
'tr' : 1,
'body' : 0,
'div' : 0
}
sxw_tag = "p"
rml2sxw = {
'para': 'p',
}
class _format(object):
def set_value(self, cr, uid, name, object, field, lang_obj):
#super(_date_format, self).__init__(self)
self.object = object
self._field = field
self.name = name
@ -82,10 +91,7 @@ class _float_format(float, _format):
digits = 2
if hasattr(self,'_field') and hasattr(self._field, 'digits') and self._field.digits:
digits = self._field.digits[1]
if self.lang_obj:
return self.lang_obj.format('%.' + str(digits) + 'f', self.name, True)
else:
return str(self.name)
return self.lang_obj.format('%.' + str(digits) + 'f', self.name, True)
return self.val
class _int_format(int, _format):
@ -95,13 +101,9 @@ class _int_format(int, _format):
def __str__(self):
if hasattr(self,'lang_obj'):
if self.lang_obj:
return self.lang_obj.format('%.d', self.name, True)
else:
return str(self.name)
return self.lang_obj.format('%.d', self.name, True)
return self.val
class _date_format(str, _format):
def __init__(self,value):
super(_date_format, self).__init__()
@ -111,10 +113,7 @@ class _date_format(str, _format):
if self.val:
if hasattr(self,'name') and (self.name):
date = mx.DateTime.strptime(self.name,DT_FORMAT)
if self.lang_obj:
return date.strftime(self.lang_obj.date_format)
else:
return date.strftime('%m/%d/%Y')
return date.strftime(self.lang_obj.date_format)
return self.val
class _dttime_format(str, _format):
@ -126,10 +125,7 @@ class _dttime_format(str, _format):
if self.val:
if hasattr(self,'name') and self.name:
datetime = mx.DateTime.strptime(self.name,DHM_FORMAT)
if self.lang_obj:
return datetime.strftime(self.lang_obj.date_format+ " " + self.lang_obj.time_format)
else:
return datetime.strftime('%m/%d/%Y %H:%M:%S')
return datetime.strftime(self.lang_obj.date_format+ " " + self.lang_obj.time_format)
return self.val
@ -155,31 +151,6 @@ class browse_record_list(list):
def __str__(self):
return "browse_record_list("+str(len(self))+")"
def repeatIn(self, name):
warnings.warn('Use repeatIn(object_list, \'variable\')', DeprecationWarning)
node = self.context['_node']
parents = self.context.get('parents', rml_parents)
node.data = ''
while True:
if not node.parentNode:
break
node = node.parentNode
if node.nodeType == node.ELEMENT_NODE and node.localName in parents:
break
parent_node = node
if not len(self):
return None
nodes = [(0,node)]
for i in range(1,len(self)):
newnode = parent_node.cloneNode(1)
n = parent_node.parentNode
n.insertBefore(newnode, parent_node)
nodes.append((i,newnode))
for i,node in nodes:
self.context[name] = self[i]
self.context['_self']._parse_node(node)
return None
class rml_parse(object):
def __init__(self, cr, uid, name, parents=rml_parents, tag=rml_tag, context=None):
if not context:
@ -187,7 +158,7 @@ class rml_parse(object):
self.cr = cr
self.uid = uid
self.pool = pooler.get_pool(cr.dbname)
user = self.pool.get('res.users').browse(cr, uid, uid, fields_process=_fields_process)
user = self.pool.get('res.users').browse(cr, uid, uid)
self.localcontext = {
'user': user,
'company': user.company_id,
@ -199,69 +170,57 @@ class rml_parse(object):
'formatLang': self.formatLang,
'logo' : user.company_id.logo,
'lang' : user.company_id.partner_id.lang,
'translate' : self._translate,
'setHtmlImage' : self.set_html_image
}
self.localcontext.update(context)
self.rml_header = user.company_id.rml_header
self.rml_header2 = user.company_id.rml_header2
self.logo = user.company_id.logo
self.name = name
self._regex = re.compile('\[\[(.+?)\]\]')
self._transl_regex = re.compile('(\[\[.+?\]\])')
self._node = None
self.parents = parents
self.tag = tag
self._lang_cache = {}
# self.already = {}
self.lang_dict = {}
self.default_lang = {}
self.lang_dict_called = False
self._transl_regex = re.compile('(\[\[.+?\]\])')
def setTag(self, oldtag, newtag, attrs=None):
if not attrs:
attrs={}
node = self._find_parent(self._node, [oldtag])
if node:
node.tagName = newtag
for key, val in attrs.items():
node.setAttribute(key, val)
return None
return newtag, attrs
def format(self, text, oldtag=None):
if not oldtag:
oldtag = self.tag
self._node.data = ''
node = self._find_parent(self._node, [oldtag])
ns = None
if node:
pp = node.parentNode
ns = node.nextSibling
pp.removeChild(node)
self._node = pp
lst = tools.ustr(text).split('\n')
if not (text and lst):
return None
nodes = []
for i in range(len(lst)):
newnode = node.cloneNode(1)
newnode.tagName=rml_tag
newnode.childNodes[0].data = lst[i]
if ns:
pp.insertBefore(newnode, ns)
else:
pp.appendChild(newnode)
nodes.append((i, newnode))
return text
def removeParentNode(self, tag=None):
if not tag:
tag = self.tag
if self.tag == sxw_tag and rml2sxw.get(tag, False):
tag = rml2sxw[tag]
node = self._find_parent(self._node, [tag])
if node:
parentNode = node.parentNode
parentNode.removeChild(node)
self._node = parentNode
raise Exception('Skip')
def set_html_image(self,attach_id):
try :
att_id = int(attach_id)
print att_id
attachment = self.pool.get('ir.attachment').browse(self.cr,self.uid,att_id)
print attachment
print attachment.datas
return attachment.datas
except :
return ''
def setLang(self, lang):
if not lang or self.default_lang.has_key(lang):
if not lang:
key = 'en_US'
self.lang_dict_called = False
self.localcontext['lang'] = lang
elif self.default_lang.has_key(lang):
key = lang
if self.default_lang.get(key,False):
self.lang_dict = self.default_lang.get(key,False).copy()
self.lang_dict_called = True
return True
self.localcontext['lang'] = lang
self.lang_dict_called = False
for obj in self.objects:
obj._context['lang'] = lang
for table in obj._cache:
@ -275,232 +234,102 @@ class rml_parse(object):
else:
obj._cache[table][id] = {'id': id}
def _get_lang_dict(self):
pool_lang = self.pool.get('res.lang')
lang = self.localcontext.get('lang', 'en_US') or 'en_US'
lang_ids = pool_lang.search(self.cr,self.uid,[('code','=',lang)])[0]
lang_obj = pool_lang.browse(self.cr,self.uid,lang_ids)
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
def formatLang(self, value, digits=2, date=False,date_time=False, grouping=True, monetary=False, currency=None):
if isinstance(value, (str, unicode)) and not value:
return ''
pool_lang = self.pool.get('res.lang')
lang = self.localcontext.get('lang', 'en_US') or 'en_US'
lids = pool_lang.search(self.cr,self.uid,[('code','=',lang)])
if not lids: return str(value)
lang_obj = pool_lang.browse(self.cr,self.uid,lids[0])
if not self.lang_dict_called:
self._get_lang_dict()
self.lang_dict_called = True
if date or date_time:
if not str(value):
return ''
date_format = lang_obj.date_format
date_format = self.lang_dict['date_format']
parse_format = DT_FORMAT
if date_time:
date_format = lang_obj.date_format + " " + lang_obj.time_format
parse_format = date_format
date_format = date_format + " " + self.lang_dict['time_format']
parse_format = DHM_FORMAT
# filtering time.strftime('%Y-%m-%d')
if type(value) == type(''):
parse_format = DHM_FORMAT
if (not date_time):
return value
return str(value)
if not isinstance(value, time.struct_time):
# assume string, parse it
# if len(str(value)) == 10:
# # length of date like 2001-01-01 is ten
# # assume format '%Y-%m-%d'
# date = mx.DateTime.strptime(value,DT_FORMAT)
# else:
# # assume format '%Y-%m-%d %H:%M:%S'
# value = str(value)[:19]
# date = mx.DateTime.strptime(str(value),DHM_FORMAT)
date = mx.DateTime.strptime(str(value),parse_format)
try:
date = mx.DateTime.strptime(str(value),parse_format)
except:# sometimes it takes converted values into value, so we dont need conversion.
return str(value)
else:
date = mx.DateTime.DateTime(*(value.timetuple()[:6]))
return date.strftime(date_format)
return lang_obj.format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary)
return self.lang_dict['lang_obj'].format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary)
def repeatIn(self, lst, name, nodes_parent=False):
self._node.data = ''
node = self._find_parent(self._node, nodes_parent or self.parents)
def repeatIn(self, lst, name,nodes_parent=False):
ret_lst = []
for id in lst:
ret_lst.append({name:id})
return ret_lst
pp = node.parentNode
ns = node.nextSibling
pp.removeChild(node)
self._node = pp
if not len(lst):
return None
nodes = []
for i in range(len(lst)):
newnode = node.cloneNode(1)
if ns:
pp.insertBefore(newnode, ns)
else:
pp.appendChild(newnode)
nodes.append((i, newnode))
for i, node in nodes:
self.node_context[node] = {name: lst[i]}
return None
def _eval(self, expr):
try:
res = eval(expr, self.localcontext)
if (res is None) or (res=='') or (res is False):
res = ''
except Exception,e:
import traceback, sys
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
netsvc.Logger().notifyChannel('report', netsvc.LOG_ERROR,
'report %s:\n%s\n%s\nexpr: %s' % (self.name, tb_s, str(e),
expr.encode('utf-8')))
res = ''
return res
def _find_parent(self, node, parents):
while True:
if not node.parentNode:
return False
node = node.parentNode
if node.nodeType == node.ELEMENT_NODE and node.localName in parents:
break
return node
def _parse_text(self, text, level=None):
if not level:
level=[]
res = self._regex.findall(text)
todo = []
# translate the text
# the "split [[]] if not match [[]]" is not very nice, but I
# don't see how I could do it better...
# what I'd like to do is a re.sub(NOT pattern, func, string)
# but I don't know how to do that...
# translate the RML file
if 'lang' in self.localcontext:
lang = self.localcontext['lang']
if lang and text and not text.isspace():
transl_obj = self.pool.get('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, 'rml', lang, source_string)
if translated_string:
piece_list[pn] = piece_list[pn].replace(source_string, translated_string)
text = ''.join(piece_list)
for key in res:
newtext = self._eval(key)
for i in range(len(level)):
if isinstance(newtext, list):
newtext = newtext[level[i]]
if isinstance(newtext, list):
todo.append((key, newtext))
else:
# if there are two [[]] blocks the same, it will replace both
# but it's ok because it should evaluate to the same thing
# anyway
newtext = tools.ustr(newtext)
text = text.replace('[['+key+']]', newtext)
self._node.data = text
if len(todo):
for key, newtext in todo:
parent_node = self._find_parent(self._node, parents)
assert parents.get(parent_node.localName, False), 'No parent node found !'
nodes = [parent_node]
for i in range(len(newtext) - 1):
newnode = parent_node.cloneNode(1)
if parents.get(parent_node.localName, False):
n = parent_node.parentNode
parent_node.parentNode.insertAfter(newnode, parent_node)
nodes.append(newnode)
return False
def _translate(self,text):
lang = self.localcontext['lang']
if lang and text and not text.isspace():
transl_obj = self.pool.get('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, 'rml', lang, source_string)
if translated_string:
piece_list[pn] = piece_list[pn].replace(source_string, translated_string)
text = ''.join(piece_list)
return text
def _parse_node(self):
level = []
while True:
if self._node.nodeType==self._node.ELEMENT_NODE:
if self._node.hasAttribute('expr'):
newattrs = self._eval(self._node.getAttribute('expr'))
for key,val in newattrs.items():
self._node.setAttribute(key,val)
if self._node.hasChildNodes():
self._node = self._node.firstChild
elif self._node.nextSibling:
self._node = self._node.nextSibling
else:
while self._node and not self._node.nextSibling:
self._node = self._node.parentNode
if not self._node:
break
self._node = self._node.nextSibling
if self._node in self.node_context:
self.localcontext.update(self.node_context[self._node])
if self._node.nodeType in (self._node.CDATA_SECTION_NODE, self._node.TEXT_NODE):
# if self._node in self.already:
# self.already[self._node] += 1
# print "second pass!", self.already[self._node], '---%s---' % self._node.data
# else:
# self.already[self._node] = 0
self._parse_text(self._node.data, level)
return True
def _find_node(self, node, localname):
if node.localName==localname:
return node
for tag in node.childNodes:
if tag.nodeType==tag.ELEMENT_NODE:
found = self._find_node(tag, localname)
if found:
return found
return False
def _add_header(self, node, header=1):
def _add_header(self, rml_dom, header=1):
if header==2:
rml_head = self.rml_header2
else:
rml_head = self.rml_header
# Refactor this patch, to use the minidom interface
if self.logo and (rml_head.find('company.logo')<0 or rml_head.find('<image')<0) and rml_head.find('<!--image')<0:
rml_head = rml_head.replace('<pageGraphics>','''<pageGraphics> <image x="10" y="26cm" height="70" width="90" >[[company.logo]] </image> ''')
if not self.logo and rml_head.find('company.logo')>=0:
rml_head = rml_head.replace('<image','<!--image')
rml_head = rml_head.replace('</image>','</image-->')
head_dom = xml.dom.minidom.parseString(rml_head.encode('utf-8'))
#for frame in head_dom.getElementsByTagName('frame'):
# frame.parentNode.removeChild(frame)
node2 = head_dom.documentElement
for tag in node2.childNodes:
if tag.nodeType==tag.ELEMENT_NODE:
found = self._find_node(node, tag.localName)
# rml_frames = found.getElementsByTagName('frame')
if found:
if tag.hasAttribute('position') and (tag.getAttribute('position')=='inside'):
found.appendChild(tag)
else:
found.parentNode.replaceChild(tag, found)
# for frame in rml_frames:
# tag.appendChild(frame)
head_dom = etree.XML(rml_head)
for tag in head_dom.getchildren():
found = rml_dom.find('.//'+tag.tag)
if found:
if tag.get('position'):
found.append(tag)
else :
found.getparent().replace(found,tag)
return True
def preprocess(self, objects, data, ids):
def set_context(self, objects, data, ids, report_type = None):
self.localcontext['data'] = data
self.localcontext['objects'] = objects
self.datas = data
self.ids = ids
self.objects = objects
if report_type:
if report_type=='odt' :
self.localcontext.update({'name_space' :common.odt_namespace})
else:
self.localcontext.update({'name_space' :common.sxw_namespace})
def _parse(self, rml_dom, objects, data, header=0):
self.node_context = {}
self.dom = rml_dom
self._node = self.dom.documentElement
if header:
self._add_header(self._node, header)
self._parse_node()
res = self.dom.documentElement.toxml('utf-8')
return res
class report_sxw(report_rml):
def __init__(self, name, table, rml, parser=rml_parse, header=True, store=False):
class report_sxw(report_rml, preprocess.report):
def __init__(self, name, table, rml=False, parser=rml_parse, header=True, store=False):
report_rml.__init__(self, name, table, rml, '')
self.name = name
self.parser = parser
@ -509,30 +338,17 @@ class report_sxw(report_rml):
def getObjects(self, cr, uid, ids, context):
table_obj = pooler.get_pool(cr.dbname).get(self.table)
return table_obj.browse(cr, uid, ids, list_class=browse_record_list, context=context,
fields_process=_fields_process)
return table_obj.browse(cr, uid, ids, list_class=browse_record_list, context=context, fields_process=_fields_process)
def create(self, cr, uid, ids, data, context=None):
if not context:
context={}
pool = pooler.get_pool(cr.dbname)
ir_obj = pool.get('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)
attach = report_xml.attachment
report_xml = ir_obj.browse(cr, uid, report_xml_ids[0], context=context)
else:
ir_menu_report_obj = pool.get('ir.ui.menu')
report_menu_ids = ir_menu_report_obj.search(cr, uid,
[('id', 'in', ids)], context=context)
title = ''
if report_menu_ids:
report_name = ir_menu_report_obj.browse(cr, uid, report_menu_ids[0],
context=context)
title = report_name.name
rml = tools.file_open(self.tmpl, subdir=None).read()
report_type= data.get('report_type', 'pdf')
class a(object):
@ -540,8 +356,28 @@ class report_sxw(report_rml):
for key,arg in argv.items():
setattr(self, key, arg)
report_xml = a(title=title, report_type=report_type, report_rml_content=rml, name=title, attachment=False, header=self.header)
attach = False
report_type = report_xml.report_type
if report_type in ['sxw','odt']:
fnct = self.create_source_odt
elif report_type in ['pdf','raw','html']:
fnct = self.create_source_pdf
elif report_type=='html2html':
fnct = self.create_source_html2html
else:
raise 'Unknown Report Type'
return fnct(cr, uid, ids, data, report_xml, context)
def create_source_odt(self, cr, uid, ids, data, report_xml, context=None):
return self.create_single_odt(cr, uid, ids, data, report_xml, context or {})
def create_source_html2html(self, cr, uid, ids, data, report_xml, context=None):
return self.create_single_html2html(cr, uid, ids, data, report_xml, context or {})
def create_source_pdf(self, cr, uid, ids, data, report_xml, context=None):
if not context:
context={}
pool = pooler.get_pool(cr.dbname)
attach = report_xml.attachment
if attach:
objs = self.getObjects(cr, uid, ids, context)
results = []
@ -557,7 +393,7 @@ class report_sxw(report_rml):
d = base64.decodestring(brow_rec.datas)
results.append((d,'pdf'))
continue
result = self.create_single(cr, uid, [obj.id], data, report_xml, context)
result = self.create_single_pdf(cr, uid, [obj.id], data, report_xml, context)
try:
if aname:
name = aname+'.'+result[1]
@ -578,7 +414,6 @@ class report_sxw(report_rml):
if results:
if results[0][1]=='pdf':
from pyPdf import PdfFileWriter, PdfFileReader
import cStringIO
output = PdfFileWriter()
for r in results:
reader = PdfFileReader(cStringIO.StringIO(r[0]))
@ -587,95 +422,102 @@ class report_sxw(report_rml):
s = cStringIO.StringIO()
output.write(s)
return s.getvalue(), results[0][1]
return self.create_single(cr, uid, ids, data, report_xml, context)
return self.create_single_pdf(cr, uid, ids, data, report_xml, context)
def create_single(self, cr, uid, ids, data, report_xml, context={}):
def create_single_pdf(self, cr, uid, ids, data, report_xml, context={}):
logo = None
context = context.copy()
pool = pooler.get_pool(cr.dbname)
want_header = self.header
title = report_xml.name
attach = report_xml.attachment
report_type = report_xml.report_type
want_header = report_xml.header
rml = report_xml.report_rml_content
rml_parser = self.parser(cr, uid, self.name2, context)
objs = self.getObjects(cr, uid, ids, context)
rml_parser.set_context(objs, data, ids, report_xml.report_type)
processed_rml = self.preprocess_rml(etree.XML(rml),report_xml.report_type)
if report_xml.header:
rml_parser._add_header(processed_rml)
if rml_parser.logo:
logo = base64.decodestring(rml_parser.logo)
create_doc = self.generators[report_xml.report_type]
pdf = create_doc(etree.tostring(processed_rml),rml_parser.localcontext,logo,title.encode('utf8'))
return (pdf, report_xml.report_type)
if report_type in ['sxw','odt']:
context['parents'] = sxw_parents
sxw_io = StringIO.StringIO(report_xml.report_sxw_content)
sxw_z = zipfile.ZipFile(sxw_io, mode='r')
rml = sxw_z.read('content.xml')
meta = sxw_z.read('meta.xml')
sxw_z.close()
def create_single_odt(self, cr, uid, ids, data, report_xml, context={}):
context = context.copy()
report_type = report_xml.report_type
context['parents'] = sxw_parents
sxw_io = StringIO.StringIO(report_xml.report_sxw_content)
sxw_z = zipfile.ZipFile(sxw_io, mode='r')
rml = sxw_z.read('content.xml')
meta = sxw_z.read('meta.xml')
sxw_z.close()
rml_parser = self.parser(cr, uid, self.name2, context)
rml_parser.parents = sxw_parents
rml_parser.tag = sxw_tag
objs = self.getObjects(cr, uid, ids, context)
rml_parser.set_context(objs, data, ids,report_xml.report_type)
rml_dom_meta = node = etree.XML(meta)
elements = node.findall(rml_parser.localcontext['name_space']["meta"]+"user-defined")
for pe in elements:
if pe.get(rml_parser.localcontext['name_space']["meta"]+"name"):
if pe.get(rml_parser.localcontext['name_space']["meta"]+"name") == "Info 3":
pe.getchildren()[0].text=data['id']
if pe.get(rml_parser.localcontext['name_space']["meta"]+"name") == "Info 4":
pe.getchildren()[0].text=data['model']
meta = etree.tostring(rml_dom_meta)
rml_dom = etree.XML(rml)
rml_dom = self.preprocess_rml(rml_dom,report_type)
create_doc = self.generators[report_type]
odt = etree.tostring(create_doc(rml_dom, rml_parser.localcontext))
sxw_z = zipfile.ZipFile(sxw_io, mode='a')
sxw_z.writestr('content.xml', "<?xml version='1.0' encoding='UTF-8'?>" + \
odt)
sxw_z.writestr('meta.xml', "<?xml version='1.0' encoding='UTF-8'?>" + \
meta)
if report_xml.header:
#Add corporate header/footer
rml = tools.file_open(os.path.join('base', 'report', 'corporate_%s_header.xml' % report_type)).read()
rml_parser = self.parser(cr, uid, self.name2, context)
rml_parser.parents = sxw_parents
rml_parser.tag = sxw_tag
objs = self.getObjects(cr, uid, ids, context)
rml_parser.preprocess(objs, data, ids)
rml_dom = xml.dom.minidom.parseString(rml)
rml_parser.set_context(objs, data, ids, report_xml.report_type)
rml_dom = self.preprocess_rml(etree.XML(rml),report_type)
create_doc = self.generators[report_type]
odt = create_doc(rml_dom,rml_parser.localcontext)
if report_xml.header:
rml_parser._add_header(odt)
odt = etree.tostring(odt)
sxw_z.writestr('styles.xml',"<?xml version='1.0' encoding='UTF-8'?>" + \
odt)
sxw_z.close()
final_op = sxw_io.getvalue()
sxw_io.close()
return (final_op, report_type)
def create_single_html2html(self, cr, uid, ids, data, report_xml, context={}):
context = context.copy()
report_type = 'html'
context['parents'] = html_parents
node = rml_dom.documentElement
rml = report_xml.report_rml_content
elements = node.getElementsByTagName("text:p")
rml_parser = self.parser(cr, uid, self.name2, context)
rml_parser.parents = html_parents
rml_parser.tag = sxw_tag
objs = self.getObjects(cr, uid, ids, context)
rml_parser.set_context(objs, data, ids, report_type)
for pe in elements:
e = pe.getElementsByTagName("text:drop-down")
for de in e:
pp=de.parentNode
for cnd in de.childNodes:
if cnd.nodeType in (cnd.CDATA_SECTION_NODE, cnd.TEXT_NODE):
pe.appendChild(cnd)
pp.removeChild(de)
rml_dom = etree.HTML(rml)
rml_dom = self.preprocess_rml(rml_dom,'html2html')
create_doc = self.generators['html2html']
html = etree.tostring(create_doc(rml_dom, rml_parser.localcontext))
# Add Information : Resource ID and Model
rml_dom_meta = xml.dom.minidom.parseString(meta)
node = rml_dom_meta.documentElement
elements = node.getElementsByTagName("meta:user-defined")
for pe in elements:
if pe.hasAttribute("meta:name"):
if pe.getAttribute("meta:name") == "Info 3":
pe.childNodes[0].data=data['id']
if pe.getAttribute("meta:name") == "Info 4":
pe.childNodes[0].data=data['model']
meta = rml_dom_meta.documentElement.toxml('utf-8')
return (html, report_type)
rml2 = rml_parser._parse(rml_dom, objs, data, header=want_header)
sxw_z = zipfile.ZipFile(sxw_io, mode='a')
sxw_z.writestr('content.xml', "<?xml version='1.0' encoding='UTF-8'?>" + \
rml2)
sxw_z.writestr('meta.xml', "<?xml version='1.0' encoding='UTF-8'?>" + \
meta)
if want_header:
#Add corporate header/footer
if report_type in ('odt', 'sxw'):
rml = tools.file_open(os.path.join('base', 'report', 'corporate_%s_header.xml' % report_type)).read()
rml_parser = self.parser(cr, uid, self.name2, context)
rml_parser.parents = sxw_parents
rml_parser.tag = sxw_tag
objs = self.getObjects(cr, uid, ids, context)
rml_parser.preprocess(objs, data, ids)
rml_dom = xml.dom.minidom.parseString(rml)
rml2 = rml_parser._parse(rml_dom, objs, data, header=want_header)
sxw_z.writestr('styles.xml',"<?xml version='1.0' encoding='UTF-8'?>" + \
rml2)
sxw_z.close()
rml2 = sxw_io.getvalue()
sxw_io.close()
else:
rml = report_xml.report_rml_content
context['parents'] = rml_parents
rml_parser = self.parser(cr, uid, self.name2, context)
rml_parser.parents = rml_parents
rml_parser.tag = rml_tag
objs = self.getObjects(cr, uid, ids, context)
rml_parser.preprocess(objs, data, ids)
rml_dom = xml.dom.minidom.parseString(rml)
rml2 = rml_parser._parse(rml_dom, objs, data, header=want_header)
if rml_parser.logo:
logo = base64.decodestring(rml_parser.logo)
create_doc = self.generators[report_type]
pdf = create_doc(rml2, logo, title.encode('utf8'))
return (pdf, report_type)

View File

@ -171,7 +171,7 @@ class db(netsvc.Service):
security.check_super(password)
logger = netsvc.Logger()
cmd = ['pg_dump', '--format=c']
cmd = ['pg_dump', '--format=c', '--no-owner']
if tools.config['db_user']:
cmd.append('--username=' + tools.config['db_user'])
if tools.config['db_host']:
@ -210,7 +210,7 @@ class db(netsvc.Service):
cr.close()
sql_db.close_db('template1')
cmd = ['pg_restore']
cmd = ['pg_restore', '--no-owner']
if tools.config['db_user']:
cmd.append('--username=' + tools.config['db_user'])
if tools.config['db_host']:

View File

@ -73,7 +73,7 @@ class Cursor(object):
@wraps(f)
def wrapper(self, *args, **kwargs):
if not '_obj' in self.__dict__:
if self.__closed:
raise psycopg2.ProgrammingError('Unable to use the cursor after having closed it')
return f(self, *args, **kwargs)
return wrapper
@ -83,6 +83,7 @@ class Cursor(object):
self._serialized = serialized
self._cnx = pool.getconn()
self._obj = self._cnx.cursor(cursor_factory=psycopg1cursor)
self.__closed = False
self.autocommit(False)
self.dbname = pool.dbname
@ -91,7 +92,7 @@ class Cursor(object):
self.__caller = tuple(stack()[2][1:3])
def __del__(self):
if '_obj' in self.__dict__ :
if not self.__closed:
if tools.config['log_level'] in (netsvc.LOG_DEBUG, netsvc.LOG_DEBUG_RPC):
# Oops. 'self' has not been closed explicitly.
# The cursor will be deleted by the garbage collector,
@ -117,6 +118,7 @@ class Cursor(object):
now = mdt.now()
try:
params = params or None
res = self._obj.execute(query, params)
except psycopg2.ProgrammingError, pe:
logger= netsvc.Logger()
@ -173,6 +175,7 @@ class Cursor(object):
# collected as fast as they should). The problem is probably due in
# part because browse records keep a reference to the cursor.
del self._obj
self.__closed = True
self._pool.putconn(self._cnx)
@check

View File

@ -37,6 +37,9 @@ class remote_contract(object):
except:
raise RemoteContractException("Unable to contact the migration server")
if not self.__userid:
raise RemoteContractException("Unable to contact the migration server")
self.__rpc = xmlrpclib.ServerProxy(self.__server + 'object')

View File

@ -388,8 +388,8 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
)
s.quit()
except Exception, e:
import logging
logging.getLogger().error(str(e))
import netsvc
netsvc.Logger().notifyChannel('email_send', netsvc.LOG_ERROR, e)
return False
return True

View File

@ -132,7 +132,7 @@ class interface(netsvc.Service):
# translate arch
if not isinstance(arch, UpdateableStr):
doc = dom.minidom.parseString(arch)
doc = dom.minidom.parseString(arch.encode('utf8'))
self.translate_view(cr, doc, state, lang)
arch = doc.toxml()

View File

@ -179,6 +179,7 @@ setup(name = name,
'openerp-server.report.render.rml2html',
'openerp-server.report.render.rml2txt',
'openerp-server.wizard',
'openerp-server.report.render.odt2odt',
'openerp-server.workflow'] + \
list(find_addons()),
package_dir = {'openerp-server': 'bin'},