[FIX] replaced <TAB> with four white space.

bzr revid: hmo@tinyerp.com-20091124144405-9mzd91chohvf0uu7
This commit is contained in:
Harry (Open ERP) 2009-11-24 20:14:05 +05:30
parent dda5ed6bb1
commit d8ce3f1e2a
24 changed files with 843 additions and 843 deletions

View File

@ -52,10 +52,10 @@ sys.path.insert(1, _ad)
ad_cnt=1 ad_cnt=1
for adp in ad_paths: for adp in ad_paths:
if adp != _ad: if adp != _ad:
sys.path.insert(ad_cnt, adp) sys.path.insert(ad_cnt, adp)
ad_cnt+=1 ad_cnt+=1
ad_paths.append(_ad) # for get_module_path ad_paths.append(_ad) # for get_module_path
# Modules already loaded # Modules already loaded
loaded = [] loaded = []
@ -289,7 +289,7 @@ def get_modules():
plist = [] plist = []
for ad in ad_paths: for ad in ad_paths:
plist.extend(listdir(ad)) plist.extend(listdir(ad))
return list(set(plist)) return list(set(plist))
def get_modules_with_version(): def get_modules_with_version():
@ -318,7 +318,7 @@ def upgrade_graph(graph, cr, module_list, force=None):
mod_path = get_module_path(module) mod_path = get_module_path(module)
terp_file = get_module_resource(module, '__terp__.py') terp_file = get_module_resource(module, '__terp__.py')
if not mod_path or not terp_file: if not mod_path or not terp_file:
logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: not installable' % (module)) logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: not installable' % (module))
cr.execute("update ir_module_module set state=%s where name=%s", ('uninstallable', module)) cr.execute("update ir_module_module set state=%s where name=%s", ('uninstallable', module))
continue continue

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
############################################################################## ##############################################################################
# #
# OpenERP, Open Source Management Solution # OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$ # $Id$
# #

View File

