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

Conflicts:

	bin/addons/base/ir/ir_actions.py
	bin/netsvc.py
	bin/report/report_sxw.py
	bin/tools/translate.py

bzr revid: p_christ@hol.gr-20081218164925-uarehzvo3ocu0x2w
This commit is contained in:
P. Christeas
2008-12-18 18:49:25 +02:00
27 changed files with 1054 additions and 733 deletions
+87 -77
View File
@@ -24,6 +24,7 @@ import os, sys, imp
from os.path import join as opj
import itertools
from sets import Set
import zipimport
import osv
import tools
@@ -268,25 +269,32 @@ def init_module_objects(cr, module_name, obj_list):
t[1](cr, *t[2])
cr.commit()
#
# Register module named m, if not already registered
#
def register_class(m):
"""
Register module named m, if not already registered
"""
global loaded
if m in loaded:
return
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: registering objects' % m)
loaded.append(m)
mod_path = get_module_path(m)
if not os.path.isfile(mod_path+'.zip'):
imp.load_module(m, *imp.find_module(m, [ad, _ad]))
else:
import zipimport
try:
zimp = zipimport.zipimporter(mod_path+'.zip')
try:
zip_mod_path = mod_path + '.zip'
if not os.path.isfile(zip_mod_path):
imp.load_module(m, *imp.find_module(m, [ad, _ad]))
else:
zimp = zipimport.zipimporter(zip_mod_path)
zimp.load_module(m)
except zipimport.ZipImportError:
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Couldn\'t find module %s' % m)
except zipimport.ZipImportError:
logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'Couldn\'t find zip module %s' % m)
raise
except ImportError:
logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'Couldn\'t find module %s' % m)
raise
except Exception:
logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'Couldn\'t find module %s' % (m))
raise
class MigrationManager(object):
@@ -535,84 +543,86 @@ def load_module_graph(cr, graph, status=None, check_access_rules=True, **kwargs)
def load_modules(db, force_demo=False, status=None, update_module=False):
if not status:
status={}
cr = db.cursor()
force = []
if force_demo:
force.append('demo')
pool = pooler.get_pool(cr.dbname)
report = tools.assertion_report()
if update_module:
basegraph = create_graph(['base'], force)
load_module_graph(cr, basegraph, status, check_access_rules=False, report=report)
try:
report = tools.assertion_report()
if update_module:
basegraph = create_graph(['base'], force)
load_module_graph(cr, basegraph, status, check_access_rules=False, report=report)
modobj = pool.get('ir.module.module')
logger.notifyChannel('init', netsvc.LOG_INFO, 'updating modules list')
modobj.update_list(cr, 1)
modobj = pool.get('ir.module.module')
logger.notifyChannel('init', netsvc.LOG_INFO, 'updating modules list')
modobj.update_list(cr, 1)
mods = [k for k in tools.config['init'] if tools.config['init'][k]]
if mods:
ids = modobj.search(cr, 1, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)])
if ids:
modobj.button_install(cr, 1, ids)
mods = [k for k in tools.config['init'] if tools.config['init'][k]]
if mods:
ids = modobj.search(cr, 1, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)])
if ids:
modobj.button_install(cr, 1, ids)
mods = [k for k in tools.config['update'] if tools.config['update'][k]]
if mods:
ids = modobj.search(cr, 1, ['&',('state', '=', 'installed'), ('name', 'in', mods)])
if ids:
modobj.button_upgrade(cr, 1, ids)
cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base'))
cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade')")
else:
cr.execute("select name from ir_module_module where state in ('installed', 'to upgrade')")
module_list = [name for (name,) in cr.fetchall()]
graph = create_graph(module_list, force)
mods = [k for k in tools.config['update'] if tools.config['update'][k]]
if mods:
ids = modobj.search(cr, 1, ['&',('state', '=', 'installed'), ('name', 'in', mods)])
if ids:
modobj.button_upgrade(cr, 1, ids)
cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base'))
cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade')")
else:
cr.execute("select name from ir_module_module where state in ('installed', 'to upgrade')")
module_list = [name for (name,) in cr.fetchall()]
graph = create_graph(module_list, force)
# the 'base' module has already been updated
base = graph['base']
base.state = 'installed'
for kind in ('init', 'demo', 'update'):
if hasattr(base, kind):
delattr(base, kind)
# the 'base' module has already been updated
base = graph['base']
base.state = 'installed'
for kind in ('init', 'demo', 'update'):
if hasattr(base, kind):
delattr(base, kind)
load_module_graph(cr, graph, status, report=report)
if report.get_report():
logger.notifyChannel('init', netsvc.LOG_INFO, report)
load_module_graph(cr, graph, status, report=report)
if report.get_report():
logger.notifyChannel('init', netsvc.LOG_INFO, report)
for kind in ('init', 'demo', 'update'):
tools.config[kind]={}
for kind in ('init', 'demo', 'update'):
tools.config[kind]={}
cr.commit()
if update_module:
cr.execute("select id,name from ir_module_module where state in ('to remove')")
for mod_id, mod_name in cr.fetchall():
pool = pooler.get_pool(cr.dbname)
cr.execute('select model,res_id from ir_model_data where not noupdate and module=%s order by id desc', (mod_name,))
for rmod,rid in cr.fetchall():
uid = 1
pool.get(rmod).unlink(cr, uid, [rid])
cr.commit()
#
# TODO: remove menu without actions of childs
#
while True:
cr.execute('''delete from
ir_ui_menu
where
(id not in (select parent_id from ir_ui_menu where parent_id is not null))
and
(id not in (select res_id from ir_values where model='ir.ui.menu'))
and
(id not in (select res_id from ir_model_data where model='ir.ui.menu'))''')
if not cr.rowcount:
break
else:
logger.notifyChannel('init', netsvc.LOG_INFO, 'removed %d unused menus' % (cr.rowcount,))
cr.execute("update ir_module_module set state=%s where state in ('to remove')", ('uninstalled', ))
cr.commit()
#pooler.restart_pool(cr.dbname)
cr.close()
if update_module:
cr.execute("select id,name from ir_module_module where state in ('to remove')")
for mod_id, mod_name in cr.fetchall():
pool = pooler.get_pool(cr.dbname)
cr.execute('select model,res_id from ir_model_data where not noupdate and module=%s order by id desc', (mod_name,))
for rmod,rid in cr.fetchall():
uid = 1
pool.get(rmod).unlink(cr, uid, [rid])
cr.commit()
#
# TODO: remove menu without actions of childs
#
while True:
cr.execute('''delete from
ir_ui_menu
where
(id not in (select parent_id from ir_ui_menu where parent_id is not null))
and
(id not in (select res_id from ir_values where model='ir.ui.menu'))
and
(id not in (select res_id from ir_model_data where model='ir.ui.menu'))''')
if not cr.rowcount:
break
else:
logger.notifyChannel('init', netsvc.LOG_INFO, 'removed %d unused menus' % (cr.rowcount,))
cr.execute("update ir_module_module set state=%s where state in ('to remove')", ('uninstalled', ))
cr.commit()
finally:
cr.close()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+1 -1
View File
@@ -19,7 +19,7 @@
<field name="view_id" ref="view_menu"/>
<field name="res_model">ir.ui.menu</field>
<field name="view_type">tree</field>
<field eval="'[(\'parent_id\',\'=\',False)]'" name="domain"/>
<field name="domain">[('parent_id', '=', False)]</field>
</record>
<record id="lang_en" model="res.lang">
File diff suppressed because it is too large Load Diff
+39 -12
View File
@@ -325,12 +325,25 @@
</record>
<menuitem action="ir_action_window" id="menu_ir_action_window" parent="base.next_id_6"/>
<record id="act_wizard_view" model="ir.ui.view">
<record id="act_wizard_view_tree" model="ir.ui.view">
<field name="name">ir.actions.wizard.tree</field>
<field name="model">ir.actions.wizard</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Wizard">
<field name="name" select="1"/>
<field name="wiz_name" select="1"/>
<field name="multi"/>
</tree>
</field>
</record>
<record id="act_wizard_view" model="ir.ui.view">
<field name="name">ir.actions.wizard</field>
<field name="model">ir.actions.wizard</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Wizard">
<form string="Wizards">
<field name="name" select="1"/>
<field name="type" select="1"/>
<field name="wiz_name" select="1"/>
@@ -341,7 +354,7 @@
</record>
<record id="ir_action_wizard" model="ir.actions.act_window">
<field name="name">Wizard</field>
<field name="name">Wizards</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">ir.actions.wizard</field>
<field name="view_type">form</field>
@@ -688,9 +701,9 @@
<group colspan="2" col="2">
<separator string="Field Type" colspan="2"/>
<field name="ttype" select="2"/>
<field name="relation_id" select="2" attrs="{'required': [('ttype','in',['many2one','one2many','many2many'])],
<field name="relation" attrs="{'required': [('ttype','in',['many2one','one2many','many2many'])],
'readonly': [('ttype','!=','one2many'), ('ttype','!=','many2one'), ('ttype','!=','many2many')]}"/>
<field name="relation_field_id" domain="[('model_id','=',relation_id)]" attrs="{'required': [('ttype','=','one2many')],
<field name="relation_field" attrs="{'required': [('ttype','=','one2many')],
'readonly': [('ttype','!=','one2many')]}"/>
<field name="selection" attrs="{'required': [('ttype','=','selection')], 'readonly': [('ttype','!=','selection')]}"/>
<field name="size" attrs="{'required': [('ttype','=','char')], 'readonly': [('ttype','!=','char')]}"/>
@@ -767,12 +780,9 @@
<page string="Properties">
<group colspan="2" col="2">
<field name="ttype" select="2"/>
<field name="relation_id" select="2" on_change="on_relation_change(relation_id)" attrs="{'required': [('ttype','in', ['many2one','one2many','many2many'])],
<field name="relation" select="2" attrs="{'required': [('ttype','in', ['many2one','one2many','many2many'])],
'readonly': [('ttype','not in', ['many2one','one2many','many2many'])]}"/>
<!-- <field name="relation" select="2" attrs="{'required': [('ttype','in', ['many2one','one2many','many2many'])],-->
<!-- 'readonly': [('ttype','not in', ['many2one','one2many','many2many'])]}"/>-->
<field name="relation_field_id" domain="[('model_id','=',relation_id)]" attrs="{'required': [('ttype','=','one2many')],
'readonly': [('ttype','!=','one2many')]}"/>
<field name="relation_field" attrs="{'required': [('ttype','=','one2many')], 'readonly': [('ttype','!=','one2many')]}"/>
<field name="selection" attrs="{'required': [('ttype','=','selection')], 'readonly': [('ttype','!=','selection')]}"/>
<field name="size" attrs="{'required': [('ttype','=','char')], 'readonly': [('ttype','!=','char')]}"/>
<field name="state"/>
@@ -1142,7 +1152,14 @@
<field name="state" select="1"/>
<field name="model_id" select="1"/>
<field name="sequence" select="2"/>
<field name="condition" colspan="4"/>
<notebook colspan="4">
<page string="Python Code" attrs="{'invisible':[('state','!=','code')]}">
<separator colspan="4" string="Python Code"/>
<field name="code" colspan="4" nolabel="1"/>
</page>
<page string="Trigger" attrs="{'invisible':[('state','!=','trigger')]}">
<separator colspan="4" string="Trigger Configuration"/>
<field name="wkf_model_id"/>
@@ -1157,6 +1174,7 @@
<page string="Email Configuration" attrs="{'invisible':[('state','!=','email')]}">
<separator colspan="4" string="Email Configuration"/>
<field name="email" domain="[('model_id','=',model_id)]"/>
<field name="subject" colspan="4"/>
<field name="message" select="2" colspan="4"/>
<newline/>
<label colspan="4" string="Access all the fields related to the current object using expression in double brackets, i.e. [[ object.partner_id.name ]]" align="0.0"/>
@@ -1172,7 +1190,7 @@
<page string="Create / Write" attrs="{'invisible':[('state','!=','object_create'),('state','!=','object_write')]}">
<separator colspan="4" string="Fields Mapping"/>
<field name="srcmodel_id" select="2"/>
<field name="srcmodel_id" select="2" attrs="{'required':[('state','!=','dummy'), ('state','!=','sms'), ('state','!=','code'), ('state','!=','loop'),('state','!=','trigger'), ('state','!=','client_action'), ('state','!=','email'), ('state','!=','sms'), ('state','!=','other')]}"/>
<field name="fields_lines" nolabel="1" select="2" colspan="4">
<tree string="Field Mappings" editable="top">
<field name="col1" domain="[('model_id','=',parent.srcmodel_id or parent.model_id)]"/>
@@ -1185,10 +1203,18 @@
<field name="value" colspan="4"/>
</form>
</field>
<field name="record_id" attrs="{'invisible':[('state','!=','object_create')]}" domain="[('model_id','in',[model_id])]"/>
<field name="record_id" attrs="{'readonly':[('state','!=','object_create')]}" domain="[('model_id','in',[model_id])]"/>
<field name="write_id" attrs="{'readonly':[('state','!=','object_write')]}"/>
<label colspan="4" string="If you use a formula type, use a python expression using the variable 'object'." align="0.0"/>
</page>
<page string="Iteration Actions" attrs="{'invisible':[('state','!=','loop')]}">
<separator colspan="4" string="Iteration Action Configuration"/>
<field name="loop_action" domain="[('state','!=','loop')]"/>
<field name="expression" attrs="{'required':[('state','=','loop')]}"/>
<label colspan="4" string="Define the expression that generate a list" align="0.0"/>
</page>
<page string="Multi Actions" attrs="{'invisible':[('state','!=','other')]}">
<separator colspan="4" string="Other Actions Configuration"/>
<field name="child_ids" nolabel="1" colspan="4"/>
@@ -1210,6 +1236,7 @@
<tree string="Server Actions">
<field name="name"/>
<field name="state"/>
<field name="sequence"/>
</tree>
</field>
</record>
+90 -30
View File
@@ -365,12 +365,7 @@ server_object_lines()
# Actions that are run on the server side
#
class actions_server(osv.osv):
def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False):
res = super(actions_server, self).fields_view_get(cr, user, view_id, view_type, context, toolbar)
#print 'RES : ',res
return res
def _select_signals(self, cr, uid, context={}):
cr.execute("select distinct t.signal as key, t.signal || ' - [ ' || w.osv || ' ] ' as val from wkf w, wkf_activity a, wkf_transition t "\
" where w.id = a.wkf_id " \
@@ -386,52 +381,62 @@ class actions_server(osv.osv):
_name = 'ir.actions.server'
_table = 'ir_act_server'
_sequence = 'ir_actions_id_seq'
_order = 'sequence'
_columns = {
'name': fields.char('Action Name', required=True, size=64),
'condition' : fields.char('Condition', size=256),
'sub_condition' : fields.char('Condition', size=256),
'state': fields.selection([
('client_action','Client Action'),
('dummy','Dummy'),
('loop','Iteration'),
('code','Python Code'),
('trigger','Trigger'),
('email','Email'),
('sms','SMS'),
('object_create','Create Object'),
('object_write','Write Object'),
('other','Multi Actions'),
], 'Action State', required=True, size=32),
'code': fields.text('Python Code'),
], 'Action Type', required=True, size=32),
'code':fields.text('Python Code'),
'sequence': fields.integer('Sequence'),
'model_id': fields.many2one('ir.model', 'Object', required=True),
'action_id': fields.many2one('ir.actions.actions', 'Client Action'),
'trigger_name': fields.selection(_select_signals, string='Trigger Name', size=128),
'wkf_model_id': fields.many2one('ir.model', 'Workflow on'),
'trigger_obj_id': fields.many2one('ir.model.fields','Trigger On'),
'email': fields.many2one('ir.model.fields', 'Contact'),
'email': fields.char('Email Address', size=512),
'subject': fields.char('Subject', size=1024, translate=True),
'message': fields.text('Message', translate=True),
'mobile': fields.many2one('ir.model.fields', 'Contact'),
'mobile': fields.char('Mobile No', size=512),
'sms': fields.char('SMS', size=160, translate=True),
'child_ids': fields.many2many('ir.actions.server', 'rel_server_actions', 'server_id', 'action_id', 'Others Actions'),
'usage': fields.char('Action Usage', size=32),
'type': fields.char('Action Type', size=32, required=True),
'srcmodel_id': fields.many2one('ir.model', 'Model', help="In which object you want to create / write the object if its empty refer to the Object field"),
'fields_lines': fields.one2many('ir.server.object.lines', 'server_id', 'Fields Mapping'),
'record_id':fields.many2one('ir.model.fields', 'Record Id', help="privide the field name from where the record id refers, if its empty it will refer to the active id of the object")
'record_id':fields.many2one('ir.model.fields', 'Create Id', help="Provide the field name from where the record id stores after the create operations, if its empty, you can not track the new record"),
'write_id':fields.char('Write Id', size=256, help="Provide the field name from where the record id refer for the write operation, if its empty it will refer to the active id of the object"),
'loop_action':fields.many2one('ir.actions.server', 'Loop Action'),
'expression':fields.char('Loop Expression', size=512),
}
_defaults = {
'state': lambda *a: 'dummy',
'condition': lambda *a: 'True',
'sub_condition': lambda *a: 'True',
'type': lambda *a: 'ir.actions.server',
'sequence': lambda *a: 5,
'code': lambda *a: """# You can use the following variables
'code': lambda *a: """# You can use the following variables
# - object
# - object2
# - time
# - cr
# - uid
# - ids
# If you plan to return an action, assign: saction = {...}
# If you plan to return an action, assign: action = {...}
""",
}
def get_email(self, cr, uid, action, context):
logger = netsvc.Logger()
obj_pool = self.pool.get(action.model_id.model)
@@ -453,7 +458,6 @@ class actions_server(osv.osv):
return obj
def get_mobile(self, cr, uid, action, context):
logger = netsvc.Logger()
obj_pool = self.pool.get(action.model_id.model)
@@ -498,15 +502,31 @@ class actions_server(osv.osv):
# OUT:
# False : Finnished correctly
# ACTION_ID : Action to launch
def run(self, cr, uid, ids, context={}):
logger = netsvc.Logger()
for action in self.browse(cr, uid, ids, context):
obj_pool = self.pool.get(action.model_id.model)
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
cxt = {
'context':context,
'object': obj,
'time':time,
'cr': cr,
'pool' : self.pool,
'uid' : uid
}
expr = eval(str(action.condition), cxt)
if not expr:
continue
if action.state=='client_action':
if not action.action_id:
raise osv.except_osv(_('Error'), _("Please specify an action to launch !"))
return self.pool.get(action.action_id.type).read(cr, uid, action.action_id.id, context=context)
raise osv.except_osv(_('Error'), _("Please specify an action to launch !"))
result = self.pool.get(action.action_id.type).read(cr, uid, action.action_id.id, context=context)
return result
if action.state=='python':
localdict = {
'self': self.pool.get(action.model_id.model),
@@ -522,14 +542,20 @@ class actions_server(osv.osv):
if action.state == 'email':
user = config['email_from']
subject = action.name
address = self.get_email(cr, uid, action, context)
address = str(action.email)
try:
address = eval(str(action.email), cxt)
except:
pass
if not address:
raise osv.except_osv(_('Error'), _("Please specify the Partner Email address !"))
if not user:
raise osv.except_osv(_('Error'), _("Please specify server option --smtp-from !"))
subject = self.merge_message(cr, uid, str(action.subject), action, context)
body = self.merge_message(cr, uid, str(action.message), action, context)
if tools.email_send(user, [address], subject, body, debug=False, subtype='html') == True:
logger.notifyChannel('email', netsvc.LOG_INFO, 'Email successfully send to : %s' % (address))
else:
@@ -556,13 +582,32 @@ class actions_server(osv.osv):
logger.notifyChannel('sms', netsvc.LOG_ERROR, 'Failed to send SMS to : %s' % (action.address))
if action.state == 'other':
res = None
res = []
for act in action.child_ids:
context['active_id'] = context['active_ids'][0]
result = self.run(cr, uid, [act.id], context)
if result:
res = result
res.append(result)
return res
if action.state == 'loop':
obj_pool = self.pool.get(action.model_id.model)
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
cxt = {
'context':context,
'object': obj,
'time':time,
'cr': cr,
'pool' : self.pool,
'uid' : uid
}
expr = eval(str(action.expression), cxt)
context['object'] = obj
for i in expr:
context['active_id'] = i.id
result = self.run(cr, uid, [action.loop_action.id], context)
if action.state == 'object_write':
res = {}
for exp in action.fields_lines:
@@ -570,23 +615,35 @@ class actions_server(osv.osv):
if exp.type == 'equation':
obj_pool = self.pool.get(action.model_id.model)
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
expr = eval(euq, {'context':context, 'object': obj, 'time':time})
cxt = {'context':context, 'object': obj, 'time':time}
expr = eval(euq, cxt)
else:
expr = exp.value
res[exp.col1.name] = expr
if not action.record_id:
if not action.write_id:
if not action.srcmodel_id:
obj_pool = self.pool.get(action.model_id.model)
obj_pool.write(cr, uid, [context.get('active_id')], res)
else:
write_id = context.get('active_id')
obj_pool = self.pool.get(action.srcmodel_id.model)
obj_pool.write(cr, uid, [context.get('active_id')], res)
else:
obj_pool.write(cr, uid, [write_id], res)
elif action.write_id:
obj_pool = self.pool.get(action.srcmodel_id.model)
id = self.pool.get(action.model_id.model).read(cr, uid, [context.get('active_id')], [action.record_id.name])
obj_pool.write(cr, uid, [int(id[0][action.record_id.name])], res)
rec = self.pool.get(action.model_id.model).browse(cr, uid, context.get('active_id'))
id = eval(action.write_id, {'object': rec})
try:
id = int(id)
except:
raise osv.except_osv(_('Error'), _("Problem in configuration `Record Id` in Server Action!"))
if type(id) != type(1):
raise osv.except_osv(_('Error'), _("Problem in configuration `Record Id` in Server Action!"))
write_id = id
obj_pool.write(cr, uid, [write_id], res)
if action.state == 'object_create':
res = {}
for exp in action.fields_lines:
@@ -603,9 +660,12 @@ class actions_server(osv.osv):
res_id = False
obj_pool = self.pool.get(action.srcmodel_id.model)
res_id = obj_pool.create(cr, uid, res)
self.pool.get(action.model_id.model).write(cr, uid, [context.get('active_id')], {action.record_id.name:res_id})
cr.commit()
if action.record_id:
self.pool.get(action.model_id.model).write(cr, uid, [context.get('active_id')], {action.record_id.name:res_id})
return False
actions_server()
class act_window_close(osv.osv):
+12 -32
View File
@@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@@ -55,7 +55,7 @@ class ir_model(osv.osv):
if model.state=='manual':
if not model.model.startswith('x_'):
return False
if not re.match('^[a-z_A-Z0-9]+$',model.model):
if not re.match('^[a-z_A-Z0-9.]+$',model.model):
return False
return True
@@ -193,9 +193,7 @@ class ir_model_fields(osv.osv):
_columns = {
'name': fields.char('Name', required=True, size=64, select=1),
'model': fields.char('Object Name', size=64, required=True),
'relation_id':fields.many2one('ir.model', 'Object Relation'),
'relation': fields.char('Object Relation', size=64),
'relation_field_id':fields.many2one('ir.model.fields', 'Relation Field'),
'relation_field': fields.char('Relation Field', size=64),
'model_id': fields.many2one('ir.model', 'Object id', required=True, select=True, ondelete='cascade'),
'field_description': fields.char('Field Label', required=True, size=256),
@@ -233,38 +231,20 @@ class ir_model_fields(osv.osv):
# MAY BE ADD A ALTER TABLE DROP ?
#
return super(ir_model_fields, self).unlink(cr, user, ids, context)
def write(self, cr, uid, ids, vals, context=None):
res = False
if 'relation_id' in vals:
model_data = self.pool.get('ir.model').browse(cr, uid, vals['relation_id'])
vals['relation'] = model_data.model
if 'relation_field_id' in vals:
field_data = self.pool.get('ir.model.fields').browse(cr, uid, vals['relation_field_id'])
vals['relation'] = field_data.name
res = super(ir_model_fields, self).write(cr, uid, ids, vals, context)
return res
def create(self, cr, user, vals, context=None):
if 'relation_id' in vals:
model_data = self.pool.get('ir.model').browse(cr,user,vals['relation_id'])
vals['relation']=model_data.model
if 'relation_field_id' in vals:
field_data = self.pool.get('ir.model.fields').browse(cr, uid, vals['relation_field_id'])
vals['relation_field'] = field_data.name
if 'model_id' in vals:
model_data=self.pool.get('ir.model').browse(cr,user,vals['model_id'])
vals['model']=model_data.model
model_data = self.pool.get('ir.model').browse(cr, user, vals['model_id'])
vals['model'] = model_data.model
if context and context.get('manual',False):
vals['state']='manual'
vals['state'] = 'manual'
res = super(ir_model_fields,self).create(cr, user, vals, context)
if vals.get('state','base')=='manual':
if vals.get('state','base') == 'manual':
if not vals['name'].startswith('x_'):
raise except_orm(_('Error'), _("Custom fields must have a name that starts with 'x_' !"))
if self.pool.get(vals['model']):
self.pool.get(vals['model']).__init__(self.pool, cr)
self.pool.get(vals['model'])._auto_init(cr,{})
self.pool.get(vals['model'])._auto_init(cr, {})
return res
ir_model_fields()
@@ -298,7 +278,7 @@ class ir_model_access(osv.osv):
model_name = model.name
else:
model_name = model
if isinstance(group_ids, (int, long)):
group_ids = [group_ids]
for group_id in group_ids:
@@ -324,7 +304,7 @@ class ir_model_access(osv.osv):
def check(self, cr, uid, model, mode='read', raise_exception=True):
if uid==1:
# User root have all accesses
# User root have all accesses
# TODO: exclude xml-rpc requests
return True
@@ -335,7 +315,7 @@ class ir_model_access(osv.osv):
model_name = model.name
else:
model_name = model
# We check if a specific rule exists
cr.execute('SELECT MAX(CASE WHEN perm_' + mode + ' THEN 1 ELSE 0 END) '
' FROM ir_model_access a '
@@ -394,7 +374,7 @@ class ir_model_access(osv.osv):
res = super(ir_model_access, self).write(cr, uid, *args, **argv)
self.check() # clear the cache of check function
return res
def create(self, cr, uid, *args, **argv):
res = super(ir_model_access, self).create(cr, uid, *args, **argv)
self.check()
+1 -1
View File
@@ -28,7 +28,7 @@ import os
def _check_xml(self, cr, uid, ids, context={}):
for view in self.browse(cr, uid, ids, context):
eview = etree.fromstring(view.arch)
eview = etree.fromstring(view.arch.encode('utf8'))
frng = tools.file_open(os.path.join('base','rng','view.rng'))
relaxng = etree.RelaxNG(file=frng)
if not relaxng.validate(eview):
+2 -1
View File
@@ -206,7 +206,8 @@ class ir_values(osv.osv):
del fields[pos]
else:
pos+=1
datas = self.pool.get(model).read(cr, uid, [id], fields, context)[0]
datas = self.pool.get(model).read(cr, uid, [id], fields, context)
datas= datas and datas[0] or None
if not datas:
#ir_del(cr, uid, x[0])
return False
+1 -1
View File
@@ -461,7 +461,7 @@ class module(osv.osv):
for lang in filter_lang:
f = os.path.join(tools.config['addons_path'], mod.name, 'i18n', lang + '.po')
if os.path.exists(f):
logger.notifyChannel("init", netsvc.LOG_INFO, 'addon %s: loading translation file for language %s' % (mod.name, lang))
logger.notifyChannel("init", netsvc.LOG_INFO, 'module %s: loading translation file for language %s' % (mod.name, lang))
tools.trans_load(cr.dbname, f, lang, verbose=False)
module()
@@ -26,7 +26,6 @@ import base64
import StringIO
import csv
import pooler
from osv import fields,osv
@@ -51,7 +50,6 @@ class wizard_export_lang(osv.osv_memory):
mods = map(lambda m: m.name, this.modules) or ['all']
mods.sort()
buf=StringIO.StringIO()
tools.trans_export(this.lang, mods, buf, this.format, dbname=cr.dbname)
if this.format == 'csv':
this.advice = _("Save this document to a .CSV file and open it with your favourite spreadsheet software. The file encoding is UTF-8. You have to translate the latest column before reimporting it.")
@@ -64,7 +62,6 @@ class wizard_export_lang(osv.osv_memory):
this.advice = _('Save this document to a .tgz file. This archive containt UTF-8 %s files and may be uploaded to launchpad.') % (ext,)
this.name = "%s.%s" % (this.lang or _('new'), this.format)
out=base64.encodestring(buf.getvalue())
buf.close()
return self.write(cr, uid, ids, {'state':'get', 'data':out, 'advice':this.advice, 'name':this.name}, context=context)
@@ -54,11 +54,8 @@ class wizard_lang_install(wizard.interface):
modobj.update_translations(cr, uid, mids, lang)
return {}
def _get_language(sel, cr, uid, context):
return tools.scan_languages()
fields_form = {
'lang': {'string':'Language', 'type':'selection', 'selection':_get_language,
'lang': {'string':'Language', 'type':'selection', 'selection':tools.scan_languages(),
},
}
+1 -1
View File
@@ -255,7 +255,7 @@ class res_partner(osv.osv):
ref = res and res[0]['ref'] or '0'
try:
nextref = int(ref)+1
except e:
except:
raise osv.except_osv(_('Warning'), _("Couldn't generate the next id because some partners have an alphabetic id !"))
# update the current partner
+4 -4
View File
@@ -143,12 +143,12 @@ class res_company(osv.osv):
<drawString x="1.3cm" y="27.2cm">[[ company.partner_id.name ]]</drawString>
<drawString x="1.3cm" y="26.8cm">[[ company.partner_id.address and company.partner_id.address[0].street ]]</drawString>
<drawString x="1.3cm" y="26.4cm">[[ company.partner_id.address and company.partner_id.address[0].zip ]] [[ company.partner_id.address and company.partner_id.address[0].city ]] - [[ company.partner_id.address and company.partner_id.address[0].country_id and company.partner_id.address[0].country_id.name ]]</drawString>
<drawString x="1.3cm" y="26.8cm">[[ company.partner_id.address and company.partner_id.address[0].street or '' ]]</drawString>
<drawString x="1.3cm" y="26.4cm">[[ company.partner_id.address and company.partner_id.address[0].zip or '' ]] [[ company.partner_id.address and company.partner_id.address[0].city or '' ]] - [[ company.partner_id.address and company.partner_id.address[0].country_id and company.partner_id.address[0].country_id.name or '']]</drawString>
<drawString x="1.3cm" y="26.0cm">Phone:</drawString>
<drawRightString x="7cm" y="26.0cm">[[ company.partner_id.address and company.partner_id.address[0].phone ]]</drawRightString>
<drawRightString x="7cm" y="26.0cm">[[ company.partner_id.address and company.partner_id.address[0].phone or '' ]]</drawRightString>
<drawString x="1.3cm" y="25.6cm">Mail:</drawString>
<drawRightString x="7cm" y="25.6cm">[[ company.partner_id.address and company.partner_id.address[0].email ]]</drawRightString>
<drawRightString x="7cm" y="25.6cm">[[ company.partner_id.address and company.partner_id.address[0].email or '' ]]</drawRightString>
<lines>1.3cm 25.5cm 7cm 25.5cm</lines>
<!--page bottom-->
+13
View File
@@ -19,6 +19,7 @@
<rng:ref name="separator"/>
<rng:ref name="image"/>
<rng:ref name="form"/>
<rng:ref name="vpaned"/>
<rng:element name="newline"><rng:empty/></rng:element>
<rng:element name="properties"><rng:empty/></rng:element>
</rng:choice>
@@ -101,6 +102,15 @@
</rng:zeroOrMore>
</rng:element>
</rng:define>
<rng:define name="vpaned">
<rng:element name="vpaned">
<rng:optional><rng:attribute name="position"/></rng:optional>
<rng:zeroOrMore>
<rng:ref name="any" />
</rng:zeroOrMore>
</rng:element>
</rng:define>
<rng:define name="any">
<rng:element>
@@ -134,6 +144,9 @@
<rng:ref name="button"/>
<rng:ref name="form" />
<rng:ref name="page" />
<rng:ref name="notebook"/>
<rng:ref name="hpaned"/>
<rng:ref name="vpaned"/>
</rng:choice>
</rng:zeroOrMore>
</rng:element>
+19 -2
View File
@@ -144,12 +144,16 @@ def service_exist(name):
def get_rpc_paths():
return map(lambda s: '/xmlrpc/%s' % s, _service)
LOG_DEBUG_RPC = 'debug_rpc'
LOG_DEBUG = 'debug'
LOG_INFO = 'info'
LOG_WARNING = 'warn'
LOG_ERROR = 'error'
LOG_CRITICAL = 'critical'
# add new log level below DEBUG
logging.DEBUG_RPC = logging.DEBUG - 1
def init_logger():
from tools import config
@@ -188,6 +192,7 @@ def init_logger():
background = lambda f: 40 + colors.index(f)
mapping = {
'DEBUG_RPC': ('blue', 'white'),
'DEBUG': ('blue', 'default'),
'INFO': ('green', 'default'),
'WARNING': ('yellow', 'default'),
@@ -203,6 +208,11 @@ def init_logger():
class Logger(object):
def notifyChannel(self, name, level, msg):
log = logging.getLogger(name)
if level == LOG_DEBUG_RPC and not hasattr(log, level):
fct = lambda msg, *args, **kwargs: log.log(logging.DEBUG_RPC, msg, *args, **kwargs)
setattr(log, LOG_DEBUG_RPC, fct)
level_method = getattr(log, level)
result = str(msg).strip().split('\n')
@@ -297,7 +307,7 @@ class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
except:
Logger().notifyChannel('init', LOG_ERROR, 'Address already in use')
Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use')
sys.exit(1)
class HttpDaemon(threading.Thread):
@@ -368,6 +378,10 @@ class TinySocketClientThread(threading.Thread):
threading.Thread.__init__(self)
self.sock = sock
self.threads = threads
self._logger = Logger()
def log(self, msg):
self._logger.notifyChannel('NETRPC', LOG_DEBUG_RPC, msg)
def run(self):
import traceback
@@ -388,6 +402,7 @@ class TinySocketClientThread(threading.Thread):
self.threads.remove(self)
return False
try:
self.log(msg)
s = LocalService(msg[0])
m = getattr(s, msg[1])
s._service._response = None
@@ -395,6 +410,7 @@ class TinySocketClientThread(threading.Thread):
res = s._service._response
if res != None:
r = res
self.log(r)
ts.mysend(r)
except Exception, e:
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
@@ -403,7 +419,8 @@ class TinySocketClientThread(threading.Thread):
import pdb
tb = sys.exc_info()[2]
pdb.post_mortem(tb)
e = Exception(e.message)
e = Exception(str(e))
self.log(str(e))
ts.mysend(e, exception=True, traceback=tb_s)
except:
pass
+16 -6
View File
@@ -284,10 +284,10 @@ class many2one(_column):
_column.__init__(self, string=string, **args)
self._obj = obj
#
# TODO: speed improvement
#
# name is the name of the relation field
def set_memory(self, cr, obj, id, field, values, user=None, context=None):
obj.datas.setdefault(id, {})
obj.datas[id][field] = values
def get_memory(self, cr, obj, ids, name, user=None, context=None, values=None):
result = {}
for id in ids:
@@ -426,6 +426,7 @@ class one2many(_column):
context = {}
if not values:
return
_table = obj.pool.get(self._obj)._table
obj = obj.pool.get(self._obj)
for act in values:
@@ -602,6 +603,9 @@ class function(_column):
if store:
self._classic_read = True
self._classic_write = True
if type=='binary':
self._symbol_get=lambda x:x and str(x)
if type == 'float':
self._symbol_c = float._symbol_c
self._symbol_f = float._symbol_f
@@ -688,15 +692,21 @@ class related(function):
self._field_get2(cr, uid, obj, context)
if not ids: return {}
relation = obj._name
res = {}
res = {}.fromkeys(ids, False)
objlst = obj.browse(cr, uid, ids)
for data in objlst:
if not data:
continue
t_data = data
relation = obj._name
for i in range(len(self.arg)):
field_detail = self._relations[i]
relation = field_detail['object']
if not t_data[self.arg[i]]:
try:
if not t_data[self.arg[i]]:
t_data = False
break
except:
t_data = False
break
if field_detail['type'] in ('one2many', 'many2many'):
+13 -5
View File
@@ -133,7 +133,6 @@ class browse_record(object):
self._data[id] = {'id': id}
self._cache = cache
pass
def __getitem__(self, name):
if name == 'id':
@@ -930,6 +929,12 @@ class orm_template(object):
def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False):
if not context:
context = {}
def encode(s):
if isinstance(s, unicode):
return s.encode('utf8')
return s
def _inherit_apply(src, inherit):
def _find(node, node2):
if node2.nodeType == node2.ELEMENT_NODE and node2.localName == 'xpath':
@@ -952,9 +957,11 @@ class orm_template(object):
if res:
return res
return None
doc_src = dom.minidom.parseString(src)
doc_dest = dom.minidom.parseString(inherit)
netsvc.Logger().notifyChannel('orm', netsvc.LOG_DEBUG, type(src))
doc_src = dom.minidom.parseString(encode(src))
doc_dest = dom.minidom.parseString(encode(inherit))
toparse = doc_dest.childNodes
while len(toparse):
node2 = toparse.pop(0)
@@ -1069,7 +1076,7 @@ class orm_template(object):
result['field_parent'] = False
result['view_id'] = 0
doc = dom.minidom.parseString(result['arch'].encode('utf-8'))
doc = dom.minidom.parseString(encode(result['arch']))
xarch, xfields = self.__view_look_dom_arch(cr, user, doc, context=context)
result['arch'] = xarch
result['fields'] = xfields
@@ -2070,7 +2077,8 @@ class orm(orm_template):
'where id in ('+str_d+')', sub_ids)
for order, object, ids, fields in result_store:
self.pool.get(object)._store_set_values(cr, uid, ids, fields, context)
if object<>self._name:
self.pool.get(object)._store_set_values(cr, uid, ids, fields, context)
return True
#
+5 -3
View File
@@ -37,9 +37,11 @@ def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False)
pool_dic[db_name] = pool
addons.load_modules(db, force_demo, status, update_module)
cr = db.cursor()
pool.init_set(cr, False)
cr.commit()
cr.close()
try:
pool.init_set(cr, False)
cr.commit()
finally:
cr.close()
if not update_module:
import report
+3 -3
View File
@@ -132,7 +132,7 @@ class report_printscreen_list(report_int):
for f in fields_order:
field = new_doc.createElement("field")
field_txt = new_doc.createTextNode(str(fields[f]['string'] or ''))
field_txt = new_doc.createTextNode(fields[f]['string'] or '')
field.appendChild(field_txt)
header.appendChild(field)
@@ -166,7 +166,7 @@ class report_printscreen_list(report_int):
col.setAttribute('para','yes')
col.setAttribute('tree','no')
if line[f] != None:
txt = new_doc.createTextNode(str(line[f] or ''))
txt = new_doc.createTextNode(line[f] or '')
if temp[count] == 1:
tsum[count] = float(tsum[count]) + float(line[f]);
@@ -204,7 +204,7 @@ class report_printscreen_list(report_int):
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())
doc = libxml2.parseDoc(new_doc.toxml(encoding='utf-8'))
rml_obj = style.applyStylesheet(doc, None)
rml = style.saveResultToString(rml_obj)
self.obj = render.rml(rml, title=self.title)
+15 -22
View File
@@ -20,30 +20,28 @@
#
##############################################################################
import base64
import xml.dom.minidom
import os, time
import ir, netsvc
import osv
from interface import report_rml
import re
import tools
import pooler
import netsvc
import warnings
import locale
import copy
import StringIO
import zipfile
import os
import base64
import copy
import ir
import locale
import mx.DateTime
import netsvc
import os
import osv
import pooler
import re
import time
import tools
import warnings
import xml.dom.minidom
import zipfile
DT_FORMAT = '%Y-%m-%d'
DHM_FORMAT = '%Y-%m-%d %H:%M:%S'
HM_FORMAT = '%H:%M:%S'
import base64
if not hasattr(locale, 'nl_langinfo'):
locale.nl_langinfo = lambda *a: '%x'
@@ -469,15 +467,10 @@ class rml_parse(object):
if isinstance(newtext, list):
todo.append((key, newtext))
else:
if not isinstance(newtext, basestring):
newtext = str(newtext)
elif isinstance(newtext,unicode):
pass
elif isinstance(newtext,str):
newtext = newtext.decode('utf8')
# 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):
+9 -1
View File
@@ -140,6 +140,12 @@ class Cursor(object):
self.sql_into_log[res_into.group(1)][1] += mdt.now() - now
return res
def drop_view_if_exists(self, viewname):
self._obj.execute("select count(1) from pg_class where relkind=%s and relname=%s", ('v', viewname,))
if self._obj.fetchone()[0]:
self._obj.execute("DROP view %s" % (viewname,))
self._obj.commit()
def print_log(self):
def process(type):
sqllogs = {'from':self.sql_from_log, 'into':self.sql_into_log}
@@ -220,13 +226,15 @@ class PoolManager(object):
logger.notifyChannel('dbpool', netsvc.LOG_INFO, 'Connecting to %s' % (db_name,))
PoolManager._pools[db_name] = ConnectionPool(ThreadedConnectionPool(1, PoolManager.maxconn, PoolManager.dsn(db_name)), db_name)
except Exception, e:
logger.notifyChannel('dbpool', netsvc.LOG_CRITICAL, 'Unable to connect to %s: %s' % (db_name, e.message))
logger.notifyChannel('dbpool', netsvc.LOG_ERROR, 'Unable to connect to %s: %s' %
(db_name, str(e)))
raise
return PoolManager._pools[db_name]
get = staticmethod(get)
def close(db_name):
if db_name in PoolManager._pools:
logger = netsvc.Logger()
logger.notifyChannel('dbpool', netsvc.LOG_INFO, 'Closing all connections to %s' % (db_name,))
PoolManager._pools[db_name].closeall()
del PoolManager._pools[db_name]
+7 -3
View File
@@ -20,8 +20,12 @@
#
##############################################################################
import ConfigParser,optparse,os,sys
import netsvc,logging
import ConfigParser
import optparse
import os
import sys
import netsvc
import logging
import release
class configmanager(object):
@@ -66,7 +70,7 @@ class configmanager(object):
'assert_exit_level': logging.WARNING, # level above which a failed assert will be raise
}
loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG')])
loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC')])
version = "%s %s" % (release.description, release.version)
parser = optparse.OptionParser(version=version)
+1 -1
View File
@@ -493,7 +493,7 @@ form: module.record_id""" % (xml_id,)
try:
npid = self.pool.get('ir.model.data')._update_dummy(cr, self.uid, 'ir.ui.menu', self.module, xml_id, idx==len(m_l)-1)
except:
self.logger.notifyChannel('init', netsvc.LOG_ERROR, "addon: %s xml_id: %s" % (self.module, xml_id))
self.logger.notifyChannel('init', netsvc.LOG_ERROR, "module: %s xml_id: %s" % (self.module, xml_id))
else:
# the menuitem does't exist but we are in branch (not a leaf)
self.logger.notifyChannel("init", netsvc.LOG_WARNING, 'Warning no ID for submenu %s of menu %s !' % (menu_elem, str(m_l)))
+31 -1
View File
@@ -715,11 +715,41 @@ def logged(f):
vector.append(' result: %s' % pformat(res))
vector.append(' time delta: %s' % (time.time() - timeb4))
#netsvc.Logger().notifyChannel('logged', netsvc.LOG_DEBUG, '\n'.join(vector))
netsvc.Logger().notifyChannel('logged', netsvc.LOG_DEBUG, '\n'.join(vector))
return res
return wrapper
def debug(what):
"""
This method allow you to debug your code without print
Example:
>>> def func_foo(bar)
... baz = bar
... debug(baz)
... qnx = (baz, bar)
... debug(qnx)
...
>>> func_foo(42)
This will output on the logger:
[Wed Dec 25 00:00:00 2008] DEBUG:func_foo:baz = 42
[Wed Dec 25 00:00:00 2008] DEBUG:func_foo:qnx = (42, 42)
To view the DEBUG lines in the logger you must start the server with the option
--log-level=debug
"""
import netsvc
from inspect import stack
import re
from pprint import pformat
st = stack()[1]
param = re.split("debug *\((.+)\)", st[4][0].strip())[1].strip()
while param.count(')') > param.count('('): param = param[:param.rfind(')')]
netsvc.Logger().notifyChannel(st[3], netsvc.LOG_DEBUG, "%s = %s" % (param, pformat(what)))
icons = map(lambda x: (x,x), ['STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD',
'STOCK_CANCEL', 'STOCK_CDROM', 'STOCK_CLEAR', 'STOCK_CLOSE', 'STOCK_COLOR_PICKER',
+37 -25
View File
@@ -354,10 +354,17 @@ def trans_generate(lang, modules, dbname=None):
tuple = (module, type, name, id, source)
if source and tuple not in _to_translate:
_to_translate.append(tuple)
def encode(s):
if isinstance(s, unicode):
return s.encode('utf8')
return s
for (xml_name,model,res_id,module) in cr.fetchall():
xml_name = module+'.'+xml_name
module = encode(module)
model = encode(model)
xml_name = "%s.%s" % (module, encode(xml_name))
if not pool.get(model):
logger.notifyChannel("db", netsvc.LOG_ERROR, "unable to find object %r" % (model,))
continue
@@ -365,9 +372,9 @@ def trans_generate(lang, modules, dbname=None):
if model=='ir.ui.view':
d = xml.dom.minidom.parseString(obj.arch)
for t in trans_parse_view(d.documentElement):
push_translation(module, 'view', obj.model, 0, t)
push_translation(module, 'view', encode(obj.model), 0, t)
elif model=='ir.actions.wizard':
service_name = 'wizard.'+obj.wiz_name
service_name = 'wizard.'+encode(obj.wiz_name)
try:
obj2 = netsvc._service[service_name]
except KeyError, exc:
@@ -378,18 +385,23 @@ def trans_generate(lang, modules, dbname=None):
result = state_def['result']
if result['type'] != 'form':
continue
name = obj.wiz_name + ',' + state_name
name = "%s,%s" % (encode(obj.wiz_name), state_name)
def_params = {
'string': ('wizard_field', lambda s: [encode(s)]),
'selection': ('selection', lambda s: [encode(e[1]) for e in s]),
'help': ('help', lambda s: [encode(s)]),
}
# export fields
for field_name, field_def in result['fields'].iteritems():
res_name = name + ',' + field_name
if 'string' in field_def:
source = field_def['string']
push_translation(module, 'wizard_field', res_name, 0, source.encode('utf8'))
if 'selection' in field_def:
for key, val in field_def['selection']:
push_translation(module, 'selection', res_name, 0, val.encode('utf8'))
for fn in def_params:
if fn in field_def:
transtype, modifier = def_params[fn]
for val in modifier(field_def[fn]):
push_translation(module, transtype, res_name, 0, val)
# export arch
arch = result['arch']
@@ -407,7 +419,7 @@ def trans_generate(lang, modules, dbname=None):
elif model=='ir.model.fields':
try:
field_name = obj.name
field_name = encode(obj.name)
except AttributeError, exc:
logger.notifyChannel("db", netsvc.LOG_ERROR, "name error in %s: %s" % (xml_name,str(exc)))
continue
@@ -416,11 +428,11 @@ def trans_generate(lang, modules, dbname=None):
continue
field_def = objmodel._columns[field_name]
name = obj.model + "," + field_name
push_translation(module, 'field', name, 0, field_def.string.encode('utf8'))
name = "%s,%s" % (encode(obj.model), field_name)
push_translation(module, 'field', name, 0, encode(field_def.string))
if field_def.help:
push_translation(module, 'help', name, 0, field_def.help.encode('utf8'))
push_translation(module, 'help', name, 0, encode(field_def.help))
if field_def.translate:
ids = objmodel.search(cr, uid, [])
@@ -434,14 +446,14 @@ def trans_generate(lang, modules, dbname=None):
('res_id', '=', res_id),
])
if not model_data_ids:
push_translation(module, 'model', name, 0, obj_value[field_name])
push_translation(module, 'model', name, 0, encode(obj_value[field_name]))
if hasattr(field_def, 'selection') and isinstance(field_def.selection, (list, tuple)):
for key, val in field_def.selection:
push_translation(module, 'selection', name, 0, val.encode('utf8'))
push_translation(module, 'selection', name, 0, encode(val))
elif model=='ir.actions.report.xml':
name = obj.report_name
name = encode(obj.report_name)
fname = ""
if obj.report_rml:
fname = obj.report_rml
@@ -462,7 +474,7 @@ def trans_generate(lang, modules, dbname=None):
for constraint in pool.get(model)._constraints:
msg = constraint[1]
push_translation(module, 'constraint', model, 0, msg.encode('utf8'))
push_translation(module, 'constraint', model, 0, encode(msg))
for field_name,field_def in pool.get(model)._columns.items():
if field_def.translate:
@@ -471,7 +483,7 @@ def trans_generate(lang, modules, dbname=None):
trad = getattr(obj, field_name) or ''
except:
trad = ''
push_translation(module, 'model', name, xml_name, trad)
push_translation(module, 'model', name, xml_name, encode(trad))
# parse source code for _() calls
def get_module_from_path(path):
@@ -497,15 +509,15 @@ def trans_generate(lang, modules, dbname=None):
'[^a-zA-Z0-9_]_\([\s]*["\'](.+?)["\'][\s]*\)',
code_string, re.M)
for i in iter:
push_translation(module, 'code', frelativepath, 0, i.group(1).encode('utf8'))
push_translation(module, 'code', frelativepath, 0, encode(i.group(1)))
out = [["module","type","name","res_id","src","value"]] # header
# translate strings marked as to be translated
for module, type, name, id, source in _to_translate:
trans = trans_obj._get_source(cr, uid, name, type, lang, source)
out.append([module, type, name, id, source, trans or ''])
out.append([module, type, name, id, source, encode(trans) or ''])
cr.close()
return out
@@ -519,7 +531,7 @@ def trans_load(db_name, filename, lang, strict=False, verbose=True):
return r
except IOError:
if verbose:
logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read translation file %s" % (filename,)) # FIXME translate message
logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read translation file %s" % (filename,))
return None
def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=None, verbose=True):
+9 -2
View File
@@ -113,15 +113,22 @@ class interface(netsvc.Service):
if lang:
# translate fields
for field in fields:
trans = translate(cr, self.wiz_name+','+state+','+field, 'wizard_field', lang)
res_name = "%s,%s,%s" % (self.wiz_name, state, field)
trans = translate(cr, res_name, 'wizard_field', lang)
if trans:
fields[field]['string'] = trans
if 'selection' in fields[field]:
trans = lambda x: translate(cr, self.wiz_name+','+state+','+field, 'selection', lang, x) or x
trans = lambda x: translate(cr, res_name, 'selection', lang, x) or x
for idx, (key, val) in enumerate(fields[field]['selection']):
fields[field]['selection'][idx] = (key, trans(val))
if 'help' in fields[field]:
t = translate(cr, res_name, 'help', lang, fields[field]['help'])
if t:
fields[field]['help'] = t
# translate arch
if not isinstance(arch, UpdateableStr):
doc = dom.minidom.parseString(arch)
-2
View File
@@ -32,8 +32,6 @@ import sys
import os
import glob
from stat import ST_MODE
from distutils.core import setup, Command
from distutils.command.install import install