diff --git a/bin/report/print_xml.py b/bin/report/print_xml.py index 03d22a70e18..e67108824b0 100644 --- a/bin/report/print_xml.py +++ b/bin/report/print_xml.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution +# OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved # $Id$ # @@ -21,12 +21,11 @@ ############################################################################## import os,types -from xml.dom import minidom - +from lxml import etree import netsvc import tools import print_fnc - +import copy from osv.orm import browse_null, browse_record import pooler @@ -35,7 +34,7 @@ class InheritDict(dict): def __init__(self, parent=None): self.parent = parent - + def __getitem__(self, name): if name in self: return super(InheritDict, self).__getitem__(name) @@ -51,36 +50,32 @@ def tounicode(val): elif isinstance(val, unicode): unicode_val = val else: - unicode_val = unicode(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.cr = cr self.pool = pooler.get_pool(cr.dbname) - self.doc = minidom.Document() self.func = func or {} self.datas = datas self.uid = uid self.bin_datas = {} def node_attrs_get(self, node): - attrs = {} - nattr = node.attributes - for i in range(nattr.length): - attr = nattr.item(i) - attrs[attr.localName] = attr.nodeValue -# attrs[attr.name] = attr.nodeValue - return attrs - + if len(node.attrib): + return node.attrib + return {} + def get_value(self, browser, field_path): fields = field_path.split('.') if not len(fields): return '' - + value = browser + for f in fields: if isinstance(value, list): if len(value)==0: @@ -90,12 +85,12 @@ class document(object): return '' else: value = value[f] - + if isinstance(value, browse_null) or (type(value)==bool and not value): return '' - else: + else: return value - + def get_value2(self, browser, field_path): value = self.get_value(browser, field_path) if isinstance(value, browse_record): @@ -104,10 +99,10 @@ class document(object): return False else: return value - + def eval(self, record, expr): #TODO: support remote variables (eg address.title) in expr -# how to do that: parse the string, find dots, replace those dotted variables by temporary +# how to do that: parse the string, find dots, replace those dotted variables by temporary # "simple ones", fetch the value of those variables and add them (temporarily) to the _data # dictionary passed to eval @@ -120,13 +115,6 @@ class document(object): return eval(expr, {}, {'obj': record}) def parse_node(self, node, parent, browser, datas=None): - # node is the node of the xml template to be parsed - # parent = the parent node in the xml data tree we are creating - - if node.nodeType == node.ELEMENT_NODE: - - # convert the attributes of the node to a dictionary - attrs = self.node_attrs_get(node) if 'type' in attrs: if attrs['type']=='field': @@ -134,28 +122,26 @@ class document(object): #TODO: test this if value == '' and 'default' in attrs: value = attrs['default'] - el = self.doc.createElement(node.localName) - parent.appendChild(el) - el_txt = self.doc.createTextNode(tounicode(value)) - el.appendChild(el_txt) - + el = etree.Element(node.tag) + parent.append(el) + el.text = tounicode(value) #TODO: test this for key, value in attrs.iteritems(): if key not in ('type', 'name', 'default'): - el.setAttribute(key, value) + el.set(key, value) elif attrs['type']=='attachment': if isinstance(browser, list): model = browser[0]._table_name - else: + else: model = browser._table_name value = self.get_value(browser, attrs['name']) - + service = netsvc.LocalService("object_proxy") ids = service.execute(self.cr.dbname, self.uid, 'ir.attachment', 'search', [('res_model','=',model),('res_id','=',int(value))]) datas = service.execute(self.cr.dbname, self.uid, 'ir.attachment', 'read', ids) - + if len(datas): # if there are several, pick first datas = datas[0] @@ -169,37 +155,31 @@ class document(object): fp.write(dt) i = str(len(self.bin_datas)) self.bin_datas[i] = fp - - el = self.doc.createElement(node.localName) - parent.appendChild(el) - # node content is the length of the image - el_txt = self.doc.createTextNode(i) - el.appendChild(el_txt) - + el = etree.Element(node.tag) + el.text = i + parent.append(el) + elif attrs['type']=='data': #TODO: test this - el = self.doc.createElement(node.localName) - parent.appendChild(el) txt = self.datas.get('form', {}).get(attrs['name'], '') - el_txt = self.doc.createTextNode(tounicode(txt)) - el.appendChild(el_txt) + el = etree.Element(node.tag) + el.text = txt + parent.append(el) elif attrs['type']=='function': - el = self.doc.createElement(node.localName) - parent.appendChild(el) if attrs['name'] in self.func: txt = self.func[attrs['name']](node) else: txt = print_fnc.print_fnc(attrs['name'], node) - el_txt = self.doc.createTextNode(txt) - el.appendChild(el_txt) + el = etree.Element(node.tag) + el.text = txt + parent.append(el) elif attrs['type']=='eval': - el = self.doc.createElement(node.localName) - parent.appendChild(el) value = self.eval(browser, attrs['expr']) - el_txt = self.doc.createTextNode(str(value)) - el.appendChild(el_txt) + el = etree.Element(node.tag) + el.text = str(value) + parent.append(el) elif attrs['type']=='fields': fields = attrs['name'].split(',') @@ -216,26 +196,24 @@ class document(object): keys.reverse() v_list = [vals[k] for k in keys] - for v in v_list: - el = self.doc.createElement(node.localName) - parent.appendChild(el) - el_cld = node.firstChild - while el_cld: + for v in v_list: + el = etree.Element(node.tag) + parent.append(el) + for el_cld in node: self.parse_node(el_cld, el, v) - el_cld = el_cld.nextSibling elif attrs['type']=='call': if len(attrs['args']): -#TODO: test this +#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 attrs.has_key('model'): obj = self.pool.get(attrs['model']) - else: + else: if isinstance(browser, list): obj = browser[0]._table else: @@ -244,38 +222,28 @@ class document(object): # get the ids if attrs.has_key('ids'): ids = self.eval(browser, attrs['ids']) - else: + else: if isinstance(browser, list): - ids = [b.id for b in browser] + ids = [b.id for b in browser] else: ids = [browser.id] - + # call the method itself newdatas = getattr(obj, attrs['name'])(self.cr, self.uid, ids, *args) - + def parse_result_tree(node, parent, datas): - if node.nodeType == node.ELEMENT_NODE: - el = self.doc.createElement(node.localName) - parent.appendChild(el) + el = etree.Element(node.tag) + parent.append(el) atr = self.node_attrs_get(node) if 'value' in atr: if not isinstance(datas[atr['value']], (str, unicode)): - txt = self.doc.createTextNode(str(datas[atr['value']])) + txt = str(datas[atr['value']]) else: -# txt = self.doc.createTextNode(datas[atr['value']].decode('utf-8')) - txt = self.doc.createTextNode(datas[atr['value']]) - el.appendChild(txt) + txt = datas[atr['value']] + el.append(txt) else: - el_cld = node.firstChild - while el_cld: + for el_cld in node: parse_result_tree(el_cld, el, datas) - el_cld = el_cld.nextSibling - elif node.nodeType==node.TEXT_NODE: - el = self.doc.createTextNode(node.nodeValue) - parent.appendChild(el) - else: - pass - if not isinstance(newdatas, list): newdatas = [newdatas] for newdata in newdatas: @@ -283,50 +251,38 @@ class document(object): 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: - el = self.doc.createElement(node.localName) - parent.appendChild(el) - el_cld = node.firstChild - while el_cld: + el = etree.Element(node.tag) + parent.append(el) + for el_cld in node: self.parse_node(el_cld, el, v) - el_cld = el_cld.nextSibling else: # if there is no "type" attribute in the node, copy it to the xml data and parse its childs - el = self.doc.createElement(node.localName) - parent.appendChild(el) - el_cld = node.firstChild - while el_cld: - self.parse_node(el_cld, el, browser) - el_cld = el_cld.nextSibling - - elif node.nodeType==node.TEXT_NODE: - # if it's a text node, copy it to the xml data - el = self.doc.createTextNode(node.nodeValue) - parent.appendChild(el) - else: - pass + for el_cld in node: + self.parse_node(el_cld, parent, browser) def xml_get(self): - return self.doc.toxml('utf-8') + #return self.doc.toxml('utf-8') + return etree.tostring(self.doc,encoding="utf-8",xml_declaration=True) def parse_tree(self, ids, model, context=None): if not context: context={} browser = self.pool.get(model).browse(self.cr, self.uid, ids, context) - self.parse_node(self.dom.documentElement, self.doc, browser) - + 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 = minidom.parseString(xml) - + self.dom = etree.XML(xml) + # create the xml data from the xml template self.parse_tree(ids, model, context) @@ -334,9 +290,8 @@ class document(object): if not context: context={} # parses the xml template to memory - self.dom = minidom.parseString(tools.file_open(filename).read()) - - # create the xml data from the xml template + self.dom = etree.XML(tools.file_open(filename).read()) + self.doc = etree.Element(self.dom.tag) self.parse_tree(ids, model, context) def close(self): diff --git a/bin/report/printscreen/ps_form.py b/bin/report/printscreen/ps_form.py index a294383f90f..ac9c499dda3 100644 --- a/bin/report/printscreen/ps_form.py +++ b/bin/report/printscreen/ps_form.py @@ -26,7 +26,6 @@ import tools from report import render from lxml import etree -from xml.dom import minidom import libxml2 import libxslt @@ -38,24 +37,19 @@ class report_printscreen_list(report_int): def _parse_node(self, root_node): result = [] - for node in root_node.getchildren(): + for node in root_node: if node.tag == 'field': - #attrsa = node.attributes attrsa = node.attrib - print "typppppp",type(attrsa),dir(attrsa) attrs = {} if not attrsa is None: - for key,val in attrsa.items(): + 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 = etree.XML(view) return self._parse_node(dom) @@ -85,16 +79,14 @@ class report_printscreen_list(report_int): 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)) @@ -119,20 +111,17 @@ class report_printscreen_list(report_int): s = fields[fields_order[pos]].get('size', 56) / 28 + 1 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(str(fields[f]['string'])) - field.appendChild(field_txt) - header.appendChild(field) - - new_doc.childNodes[0].appendChild(header) - - lines = new_doc.createElement("lines") + field = etree.Element("field") + field.text = fields[f]['string'] or '' + header.append(field) + new_doc.append(header) + lines = etree.Element("lines") for line in results: - node_line = new_doc.createElement("row") + node_line = etree.Element("row") for f in fields_order: if fields[f]['type']=='many2one' and line[f]: line[f] = line[f][1] @@ -141,16 +130,15 @@ class report_printscreen_list(report_int): if fields[f]['type'] == 'float': precision=(('digits' in fields[f]) and fields[f]['digits'][1]) or 2 line[f]=round(line[f],precision) - col = new_doc.createElement("col") - col.setAttribute('tree','no') + col = etree.Element("col") + col.set('tree','no') if line[f] != None: - txt = new_doc.createTextNode(str(line[f] or '')) + col.text = tools.ustr(line[f] or '') else: - txt = new_doc.createTextNode('/') - col.appendChild(txt) - node_line.appendChild(col) - lines.appendChild(node_line) - new_doc.childNodes[0].appendChild(lines) + col.text = '/' + node_line.append(col) + lines.append(node_line) + new_doc.append(node_line) styledoc = libxml2.parseFile(os.path.join(tools.config['root_path'],'addons/base/report/custom_new.xsl')) style = libxslt.parseStylesheetDoc(styledoc) diff --git a/bin/service/web_services.py b/bin/service/web_services.py index 1fb201dcd90..f5ad5e402e1 100644 --- a/bin/service/web_services.py +++ b/bin/service/web_services.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution +# OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved # $Id$ # @@ -20,7 +20,7 @@ # ############################################################################## -import base64 +import base64 import logging import os import security @@ -258,7 +258,7 @@ class db(netsvc.Service): fs = os.path.join(tools.config['root_path'], 'filestore') if os.path.exists(os.path.join(fs, old_name)): os.rename(os.path.join(fs, old_name), os.path.join(fs, new_name)) - + logger.notifyChannel("web-services", netsvc.LOG_INFO, 'RENAME DB: %s -> %s' % (old_name, new_name)) finally: @@ -326,7 +326,7 @@ class db(netsvc.Service): try: l.notifyChannel('migration', netsvc.LOG_INFO, 'migrate database %s' % (db,)) tools.config['update']['base'] = True - pooler.restart_pool(db, force_demo=False, update_module=True) + pooler.restart_pool(db, force_demo=False, update_module=True) except except_orm, inst: self.abortResponse(1, inst.name, 'warning', inst.value) except except_osv, inst: @@ -352,6 +352,7 @@ class common(netsvc.Service): self.exportMethod(self.timezone_get) self.exportMethod(self.get_available_updates) self.exportMethod(self.get_migration_scripts) + self.exportMethod(self.get_server_environment) def ir_set(self, db, uid, password, keys, args, name, value, replace=True, isobject=False): security.check(db, uid, password) @@ -416,36 +417,36 @@ GNU Public Licence. def timezone_get(self, db, login, password): return time.tzname[0] - + def get_available_updates(self, password, contract_id, contract_password): security.check_super(password) import tools.maintenance as tm try: rc = tm.remote_contract(contract_id, contract_password) if not rc.id: - raise tm.RemoteContractException('This contract does not exist or is not active') - + raise tm.RemoteContractException('This contract does not exist or is not active') + return rc.get_available_updates(rc.id, addons.get_modules_with_version()) except tm.RemoteContractException, e: self.abortResponse(1, 'Migration Error', 'warning', str(e)) - + def get_migration_scripts(self, password, contract_id, contract_password): security.check_super(password) l = netsvc.Logger() import tools.maintenance as tm - try: + try: rc = tm.remote_contract(contract_id, contract_password) if not rc.id: - raise tm.RemoteContractException('This contract does not exist or is not active') + raise tm.RemoteContractException('This contract does not exist or is not active') if rc.status != 'full': raise tm.RemoteContractException('Can not get updates for a partial contract') l.notifyChannel('migration', netsvc.LOG_INFO, 'starting migration with contract %s' % (rc.name,)) zips = rc.retrieve_updates(rc.id, addons.get_modules_with_version()) - + from shutil import rmtree, copytree, copy backup_directory = os.path.join(tools.config['root_path'], 'backup', time.strftime('%Y-%m-%d-%H-%M')) @@ -503,7 +504,29 @@ GNU Public Licence. tb_s = reduce(lambda x, y: x+y, traceback.format_exception( sys.exc_type, sys.exc_value, sys.exc_traceback)) l.notifyChannel('migration', netsvc.LOG_ERROR, tb_s) raise - + + def get_server_environment(self,lang=False): + try: + if '.bzr' in os.listdir((os.getcwd()[0:-3])): + fp = open(os.path.join(os.getcwd()[0:-3],'.bzr/branch/last-revision')) + rev_no = fp.read() + fp.close() + else: + rev_no = 'Bazaar Not Installed !' + except: + rev_no = 'Bazaar Not Installed !' + if not lang: + lang = os.environ.get('LANG', '').split('.')[0] + environment = 'Environment_Information : \n' \ + 'Operating System : %s\n' \ + 'PlatForm : %s\n' \ + 'Operating System Version : %s\n' \ + 'Python Version : %s\n'\ + 'Locale : %s\n' \ + 'OpenERP-Server Version : %s\n'\ + 'OpenERP-Server Last Revision ID : %s' \ + %(os.name,sys.platform,str(sys.version.split('\n')[1]),str(sys.version[0:5]), lang, release.version,rev_no) + return environment common() class objects_proxy(netsvc.Service): @@ -637,6 +660,7 @@ class report_spool(netsvc.Service): tb = sys.exc_info() tb_s = "".join(traceback.format_exception(*tb)) logger = netsvc.Logger() + logger.notifyChannel('web-services', netsvc.LOG_ERROR,common().get_server_environment(context.get('lang',False))) logger.notifyChannel('web-services', netsvc.LOG_ERROR, 'Exception: %s\n%s' % (str(exception), tb_s)) self._reports[id]['exception'] = ExceptionWithTraceback(tools.exception_to_unicode(exception), tb)