@ -47,15 +47,15 @@ class ir_sequence(osv.osv):
'number_next': fields.integer('Next Number', required=True), 'number_next': fields.integer('Next Number', required=True),
'number_increment': fields.integer('Increment Number', required=True), 'number_increment': fields.integer('Increment Number', required=True),
'padding' : fields.integer('Number padding', required=True), 'padding' : fields.integer('Number padding', required=True),
'condition': fields.char('Condition', size=250, help="If set, sequence will only be used in case this python expression matches, and will precede other sequences."), 'condition': fields.char('Condition', size=250, help="If set, sequence will only be used in case this python expression matches, and will precede other sequences."),
'weight': fields.integer('Weight',required=True, help="If two sequences match, the highest weight will be used.") 'weight': fields.integer('Weight',required=True, help="If two sequences match, the highest weight will be used.")
} }
_defaults = { _defaults = {
'active': lambda *a: True, 'active': lambda *a: True,
'number_increment': lambda *a: 1, 'number_increment': lambda *a: 1,
'number_next': lambda *a: 1, 'number_next': lambda *a: 1,
'padding' : lambda *a : 0, 'padding' : lambda *a : 0,
'weight' : lambda *a: 10, 'weight' : lambda *a: 10,
} }
def _process(self, s): def _process(self, s):
@ -74,28 +74,28 @@ class ir_sequence(osv.osv):
} }
def get_id(self, cr, uid, sequence_id, test='id=%s', context=None): def get_id(self, cr, uid, sequence_id, test='id=%s', context=None):
if not context: if not context:
context = {} context = {}
try: try:
cr.execute('SELECT id, number_next, prefix, suffix, padding, condition \ cr.execute('SELECT id, number_next, prefix, suffix, padding, condition \
FROM ir_sequence \ FROM ir_sequence \
WHERE '+test+' AND active=%s ORDER BY weight DESC, length(COALESCE(condition,\'\')) DESC \ WHERE '+test+' AND active=%s ORDER BY weight DESC, length(COALESCE(condition,\'\')) DESC \
FOR UPDATE', (sequence_id, True)) FOR UPDATE', (sequence_id, True))
for res in cr.dictfetchall(): for res in cr.dictfetchall():
if res['condition']: if res['condition']:
print "ir_seq: %s has condition:" %res['id'], res['condition'], print "ir_seq: %s has condition:" %res['id'], res['condition'],
try: try:
bo = safe_eval(res['condition'],context) bo = safe_eval(res['condition'],context)
if not bo: if not bo:
print "not matched" print "not matched"
continue continue
except Exception,e: except Exception,e:
# it would be normal to have exceptions, because # it would be normal to have exceptions, because
# the domain may contain errors # the domain may contain errors
print "Exception.\ne:",e print "Exception.\ne:",e
print "Context:", context print "Context:", context
continue continue
print "Matched!" print "Matched!"
cr.execute('UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s AND active=%s', (res['id'], True)) cr.execute('UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s AND active=%s', (res['id'], True))
if res['number_next']: if res['number_next']:

View File

@ -147,7 +147,7 @@ showpage'''
inst_id = inst_id[0] inst_id = inst_id[0]
graph = pydot.Dot(fontsize='16', label="""\\\n\\nWorkflow: %s\\n OSV: %s""" % (wkfinfo['name'],wkfinfo['osv']), graph = pydot.Dot(fontsize='16', label="""\\\n\\nWorkflow: %s\\n OSV: %s""" % (wkfinfo['name'],wkfinfo['osv']),
size='7.3, 10.1', center='1', ratio='auto', rotate='0', rankdir='TB', size='7.3, 10.1', center='1', ratio='auto', rotate='0', rankdir='TB',
ordering='out' ordering='out'
) )
graph_instance_get(cr, graph, inst_id, data.get('nested', False)) graph_instance_get(cr, graph, inst_id, data.get('nested', False))
ps_string = graph.create(prog='dot', format='ps') ps_string = graph.create(prog='dot', format='ps')

View File

@ -29,37 +29,37 @@ class ir_module_reference_print(report_sxw.rml_parse):
'time': time, 'time': time,
'findobj': self._object_find, 'findobj': self._object_find,
'objdoc': self._object_doc, 'objdoc': self._object_doc,
'objdoc2': self._object_doc2, 'objdoc2': self._object_doc2,
'findflds': self._fields_find, 'findflds': self._fields_find,
}) })
def _object_doc(self, obj): def _object_doc(self, obj):
modobj = self.pool.get(obj) modobj = self.pool.get(obj)
strdocs= modobj.__doc__ strdocs= modobj.__doc__
if not strdocs: if not strdocs:
return None return None
else: else:
strdocs=strdocs.strip().splitlines(True) strdocs=strdocs.strip().splitlines(True)
res = '' res = ''
for stre in strdocs: for stre in strdocs:
if not stre or stre.isspace(): if not stre or stre.isspace():
break break
res += stre res += stre
return res return res
def _object_doc2(self, obj): def _object_doc2(self, obj):
modobj = self.pool.get(obj) modobj = self.pool.get(obj)
strdocs= modobj.__doc__ strdocs= modobj.__doc__
if not strdocs: if not strdocs:
return None return None
else: else:
strdocs=strdocs.strip().splitlines(True) strdocs=strdocs.strip().splitlines(True)
res = [] res = []
fou = False fou = False
for stre in strdocs: for stre in strdocs:
if fou: if fou:
res.append(stre.strip()) res.append(stre.strip())
elif not stre or stre.isspace(): elif not stre or stre.isspace():
fou = True fou = True
return res return res
def _object_find(self, module): def _object_find(self, module):

View File

@ -80,7 +80,7 @@ class wizard_export_lang(osv.osv_memory):
) ), ) ),
} }
_defaults = { 'state': lambda *a: 'choose', _defaults = { 'state': lambda *a: 'choose',
'name': lambda *a: 'lang.tar.gz' 'name': lambda *a: 'lang.tar.gz'
} }
wizard_export_lang() wizard_export_lang()

View File

@ -72,10 +72,10 @@ class groups(osv.osv):
return gid return gid
def copy(self, cr, uid, id, default={}, context={}, done_list=[], local=False): def copy(self, cr, uid, id, default={}, context={}, done_list=[], local=False):
group = self.browse(cr, uid, id, context=context) group = self.browse(cr, uid, id, context=context)
default = default.copy() default = default.copy()
if not 'name' in default: if not 'name' in default:
default['name'] = group['name'] default['name'] = group['name']
default['name'] = default['name'] + _(' (copy)') default['name'] = default['name'] + _(' (copy)')
return super(groups, self).copy(cr, uid, id, default, context=context) return super(groups, self).copy(cr, uid, id, default, context=context)

View File

@ -39,7 +39,7 @@ import release
class Service(object): class Service(object):
""" Base class for *Local* services """ Base class for *Local* services
Functionality here is trusted, no authentication. Functionality here is trusted, no authentication.
""" """
_services = {} _services = {}
def __init__(self, name, audience=''): def __init__(self, name, audience=''):
@ -48,11 +48,11 @@ class Service(object):
self._methods = {} self._methods = {}
def joinGroup(self, name): def joinGroup(self, name):
raise Exception("No group for local services") raise Exception("No group for local services")
#GROUPS.setdefault(name, {})[self.__name] = self #GROUPS.setdefault(name, {})[self.__name] = self
def service_exist(self,name): def service_exist(self,name):
return Service._services.has_key(name) return Service._services.has_key(name)
def exportMethod(self, method): def exportMethod(self, method):
if callable(method): if callable(method):
@ -67,9 +67,9 @@ class Service(object):
class LocalService(object): class LocalService(object):
""" Proxy for local services. """ Proxy for local services.
Any instance of this class will behave like the single instance Any instance of this class will behave like the single instance
of Service(name) of Service(name)
""" """
def __init__(self, name): def __init__(self, name):
self.__name = name self.__name = name
try: try:
@ -158,12 +158,12 @@ def init_logger():
dirname = os.path.dirname(logf) dirname = os.path.dirname(logf)
if dirname and not os.path.isdir(dirname): if dirname and not os.path.isdir(dirname):
os.makedirs(dirname) os.makedirs(dirname)
if tools.config['logrotate'] is not False: if tools.config['logrotate'] is not False:
handler = logging.handlers.TimedRotatingFileHandler(logf,'D',1,30) handler = logging.handlers.TimedRotatingFileHandler(logf,'D',1,30)
elif os.name == 'posix': elif os.name == 'posix':
handler = logging.handlers.WatchedFileHandler(logf) handler = logging.handlers.WatchedFileHandler(logf)
else: else:
handler = logging.handlers.FileHandler(logf) handler = logging.handlers.FileHandler(logf)
except Exception, ex: except Exception, ex:
sys.stderr.write("ERROR: couldn't create the logfile directory. Logging to the standard output.\n") sys.stderr.write("ERROR: couldn't create the logfile directory. Logging to the standard output.\n")
handler = logging.StreamHandler(sys.stdout) handler = logging.StreamHandler(sys.stdout)
@ -223,27 +223,27 @@ class Logger(object):
if isinstance(msg, Exception): if isinstance(msg, Exception):
msg = tools.exception_to_unicode(msg) msg = tools.exception_to_unicode(msg)
try: try:
msg = tools.ustr(msg).strip() msg = tools.ustr(msg).strip()
if level in (LOG_ERROR,LOG_CRITICAL) and tools.config.get_misc('debug','env_info',True): if level in (LOG_ERROR,LOG_CRITICAL) and tools.config.get_misc('debug','env_info',True):
msg = common().exp_get_server_environment() + "\n" + msg msg = common().exp_get_server_environment() + "\n" + msg
result = msg.split('\n') result = msg.split('\n')
except UnicodeDecodeError: except UnicodeDecodeError:
result = msg.strip().split('\n') result = msg.strip().split('\n')
try: try:
if len(result)>1: if len(result)>1:
for idx, s in enumerate(result): for idx, s in enumerate(result):
level_method('[%02d]: %s' % (idx+1, s,)) level_method('[%02d]: %s' % (idx+1, s,))
elif result: elif result:
level_method(result[0]) level_method(result[0])
except IOError,e: except IOError,e:
# TODO: perhaps reset the logger streams? # TODO: perhaps reset the logger streams?
#if logrotate closes our files, we end up here.. #if logrotate closes our files, we end up here..
pass pass
except: except:
# better ignore the exception and carry on.. # better ignore the exception and carry on..
pass pass
def set_loglevel(self, level): def set_loglevel(self, level):
log = logging.getLogger() log = logging.getLogger()
@ -364,10 +364,10 @@ class OpenERPDispatcher:
self.log('service', service_name) self.log('service', service_name)
self.log('method', method) self.log('method', method)
self.log('params', params) self.log('params', params)
if hasattr(self,'auth_provider'): if hasattr(self,'auth_provider'):
auth = self.auth_provider auth = self.auth_provider
else: else:
auth = None auth = None
result = ExportService.getService(service_name).dispatch(method, auth, params) result = ExportService.getService(service_name).dispatch(method, auth, params)
self.log('result', result) self.log('result', result)
# We shouldn't marshall None, # We shouldn't marshall None,

View File

@ -56,8 +56,8 @@ __version__ = release.version
# We DON't log this using the standard logger, because we might mess # We DON't log this using the standard logger, because we might mess
# with the logfile's permissions. Just do a quick exit here. # with the logfile's permissions. Just do a quick exit here.
if pwd.getpwuid(os.getuid())[0] == 'root' : if pwd.getpwuid(os.getuid())[0] == 'root' :
sys.stderr.write("Attempted to run OpenERP server as root. This is not good, aborting.\n") sys.stderr.write("Attempted to run OpenERP server as root. This is not good, aborting.\n")
sys.exit(1) sys.exit(1)
#---------------------------------------------------------- #----------------------------------------------------------
# get logger # get logger
@ -114,13 +114,13 @@ import addons
import service.http_server import service.http_server
if not ( tools.config["stop_after_init"] or \ if not ( tools.config["stop_after_init"] or \
tools.config["translate_in"] or \ tools.config["translate_in"] or \
tools.config["translate_out"] ): tools.config["translate_out"] ):
service.http_server.init_servers() service.http_server.init_servers()
service.http_server.init_xmlrpc() service.http_server.init_xmlrpc()
import service.netrpc_server import service.netrpc_server
service.netrpc_server.init_servers() service.netrpc_server.init_servers()
if tools.config['db_name']: if tools.config['db_name']:
for db in tools.config['db_name'].split(','): for db in tools.config['db_name'].split(','):

View File

@ -585,14 +585,14 @@ class many2many(_column):
def get_nice_size(a): def get_nice_size(a):
(x,y) = a (x,y) = a
if isinstance(y, (int,long)): if isinstance(y, (int,long)):
size = y size = y
elif y: elif y:
y = len(y) y = len(y)
else: else:
y = 0 y = 0
return (x, tools.human_size(size)) return (x, tools.human_size(size))
# --------------------------------------------------------- # ---------------------------------------------------------
# Function fields # Function fields

View File

@ -205,9 +205,9 @@ class browse_record(object):
d[n].set_value(self._cr, self._uid, d[n], self, f, lang_obj) d[n].set_value(self._cr, self._uid, d[n], self, f, lang_obj)
if not datas: if not datas:
# Where did those ids come from? Perhaps old entries in ir_model_data? # Where did those ids come from? Perhaps old entries in ir_model_data?
raise except_orm('NoDataError', 'Field %s in %s%s'%(name,self._table_name,str(ids))) raise except_orm('NoDataError', 'Field %s in %s%s'%(name,self._table_name,str(ids)))
# create browse records for 'remote' objects # create browse records for 'remote' objects
for data in datas: for data in datas:
for n, f in ffields: for n, f in ffields:
@ -228,12 +228,12 @@ class browse_record(object):
elif f._type in ('one2many', 'many2many') and len(data[n]): elif f._type in ('one2many', 'many2many') and len(data[n]):
data[n] = self._list_class([browse_record(self._cr, self._uid, id, self._table.pool.get(f._obj), self._cache, context=self._context, list_class=self._list_class, fields_process=self._fields_process) for id in data[n]], self._context) data[n] = self._list_class([browse_record(self._cr, self._uid, id, self._table.pool.get(f._obj), self._cache, context=self._context, list_class=self._list_class, fields_process=self._fields_process) for id in data[n]], self._context)
self._data[data['id']].update(data) self._data[data['id']].update(data)
if not name in self._data[self._id]: if not name in self._data[self._id]:
#how did this happen? #how did this happen?
logger = netsvc.Logger() logger = netsvc.Logger()
logger.notifyChannel("browse_record", netsvc.LOG_ERROR,"Ffields: %s, datas: %s"%(str(fffields),str(datas))) logger.notifyChannel("browse_record", netsvc.LOG_ERROR,"Ffields: %s, datas: %s"%(str(fffields),str(datas)))
logger.notifyChannel("browse_record", netsvc.LOG_ERROR,"Data: %s, Table: %s"%(str(self._data[self._id]),str(self._table))) logger.notifyChannel("browse_record", netsvc.LOG_ERROR,"Data: %s, Table: %s"%(str(self._data[self._id]),str(self._table)))
raise AttributeError(_('Unknown attribute %s in %s ') % (str(name),self._table_name)) raise AttributeError(_('Unknown attribute %s in %s ') % (str(name),self._table_name))
return self._data[self._id][name] return self._data[self._id][name]
def __getattr__(self, name): def __getattr__(self, name):
@ -671,10 +671,10 @@ class orm_template(object):
else: else:
module, xml_id = current_module, line[i] module, xml_id = current_module, line[i]
id = ir_model_data_obj._get_id(cr, uid, module, xml_id) id = ir_model_data_obj._get_id(cr, uid, module, xml_id)
res_res_id = ir_model_data_obj.read(cr, uid, [id], res_res_id = ir_model_data_obj.read(cr, uid, [id],
['res_id']) ['res_id'])
if res_res_id: if res_res_id:
res_id = res_res_id[0]['res_id'] res_id = res_res_id[0]['res_id']
row[field[-1][:-3]] = res_id or False row[field[-1][:-3]] = res_id or False
continue continue
if (len(field) == len(prefix)+1) and \ if (len(field) == len(prefix)+1) and \
@ -962,7 +962,7 @@ class orm_template(object):
and getattr(self._columns[f], arg): and getattr(self._columns[f], arg):
res[f][arg] = getattr(self._columns[f], arg) res[f][arg] = getattr(self._columns[f], arg)
#TODO: optimize #TODO: optimize
res_trans = translation_obj._get_source(cr, user, self._name + ',' + f, 'field', context.get('lang', False) or 'en_US') res_trans = translation_obj._get_source(cr, user, self._name + ',' + f, 'field', context.get('lang', False) or 'en_US')
if res_trans: if res_trans:
res[f]['string'] = res_trans res[f]['string'] = res_trans
@ -1373,7 +1373,7 @@ class orm_template(object):
result['name'] = 'default' result['name'] = 'default'
result['field_parent'] = False result['field_parent'] = False
result['view_id'] = 0 result['view_id'] = 0
xarch, xfields = self.__view_look_dom_arch(cr, user, result['arch'], view_id, context=context) xarch, xfields = self.__view_look_dom_arch(cr, user, result['arch'], view_id, context=context)
result['arch'] = xarch result['arch'] = xarch
result['fields'] = xfields result['fields'] = xfields
@ -1454,7 +1454,7 @@ class orm_template(object):
self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'read', context=context) self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'read', context=context)
if not fields: if not fields:
fields = self._columns.keys() + self._inherit_fields.keys() fields = self._columns.keys() + self._inherit_fields.keys()
#FIXME: collect all calls to _get_source into one SQL call. #FIXME: collect all calls to _get_source into one SQL call.
for lang in langs: for lang in langs:
res[lang] = {'code': lang} res[lang] = {'code': lang}
for f in fields: for f in fields:
@ -1476,7 +1476,7 @@ class orm_template(object):
def write_string(self, cr, uid, id, langs, vals, context=None): def write_string(self, cr, uid, id, langs, vals, context=None):
self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'write', context=context) self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'write', context=context)
#FIXME: try to only call the translation in one SQL #FIXME: try to only call the translation in one SQL
for lang in langs: for lang in langs:
for field in vals: for field in vals:
if field in self._columns: if field in self._columns:
@ -1897,20 +1897,20 @@ class orm(orm_template):
"AND c.oid=a.attrelid " \ "AND c.oid=a.attrelid " \
"AND a.atttypid=t.oid", (self._table, k)) "AND a.atttypid=t.oid", (self._table, k))
res = cr.dictfetchall() res = cr.dictfetchall()
if not res and hasattr(f,'oldname'): if not res and hasattr(f,'oldname'):
cr.execute("SELECT c.relname,a.attname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,t.typname,CASE WHEN a.attlen=-1 THEN a.atttypmod-4 ELSE a.attlen END as size " \ cr.execute("SELECT c.relname,a.attname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,t.typname,CASE WHEN a.attlen=-1 THEN a.atttypmod-4 ELSE a.attlen END as size " \
"FROM pg_class c,pg_attribute a,pg_type t " \ "FROM pg_class c,pg_attribute a,pg_type t " \
"WHERE c.relname=%s " \ "WHERE c.relname=%s " \
"AND a.attname=%s " \ "AND a.attname=%s " \
"AND c.oid=a.attrelid " \ "AND c.oid=a.attrelid " \
"AND a.atttypid=t.oid", (self._table, f.oldname)) "AND a.atttypid=t.oid", (self._table, f.oldname))
res_old = cr.dictfetchall() res_old = cr.dictfetchall()
logger.notifyChannel('orm', netsvc.LOG_DEBUG, 'trying to rename %s(%s) to %s'% (self._table, f.oldname, k)) logger.notifyChannel('orm', netsvc.LOG_DEBUG, 'trying to rename %s(%s) to %s'% (self._table, f.oldname, k))
if res_old and len(res_old)==1: if res_old and len(res_old)==1:
cr.execute('ALTER TABLE "%s" RENAME "%s" TO "%s"' % ( self._table,f.oldname, k)) cr.execute('ALTER TABLE "%s" RENAME "%s" TO "%s"' % ( self._table,f.oldname, k))
res = res_old res = res_old
res[0]['attname'] = k res[0]['attname'] = k
if not res: if not res:
if not isinstance(f, fields.function) or f.store: if not isinstance(f, fields.function) or f.store:
@ -2342,7 +2342,7 @@ class orm(orm_template):
continue continue
if self._columns[f].translate: if self._columns[f].translate:
ids = map(lambda x: x['id'], res) ids = map(lambda x: x['id'], res)
#TODO: optimize out of this loop #TODO: optimize out of this loop
res_trans = self.pool.get('ir.translation')._get_ids(cr, user, self._name+','+f, 'model', context.get('lang', False) or 'en_US', ids) res_trans = self.pool.get('ir.translation')._get_ids(cr, user, self._name+','+f, 'model', context.get('lang', False) or 'en_US', ids)
for r in res: for r in res:
r[f] = res_trans.get(r['id'], False) or r[f] r[f] = res_trans.get(r['id'], False) or r[f]
@ -2658,7 +2658,7 @@ class orm(orm_template):
'where id in ('+ids_str+')', upd1) 'where id in ('+ids_str+')', upd1)
if totranslate: if totranslate:
# TODO: optimize # TODO: optimize
for f in direct: for f in direct:
if self._columns[f].translate: if self._columns[f].translate:
src_trans = self.pool.get(self._name).read(cr,user,ids,[f]) src_trans = self.pool.get(self._name).read(cr,user,ids,[f])
@ -3189,7 +3189,7 @@ class orm(orm_template):
data[f] = [(6, 0, data[f])] data[f] = [(6, 0, data[f])]
trans_obj = self.pool.get('ir.translation') trans_obj = self.pool.get('ir.translation')
#TODO: optimize translations #TODO: optimize translations
trans_name='' trans_name=''
for f in fields: for f in fields:
trans_flag=True trans_flag=True

View File

@ -80,7 +80,7 @@ class report_rml(report_int):
'html': self.create_html, 'html': self.create_html,
'raw': self.create_raw, 'raw': self.create_raw,
'sxw': self.create_sxw, 'sxw': self.create_sxw,
'txt': self.create_txt, 'txt': self.create_txt,
'odt': self.create_odt, 'odt': self.create_odt,
'html2html' : self.create_html2html, 'html2html' : self.create_html2html,
'makohtml2html' :self.create_makohtml2html, 'makohtml2html' :self.create_makohtml2html,

View File

@ -22,28 +22,28 @@
CustomTTFonts = [ ('Helvetica',"DejaVu Sans", "DejaVuSans.ttf", 'normal'), CustomTTFonts = [ ('Helvetica',"DejaVu Sans", "DejaVuSans.ttf", 'normal'),
('Helvetica',"DejaVu Sans Bold", "DejaVuSans-Bold.ttf", 'bold'), ('Helvetica',"DejaVu Sans Bold", "DejaVuSans-Bold.ttf", 'bold'),
('Helvetica',"DejaVu Sans Oblique", "DejaVuSans-Oblique.ttf", 'italic'), ('Helvetica',"DejaVu Sans Oblique", "DejaVuSans-Oblique.ttf", 'italic'),
('Helvetica',"DejaVu Sans BoldOblique", "DejaVuSans-BoldOblique.ttf", 'bolditalic'), ('Helvetica',"DejaVu Sans BoldOblique", "DejaVuSans-BoldOblique.ttf", 'bolditalic'),
('Times',"Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'), ('Times',"Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'),
('Times',"Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'), ('Times',"Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'),
('Times',"Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'), ('Times',"Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'),
('Times',"Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'), ('Times',"Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'),
('Times-Roman',"Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'), ('Times-Roman',"Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'),
('Times-Roman',"Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'), ('Times-Roman',"Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'),
('Times-Roman',"Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'), ('Times-Roman',"Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'),
('Times-Roman',"Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'), ('Times-Roman',"Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'),
('ZapfDingbats',"DejaVu Serif", "DejaVuSerif.ttf", 'normal'), ('ZapfDingbats',"DejaVu Serif", "DejaVuSerif.ttf", 'normal'),
('ZapfDingbats',"DejaVu Serif Bold", "DejaVuSerif-Bold.ttf", 'bold'), ('ZapfDingbats',"DejaVu Serif Bold", "DejaVuSerif-Bold.ttf", 'bold'),
('ZapfDingbats',"DejaVu Serif Italic", "DejaVuSerif-Italic.ttf", 'italic'), ('ZapfDingbats',"DejaVu Serif Italic", "DejaVuSerif-Italic.ttf", 'italic'),
('ZapfDingbats',"DejaVu Serif BoldItalic", "DejaVuSerif-BoldItalic.ttf", 'bolditalic'), ('ZapfDingbats',"DejaVu Serif BoldItalic", "DejaVuSerif-BoldItalic.ttf", 'bolditalic'),
('Courier',"FreeMono", "FreeMono.ttf", 'normal'), ('Courier',"FreeMono", "FreeMono.ttf", 'normal'),
('Courier',"FreeMono Bold", "FreeMonoBold.ttf", 'bold'), ('Courier',"FreeMono Bold", "FreeMonoBold.ttf", 'bold'),
('Courier',"FreeMono Oblique", "FreeMonoOblique.ttf", 'italic'), ('Courier',"FreeMono Oblique", "FreeMonoOblique.ttf", 'italic'),
('Courier',"FreeMono BoldOblique", "FreeMonoBoldOblique.ttf", 'bolditalic'),] ('Courier',"FreeMono BoldOblique", "FreeMonoBoldOblique.ttf", 'bolditalic'),]
def SetCustomFonts(rmldoc): def SetCustomFonts(rmldoc):
for name, font, fname, mode in CustomTTFonts: for name, font, fname, mode in CustomTTFonts:
rmldoc.setTTFontMapping(name, font,fname, mode) rmldoc.setTTFontMapping(name, font,fname, mode)
#eof #eof

View File

@ -167,21 +167,21 @@ class _rml_doc(object):
from reportlab.lib.fonts import addMapping from reportlab.lib.fonts import addMapping
from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase.ttfonts import TTFont
pdfmetrics.registerFont(TTFont(fontname, filename )) pdfmetrics.registerFont(TTFont(fontname, filename ))
if (mode == 'all'): if (mode == 'all'):
addMapping(face, 0, 0, fontname) #normal addMapping(face, 0, 0, fontname) #normal
addMapping(face, 0, 1, fontname) #italic addMapping(face, 0, 1, fontname) #italic
addMapping(face, 1, 0, fontname) #bold addMapping(face, 1, 0, fontname) #bold
addMapping(face, 1, 1, fontname) #italic and bold addMapping(face, 1, 1, fontname) #italic and bold
elif (mode== 'normal') or (mode == 'regular'): elif (mode== 'normal') or (mode == 'regular'):
addMapping(face, 0, 0, fontname) #normal addMapping(face, 0, 0, fontname) #normal
elif (mode == 'italic'): elif (mode == 'italic'):
addMapping(face, 0, 1, fontname) #italic addMapping(face, 0, 1, fontname) #italic
elif (mode == 'bold'): elif (mode == 'bold'):
addMapping(face, 1, 0, fontname) #bold addMapping(face, 1, 0, fontname) #bold
elif (mode == 'bolditalic'): elif (mode == 'bolditalic'):
addMapping(face, 1, 1, fontname) #italic and bold addMapping(face, 1, 1, fontname) #italic and bold
def _textual_image(self, node): def _textual_image(self, node):
rc = '' rc = ''
@ -797,10 +797,10 @@ def parseNode(rml, localcontext = {},fout=None, images={}, path='.',title=None):
r = _rml_doc(node, localcontext, images, path, title=title) r = _rml_doc(node, localcontext, images, path, title=title)
#try to override some font mappings #try to override some font mappings
try: try:
from customfonts import SetCustomFonts from customfonts import SetCustomFonts
SetCustomFonts(r) SetCustomFonts(r)
except: except:
pass pass
fp = cStringIO.StringIO() fp = cStringIO.StringIO()
r.render(fp) r.render(fp)
return fp.getvalue() return fp.getvalue()
@ -811,10 +811,10 @@ def parseString(rml, localcontext = {},fout=None, images={}, path='.',title=None
#try to override some font mappings #try to override some font mappings
try: try:
from customfonts import SetCustomFonts from customfonts import SetCustomFonts
SetCustomFonts(r) SetCustomFonts(r)
except: except:
pass pass
if fout: if fout:
fp = file(fout,'wb') fp = file(fout,'wb')

View File

@ -2,7 +2,7 @@
# -*- encoding: utf-8 -*- # -*- 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 # Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$ # $Id$
# #
@ -49,93 +49,93 @@ import utils
Font_size= 10.0 Font_size= 10.0
def verbose(text): def verbose(text):
sys.stderr.write(text+"\n"); sys.stderr.write(text+"\n");
class textbox(): class textbox():
"""A box containing plain text. """A box containing plain text.
It can have an offset, in chars. It can have an offset, in chars.
Lines can be either text strings, or textbox'es, recursively. Lines can be either text strings, or textbox'es, recursively.
""" """
def __init__(self,x=0, y=0): def __init__(self,x=0, y=0):
self.posx = x self.posx = x
self.posy = y self.posy = y
self.lines = [] self.lines = []
self.curline = '' self.curline = ''
self.endspace = False self.endspace = False
def newline(self): def newline(self):
if isinstance(self.curline, textbox): if isinstance(self.curline, textbox):
self.lines.extend(self.curline.renderlines()) self.lines.extend(self.curline.renderlines())
else: else:
self.lines.append(self.curline) self.lines.append(self.curline)
self.curline = '' self.curline = ''
def fline(self): def fline(self):
if isinstance(self.curline, textbox): if isinstance(self.curline, textbox):
self.lines.extend(self.curline.renderlines()) self.lines.extend(self.curline.renderlines())
elif len(self.curline): elif len(self.curline):
self.lines.append(self.curline) self.lines.append(self.curline)
self.curline = '' self.curline = ''
def appendtxt(self,txt): def appendtxt(self,txt):
"""Append some text to the current line. """Append some text to the current line.
Mimic the HTML behaviour, where all whitespace evaluates to Mimic the HTML behaviour, where all whitespace evaluates to
a single space """ a single space """
if not txt: if not txt:
return return
bs = es = False bs = es = False
if txt[0].isspace(): if txt[0].isspace():
bs = True bs = True
if txt[len(txt)-1].isspace(): if txt[len(txt)-1].isspace():
es = True es = True
if bs and not self.endspace: if bs and not self.endspace:
self.curline += " " self.curline += " "
self.curline += txt.strip().replace("\n"," ").replace("\t"," ") self.curline += txt.strip().replace("\n"," ").replace("\t"," ")
if es: if es:
self.curline += " " self.curline += " "
self.endspace = es self.endspace = es
def rendertxt(self,xoffset=0): def rendertxt(self,xoffset=0):
result = '' result = ''
lineoff = "" lineoff = ""
for i in range(self.posy): for i in range(self.posy):
result +="\n" result +="\n"
for i in range(self.posx+xoffset): for i in range(self.posx+xoffset):
lineoff+=" " lineoff+=" "
for l in self.lines: for l in self.lines:
result+= lineoff+ l +"\n" result+= lineoff+ l +"\n"
return result return result
def renderlines(self,pad=0): def renderlines(self,pad=0):
"""Returns a list of lines, from the current object """Returns a list of lines, from the current object
pad: all lines must be at least pad characters. pad: all lines must be at least pad characters.
""" """
result = [] result = []
lineoff = "" lineoff = ""
for i in range(self.posx): for i in range(self.posx):
lineoff+=" " lineoff+=" "
for l in self.lines: for l in self.lines:
lpad = "" lpad = ""
if pad and len(l) < pad : if pad and len(l) < pad :
for i in range(pad - len(l)): for i in range(pad - len(l)):
lpad += " " lpad += " "
#elif pad and len(l) > pad ? #elif pad and len(l) > pad ?
result.append(lineoff+ l+lpad) result.append(lineoff+ l+lpad)
return result return result
def haplines(self,arr,offset,cc= ''): def haplines(self,arr,offset,cc= ''):
""" Horizontaly append lines """ Horizontaly append lines
""" """
while (len(self.lines) < len(arr)): while (len(self.lines) < len(arr)):
self.lines.append("") self.lines.append("")
for i in range(len(self.lines)): for i in range(len(self.lines)):
while (len(self.lines[i]) < offset): while (len(self.lines[i]) < offset):
self.lines[i] += " " self.lines[i] += " "
for i in range(len(arr)): for i in range(len(arr)):
self.lines[i] += cc +arr[i] self.lines[i] += cc +arr[i]
class _flowable(object): class _flowable(object):
def __init__(self, template, doc,localcontext): def __init__(self, template, doc,localcontext):
@ -143,8 +143,8 @@ class _flowable(object):
'1title': self._tag_title, '1title': self._tag_title,
'1spacer': self._tag_spacer, '1spacer': self._tag_spacer,
'para': self._tag_para, 'para': self._tag_para,
'font': self._tag_font, 'font': self._tag_font,
'section': self._tag_section, 'section': self._tag_section,
'1nextFrame': self._tag_next_frame, '1nextFrame': self._tag_next_frame,
'blockTable': self._tag_table, 'blockTable': self._tag_table,
'1pageBreak': self._tag_page_break, '1pageBreak': self._tag_page_break,
@ -152,15 +152,15 @@ class _flowable(object):
} }
self.template = template self.template = template
self.doc = doc self.doc = doc
self.localcontext = localcontext self.localcontext = localcontext
self.nitags = [] self.nitags = []
self.tbox = None self.tbox = None
def warn_nitag(self,tag): def warn_nitag(self,tag):
if tag not in self.nitags: if tag not in self.nitags:
verbose("Unknown tag \"%s\", please implement it." % tag) verbose("Unknown tag \"%s\", please implement it." % tag)
self.nitags.append(tag) self.nitags.append(tag)
def _tag_page_break(self, node): def _tag_page_break(self, node):
return "\f" return "\f"
@ -182,79 +182,79 @@ class _flowable(object):
return "\n"*length return "\n"*length
def _tag_table(self, node): def _tag_table(self, node):
self.tb.fline() self.tb.fline()
saved_tb = self.tb saved_tb = self.tb
self.tb = None self.tb = None
sizes = None sizes = None
if node.get('colWidths'): if node.get('colWidths'):
sizes = map(lambda x: utils.unit_get(x), node.get('colWidths').split(',')) sizes = map(lambda x: utils.unit_get(x), node.get('colWidths').split(','))
trs = [] trs = []
for n in utils._child_get(node,self): for n in utils._child_get(node,self):
if n.tag == 'tr': if n.tag == 'tr':
tds = [] tds = []
for m in utils._child_get(n,self): for m in utils._child_get(n,self):
if m.tag == 'td': if m.tag == 'td':
self.tb = textbox() self.tb = textbox()
self.rec_render_cnodes(m) self.rec_render_cnodes(m)
tds.append(self.tb) tds.append(self.tb)
self.tb = None self.tb = None
if len(tds): if len(tds):
trs.append(tds) trs.append(tds)
if not sizes: if not sizes:
verbose("computing table sizes..") verbose("computing table sizes..")
for tds in trs: for tds in trs:
trt = textbox() trt = textbox()
off=0 off=0
for i in range(len(tds)): for i in range(len(tds)):
p = int(sizes[i]/Font_size) p = int(sizes[i]/Font_size)
trl = tds[i].renderlines(pad=p) trl = tds[i].renderlines(pad=p)
trt.haplines(trl,off) trt.haplines(trl,off)
off += sizes[i]/Font_size off += sizes[i]/Font_size
saved_tb.curline = trt saved_tb.curline = trt
saved_tb.fline() saved_tb.fline()
self.tb = saved_tb self.tb = saved_tb
return return
def _tag_para(self, node): def _tag_para(self, node):
#TODO: styles #TODO: styles
self.rec_render_cnodes(node) self.rec_render_cnodes(node)
self.tb.newline() self.tb.newline()
def _tag_section(self, node): def _tag_section(self, node):
#TODO: styles #TODO: styles
self.rec_render_cnodes(node) self.rec_render_cnodes(node)
self.tb.newline() self.tb.newline()
def _tag_font(self, node): def _tag_font(self, node):
"""We do ignore fonts..""" """We do ignore fonts.."""
self.rec_render_cnodes(node) self.rec_render_cnodes(node)
def rec_render_cnodes(self,node): def rec_render_cnodes(self,node):
self.tb.appendtxt(utils._process_text(self, node.text or '')) self.tb.appendtxt(utils._process_text(self, node.text or ''))
for n in utils._child_get(node,self): for n in utils._child_get(node,self):
self.rec_render(n) self.rec_render(n)
self.tb.appendtxt(utils._process_text(self, node.tail or '')) self.tb.appendtxt(utils._process_text(self, node.tail or ''))
def rec_render(self,node): def rec_render(self,node):
""" Recursive render: fill outarr with text of current node """ Recursive render: fill outarr with text of current node
""" """
if node.tag != None: if node.tag != None:
if node.tag in self._tags: if node.tag in self._tags:
self._tags[node.tag](node) self._tags[node.tag](node)
else: else:
self.warn_nitag(node.tag) self.warn_nitag(node.tag)
def render(self, node): def render(self, node):
self.tb= textbox() self.tb= textbox()
#result = self.template.start() #result = self.template.start()
#result += self.template.frame_start() #result += self.template.frame_start()
self.rec_render_cnodes(node) self.rec_render_cnodes(node)
#result += self.template.frame_stop() #result += self.template.frame_stop()
#result += self.template.end() #result += self.template.end()
result = self.tb.rendertxt() result = self.tb.rendertxt()
del self.tb del self.tb
return result return result
class _rml_tmpl_tag(object): class _rml_tmpl_tag(object):
@ -274,12 +274,12 @@ class _rml_tmpl_frame(_rml_tmpl_tag):
self.width = width self.width = width
self.posx = posx self.posx = posx
def tag_start(self): def tag_start(self):
return "frame start" return "frame start"
return '<table border="0" width="%d"><tr><td width="%d">&nbsp;</td><td>' % (self.width+self.posx,self.posx) return '<table border="0" width="%d"><tr><td width="%d">&nbsp;</td><td>' % (self.width+self.posx,self.posx)
def tag_end(self): def tag_end(self):
return True return True
def tag_stop(self): def tag_stop(self):
return "frame stop" return "frame stop"
return '</td></tr></table><br/>' return '</td></tr></table><br/>'
def tag_mergeable(self): def tag_mergeable(self):
return False return False
@ -301,7 +301,7 @@ class _rml_tmpl_draw_string(_rml_tmpl_tag):
self.pos = [(self.posx, self.posy, align, utils.text_get(node), style.get('td'), style.font_size_get('td'))] self.pos = [(self.posx, self.posy, align, utils.text_get(node), style.get('td'), style.font_size_get('td'))]
def tag_start(self): def tag_start(self):
return "draw string \"%s\" @(%d,%d)..\n" %("txt",self.posx,self.posy) return "draw string \"%s\" @(%d,%d)..\n" %("txt",self.posx,self.posy)
self.pos.sort() self.pos.sort()
res = '\\table ...' res = '\\table ...'
posx = 0 posx = 0
@ -335,7 +335,7 @@ class _rml_tmpl_draw_lines(_rml_tmpl_tag):
self.style = style.get('hr') self.style = style.get('hr')
def tag_start(self): def tag_start(self):
return "draw lines..\n" return "draw lines..\n"
if self.ok: if self.ok:
return '<table border="0" cellpadding="0" cellspacing="0" width="%d"><tr><td width="%d"></td><td><hr width="100%%" style="margin:0px; %s"></td></tr></table>' % (self.posx+self.width,self.posx,self.style) return '<table border="0" cellpadding="0" cellspacing="0" width="%d"><tr><td width="%d"></td><td><hr width="100%%" style="margin:0px; %s"></td></tr></table>' % (self.posx+self.width,self.posx,self.style)
else: else:
@ -475,7 +475,7 @@ class _rml_template(object):
return '' return ''
def end(self): def end(self):
return "template end\n" return "template end\n"
result = '' result = ''
while not self.loop: while not self.loop:
result += self.frame_start() result += self.frame_start()
@ -498,16 +498,16 @@ class _rml_doc(object):
#self.styles = _rml_styles(el,self.localcontext) #self.styles = _rml_styles(el,self.localcontext)
el = self.etree.findall('template') el = self.etree.findall('template')
self.result ="" self.result =""
if len(el): if len(el):
pt_obj = _rml_template(self.localcontext, out, el[0], self) pt_obj = _rml_template(self.localcontext, out, el[0], self)
stories = utils._child_get(self.etree, self, 'story') stories = utils._child_get(self.etree, self, 'story')
for story in stories: for story in stories:
if self.result: if self.result:
self.result += '\f' self.result += '\f'
f = _flowable(pt_obj,story,self.localcontext) f = _flowable(pt_obj,story,self.localcontext)
self.result += f.render(story) self.result += f.render(story)
del f del f
else: else:
self.result = "<cannot render w/o template>" self.result = "<cannot render w/o template>"
self.result += '\n' self.result += '\n'

View File

@ -46,15 +46,15 @@ except ImportError:
fcntl = None fcntl = None
try: try:
from ssl import SSLError from ssl import SSLError
except ImportError: except ImportError:
class SSLError(Exception): pass class SSLError(Exception): pass
class ThreadedHTTPServer(ConnThreadingMixIn, SimpleXMLRPCDispatcher, HTTPServer): class ThreadedHTTPServer(ConnThreadingMixIn, SimpleXMLRPCDispatcher, HTTPServer):
""" A threaded httpd server, with all the necessary functionality for us. """ A threaded httpd server, with all the necessary functionality for us.
It also inherits the xml-rpc dispatcher, so that some xml-rpc functions It also inherits the xml-rpc dispatcher, so that some xml-rpc functions
will be available to the request handler will be available to the request handler
""" """
encoding = None encoding = None
allow_none = False allow_none = False
@ -81,46 +81,46 @@ class ThreadedHTTPServer(ConnThreadingMixIn, SimpleXMLRPCDispatcher, HTTPServer)
""" Override the error handler """ Override the error handler
""" """
import traceback import traceback
netsvc.Logger().notifyChannel("init", netsvc.LOG_ERROR,"Server error in request from %s:\n%s" % netsvc.Logger().notifyChannel("init", netsvc.LOG_ERROR,"Server error in request from %s:\n%s" %
(client_address,traceback.format_exc())) (client_address,traceback.format_exc()))
class MultiHandler2(MultiHTTPHandler): class MultiHandler2(MultiHTTPHandler):
def log_message(self, format, *args): def log_message(self, format, *args):
netsvc.Logger().notifyChannel('http',netsvc.LOG_DEBUG,format % args) netsvc.Logger().notifyChannel('http',netsvc.LOG_DEBUG,format % args)
def log_error(self, format, *args): def log_error(self, format, *args):
netsvc.Logger().notifyChannel('http',netsvc.LOG_ERROR,format % args) netsvc.Logger().notifyChannel('http',netsvc.LOG_ERROR,format % args)
class SecureMultiHandler2(SecureMultiHTTPHandler): class SecureMultiHandler2(SecureMultiHTTPHandler):
def log_message(self, format, *args): def log_message(self, format, *args):
netsvc.Logger().notifyChannel('https',netsvc.LOG_DEBUG,format % args) netsvc.Logger().notifyChannel('https',netsvc.LOG_DEBUG,format % args)
def getcert_fnames(self): def getcert_fnames(self):
tc = tools.config tc = tools.config
fcert = tc.get_misc('httpsd','sslcert', 'ssl/server.cert') fcert = tc.get_misc('httpsd','sslcert', 'ssl/server.cert')
fkey = tc.get_misc('httpsd','sslkey', 'ssl/server.key') fkey = tc.get_misc('httpsd','sslkey', 'ssl/server.key')
return (fcert,fkey) return (fcert,fkey)
def log_message(self, format, *args): def log_message(self, format, *args):
netsvc.Logger().notifyChannel('http',netsvc.LOG_DEBUG,format % args) netsvc.Logger().notifyChannel('http',netsvc.LOG_DEBUG,format % args)
def log_error(self, format, *args): def log_error(self, format, *args):
netsvc.Logger().notifyChannel('http',netsvc.LOG_ERROR,format % args) netsvc.Logger().notifyChannel('http',netsvc.LOG_ERROR,format % args)
class HttpDaemon(threading.Thread, netsvc.Server): class HttpDaemon(threading.Thread, netsvc.Server):
def __init__(self, interface, port): def __init__(self, interface, port):
threading.Thread.__init__(self) threading.Thread.__init__(self)
netsvc.Server.__init__(self) netsvc.Server.__init__(self)
self.__port = port self.__port = port
self.__interface = interface self.__interface = interface
try: try:
self.server = ThreadedHTTPServer((interface, port), MultiHandler2) self.server = ThreadedHTTPServer((interface, port), MultiHandler2)
self.server.vdirs = [] self.server.vdirs = []
self.server.logRequests = True self.server.logRequests = True
netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO, netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO,
"starting HTTP service at %s port %d" % (interface or '0.0.0.0', port,)) "starting HTTP service at %s port %d" % (interface or '0.0.0.0', port,))
except Exception, e: except Exception, e:
netsvc.Logger().notifyChannel('httpd', netsvc.LOG_CRITICAL, "Error occur when starting the server daemon: %s" % (e,)) netsvc.Logger().notifyChannel('httpd', netsvc.LOG_CRITICAL, "Error occur when starting the server daemon: %s" % (e,))
raise raise
@ -146,16 +146,16 @@ class HttpDaemon(threading.Thread, netsvc.Server):
class HttpSDaemon(threading.Thread, netsvc.Server): class HttpSDaemon(threading.Thread, netsvc.Server):
def __init__(self, interface, port): def __init__(self, interface, port):
threading.Thread.__init__(self) threading.Thread.__init__(self)
netsvc.Server.__init__(self) netsvc.Server.__init__(self)
self.__port = port self.__port = port
self.__interface = interface self.__interface = interface
try: try:
self.server = ThreadedHTTPServer((interface, port), SecureMultiHandler2) self.server = ThreadedHTTPServer((interface, port), SecureMultiHandler2)
self.server.vdirs = [] self.server.vdirs = []
self.server.logRequests = True self.server.logRequests = True
netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO, netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO,
"starting HTTPS service at %s port %d" % (interface or '0.0.0.0', port,)) "starting HTTPS service at %s port %d" % (interface or '0.0.0.0', port,))
except SSLError, e: except SSLError, e:
netsvc.Logger().notifyChannel('httpd-ssl', netsvc.LOG_CRITICAL, "Can not load the certificate and/or the private key files") netsvc.Logger().notifyChannel('httpd-ssl', netsvc.LOG_CRITICAL, "Can not load the certificate and/or the private key files")
raise raise
@ -184,32 +184,32 @@ httpd = None
httpsd = None httpsd = None
def init_servers(): def init_servers():
global httpd, httpsd global httpd, httpsd
if tools.config.get_misc('httpd','enable', True): if tools.config.get_misc('httpd','enable', True):
httpd = HttpDaemon(tools.config.get_misc('httpd','interface', ''), \ httpd = HttpDaemon(tools.config.get_misc('httpd','interface', ''), \
tools.config.get_misc('httpd','port', 8069)) tools.config.get_misc('httpd','port', 8069))
if tools.config.get_misc('httpsd','enable', False): if tools.config.get_misc('httpsd','enable', False):
httpsd = HttpSDaemon(tools.config.get_misc('httpsd','interface', ''), \ httpsd = HttpSDaemon(tools.config.get_misc('httpsd','interface', ''), \
tools.config.get_misc('httpsd','port', 8071)) tools.config.get_misc('httpsd','port', 8071))
def reg_http_service(hts, secure_only = False): def reg_http_service(hts, secure_only = False):
""" Register some handler to httpd. """ Register some handler to httpd.
hts must be an HTTPDir hts must be an HTTPDir
""" """
global httpd, httpsd global httpd, httpsd
if not isinstance(hts, HTTPDir): if not isinstance(hts, HTTPDir):
raise Exception("Wrong class for http service") raise Exception("Wrong class for http service")
if httpd and not secure_only: if httpd and not secure_only:
httpd.server.vdirs.append(hts) httpd.server.vdirs.append(hts)
if httpsd: if httpsd:
httpsd.server.vdirs.append(hts) httpsd.server.vdirs.append(hts)
if (not httpd) and (not httpsd): if (not httpd) and (not httpsd):
netsvc.Logger().notifyChannel('httpd',netsvc.LOG_WARNING,"No httpd available to register service %s" % hts.path) netsvc.Logger().notifyChannel('httpd',netsvc.LOG_WARNING,"No httpd available to register service %s" % hts.path)
return return
import SimpleXMLRPCServer import SimpleXMLRPCServer
class XMLRPCRequestHandler(netsvc.OpenERPDispatcher,FixSendError,SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): class XMLRPCRequestHandler(netsvc.OpenERPDispatcher,FixSendError,SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
@ -223,7 +223,7 @@ class XMLRPCRequestHandler(netsvc.OpenERPDispatcher,FixSendError,SimpleXMLRPCSer
raise xmlrpclib.Fault(tools.exception_to_unicode(e.exception), e.traceback) raise xmlrpclib.Fault(tools.exception_to_unicode(e.exception), e.traceback)
def log_message(self, format, *args): def log_message(self, format, *args):
netsvc.Logger().notifyChannel('xmlrpc',netsvc.LOG_DEBUG_RPC,format % args) netsvc.Logger().notifyChannel('xmlrpc',netsvc.LOG_DEBUG_RPC,format % args)
def handle(self): def handle(self):
pass pass
@ -233,87 +233,87 @@ class XMLRPCRequestHandler(netsvc.OpenERPDispatcher,FixSendError,SimpleXMLRPCSer
def setup(self): def setup(self):
self.connection = dummyconn() self.connection = dummyconn()
if not len(XMLRPCRequestHandler.rpc_paths): if not len(XMLRPCRequestHandler.rpc_paths):
XMLRPCRequestHandler.rpc_paths = map(lambda s: '/%s' % s, netsvc.ExportService._services.keys()) XMLRPCRequestHandler.rpc_paths = map(lambda s: '/%s' % s, netsvc.ExportService._services.keys())
pass pass
def init_xmlrpc(): def init_xmlrpc():
if not tools.config.get_misc('xmlrpc','enable', True): if not tools.config.get_misc('xmlrpc','enable', True):
return return
reg_http_service(HTTPDir('/xmlrpc/',XMLRPCRequestHandler)) reg_http_service(HTTPDir('/xmlrpc/',XMLRPCRequestHandler))
# Example of http file serving: # Example of http file serving:
# reg_http_service(HTTPDir('/test/',HTTPHandler)) # reg_http_service(HTTPDir('/test/',HTTPHandler))
netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO, netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO,
"Registered XML-RPC over HTTP") "Registered XML-RPC over HTTP")
class OerpAuthProxy(AuthProxy): class OerpAuthProxy(AuthProxy):
""" Require basic authentication.. """ Require basic authentication..
This is a copy of the BasicAuthProxy, which however checks/caches the db This is a copy of the BasicAuthProxy, which however checks/caches the db
as well. as well.
""" """
def __init__(self,provider): def __init__(self,provider):
AuthProxy.__init__(self,provider) AuthProxy.__init__(self,provider)
self.auth_creds = {} self.auth_creds = {}
self.auth_tries = 0 self.auth_tries = 0
self.last_auth = None self.last_auth = None
def checkRequest(self,handler,path = '/'): def checkRequest(self,handler,path = '/'):
if self.auth_creds: if self.auth_creds:
return True return True
auth_str = handler.headers.get('Authorization',False) auth_str = handler.headers.get('Authorization',False)
try: try:
db = handler.get_db_from_path(path) db = handler.get_db_from_path(path)
print "Got db:",db print "Got db:",db
except: except:
if path.startswith('/'): if path.startswith('/'):
path = path[1:] path = path[1:]
psp= path.split('/') psp= path.split('/')
if len(psp)>1: if len(psp)>1:
db = psp[0] db = psp[0]
else: else:
#FIXME! #FIXME!
self.provider.log("Wrong path: %s, failing auth" %path) self.provider.log("Wrong path: %s, failing auth" %path)
raise AuthRejectedExc("Authorization failed. Wrong sub-path.") raise AuthRejectedExc("Authorization failed. Wrong sub-path.")
if auth_str and auth_str.startswith('Basic '): if auth_str and auth_str.startswith('Basic '):
auth_str=auth_str[len('Basic '):] auth_str=auth_str[len('Basic '):]
(user,passwd) = base64.decodestring(auth_str).split(':') (user,passwd) = base64.decodestring(auth_str).split(':')
self.provider.log("Found user=\"%s\", passwd=\"***\" for db=\"%s\"" %(user,db)) self.provider.log("Found user=\"%s\", passwd=\"***\" for db=\"%s\"" %(user,db))
acd = self.provider.authenticate(db,user,passwd,handler.client_address) acd = self.provider.authenticate(db,user,passwd,handler.client_address)
if acd != False: if acd != False:
self.auth_creds[db] = acd self.auth_creds[db] = acd
self.last_auth=db self.last_auth=db
return True return True
if self.auth_tries > 5: if self.auth_tries > 5:
self.provider.log("Failing authorization after 5 requests w/o password") self.provider.log("Failing authorization after 5 requests w/o password")
raise AuthRejectedExc("Authorization failed.") raise AuthRejectedExc("Authorization failed.")
self.auth_tries += 1 self.auth_tries += 1
raise AuthRequiredExc(atype = 'Basic', realm=self.provider.realm) raise AuthRequiredExc(atype = 'Basic', realm=self.provider.realm)
import security import security
class OpenERPAuthProvider(AuthProvider): class OpenERPAuthProvider(AuthProvider):
def __init__(self,realm = 'OpenERP User'): def __init__(self,realm = 'OpenERP User'):
self.realm = realm self.realm = realm
def setupAuth(self, multi, handler): def setupAuth(self, multi, handler):
if not multi.sec_realms.has_key(self.realm): if not multi.sec_realms.has_key(self.realm):
multi.sec_realms[self.realm] = OerpAuthProxy(self) multi.sec_realms[self.realm] = OerpAuthProxy(self)
handler.auth_proxy = multi.sec_realms[self.realm] handler.auth_proxy = multi.sec_realms[self.realm]
def authenticate(self, db, user, passwd, client_address): def authenticate(self, db, user, passwd, client_address):
try: try:
uid = security.login(db,user,passwd) uid = security.login(db,user,passwd)
if uid is False: if uid is False:
return False return False
return (user, passwd, db, uid) return (user, passwd, db, uid)
except Exception,e: except Exception,e:
netsvc.Logger().notifyChannel("auth",netsvc.LOG_DEBUG,"Fail auth:"+ str(e)) netsvc.Logger().notifyChannel("auth",netsvc.LOG_DEBUG,"Fail auth:"+ str(e))
return False return False
def log(self, msg): def log(self, msg):
netsvc.Logger().notifyChannel("auth",netsvc.LOG_INFO,msg) netsvc.Logger().notifyChannel("auth",netsvc.LOG_INFO,msg)
#eof #eof

View File

@ -141,23 +141,23 @@ class TinySocketServerThread(threading.Thread,netsvc.Server):
return False return False
def stats(self): def stats(self):
res = "Net-RPC: " + ( (self.running and "running") or "stopped") res = "Net-RPC: " + ( (self.running and "running") or "stopped")
i = 0 i = 0
for t in self.threads: for t in self.threads:
i += 1 i += 1
res += "\nNet-RPC #%d: %s " % (i, t.name) res += "\nNet-RPC #%d: %s " % (i, t.name)
if t.isAlive(): if t.isAlive():
res += "running" res += "running"
else: else:
res += "finished" res += "finished"
if t.sock: if t.sock:
res += ", socket" res += ", socket"
return res return res
netrpcd = None netrpcd = None
def init_servers(): def init_servers():
global netrpcd global netrpcd
if tools.config.get_misc('netrpcd','enable', True): if tools.config.get_misc('netrpcd','enable', True):
netrpcd = TinySocketServerThread(tools.config.get_misc('netrpcd','interface', ''), \ netrpcd = TinySocketServerThread(tools.config.get_misc('netrpcd','interface', ''), \
tools.config.get_misc('netrpcd','port', 8070)) tools.config.get_misc('netrpcd','port', 8070))

View File

@ -51,23 +51,23 @@ class db(netsvc.ExportService):
self._pg_psw_env_var_is_set = False # on win32, pg_dump need the PGPASSWORD env var self._pg_psw_env_var_is_set = False # on win32, pg_dump need the PGPASSWORD env var
def dispatch(self, method, auth, params): def dispatch(self, method, auth, params):
if method in [ 'create', 'get_progress', 'drop', 'dump', if method in [ 'create', 'get_progress', 'drop', 'dump',
'restore', 'rename', 'restore', 'rename',
'change_admin_password', 'migrate_databases' ]: 'change_admin_password', 'migrate_databases' ]:
passwd = params[0] passwd = params[0]
params = params[1:] params = params[1:]
security.check_super(passwd) security.check_super(passwd)
elif method in [ 'db_exist', 'list', 'list_lang', 'server_version' ]: elif method in [ 'db_exist', 'list', 'list_lang', 'server_version' ]:
# params = params # params = params
# No security check for these methods # No security check for these methods
pass pass
else: else:
raise KeyError("Method not found: %s" % method) raise KeyError("Method not found: %s" % method)
fn = getattr(self, 'exp_'+method) fn = getattr(self, 'exp_'+method)
return fn(*params) return fn(*params)
def new_dispatch(self,method,auth,params): def new_dispatch(self,method,auth,params):
pass pass
def exp_create(self, db_name, demo, lang, user_password='admin'): def exp_create(self, db_name, demo, lang, user_password='admin'):
self.id_protect.acquire() self.id_protect.acquire()
@ -366,15 +366,15 @@ class _ObjectService(netsvc.ExportService):
"A common base class for those who have fn(db, uid, password,...) " "A common base class for those who have fn(db, uid, password,...) "
def common_dispatch(self, method, auth, params): def common_dispatch(self, method, auth, params):
(db, uid, passwd ) = params[0:3] (db, uid, passwd ) = params[0:3]
params = params[3:] params = params[3:]
security.check(db,uid,passwd) security.check(db,uid,passwd)
cr = pooler.get_db(db).cursor() cr = pooler.get_db(db).cursor()
fn = getattr(self, 'exp_'+method) fn = getattr(self, 'exp_'+method)
res = fn(cr, uid, *params) res = fn(cr, uid, *params)
cr.commit() cr.commit()
cr.close() cr.close()
return res return res
class common(_ObjectService): class common(_ObjectService):
def __init__(self,name="common"): def __init__(self,name="common"):
@ -382,36 +382,36 @@ class common(_ObjectService):
self.joinGroup("web-services") self.joinGroup("web-services")
def dispatch(self, method, auth, params): def dispatch(self, method, auth, params):
logger = netsvc.Logger() logger = netsvc.Logger()
if method in [ 'ir_set','ir_del', 'ir_get' ]: if method in [ 'ir_set','ir_del', 'ir_get' ]:
return self.common_dispatch(method,auth,params) return self.common_dispatch(method,auth,params)
if method == 'login': if method == 'login':
# At this old dispatcher, we do NOT update the auth proxy # At this old dispatcher, we do NOT update the auth proxy
res = security.login(params[0], params[1], params[2]) res = security.login(params[0], params[1], params[2])
msg = res and 'successful login' or 'bad login or password' msg = res and 'successful login' or 'bad login or password'
# TODO log the client ip address.. # TODO log the client ip address..
logger.notifyChannel("web-service", netsvc.LOG_INFO, "%s from '%s' using database '%s'" % (msg, params[1], params[0].lower())) logger.notifyChannel("web-service", netsvc.LOG_INFO, "%s from '%s' using database '%s'" % (msg, params[1], params[0].lower()))
return res or False return res or False
elif method == 'logout': elif method == 'logout':
if auth: if auth:
auth.logout(params[1]) auth.logout(params[1])
logger.notifyChannel("web-service", netsvc.LOG_INFO,'Logout %s from database %s'%(login,db)) logger.notifyChannel("web-service", netsvc.LOG_INFO,'Logout %s from database %s'%(login,db))
return True return True
elif method in ['about', 'timezone_get', 'get_server_environment', 'login_message', 'get_stats' ]: elif method in ['about', 'timezone_get', 'get_server_environment', 'login_message', 'get_stats' ]:
pass pass
elif method in ['get_available_updates', 'get_migration_scripts', 'set_loglevel']: elif method in ['get_available_updates', 'get_migration_scripts', 'set_loglevel']:
passwd = params[0] passwd = params[0]
params = params[1:] params = params[1:]
security.check_super(passwd) security.check_super(passwd)
else: else:
raise Exception("Method not found: %s" % method) raise Exception("Method not found: %s" % method)
fn = getattr(self, 'exp_'+method) fn = getattr(self, 'exp_'+method)
return fn(*params) return fn(*params)
def new_dispatch(self,method,auth,params): def new_dispatch(self,method,auth,params):
pass pass
def exp_ir_set(self, cr, uid, keys, args, name, value, replace=True, isobject=False): def exp_ir_set(self, cr, uid, keys, args, name, value, replace=True, isobject=False):
res = ir.ir_set(cr,uid, keys, args, name, value, replace, isobject) res = ir.ir_set(cr,uid, keys, args, name, value, replace, isobject)
@ -574,7 +574,7 @@ GNU Public Licence.
def exp_get_stats(self): def exp_get_stats(self):
import threading import threading
res = "OpenERP server: %d threads\n" % threading.active_count() res = "OpenERP server: %d threads\n" % threading.active_count()
res += netsvc.Server.allStats() res += netsvc.Server.allStats()
return res return res
common() common()
@ -585,19 +585,19 @@ class objects_proxy(netsvc.ExportService):
self.joinGroup('web-services') self.joinGroup('web-services')
def dispatch(self, method, auth, params): def dispatch(self, method, auth, params):
(db, uid, passwd ) = params[0:3] (db, uid, passwd ) = params[0:3]
params = params[3:] params = params[3:]
if method not in ['execute','exec_workflow','obj_list']: if method not in ['execute','exec_workflow','obj_list']:
raise KeyError("Method not supported %s" % method) raise KeyError("Method not supported %s" % method)
security.check(db,uid,passwd) security.check(db,uid,passwd)
ls = netsvc.LocalService('object_proxy') ls = netsvc.LocalService('object_proxy')
fn = getattr(ls, method) fn = getattr(ls, method)
res = fn(db, uid, *params) res = fn(db, uid, *params)
return res return res
def new_dispatch(self,method,auth,params): def new_dispatch(self,method,auth,params):
pass pass
objects_proxy() objects_proxy()
@ -623,17 +623,17 @@ class wizard(netsvc.ExportService):
self.wiz_uid = {} self.wiz_uid = {}
def dispatch(self, method, auth, params): def dispatch(self, method, auth, params):
(db, uid, passwd ) = params[0:3] (db, uid, passwd ) = params[0:3]
params = params[3:] params = params[3:]
if method not in ['execute','create']: if method not in ['execute','create']:
raise KeyError("Method not supported %s" % method) raise KeyError("Method not supported %s" % method)
security.check(db,uid,passwd) security.check(db,uid,passwd)
fn = getattr(self, 'exp_'+method) fn = getattr(self, 'exp_'+method)
res = fn(db, uid, *params) res = fn(db, uid, *params)
return res return res
def new_dispatch(self,method,auth,params): def new_dispatch(self,method,auth,params):
pass pass
def _execute(self, db, uid, wiz_id, datas, action, context): def _execute(self, db, uid, wiz_id, datas, action, context):
self.wiz_datas[wiz_id].update(datas) self.wiz_datas[wiz_id].update(datas)
@ -685,18 +685,18 @@ class report_spool(netsvc.ExportService):
self.id_protect = threading.Semaphore() self.id_protect = threading.Semaphore()
def dispatch(self, method, auth, params): def dispatch(self, method, auth, params):
(db, uid, passwd ) = params[0:3] (db, uid, passwd ) = params[0:3]
params = params[3:] params = params[3:]
if method not in ['report','report_get']: if method not in ['report','report_get']:
raise KeyError("Method not supported %s" % method) raise KeyError("Method not supported %s" % method)
security.check(db,uid,passwd) security.check(db,uid,passwd)
fn = getattr(self, 'exp_' + method) fn = getattr(self, 'exp_' + method)
res = fn(db, uid, *params) res = fn(db, uid, *params)
return res return res
def new_dispatch(self,method,auth,params): def new_dispatch(self,method,auth,params):
pass pass
def exp_report(self, db, uid, object, ids, datas=None, context=None): def exp_report(self, db, uid, object, ids, datas=None, context=None):
if not datas: if not datas:

View File

@ -37,115 +37,115 @@ from BaseHTTPServer import *
from SimpleHTTPServer import SimpleHTTPRequestHandler from SimpleHTTPServer import SimpleHTTPRequestHandler
class AuthRequiredExc(Exception): class AuthRequiredExc(Exception):
def __init__(self,atype,realm): def __init__(self,atype,realm):
Exception.__init__(self) Exception.__init__(self)
self.atype = atype self.atype = atype
self.realm = realm self.realm = realm
class AuthRejectedExc(Exception): class AuthRejectedExc(Exception):
pass pass
class AuthProvider: class AuthProvider:
def __init__(self,realm): def __init__(self,realm):
self.realm = realm self.realm = realm
def setupAuth(self, multi,handler): def setupAuth(self, multi,handler):
""" Attach an AuthProxy object to handler """ Attach an AuthProxy object to handler
""" """
pass pass
def authenticate(self, user, passwd, client_address): def authenticate(self, user, passwd, client_address):
return False return False
def log(self, msg): def log(self, msg):
print msg print msg
class BasicAuthProvider(AuthProvider): class BasicAuthProvider(AuthProvider):
def setupAuth(self, multi, handler): def setupAuth(self, multi, handler):
if not multi.sec_realms.has_key(self.realm): if not multi.sec_realms.has_key(self.realm):
multi.sec_realms[self.realm] = BasicAuthProxy(self) multi.sec_realms[self.realm] = BasicAuthProxy(self)
class AuthProxy: class AuthProxy:
""" This class will hold authentication information for a handler, """ This class will hold authentication information for a handler,
i.e. a connection i.e. a connection
""" """
def __init__(self, provider): def __init__(self, provider):
self.provider = provider self.provider = provider
def checkRequest(self,handler,path = '/'): def checkRequest(self,handler,path = '/'):
""" Check if we are allowed to process that request """ Check if we are allowed to process that request
""" """
pass pass
class BasicAuthProxy(AuthProxy): class BasicAuthProxy(AuthProxy):
""" Require basic authentication.. """ Require basic authentication..
""" """
def __init__(self,provider): def __init__(self,provider):
AuthProxy.__init__(self,provider) AuthProxy.__init__(self,provider)
self.auth_creds = None self.auth_creds = None
self.auth_tries = 0 self.auth_tries = 0
def checkRequest(self,handler,path = '/'): def checkRequest(self,handler,path = '/'):
if self.auth_creds: if self.auth_creds:
return True return True
auth_str = handler.headers.get('Authorization',False) auth_str = handler.headers.get('Authorization',False)
if auth_str and auth_str.startswith('Basic '): if auth_str and auth_str.startswith('Basic '):
auth_str=auth_str[len('Basic '):] auth_str=auth_str[len('Basic '):]
(user,passwd) = base64.decodestring(auth_str).split(':') (user,passwd) = base64.decodestring(auth_str).split(':')
self.provider.log("Found user=\"%s\", passwd=\"%s\"" %(user,passwd)) self.provider.log("Found user=\"%s\", passwd=\"%s\"" %(user,passwd))
self.auth_creds = self.provider.authenticate(user,passwd,handler.client_address) self.auth_creds = self.provider.authenticate(user,passwd,handler.client_address)
if self.auth_creds: if self.auth_creds:
return True return True
if self.auth_tries > 5: if self.auth_tries > 5:
self.provider.log("Failing authorization after 5 requests w/o password") self.provider.log("Failing authorization after 5 requests w/o password")
raise AuthRejectedExc("Authorization failed.") raise AuthRejectedExc("Authorization failed.")
self.auth_tries += 1 self.auth_tries += 1
raise AuthRequiredExc(atype = 'Basic', realm=self.provider.realm) raise AuthRequiredExc(atype = 'Basic', realm=self.provider.realm)
class HTTPHandler(SimpleHTTPRequestHandler): class HTTPHandler(SimpleHTTPRequestHandler):
def __init__(self,request, client_address, server): def __init__(self,request, client_address, server):
SimpleHTTPRequestHandler.__init__(self,request,client_address,server) SimpleHTTPRequestHandler.__init__(self,request,client_address,server)
# print "Handler for %s inited" % str(client_address) # print "Handler for %s inited" % str(client_address)
self.protocol_version = 'HTTP/1.1' self.protocol_version = 'HTTP/1.1'
self.connection = dummyconn() self.connection = dummyconn()
def handle(self): def handle(self):
""" Classes here should NOT handle inside their constructor """ Classes here should NOT handle inside their constructor
""" """
pass pass
def finish(self): def finish(self):
pass pass
def setup(self): def setup(self):
pass pass
class HTTPDir: class HTTPDir:
""" A dispatcher class, like a virtual folder in httpd """ A dispatcher class, like a virtual folder in httpd
""" """
def __init__(self,path,handler, auth_provider = None): def __init__(self,path,handler, auth_provider = None):
self.path = path self.path = path
self.handler = handler self.handler = handler
self.auth_provider = auth_provider self.auth_provider = auth_provider
def matches(self, request): def matches(self, request):
""" Test if some request matches us. If so, return """ Test if some request matches us. If so, return
the matched path. """ the matched path. """
if request.startswith(self.path): if request.startswith(self.path):
return self.path return self.path
return False return False
class noconnection: class noconnection:
""" a class to use instead of the real connection """ a class to use instead of the real connection
""" """
def makefile(self, mode, bufsize): def makefile(self, mode, bufsize):
return None return None
class dummyconn: class dummyconn:
def shutdown(self, tru): def shutdown(self, tru):
pass pass
def _quote_html(html): def _quote_html(html):
return html.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;") return html.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
@ -168,7 +168,7 @@ class FixSendError:
self.send_response(code, message) self.send_response(code, message)
self.send_header("Content-Type", self.error_content_type) self.send_header("Content-Type", self.error_content_type)
self.send_header('Connection', 'close') self.send_header('Connection', 'close')
self.send_header('Content-Length', len(content) or 0) self.send_header('Content-Length', len(content) or 0)
self.end_headers() self.end_headers()
if self.command != 'HEAD' and code >= 200 and code not in (204, 304): if self.command != 'HEAD' and code >= 200 and code not in (204, 304):
self.wfile.write(content) self.wfile.write(content)
@ -176,65 +176,65 @@ class FixSendError:
class MultiHTTPHandler(FixSendError,BaseHTTPRequestHandler): class MultiHTTPHandler(FixSendError,BaseHTTPRequestHandler):
""" this is a multiple handler, that will dispatch each request """ this is a multiple handler, that will dispatch each request
to a nested handler, iff it matches to a nested handler, iff it matches
The handler will also have *one* dict of authentication proxies, The handler will also have *one* dict of authentication proxies,
groupped by their realm. groupped by their realm.
""" """
protocol_version = "HTTP/1.1" protocol_version = "HTTP/1.1"
default_request_version = "HTTP/0.9" # compatibility with py2.5 default_request_version = "HTTP/0.9" # compatibility with py2.5
auth_required_msg = """ <html><head><title>Authorization required</title></head> auth_required_msg = """ <html><head><title>Authorization required</title></head>
<body>You must authenticate to use this service</body><html>\r\r""" <body>You must authenticate to use this service</body><html>\r\r"""
def __init__(self, request, client_address, server): def __init__(self, request, client_address, server):
self.in_handlers = {} self.in_handlers = {}
self.sec_realms = {} self.sec_realms = {}
SocketServer.StreamRequestHandler.__init__(self,request,client_address,server) SocketServer.StreamRequestHandler.__init__(self,request,client_address,server)
self.log_message("MultiHttpHandler init for %s" %(str(client_address))) self.log_message("MultiHttpHandler init for %s" %(str(client_address)))
def _handle_one_foreign(self,fore, path, auth_provider): def _handle_one_foreign(self,fore, path, auth_provider):
""" This method overrides the handle_one_request for *children* """ This method overrides the handle_one_request for *children*
handlers. It is required, since the first line should not be handlers. It is required, since the first line should not be
read again.. read again..
""" """
fore.raw_requestline = "%s %s %s\n" % (self.command, path, self.version) fore.raw_requestline = "%s %s %s\n" % (self.command, path, self.version)
if not fore.parse_request(): # An error code has been sent, just exit if not fore.parse_request(): # An error code has been sent, just exit
return return
self.request_version = fore.request_version self.request_version = fore.request_version
if auth_provider and auth_provider.realm: if auth_provider and auth_provider.realm:
try: try:
self.sec_realms[auth_provider.realm].checkRequest(fore,path) self.sec_realms[auth_provider.realm].checkRequest(fore,path)
except AuthRequiredExc,ae: except AuthRequiredExc,ae:
if self.request_version != 'HTTP/1.1': if self.request_version != 'HTTP/1.1':
self.log_error("Cannot require auth at %s",self.request_version) self.log_error("Cannot require auth at %s",self.request_version)
self.send_error(401) self.send_error(401)
return return
self._get_ignore_body(fore) # consume any body that came, not loose sync with input self._get_ignore_body(fore) # consume any body that came, not loose sync with input
self.send_response(401,'Authorization required') self.send_response(401,'Authorization required')
self.send_header('WWW-Authenticate','%s realm="%s"' % (ae.atype,ae.realm)) self.send_header('WWW-Authenticate','%s realm="%s"' % (ae.atype,ae.realm))
self.send_header('Connection', 'keep-alive') self.send_header('Connection', 'keep-alive')
self.send_header('Content-Type','text/html') self.send_header('Content-Type','text/html')
self.send_header('Content-Length',len(self.auth_required_msg)) self.send_header('Content-Length',len(self.auth_required_msg))
self.end_headers() self.end_headers()
self.wfile.write(self.auth_required_msg) self.wfile.write(self.auth_required_msg)
return return
except AuthRejectedExc,e: except AuthRejectedExc,e:
self.log_error("Rejected auth: %s" % e.args[0]) self.log_error("Rejected auth: %s" % e.args[0])
self.send_error(401,e.args[0]) self.send_error(401,e.args[0])
self.close_connection = 1 self.close_connection = 1
return return
mname = 'do_' + fore.command mname = 'do_' + fore.command
if not hasattr(fore, mname): if not hasattr(fore, mname):
fore.send_error(501, "Unsupported method (%r)" % fore.command) fore.send_error(501, "Unsupported method (%r)" % fore.command)
return return
fore.close_connection = 0 fore.close_connection = 0
method = getattr(fore, mname) method = getattr(fore, mname)
method() method()
if fore.close_connection: if fore.close_connection:
# print "Closing connection because of handler" # print "Closing connection because of handler"
self.close_connection = fore.close_connection self.close_connection = fore.close_connection
def parse_rawline(self): def parse_rawline(self):
"""Parse a request (internal). """Parse a request (internal).
@ -295,67 +295,67 @@ class MultiHTTPHandler(FixSendError,BaseHTTPRequestHandler):
else: else:
self.send_error(400, "Bad request syntax (%r)" % requestline) self.send_error(400, "Bad request syntax (%r)" % requestline)
return False return False
self.request_version = version self.request_version = version
self.command, self.path, self.version = command, path, version self.command, self.path, self.version = command, path, version
return True return True
def handle_one_request(self): def handle_one_request(self):
"""Handle a single HTTP request. """Handle a single HTTP request.
Dispatch to the correct handler. Dispatch to the correct handler.
""" """
self.request.setblocking(True) self.request.setblocking(True)
self.raw_requestline = self.rfile.readline() self.raw_requestline = self.rfile.readline()
if not self.raw_requestline: if not self.raw_requestline:
self.close_connection = 1 self.close_connection = 1
# self.log_message("no requestline, connection closed?") # self.log_message("no requestline, connection closed?")
return return
if not self.parse_rawline(): if not self.parse_rawline():
self.log_message("Could not parse rawline.") self.log_message("Could not parse rawline.")
return return
# self.parse_request(): # Do NOT parse here. the first line should be the only # self.parse_request(): # Do NOT parse here. the first line should be the only
for vdir in self.server.vdirs: for vdir in self.server.vdirs:
p = vdir.matches(self.path) p = vdir.matches(self.path)
if p == False: if p == False:
continue continue
npath = self.path[len(p):] npath = self.path[len(p):]
if not npath.startswith('/'): if not npath.startswith('/'):
npath = '/' + npath npath = '/' + npath
if not self.in_handlers.has_key(p): if not self.in_handlers.has_key(p):
self.in_handlers[p] = vdir.handler(noconnection(),self.client_address,self.server) self.in_handlers[p] = vdir.handler(noconnection(),self.client_address,self.server)
if vdir.auth_provider: if vdir.auth_provider:
vdir.auth_provider.setupAuth(self, self.in_handlers[p]) vdir.auth_provider.setupAuth(self, self.in_handlers[p])
hnd = self.in_handlers[p] hnd = self.in_handlers[p]
hnd.rfile = self.rfile hnd.rfile = self.rfile
hnd.wfile = self.wfile hnd.wfile = self.wfile
self.rlpath = self.raw_requestline self.rlpath = self.raw_requestline
self._handle_one_foreign(hnd,npath, vdir.auth_provider) self._handle_one_foreign(hnd,npath, vdir.auth_provider)
# print "Handled, closing = ", self.close_connection # print "Handled, closing = ", self.close_connection
return return
# if no match: # if no match:
self.send_error(404, "Path not found: %s" % self.path) self.send_error(404, "Path not found: %s" % self.path)
return return
def _get_ignore_body(self,fore): def _get_ignore_body(self,fore):
if not fore.headers.has_key("content-length"): if not fore.headers.has_key("content-length"):
return return
max_chunk_size = 10*1024*1024 max_chunk_size = 10*1024*1024
size_remaining = int(fore.headers["content-length"]) size_remaining = int(fore.headers["content-length"])
got = '' got = ''
while size_remaining: while size_remaining:
chunk_size = min(size_remaining, max_chunk_size) chunk_size = min(size_remaining, max_chunk_size)
got = fore.rfile.read(chunk_size) got = fore.rfile.read(chunk_size)
size_remaining -= len(got) size_remaining -= len(got)
class SecureMultiHTTPHandler(MultiHTTPHandler): class SecureMultiHTTPHandler(MultiHTTPHandler):
def getcert_fnames(self): def getcert_fnames(self):
""" Return a pair with the filenames of ssl cert,key """ Return a pair with the filenames of ssl cert,key
Override this to direct to other filenames Override this to direct to other filenames
""" """
return ('server.cert','server.key') return ('server.cert','server.key')
def setup(self): def setup(self):
import ssl import ssl
certfile, keyfile = self.getcert_fnames() certfile, keyfile = self.getcert_fnames()
@ -386,10 +386,10 @@ import threading
class ConnThreadingMixIn: class ConnThreadingMixIn:
"""Mix-in class to handle each _connection_ in a new thread. """Mix-in class to handle each _connection_ in a new thread.
This is necessary for persistent connections, where multiple This is necessary for persistent connections, where multiple
requests should be handled synchronously at each connection, but requests should be handled synchronously at each connection, but
multiple connections can run in parallel. multiple connections can run in parallel.
""" """
# Decides how threads will act upon termination of the # Decides how threads will act upon termination of the
# main process # main process
@ -401,7 +401,7 @@ class ConnThreadingMixIn:
if self.daemon_threads: if self.daemon_threads:
t.setDaemon (1) t.setDaemon (1)
t.start() t.start()
def _handle_request2(self): def _handle_request2(self):
"""Handle one request, without blocking. """Handle one request, without blocking.

View File

@ -119,14 +119,14 @@ class Cursor(object):
try: try:
params = params or None params = params or None
res = self._obj.execute(query, params) res = self._obj.execute(query, params)
except psycopg2.ProgrammingError, pe: except psycopg2.ProgrammingError, pe:
logger= netsvc.Logger() logger= netsvc.Logger()
logger.notifyChannel('sql_db', netsvc.LOG_ERROR, "Programming error: %s, in query %s" % (pe, query)) logger.notifyChannel('sql_db', netsvc.LOG_ERROR, "Programming error: %s, in query %s" % (pe, query))
raise raise
except Exception, e: except Exception, e:
log("bad query: %s" % self._obj.query) log("bad query: %s" % self._obj.query)
log(e) log(e)
raise raise
if self.sql_log: if self.sql_log:
log("query: %s" % self._obj.query) log("query: %s" % self._obj.query)
@ -144,8 +144,8 @@ class Cursor(object):
return res return res
def print_log(self): def print_log(self):
global sql_counter global sql_counter
sql_counter += self.count sql_counter += self.count
def process(type): def process(type):
sqllogs = {'from':self.sql_from_log, 'into':self.sql_into_log} sqllogs = {'from':self.sql_from_log, 'into':self.sql_into_log}
sum = 0 sum = 0

View File

@ -66,7 +66,7 @@ class configmanager(object):
'import_partial': "", 'import_partial': "",
'pidfile': None, 'pidfile': None,
'logfile': None, 'logfile': None,
'logrotate': '1', 'logrotate': '1',
'smtp_server': 'localhost', 'smtp_server': 'localhost',
'smtp_user': False, 'smtp_user': False,
'smtp_port':25, 'smtp_port':25,
@ -82,8 +82,8 @@ class configmanager(object):
'login_message': False, 'login_message': False,
'list_db' : True, 'list_db' : True,
} }
self.misc = {} self.misc = {}
hasSSL = check_ssl() hasSSL = check_ssl()
@ -135,7 +135,7 @@ class configmanager(object):
group = optparse.OptionGroup(parser, "Logging Configuration") group = optparse.OptionGroup(parser, "Logging Configuration")
group.add_option("--logfile", dest="logfile", help="file where the server log will be stored") group.add_option("--logfile", dest="logfile", help="file where the server log will be stored")
group.add_option("--no-logrotate", dest="logrotate", action="store_false", group.add_option("--no-logrotate", dest="logrotate", action="store_false",
default=None, help="do not rotate the logfile") default=None, help="do not rotate the logfile")
group.add_option("--syslog", action="store_true", dest="syslog", group.add_option("--syslog", action="store_true", dest="syslog",
default=False, help="Send the log to the syslog server") default=False, help="Send the log to the syslog server")
group.add_option('--log-level', dest='log_level', type='choice', choices=self._LOGLEVELS.keys(), group.add_option('--log-level', dest='log_level', type='choice', choices=self._LOGLEVELS.keys(),
@ -226,7 +226,7 @@ class configmanager(object):
'db_port', 'list_db', 'logfile', 'pidfile', 'smtp_port', 'cache_timeout', 'db_port', 'list_db', 'logfile', 'pidfile', 'smtp_port', 'cache_timeout',
'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy', 'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy',
'netinterface', 'netport', 'db_maxconn', 'import_partial', 'addons_path', 'netinterface', 'netport', 'db_maxconn', 'import_partial', 'addons_path',
'netrpc', 'xmlrpc', 'syslog', 'without_demo'] 'netrpc', 'xmlrpc', 'syslog', 'without_demo']
if hasSSL: if hasSSL:
keys.extend(['smtp_ssl', 'secure_cert_file', 'secure_pkey_file']) keys.extend(['smtp_ssl', 'secure_cert_file', 'secure_pkey_file'])
@ -341,18 +341,18 @@ class configmanager(object):
if value=='False' or value=='false': if value=='False' or value=='false':
value = False value = False
self.options[name] = value self.options[name] = value
#parse the other sections, as well #parse the other sections, as well
for sec in p.sections(): for sec in p.sections():
if sec == 'options': if sec == 'options':
continue continue
if not self.misc.has_key(sec): if not self.misc.has_key(sec):
self.misc[sec]= {} self.misc[sec]= {}
for (name, value) in p.items(sec): for (name, value) in p.items(sec):
if value=='True' or value=='true': if value=='True' or value=='true':
value = True value = True
if value=='False' or value=='false': if value=='False' or value=='false':
value = False value = False
self.misc[sec][name] = value self.misc[sec][name] = value
except IOError: except IOError:
pass pass
except ConfigParser.NoSectionError: except ConfigParser.NoSectionError:
@ -369,10 +369,10 @@ class configmanager(object):
p.set('options', opt, loglevelnames.get(self.options[opt], self.options[opt])) p.set('options', opt, loglevelnames.get(self.options[opt], self.options[opt]))
else: else:
p.set('options', opt, self.options[opt]) p.set('options', opt, self.options[opt])
for sec in self.misc.keys(): for sec in self.misc.keys():
for opt in self.misc[sec].keys(): for opt in self.misc[sec].keys():
p.set(sec,opt,self.misc[sec][opt]) p.set(sec,opt,self.misc[sec][opt])
# try to create the directories and write the file # try to create the directories and write the file
try: try:

View File

@ -386,15 +386,15 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
smtp_server = config['smtp_server'] smtp_server = config['smtp_server']
if smtp_server.startswith('maildir:/'): if smtp_server.startswith('maildir:/'):
from mailbox import Maildir from mailbox import Maildir
maildir_path = smtp_server[8:] maildir_path = smtp_server[8:]
try: try:
mdir = Maildir(maildir_path,factory=None, create = True) mdir = Maildir(maildir_path,factory=None, create = True)
mdir.add(msg.as_string(True)) mdir.add(msg.as_string(True))
return True return True
except Exception,e: except Exception,e:
netsvc.Logger().notifyChannel('email_send (maildir)', netsvc.LOG_ERROR, e) netsvc.Logger().notifyChannel('email_send (maildir)', netsvc.LOG_ERROR, e)
return False return False
try: try:
oldstderr = smtplib.stderr oldstderr = smtplib.stderr
s = smtplib.SMTP() s = smtplib.SMTP()

View File

@ -29,38 +29,38 @@ __export_bis = {}
import sys import sys
def __init_ebis(): def __init_ebis():
global __export_bis global __export_bis
_evars = [ 'abs', 'all', 'any', 'basestring' , 'bool', _evars = [ 'abs', 'all', 'any', 'basestring' , 'bool',
'chr', 'cmp','complex', 'dict', 'divmod', 'enumerate', 'chr', 'cmp','complex', 'dict', 'divmod', 'enumerate',
'float', 'frozenset', 'getattr', 'hasattr', 'hash', 'float', 'frozenset', 'getattr', 'hasattr', 'hash',
'hex', 'id','int', 'iter', 'len', 'list', 'long', 'map', 'max', 'hex', 'id','int', 'iter', 'len', 'list', 'long', 'map', 'max',
'min', 'oct', 'ord','pow', 'range', 'reduce', 'repr', 'min', 'oct', 'ord','pow', 'range', 'reduce', 'repr',
'reversed', 'round', 'set', 'setattr', 'slice','sorted', 'str', 'reversed', 'round', 'set', 'setattr', 'slice','sorted', 'str',
'sum', 'tuple','type', 'unichr','unicode', 'xrange', 'sum', 'tuple','type', 'unichr','unicode', 'xrange',
'True','False', 'None', 'NotImplemented', 'Ellipsis', ] 'True','False', 'None', 'NotImplemented', 'Ellipsis', ]
if sys.version_info[0:2] >= (2,6): if sys.version_info[0:2] >= (2,6):
_evars.extend(['bin', 'format', 'next']) _evars.extend(['bin', 'format', 'next'])
for v in _evars: for v in _evars:
__export_bis[v] = __builtins__[v] __export_bis[v] = __builtins__[v]
__init_ebis() __init_ebis()
def safe_eval(expr,sglobals,slocals = None): def safe_eval(expr,sglobals,slocals = None):
""" A little safer version of eval(). """ A little safer version of eval().
This one, will use fewer builtin functions, so that only This one, will use fewer builtin functions, so that only
arithmetic and logic expressions can really work """ arithmetic and logic expressions can really work """
global __export_bis global __export_bis
if not sglobals.has_key('__builtins__'): if not sglobals.has_key('__builtins__'):
# we copy, because we wouldn't want successive calls to safe_eval # we copy, because we wouldn't want successive calls to safe_eval
# to be able to alter the builtins. # to be able to alter the builtins.
sglobals['__builtins__'] = __export_bis.copy() sglobals['__builtins__'] = __export_bis.copy()
return eval(expr,sglobals,slocals) return eval(expr,sglobals,slocals)
#eof #eof

View File

@ -133,12 +133,12 @@ class GettextAlias(object):
return source return source
cr = frame.f_locals.get('cr') cr = frame.f_locals.get('cr')
try: try:
lang = (frame.f_locals.get('context') or {}).get('lang', False) lang = (frame.f_locals.get('context') or {}).get('lang', False)
if not (lang and cr): if not (lang and cr):
return source return source
except: except:
return source return source
cr.execute('select value from ir_translation where lang=%s and type=%s and src=%s', (lang, 'code', source)) cr.execute('select value from ir_translation where lang=%s and type=%s and src=%s', (lang, 'code', source))
res_trans = cr.fetchone() res_trans = cr.fetchone()
@ -154,7 +154,7 @@ class TinyPoFile(object):
def __iter__(self): def __iter__(self):
self.buffer.seek(0) self.buffer.seek(0)
self.lines = self._get_lines() self.lines = self._get_lines()
self.lines_count = len(self.lines); self.lines_count = len(self.lines);
self.first = True self.first = True
self.tnrs= [] self.tnrs= []
@ -170,7 +170,7 @@ class TinyPoFile(object):
return lines return lines
def cur_line(self): def cur_line(self):
return (self.lines_count - len(self.lines)) return (self.lines_count - len(self.lines))
def next(self): def next(self):
def unquote(str): def unquote(str):
@ -185,30 +185,30 @@ class TinyPoFile(object):
else: else:
tmp_tnrs = [] tmp_tnrs = []
line = None line = None
fuzzy = False fuzzy = False
while (not line): while (not line):
if 0 == len(self.lines): if 0 == len(self.lines):
raise StopIteration() raise StopIteration()
line = self.lines.pop(0).strip() line = self.lines.pop(0).strip()
if line.startswith('#:'): if line.startswith('#:'):
if ' ' in line[2:].strip(): if ' ' in line[2:].strip():
for lpart in line[2:].strip().split(' '): for lpart in line[2:].strip().split(' '):
tmp_tnrs.append(lpart.strip().split(':',2)) tmp_tnrs.append(lpart.strip().split(':',2))
else: else:
tmp_tnrs.append( line[2:].strip().split(':',2) ) tmp_tnrs.append( line[2:].strip().split(':',2) )
elif line.startswith('#,') and (line[2:].strip() == 'fuzzy'): elif line.startswith('#,') and (line[2:].strip() == 'fuzzy'):
fuzzy = True fuzzy = True
line = self.lines.pop(0).strip() line = self.lines.pop(0).strip()
while not line: while not line:
# allow empty lines between comments and msgid # allow empty lines between comments and msgid
line = self.lines.pop(0).strip() line = self.lines.pop(0).strip()
if line.startswith('#~ '): if line.startswith('#~ '):
while line.startswith('#~ ') or not line.strip(): while line.startswith('#~ ') or not line.strip():
if 0 == len(self.lines): if 0 == len(self.lines):
raise StopIteration() raise StopIteration()
line = self.lines.pop(0) line = self.lines.pop(0)
# This has been a deprecated entry, don't return anything # This has been a deprecated entry, don't return anything
return self.next() return self.next()
if not line.startswith('msgid'): if not line.startswith('msgid'):
@ -242,9 +242,9 @@ class TinyPoFile(object):
self.tnrs.append((t, n, r, source, trad)) self.tnrs.append((t, n, r, source, trad))
self.first = False self.first = False
if name == None: if name == None:
return self.next() return self.next()
return type, name, res_id, source, trad return type, name, res_id, source, trad
def write_infos(self, modules): def write_infos(self, modules):
@ -279,7 +279,7 @@ class TinyPoFile(object):
def quote(s): def quote(s):
return '"%s"' % s.replace('"','\\"') \ return '"%s"' % s.replace('"','\\"') \
.replace('\n', '\\n"\n"') \ .replace('\n', '\\n"\n"') \
.replace(' \\ ',' \\\\ ') .replace(' \\ ',' \\\\ ')
plurial = len(modules) > 1 and 's' or '' plurial = len(modules) > 1 and 's' or ''
@ -490,9 +490,9 @@ def trans_generate(lang, modules, dbname=None):
} }
# export fields # export fields
if not result.has_key('fields'): if not result.has_key('fields'):
logger.notifyChannel("db",netsvc.LOG_WARNING,"res has no fields: %r" % result) logger.notifyChannel("db",netsvc.LOG_WARNING,"res has no fields: %r" % result)
continue continue
for field_name, field_def in result['fields'].iteritems(): for field_name, field_def in result['fields'].iteritems():
res_name = name + ',' + field_name res_name = name + ',' + field_name
@ -517,11 +517,11 @@ def trans_generate(lang, modules, dbname=None):
push_translation(module, 'wizard_button', res_name, 0, button_label) push_translation(module, 'wizard_button', res_name, 0, button_label)
elif model=='ir.model.fields': elif model=='ir.model.fields':
try: try:
field_name = encode(obj.name) field_name = encode(obj.name)
except AttributeError, exc: except AttributeError, exc:
logger.notifyChannel("db", netsvc.LOG_ERROR, "name error in %s: %s" % (xml_name,str(exc))) logger.notifyChannel("db", netsvc.LOG_ERROR, "name error in %s: %s" % (xml_name,str(exc)))
continue continue
objmodel = pool.get(obj.model) objmodel = pool.get(obj.model)
if not objmodel or not field_name in objmodel._columns: if not objmodel or not field_name in objmodel._columns:
continue continue
@ -578,28 +578,28 @@ def trans_generate(lang, modules, dbname=None):
for field_name,field_def in pool.get(model)._columns.items(): for field_name,field_def in pool.get(model)._columns.items():
if field_def.translate: if field_def.translate:
name = model + "," + field_name name = model + "," + field_name
try: try:
trad = getattr(obj, field_name) or '' trad = getattr(obj, field_name) or ''
except: except:
trad = '' trad = ''
push_translation(module, 'model', name, xml_name, encode(trad)) push_translation(module, 'model', name, xml_name, encode(trad))
# parse source code for _() calls # parse source code for _() calls
def get_module_from_path(path,mod_paths=None): def get_module_from_path(path,mod_paths=None):
if not mod_paths: if not mod_paths:
# First, construct a list of possible paths # First, construct a list of possible paths
def_path = os.path.abspath(os.path.join(tools.config['root_path'], 'addons')) # default addons path (base) def_path = os.path.abspath(os.path.join(tools.config['root_path'], 'addons')) # default addons path (base)
ad_paths= map(lambda m: os.path.abspath(m.strip()),tools.config['addons_path'].split(',')) ad_paths= map(lambda m: os.path.abspath(m.strip()),tools.config['addons_path'].split(','))
mod_paths=[def_path] mod_paths=[def_path]
for adp in ad_paths: for adp in ad_paths:
mod_paths.append(adp) mod_paths.append(adp)
if not adp.startswith('/'): if not adp.startswith('/'):
mod_paths.append(os.path.join(def_path,adp)) mod_paths.append(os.path.join(def_path,adp))
elif adp.startswith(def_path): elif adp.startswith(def_path):
mod_paths.append(adp[len(def_path)+1:]) mod_paths.append(adp[len(def_path)+1:])
for mp in mod_paths: for mp in mod_paths:
if path.startswith(mp) and (os.path.dirname(path) != mp): if path.startswith(mp) and (os.path.dirname(path) != mp):
path = path[len(mp)+1:] path = path[len(mp)+1:]
return path.split(os.path.sep)[0] return path.split(os.path.sep)[0]
return 'base' # files that are not in a module are considered as being in 'base' module return 'base' # files that are not in a module are considered as being in 'base' module
@ -760,8 +760,8 @@ def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=
# if the resource id (res_id) is in that list, use it, # if the resource id (res_id) is in that list, use it,
# otherwise use the whole list # otherwise use the whole list
if not ids: if not ids:
ids = [] ids = []
ids = (dic['res_id'] in ids) and [dic['res_id']] or ids ids = (dic['res_id'] in ids) and [dic['res_id']] or ids
for id in ids: for id in ids:
dic['res_id'] = id dic['res_id'] = id