summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorHarry (Open ERP) <hmo@tinyerp.com>2009-11-24 20:14:05 +0530
committerHarry (Open ERP) <hmo@tinyerp.com>2009-11-24 20:14:05 +0530
commitd8ce3f1e2a5a55f0c28eb1cf8cb4cfcd2d6d5dab (patch)
treef1dbd61528db0d90cebb5f2b5e4e836f00f71aef /bin
parentdda5ed6bb1710e4690c1e01fe4265cc7db147068 (diff)
[FIX] replaced <TAB> with four white space.
bzr revid: hmo@tinyerp.com-20091124144405-9mzd91chohvf0uu7
Diffstat (limited to 'bin')
-rw-r--r--bin/addons/__init__.py10
-rw-r--r--bin/addons/base/ir/ir_cron.py2
-rw-r--r--bin/addons/base/ir/ir_sequence.py44
-rw-r--r--bin/addons/base/ir/workflow/print_instance.py2
-rw-r--r--bin/addons/base/module/report/ir_module_reference_print.py46
-rw-r--r--bin/addons/base/module/wizard/wizard_export_lang.py2
-rw-r--r--bin/addons/base/res/res_user.py6
-rw-r--r--bin/netsvc.py54
-rwxr-xr-xbin/openerp-server.py16
-rw-r--r--bin/osv/fields.py16
-rw-r--r--bin/osv/orm.py68
-rw-r--r--bin/report/interface.py2
-rw-r--r--bin/report/render/rml2pdf/customfonts.py44
-rw-r--r--bin/report/render/rml2pdf/trml2pdf.py42
-rwxr-xr-xbin/report/render/rml2txt/rml2txt.py316
-rw-r--r--bin/service/http_server.py242
-rw-r--r--bin/service/netrpc_server.py32
-rw-r--r--bin/service/web_services.py172
-rw-r--r--bin/service/websrv_lib.py354
-rw-r--r--bin/sql_db.py14
-rw-r--r--bin/tools/config.py42
-rw-r--r--bin/tools/misc.py18
-rw-r--r--bin/tools/safe_eval.py58
-rw-r--r--bin/tools/translate.py102
24 files changed, 852 insertions, 852 deletions
diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py
index 713dc88b793..395cf573c0a 100644
--- a/bin/addons/__init__.py
+++ b/bin/addons/__init__.py
@@ -52,10 +52,10 @@ sys.path.insert(1, _ad)
ad_cnt=1
for adp in ad_paths:
if adp != _ad:
- sys.path.insert(ad_cnt, adp)
- ad_cnt+=1
+ sys.path.insert(ad_cnt, adp)
+ ad_cnt+=1
-ad_paths.append(_ad) # for get_module_path
+ad_paths.append(_ad) # for get_module_path
# Modules already loaded
loaded = []
@@ -289,7 +289,7 @@ def get_modules():
plist = []
for ad in ad_paths:
- plist.extend(listdir(ad))
+ plist.extend(listdir(ad))
return list(set(plist))
def get_modules_with_version():
@@ -318,7 +318,7 @@ def upgrade_graph(graph, cr, module_list, force=None):
mod_path = get_module_path(module)
terp_file = get_module_resource(module, '__terp__.py')
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))
continue
diff --git a/bin/addons/base/ir/ir_cron.py b/bin/addons/base/ir/ir_cron.py
index 78f3b97ddaf..6530561f675 100644
--- a/bin/addons/base/ir/ir_cron.py
+++ b/bin/addons/base/ir/ir_cron.py
@@ -1,7 +1,7 @@
# -*- 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
# $Id$
#
diff --git a/bin/addons/base/ir/ir_sequence.py b/bin/addons/base/ir/ir_sequence.py
index 8f6eb8d8dcd..87f1e3f490e 100644
--- a/bin/addons/base/ir/ir_sequence.py
+++ b/bin/addons/base/ir/ir_sequence.py
@@ -47,15 +47,15 @@ class ir_sequence(osv.osv):
'number_next': fields.integer('Next Number', required=True),
'number_increment': fields.integer('Increment Number', 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."),
- 'weight': fields.integer('Weight',required=True, help="If two sequences match, the highest weight will be used.")
+ '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.")
}
_defaults = {
'active': lambda *a: True,
'number_increment': lambda *a: 1,
'number_next': lambda *a: 1,
'padding' : lambda *a : 0,
- 'weight' : lambda *a: 10,
+ 'weight' : lambda *a: 10,
}
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):
- if not context:
- context = {}
+ if not context:
+ context = {}
try:
cr.execute('SELECT id, number_next, prefix, suffix, padding, condition \
- FROM ir_sequence \
- WHERE '+test+' AND active=%s ORDER BY weight DESC, length(COALESCE(condition,\'\')) DESC \
- FOR UPDATE', (sequence_id, True))
+ FROM ir_sequence \
+ WHERE '+test+' AND active=%s ORDER BY weight DESC, length(COALESCE(condition,\'\')) DESC \
+ FOR UPDATE', (sequence_id, True))
for res in cr.dictfetchall():
- if res['condition']:
- print "ir_seq: %s has condition:" %res['id'], res['condition'],
- try:
- bo = safe_eval(res['condition'],context)
- if not bo:
- print "not matched"
- continue
- except Exception,e:
- # it would be normal to have exceptions, because
- # the domain may contain errors
- print "Exception.\ne:",e
- print "Context:", context
- continue
- print "Matched!"
+ if res['condition']:
+ print "ir_seq: %s has condition:" %res['id'], res['condition'],
+ try:
+ bo = safe_eval(res['condition'],context)
+ if not bo:
+ print "not matched"
+ continue
+ except Exception,e:
+ # it would be normal to have exceptions, because
+ # the domain may contain errors
+ print "Exception.\ne:",e
+ print "Context:", context
+ continue
+ print "Matched!"
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']:
diff --git a/bin/addons/base/ir/workflow/print_instance.py b/bin/addons/base/ir/workflow/print_instance.py
index 659c6b3d2ff..f9885b9e838 100644
--- a/bin/addons/base/ir/workflow/print_instance.py
+++ b/bin/addons/base/ir/workflow/print_instance.py
@@ -147,7 +147,7 @@ showpage'''
inst_id = inst_id[0]
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',
- ordering='out'
+ ordering='out'
)
graph_instance_get(cr, graph, inst_id, data.get('nested', False))
ps_string = graph.create(prog='dot', format='ps')
diff --git a/bin/addons/base/module/report/ir_module_reference_print.py b/bin/addons/base/module/report/ir_module_reference_print.py
index ac90ddd833f..7364499af7e 100644
--- a/bin/addons/base/module/report/ir_module_reference_print.py
+++ b/bin/addons/base/module/report/ir_module_reference_print.py
@@ -29,37 +29,37 @@ class ir_module_reference_print(report_sxw.rml_parse):
'time': time,
'findobj': self._object_find,
'objdoc': self._object_doc,
- 'objdoc2': self._object_doc2,
+ 'objdoc2': self._object_doc2,
'findflds': self._fields_find,
})
def _object_doc(self, obj):
modobj = self.pool.get(obj)
- strdocs= modobj.__doc__
- if not strdocs:
- return None
- else:
- strdocs=strdocs.strip().splitlines(True)
- res = ''
- for stre in strdocs:
- if not stre or stre.isspace():
- break
- res += stre
+ strdocs= modobj.__doc__
+ if not strdocs:
+ return None
+ else:
+ strdocs=strdocs.strip().splitlines(True)
+ res = ''
+ for stre in strdocs:
+ if not stre or stre.isspace():
+ break
+ res += stre
return res
def _object_doc2(self, obj):
modobj = self.pool.get(obj)
- strdocs= modobj.__doc__
- if not strdocs:
- return None
- else:
- strdocs=strdocs.strip().splitlines(True)
- res = []
- fou = False
- for stre in strdocs:
- if fou:
- res.append(stre.strip())
- elif not stre or stre.isspace():
- fou = True
+ strdocs= modobj.__doc__
+ if not strdocs:
+ return None
+ else:
+ strdocs=strdocs.strip().splitlines(True)
+ res = []
+ fou = False
+ for stre in strdocs:
+ if fou:
+ res.append(stre.strip())
+ elif not stre or stre.isspace():
+ fou = True
return res
def _object_find(self, module):
diff --git a/bin/addons/base/module/wizard/wizard_export_lang.py b/bin/addons/base/module/wizard/wizard_export_lang.py
index d0f16680413..1e538b95cfb 100644
--- a/bin/addons/base/module/wizard/wizard_export_lang.py
+++ b/bin/addons/base/module/wizard/wizard_export_lang.py
@@ -80,7 +80,7 @@ class wizard_export_lang(osv.osv_memory):
) ),
}
_defaults = { 'state': lambda *a: 'choose',
- 'name': lambda *a: 'lang.tar.gz'
+ 'name': lambda *a: 'lang.tar.gz'
}
wizard_export_lang()
diff --git a/bin/addons/base/res/res_user.py b/bin/addons/base/res/res_user.py
index b14daa2b553..d6b7cd6eec0 100644
--- a/bin/addons/base/res/res_user.py
+++ b/bin/addons/base/res/res_user.py
@@ -72,10 +72,10 @@ class groups(osv.osv):
return gid
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()
- if not 'name' in default:
- default['name'] = group['name']
+ if not 'name' in default:
+ default['name'] = group['name']
default['name'] = default['name'] + _(' (copy)')
return super(groups, self).copy(cr, uid, id, default, context=context)
diff --git a/bin/netsvc.py b/bin/netsvc.py
index 285c1ad44b1..8abdf4d7901 100644
--- a/bin/netsvc.py
+++ b/bin/netsvc.py
@@ -39,7 +39,7 @@ import release
class Service(object):
""" Base class for *Local* services
- Functionality here is trusted, no authentication.
+ Functionality here is trusted, no authentication.
"""
_services = {}
def __init__(self, name, audience=''):
@@ -48,11 +48,11 @@ class Service(object):
self._methods = {}
def joinGroup(self, name):
- raise Exception("No group for local services")
+ raise Exception("No group for local services")
#GROUPS.setdefault(name, {})[self.__name] = self
def service_exist(self,name):
- return Service._services.has_key(name)
+ return Service._services.has_key(name)
def exportMethod(self, method):
if callable(method):
@@ -67,9 +67,9 @@ class Service(object):
class LocalService(object):
""" Proxy for local services.
- Any instance of this class will behave like the single instance
- of Service(name)
- """
+ Any instance of this class will behave like the single instance
+ of Service(name)
+ """
def __init__(self, name):
self.__name = name
try:
@@ -158,12 +158,12 @@ def init_logger():
dirname = os.path.dirname(logf)
if dirname and not os.path.isdir(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)
- elif os.name == 'posix':
- handler = logging.handlers.WatchedFileHandler(logf)
- else:
- handler = logging.handlers.FileHandler(logf)
+ elif os.name == 'posix':
+ handler = logging.handlers.WatchedFileHandler(logf)
+ else:
+ handler = logging.handlers.FileHandler(logf)
except Exception, ex:
sys.stderr.write("ERROR: couldn't create the logfile directory. Logging to the standard output.\n")
handler = logging.StreamHandler(sys.stdout)
@@ -223,27 +223,27 @@ class Logger(object):
if isinstance(msg, Exception):
msg = tools.exception_to_unicode(msg)
- try:
- msg = tools.ustr(msg).strip()
+ try:
+ msg = tools.ustr(msg).strip()
if level in (LOG_ERROR,LOG_CRITICAL) and tools.config.get_misc('debug','env_info',True):
msg = common().exp_get_server_environment() + "\n" + msg
result = msg.split('\n')
- except UnicodeDecodeError:
- result = msg.strip().split('\n')
- try:
+ except UnicodeDecodeError:
+ result = msg.strip().split('\n')
+ try:
if len(result)>1:
for idx, s in enumerate(result):
level_method('[%02d]: %s' % (idx+1, s,))
elif result:
level_method(result[0])
- except IOError,e:
- # TODO: perhaps reset the logger streams?
- #if logrotate closes our files, we end up here..
- pass
- except:
- # better ignore the exception and carry on..
- pass
+ except IOError,e:
+ # TODO: perhaps reset the logger streams?
+ #if logrotate closes our files, we end up here..
+ pass
+ except:
+ # better ignore the exception and carry on..
+ pass
def set_loglevel(self, level):
log = logging.getLogger()
@@ -364,10 +364,10 @@ class OpenERPDispatcher:
self.log('service', service_name)
self.log('method', method)
self.log('params', params)
- if hasattr(self,'auth_provider'):
- auth = self.auth_provider
- else:
- auth = None
+ if hasattr(self,'auth_provider'):
+ auth = self.auth_provider
+ else:
+ auth = None
result = ExportService.getService(service_name).dispatch(method, auth, params)
self.log('result', result)
# We shouldn't marshall None,
diff --git a/bin/openerp-server.py b/bin/openerp-server.py
index a18db85d2e4..dbf1caa7532 100755
--- a/bin/openerp-server.py
+++ b/bin/openerp-server.py
@@ -56,8 +56,8 @@ __version__ = release.version
# We DON't log this using the standard logger, because we might mess
# with the logfile's permissions. Just do a quick exit here.
if pwd.getpwuid(os.getuid())[0] == 'root' :
- sys.stderr.write("Attempted to run OpenERP server as root. This is not good, aborting.\n")
- sys.exit(1)
+ sys.stderr.write("Attempted to run OpenERP server as root. This is not good, aborting.\n")
+ sys.exit(1)
#----------------------------------------------------------
# get logger
@@ -114,13 +114,13 @@ import addons
import service.http_server
if not ( tools.config["stop_after_init"] or \
- tools.config["translate_in"] or \
- tools.config["translate_out"] ):
- service.http_server.init_servers()
- service.http_server.init_xmlrpc()
+ tools.config["translate_in"] or \
+ tools.config["translate_out"] ):
+ service.http_server.init_servers()
+ service.http_server.init_xmlrpc()
- import service.netrpc_server
- service.netrpc_server.init_servers()
+ import service.netrpc_server
+ service.netrpc_server.init_servers()
if tools.config['db_name']:
for db in tools.config['db_name'].split(','):
diff --git a/bin/osv/fields.py b/bin/osv/fields.py
index ef27c222ea4..dde80f0ffb9 100644
--- a/bin/osv/fields.py
+++ b/bin/osv/fields.py
@@ -585,14 +585,14 @@ class many2many(_column):
def get_nice_size(a):
- (x,y) = a
- if isinstance(y, (int,long)):
- size = y
- elif y:
- y = len(y)
- else:
- y = 0
- return (x, tools.human_size(size))
+ (x,y) = a
+ if isinstance(y, (int,long)):
+ size = y
+ elif y:
+ y = len(y)
+ else:
+ y = 0
+ return (x, tools.human_size(size))
# ---------------------------------------------------------
# Function fields
diff --git a/bin/osv/orm.py b/bin/osv/orm.py
index 226934da366..87014cbf563 100644
--- a/bin/osv/orm.py
+++ b/bin/osv/orm.py
@@ -205,9 +205,9 @@ class browse_record(object):
d[n].set_value(self._cr, self._uid, d[n], self, f, lang_obj)
- if not datas:
- # 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)))
+ if not datas:
+ # 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)))
# create browse records for 'remote' objects
for data in datas:
for n, f in ffields:
@@ -228,12 +228,12 @@ class browse_record(object):
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)
self._data[data['id']].update(data)
- if not name in self._data[self._id]:
- #how did this happen?
- 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,"Data: %s, Table: %s"%(str(self._data[self._id]),str(self._table)))
- raise AttributeError(_('Unknown attribute %s in %s ') % (str(name),self._table_name))
+ if not name in self._data[self._id]:
+ #how did this happen?
+ 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,"Data: %s, Table: %s"%(str(self._data[self._id]),str(self._table)))
+ raise AttributeError(_('Unknown attribute %s in %s ') % (str(name),self._table_name))
return self._data[self._id][name]
def __getattr__(self, name):
@@ -671,10 +671,10 @@ class orm_template(object):
else:
module, xml_id = current_module, line[i]
id = ir_model_data_obj._get_id(cr, uid, module, xml_id)
- res_res_id = ir_model_data_obj.read(cr, uid, [id],
- ['res_id'])
- if res_res_id:
- res_id = res_res_id[0]['res_id']
+ res_res_id = ir_model_data_obj.read(cr, uid, [id],
+ ['res_id'])
+ if res_res_id:
+ res_id = res_res_id[0]['res_id']
row[field[-1][:-3]] = res_id or False
continue
if (len(field) == len(prefix)+1) and \
@@ -962,7 +962,7 @@ class orm_template(object):
and 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')
if res_trans:
res[f]['string'] = res_trans
@@ -1373,7 +1373,7 @@ class orm_template(object):
result['name'] = 'default'
result['field_parent'] = False
result['view_id'] = 0
-
+
xarch, xfields = self.__view_look_dom_arch(cr, user, result['arch'], view_id, context=context)
result['arch'] = xarch
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)
if not fields:
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:
res[lang] = {'code': lang}
for f in fields:
@@ -1476,7 +1476,7 @@ class orm_template(object):
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)
- #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 field in vals:
if field in self._columns:
@@ -1897,20 +1897,20 @@ class orm(orm_template):
"AND c.oid=a.attrelid " \
"AND a.atttypid=t.oid", (self._table, k))
res = cr.dictfetchall()
- 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 " \
- "FROM pg_class c,pg_attribute a,pg_type t " \
- "WHERE c.relname=%s " \
- "AND a.attname=%s " \
- "AND c.oid=a.attrelid " \
- "AND a.atttypid=t.oid", (self._table, f.oldname))
- res_old = cr.dictfetchall()
- 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:
- cr.execute('ALTER TABLE "%s" RENAME "%s" TO "%s"' % ( self._table,f.oldname, k))
- res = res_old
- res[0]['attname'] = k
-
+ 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 " \
+ "FROM pg_class c,pg_attribute a,pg_type t " \
+ "WHERE c.relname=%s " \
+ "AND a.attname=%s " \
+ "AND c.oid=a.attrelid " \
+ "AND a.atttypid=t.oid", (self._table, f.oldname))
+ res_old = cr.dictfetchall()
+ 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:
+ cr.execute('ALTER TABLE "%s" RENAME "%s" TO "%s"' % ( self._table,f.oldname, k))
+ res = res_old
+ res[0]['attname'] = k
+
if not res:
if not isinstance(f, fields.function) or f.store:
@@ -2342,7 +2342,7 @@ class orm(orm_template):
continue
if self._columns[f].translate:
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)
for r in res:
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)
if totranslate:
- # TODO: optimize
+ # TODO: optimize
for f in direct:
if self._columns[f].translate:
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])]
trans_obj = self.pool.get('ir.translation')
- #TODO: optimize translations
+ #TODO: optimize translations
trans_name=''
for f in fields:
trans_flag=True
diff --git a/bin/report/interface.py b/bin/report/interface.py
index b5f465c81ec..d50107f507b 100644
--- a/bin/report/interface.py
+++ b/bin/report/interface.py
@@ -80,7 +80,7 @@ class report_rml(report_int):
'html': self.create_html,
'raw': self.create_raw,
'sxw': self.create_sxw,
- 'txt': self.create_txt,
+ 'txt': self.create_txt,
'odt': self.create_odt,
'html2html' : self.create_html2html,
'makohtml2html' :self.create_makohtml2html,
diff --git a/bin/report/render/rml2pdf/customfonts.py b/bin/report/render/rml2pdf/customfonts.py
index 502b954071b..49165a10710 100644
--- a/bin/report/render/rml2pdf/customfonts.py
+++ b/bin/report/render/rml2pdf/customfonts.py
@@ -22,28 +22,28 @@
CustomTTFonts = [ ('Helvetica',"DejaVu Sans", "DejaVuSans.ttf", 'normal'),
- ('Helvetica',"DejaVu Sans Bold", "DejaVuSans-Bold.ttf", 'bold'),
- ('Helvetica',"DejaVu Sans Oblique", "DejaVuSans-Oblique.ttf", 'italic'),
- ('Helvetica',"DejaVu Sans BoldOblique", "DejaVuSans-BoldOblique.ttf", 'bolditalic'),
- ('Times',"Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'),
- ('Times',"Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'),
- ('Times',"Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'),
- ('Times',"Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'),
- ('Times-Roman',"Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'),
- ('Times-Roman',"Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'),
- ('Times-Roman',"Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'),
- ('Times-Roman',"Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'),
- ('ZapfDingbats',"DejaVu Serif", "DejaVuSerif.ttf", 'normal'),
- ('ZapfDingbats',"DejaVu Serif Bold", "DejaVuSerif-Bold.ttf", 'bold'),
- ('ZapfDingbats',"DejaVu Serif Italic", "DejaVuSerif-Italic.ttf", 'italic'),
- ('ZapfDingbats',"DejaVu Serif BoldItalic", "DejaVuSerif-BoldItalic.ttf", 'bolditalic'),
- ('Courier',"FreeMono", "FreeMono.ttf", 'normal'),
- ('Courier',"FreeMono Bold", "FreeMonoBold.ttf", 'bold'),
- ('Courier',"FreeMono Oblique", "FreeMonoOblique.ttf", 'italic'),
- ('Courier',"FreeMono BoldOblique", "FreeMonoBoldOblique.ttf", 'bolditalic'),]
+ ('Helvetica',"DejaVu Sans Bold", "DejaVuSans-Bold.ttf", 'bold'),
+ ('Helvetica',"DejaVu Sans Oblique", "DejaVuSans-Oblique.ttf", 'italic'),
+ ('Helvetica',"DejaVu Sans BoldOblique", "DejaVuSans-BoldOblique.ttf", 'bolditalic'),
+ ('Times',"Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'),
+ ('Times',"Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'),
+ ('Times',"Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'),
+ ('Times',"Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'),
+ ('Times-Roman',"Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'),
+ ('Times-Roman',"Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'),
+ ('Times-Roman',"Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'),
+ ('Times-Roman',"Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'),
+ ('ZapfDingbats',"DejaVu Serif", "DejaVuSerif.ttf", 'normal'),
+ ('ZapfDingbats',"DejaVu Serif Bold", "DejaVuSerif-Bold.ttf", 'bold'),
+ ('ZapfDingbats',"DejaVu Serif Italic", "DejaVuSerif-Italic.ttf", 'italic'),
+ ('ZapfDingbats',"DejaVu Serif BoldItalic", "DejaVuSerif-BoldItalic.ttf", 'bolditalic'),
+ ('Courier',"FreeMono", "FreeMono.ttf", 'normal'),
+ ('Courier',"FreeMono Bold", "FreeMonoBold.ttf", 'bold'),
+ ('Courier',"FreeMono Oblique", "FreeMonoOblique.ttf", 'italic'),
+ ('Courier',"FreeMono BoldOblique", "FreeMonoBoldOblique.ttf", 'bolditalic'),]
def SetCustomFonts(rmldoc):
- for name, font, fname, mode in CustomTTFonts:
- rmldoc.setTTFontMapping(name, font,fname, mode)
+ for name, font, fname, mode in CustomTTFonts:
+ rmldoc.setTTFontMapping(name, font,fname, mode)
-#eof \ No newline at end of file
+#eof
diff --git a/bin/report/render/rml2pdf/trml2pdf.py b/bin/report/render/rml2pdf/trml2pdf.py
index f56b4201fa9..65266c0043a 100644
--- a/bin/report/render/rml2pdf/trml2pdf.py
+++ b/bin/report/render/rml2pdf/trml2pdf.py
@@ -167,21 +167,21 @@ class _rml_doc(object):
from reportlab.lib.fonts import addMapping
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
-
- pdfmetrics.registerFont(TTFont(fontname, filename ))
- if (mode == 'all'):
- addMapping(face, 0, 0, fontname) #normal
- addMapping(face, 0, 1, fontname) #italic
- addMapping(face, 1, 0, fontname) #bold
- addMapping(face, 1, 1, fontname) #italic and bold
- elif (mode== 'normal') or (mode == 'regular'):
- addMapping(face, 0, 0, fontname) #normal
- elif (mode == 'italic'):
- addMapping(face, 0, 1, fontname) #italic
- elif (mode == 'bold'):
- addMapping(face, 1, 0, fontname) #bold
- elif (mode == 'bolditalic'):
- addMapping(face, 1, 1, fontname) #italic and bold
+
+ pdfmetrics.registerFont(TTFont(fontname, filename ))
+ if (mode == 'all'):
+ addMapping(face, 0, 0, fontname) #normal
+ addMapping(face, 0, 1, fontname) #italic
+ addMapping(face, 1, 0, fontname) #bold
+ addMapping(face, 1, 1, fontname) #italic and bold
+ elif (mode== 'normal') or (mode == 'regular'):
+ addMapping(face, 0, 0, fontname) #normal
+ elif (mode == 'italic'):
+ addMapping(face, 0, 1, fontname) #italic
+ elif (mode == 'bold'):
+ addMapping(face, 1, 0, fontname) #bold
+ elif (mode == 'bolditalic'):
+ addMapping(face, 1, 1, fontname) #italic and bold
def _textual_image(self, node):
rc = ''
@@ -797,10 +797,10 @@ def parseNode(rml, localcontext = {},fout=None, images={}, path='.',title=None):
r = _rml_doc(node, localcontext, images, path, title=title)
#try to override some font mappings
try:
- from customfonts import SetCustomFonts
- SetCustomFonts(r)
+ from customfonts import SetCustomFonts
+ SetCustomFonts(r)
except:
- pass
+ pass
fp = cStringIO.StringIO()
r.render(fp)
return fp.getvalue()
@@ -811,10 +811,10 @@ def parseString(rml, localcontext = {},fout=None, images={}, path='.',title=None
#try to override some font mappings
try:
- from customfonts import SetCustomFonts
- SetCustomFonts(r)
+ from customfonts import SetCustomFonts
+ SetCustomFonts(r)
except:
- pass
+ pass
if fout:
fp = file(fout,'wb')
diff --git a/bin/report/render/rml2txt/rml2txt.py b/bin/report/render/rml2txt/rml2txt.py
index 05fc5475343..0cddacb287d 100755
--- a/bin/report/render/rml2txt/rml2txt.py
+++ b/bin/report/render/rml2txt/rml2txt.py
@@ -2,7 +2,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
-# OpenERP, Open Source Management Solution
+# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@@ -49,93 +49,93 @@ import utils
Font_size= 10.0
def verbose(text):
- sys.stderr.write(text+"\n");
+ sys.stderr.write(text+"\n");
class textbox():
- """A box containing plain text.
- It can have an offset, in chars.
- Lines can be either text strings, or textbox'es, recursively.
- """
- def __init__(self,x=0, y=0):
- self.posx = x
- self.posy = y
- self.lines = []
- self.curline = ''
- self.endspace = False
-
- def newline(self):
- if isinstance(self.curline, textbox):
- self.lines.extend(self.curline.renderlines())
- else:
- self.lines.append(self.curline)
- self.curline = ''
-
- def fline(self):
- if isinstance(self.curline, textbox):
- self.lines.extend(self.curline.renderlines())
- elif len(self.curline):
- self.lines.append(self.curline)
- self.curline = ''
-
- def appendtxt(self,txt):
- """Append some text to the current line.
- Mimic the HTML behaviour, where all whitespace evaluates to
- a single space """
- if not txt:
- return
- bs = es = False
- if txt[0].isspace():
- bs = True
- if txt[len(txt)-1].isspace():
- es = True
- if bs and not self.endspace:
- self.curline += " "
- self.curline += txt.strip().replace("\n"," ").replace("\t"," ")
- if es:
- self.curline += " "
- self.endspace = es
-
- def rendertxt(self,xoffset=0):
- result = ''
- lineoff = ""
- for i in range(self.posy):
- result +="\n"
- for i in range(self.posx+xoffset):
- lineoff+=" "
- for l in self.lines:
- result+= lineoff+ l +"\n"
- return result
-
- def renderlines(self,pad=0):
- """Returns a list of lines, from the current object
- pad: all lines must be at least pad characters.
- """
- result = []
- lineoff = ""
- for i in range(self.posx):
- lineoff+=" "
- for l in self.lines:
- lpad = ""
- if pad and len(l) < pad :
- for i in range(pad - len(l)):
- lpad += " "
- #elif pad and len(l) > pad ?
- result.append(lineoff+ l+lpad)
- return result
-
-
- def haplines(self,arr,offset,cc= ''):
- """ Horizontaly append lines
- """
- while (len(self.lines) < len(arr)):
- self.lines.append("")
-
- for i in range(len(self.lines)):
- while (len(self.lines[i]) < offset):
- self.lines[i] += " "
- for i in range(len(arr)):
- self.lines[i] += cc +arr[i]
-
+ """A box containing plain text.
+ It can have an offset, in chars.
+ Lines can be either text strings, or textbox'es, recursively.
+ """
+ def __init__(self,x=0, y=0):
+ self.posx = x
+ self.posy = y
+ self.lines = []
+ self.curline = ''
+ self.endspace = False
+
+ def newline(self):
+ if isinstance(self.curline, textbox):
+ self.lines.extend(self.curline.renderlines())
+ else:
+ self.lines.append(self.curline)
+ self.curline = ''
+
+ def fline(self):
+ if isinstance(self.curline, textbox):
+ self.lines.extend(self.curline.renderlines())
+ elif len(self.curline):
+ self.lines.append(self.curline)
+ self.curline = ''
+
+ def appendtxt(self,txt):
+ """Append some text to the current line.
+ Mimic the HTML behaviour, where all whitespace evaluates to
+ a single space """
+ if not txt:
+ return
+ bs = es = False
+ if txt[0].isspace():
+ bs = True
+ if txt[len(txt)-1].isspace():
+ es = True
+ if bs and not self.endspace:
+ self.curline += " "
+ self.curline += txt.strip().replace("\n"," ").replace("\t"," ")
+ if es:
+ self.curline += " "
+ self.endspace = es
+
+ def rendertxt(self,xoffset=0):
+ result = ''
+ lineoff = ""
+ for i in range(self.posy):
+ result +="\n"
+ for i in range(self.posx+xoffset):
+ lineoff+=" "
+ for l in self.lines:
+ result+= lineoff+ l +"\n"
+ return result
+
+ def renderlines(self,pad=0):
+ """Returns a list of lines, from the current object
+ pad: all lines must be at least pad characters.
+ """
+ result = []
+ lineoff = ""
+ for i in range(self.posx):
+ lineoff+=" "
+ for l in self.lines:
+ lpad = ""
+ if pad and len(l) < pad :
+ for i in range(pad - len(l)):
+ lpad += " "
+ #elif pad and len(l) > pad ?
+ result.append(lineoff+ l+lpad)
+ return result
+
+
+ def haplines(self,arr,offset,cc= ''):
+ """ Horizontaly append lines
+ """
+ while (len(self.lines) < len(arr)):
+ self.lines.append("")
+
+ for i in range(len(self.lines)):
+ while (len(self.lines[i]) < offset):
+ self.lines[i] += " "
+ for i in range(len(arr)):
+ self.lines[i] += cc +arr[i]
+
class _flowable(object):
def __init__(self, template, doc,localcontext):
@@ -143,8 +143,8 @@ class _flowable(object):
'1title': self._tag_title,
'1spacer': self._tag_spacer,
'para': self._tag_para,
- 'font': self._tag_font,
- 'section': self._tag_section,
+ 'font': self._tag_font,
+ 'section': self._tag_section,
'1nextFrame': self._tag_next_frame,
'blockTable': self._tag_table,
'1pageBreak': self._tag_page_break,
@@ -152,15 +152,15 @@ class _flowable(object):
}
self.template = template
self.doc = doc
- self.localcontext = localcontext
- self.nitags = []
- self.tbox = None
+ self.localcontext = localcontext
+ self.nitags = []
+ self.tbox = None
def warn_nitag(self,tag):
- if tag not in self.nitags:
- verbose("Unknown tag \"%s\", please implement it." % tag)
- self.nitags.append(tag)
-
+ if tag not in self.nitags:
+ verbose("Unknown tag \"%s\", please implement it." % tag)
+ self.nitags.append(tag)
+
def _tag_page_break(self, node):
return "\f"
@@ -182,79 +182,79 @@ class _flowable(object):
return "\n"*length
def _tag_table(self, node):
- self.tb.fline()
- saved_tb = self.tb
- self.tb = None
- sizes = None
+ self.tb.fline()
+ saved_tb = self.tb
+ self.tb = None
+ sizes = None
if node.get('colWidths'):
sizes = map(lambda x: utils.unit_get(x), node.get('colWidths').split(','))
- trs = []
- for n in utils._child_get(node,self):
- if n.tag == 'tr':
- tds = []
- for m in utils._child_get(n,self):
- if m.tag == 'td':
- self.tb = textbox()
- self.rec_render_cnodes(m)
- tds.append(self.tb)
- self.tb = None
- if len(tds):
- trs.append(tds)
-
- if not sizes:
- verbose("computing table sizes..")
- for tds in trs:
- trt = textbox()
- off=0
- for i in range(len(tds)):
- p = int(sizes[i]/Font_size)
- trl = tds[i].renderlines(pad=p)
- trt.haplines(trl,off)
- off += sizes[i]/Font_size
- saved_tb.curline = trt
- saved_tb.fline()
-
- self.tb = saved_tb
+ trs = []
+ for n in utils._child_get(node,self):
+ if n.tag == 'tr':
+ tds = []
+ for m in utils._child_get(n,self):
+ if m.tag == 'td':
+ self.tb = textbox()
+ self.rec_render_cnodes(m)
+ tds.append(self.tb)
+ self.tb = None
+ if len(tds):
+ trs.append(tds)
+
+ if not sizes:
+ verbose("computing table sizes..")
+ for tds in trs:
+ trt = textbox()
+ off=0
+ for i in range(len(tds)):
+ p = int(sizes[i]/Font_size)
+ trl = tds[i].renderlines(pad=p)
+ trt.haplines(trl,off)
+ off += sizes[i]/Font_size
+ saved_tb.curline = trt
+ saved_tb.fline()
+
+ self.tb = saved_tb
return
def _tag_para(self, node):
- #TODO: styles
- self.rec_render_cnodes(node)
- self.tb.newline()
+ #TODO: styles
+ self.rec_render_cnodes(node)
+ self.tb.newline()
def _tag_section(self, node):
- #TODO: styles
- self.rec_render_cnodes(node)
- self.tb.newline()
+ #TODO: styles
+ self.rec_render_cnodes(node)
+ self.tb.newline()
def _tag_font(self, node):
- """We do ignore fonts.."""
- self.rec_render_cnodes(node)
+ """We do ignore fonts.."""
+ self.rec_render_cnodes(node)
def rec_render_cnodes(self,node):
self.tb.appendtxt(utils._process_text(self, node.text or ''))
for n in utils._child_get(node,self):
- self.rec_render(n)
- self.tb.appendtxt(utils._process_text(self, node.tail or ''))
+ self.rec_render(n)
+ self.tb.appendtxt(utils._process_text(self, node.tail or ''))
def rec_render(self,node):
""" Recursive render: fill outarr with text of current node
- """
- if node.tag != None:
- if node.tag in self._tags:
- self._tags[node.tag](node)
- else:
- self.warn_nitag(node.tag)
+ """
+ if node.tag != None:
+ if node.tag in self._tags:
+ self._tags[node.tag](node)
+ else:
+ self.warn_nitag(node.tag)
def render(self, node):
- self.tb= textbox()
+ self.tb= textbox()
#result = self.template.start()
#result += self.template.frame_start()
- self.rec_render_cnodes(node)
+ self.rec_render_cnodes(node)
#result += self.template.frame_stop()
#result += self.template.end()
- result = self.tb.rendertxt()
- del self.tb
+ result = self.tb.rendertxt()
+ del self.tb
return result
class _rml_tmpl_tag(object):
@@ -274,12 +274,12 @@ class _rml_tmpl_frame(_rml_tmpl_tag):
self.width = width
self.posx = posx
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)
def tag_end(self):
return True
def tag_stop(self):
- return "frame stop"
+ return "frame stop"
return '</td></tr></table><br/>'
def tag_mergeable(self):
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'))]
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()
res = '\\table ...'
posx = 0
@@ -335,7 +335,7 @@ class _rml_tmpl_draw_lines(_rml_tmpl_tag):
self.style = style.get('hr')
def tag_start(self):
- return "draw lines..\n"
+ return "draw lines..\n"
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)
else:
@@ -475,7 +475,7 @@ class _rml_template(object):
return ''
def end(self):
- return "template end\n"
+ return "template end\n"
result = ''
while not self.loop:
result += self.frame_start()
@@ -498,16 +498,16 @@ class _rml_doc(object):
#self.styles = _rml_styles(el,self.localcontext)
el = self.etree.findall('template')
- self.result =""
+ self.result =""
if len(el):
pt_obj = _rml_template(self.localcontext, out, el[0], self)
stories = utils._child_get(self.etree, self, 'story')
- for story in stories:
- if self.result:
- self.result += '\f'
- f = _flowable(pt_obj,story,self.localcontext)
- self.result += f.render(story)
- del f
+ for story in stories:
+ if self.result:
+ self.result += '\f'
+ f = _flowable(pt_obj,story,self.localcontext)
+ self.result += f.render(story)
+ del f
else:
self.result = "<cannot render w/o template>"
self.result += '\n'
diff --git a/bin/service/http_server.py b/bin/service/http_server.py
index 9c63bec907b..f9d35ed2ef7 100644
--- a/bin/service/http_server.py
+++ b/bin/service/http_server.py
@@ -46,15 +46,15 @@ except ImportError:
fcntl = None
try:
- from ssl import SSLError
+ from ssl import SSLError
except ImportError:
- class SSLError(Exception): pass
+ class SSLError(Exception): pass
class ThreadedHTTPServer(ConnThreadingMixIn, SimpleXMLRPCDispatcher, HTTPServer):
""" A threaded httpd server, with all the necessary functionality for us.
- It also inherits the xml-rpc dispatcher, so that some xml-rpc functions
- will be available to the request handler
+ It also inherits the xml-rpc dispatcher, so that some xml-rpc functions
+ will be available to the request handler
"""
encoding = None
allow_none = False
@@ -81,46 +81,46 @@ class ThreadedHTTPServer(ConnThreadingMixIn, SimpleXMLRPCDispatcher, HTTPServer)
""" Override the error handler
"""
import traceback
- netsvc.Logger().notifyChannel("init", netsvc.LOG_ERROR,"Server error in request from %s:\n%s" %
- (client_address,traceback.format_exc()))
+ netsvc.Logger().notifyChannel("init", netsvc.LOG_ERROR,"Server error in request from %s:\n%s" %
+ (client_address,traceback.format_exc()))
class MultiHandler2(MultiHTTPHandler):
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):
- netsvc.Logger().notifyChannel('http',netsvc.LOG_ERROR,format % args)
+ netsvc.Logger().notifyChannel('http',netsvc.LOG_ERROR,format % args)
class SecureMultiHandler2(SecureMultiHTTPHandler):
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):
tc = tools.config
fcert = tc.get_misc('httpsd','sslcert', 'ssl/server.cert')
- fkey = tc.get_misc('httpsd','sslkey', 'ssl/server.key')
- return (fcert,fkey)
+ fkey = tc.get_misc('httpsd','sslkey', 'ssl/server.key')
+ return (fcert,fkey)
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):
- netsvc.Logger().notifyChannel('http',netsvc.LOG_ERROR,format % args)
+ netsvc.Logger().notifyChannel('http',netsvc.LOG_ERROR,format % args)
class HttpDaemon(threading.Thread, netsvc.Server):
def __init__(self, interface, port):
threading.Thread.__init__(self)
- netsvc.Server.__init__(self)
+ netsvc.Server.__init__(self)
self.__port = port
self.__interface = interface
try:
self.server = ThreadedHTTPServer((interface, port), MultiHandler2)
- self.server.vdirs = []
- self.server.logRequests = True
- netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO,
- "starting HTTP service at %s port %d" % (interface or '0.0.0.0', port,))
+ self.server.vdirs = []
+ self.server.logRequests = True
+ netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO,
+ "starting HTTP service at %s port %d" % (interface or '0.0.0.0', port,))
except Exception, e:
netsvc.Logger().notifyChannel('httpd', netsvc.LOG_CRITICAL, "Error occur when starting the server daemon: %s" % (e,))
raise
@@ -146,16 +146,16 @@ class HttpDaemon(threading.Thread, netsvc.Server):
class HttpSDaemon(threading.Thread, netsvc.Server):
def __init__(self, interface, port):
threading.Thread.__init__(self)
- netsvc.Server.__init__(self)
+ netsvc.Server.__init__(self)
self.__port = port
self.__interface = interface
try:
- self.server = ThreadedHTTPServer((interface, port), SecureMultiHandler2)
- self.server.vdirs = []
- self.server.logRequests = True
- netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO,
- "starting HTTPS service at %s port %d" % (interface or '0.0.0.0', port,))
+ self.server = ThreadedHTTPServer((interface, port), SecureMultiHandler2)
+ self.server.vdirs = []
+ self.server.logRequests = True
+ netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO,
+ "starting HTTPS service at %s port %d" % (interface or '0.0.0.0', port,))
except SSLError, e:
netsvc.Logger().notifyChannel('httpd-ssl', netsvc.LOG_CRITICAL, "Can not load the certificate and/or the private key files")
raise
@@ -184,32 +184,32 @@ httpd = None
httpsd = None
def init_servers():
- global httpd, httpsd
- if tools.config.get_misc('httpd','enable', True):
- httpd = HttpDaemon(tools.config.get_misc('httpd','interface', ''), \
- tools.config.get_misc('httpd','port', 8069))
+ global httpd, httpsd
+ if tools.config.get_misc('httpd','enable', True):
+ httpd = HttpDaemon(tools.config.get_misc('httpd','interface', ''), \
+ tools.config.get_misc('httpd','port', 8069))
- if tools.config.get_misc('httpsd','enable', False):
- httpsd = HttpSDaemon(tools.config.get_misc('httpsd','interface', ''), \
- tools.config.get_misc('httpsd','port', 8071))
+ if tools.config.get_misc('httpsd','enable', False):
+ httpsd = HttpSDaemon(tools.config.get_misc('httpsd','interface', ''), \
+ tools.config.get_misc('httpsd','port', 8071))
def reg_http_service(hts, secure_only = False):
- """ Register some handler to httpd.
- hts must be an HTTPDir
- """
- global httpd, httpsd
- if not isinstance(hts, HTTPDir):
- raise Exception("Wrong class for http service")
-
- if httpd and not secure_only:
- httpd.server.vdirs.append(hts)
-
- if httpsd:
- httpsd.server.vdirs.append(hts)
-
- if (not httpd) and (not httpsd):
- netsvc.Logger().notifyChannel('httpd',netsvc.LOG_WARNING,"No httpd available to register service %s" % hts.path)
- return
+ """ Register some handler to httpd.
+ hts must be an HTTPDir
+ """
+ global httpd, httpsd
+ if not isinstance(hts, HTTPDir):
+ raise Exception("Wrong class for http service")
+
+ if httpd and not secure_only:
+ httpd.server.vdirs.append(hts)
+
+ if httpsd:
+ httpsd.server.vdirs.append(hts)
+
+ if (not httpd) and (not httpsd):
+ netsvc.Logger().notifyChannel('httpd',netsvc.LOG_WARNING,"No httpd available to register service %s" % hts.path)
+ return
import SimpleXMLRPCServer
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)
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):
pass
@@ -233,87 +233,87 @@ class XMLRPCRequestHandler(netsvc.OpenERPDispatcher,FixSendError,SimpleXMLRPCSer
def setup(self):
self.connection = dummyconn()
- if not len(XMLRPCRequestHandler.rpc_paths):
- XMLRPCRequestHandler.rpc_paths = map(lambda s: '/%s' % s, netsvc.ExportService._services.keys())
+ if not len(XMLRPCRequestHandler.rpc_paths):
+ XMLRPCRequestHandler.rpc_paths = map(lambda s: '/%s' % s, netsvc.ExportService._services.keys())
pass
def init_xmlrpc():
- if not tools.config.get_misc('xmlrpc','enable', True):
- return
- reg_http_service(HTTPDir('/xmlrpc/',XMLRPCRequestHandler))
- # Example of http file serving:
- # reg_http_service(HTTPDir('/test/',HTTPHandler))
- netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO,
- "Registered XML-RPC over HTTP")
-
+ if not tools.config.get_misc('xmlrpc','enable', True):
+ return
+ reg_http_service(HTTPDir('/xmlrpc/',XMLRPCRequestHandler))
+ # Example of http file serving:
+ # reg_http_service(HTTPDir('/test/',HTTPHandler))
+ netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO,
+ "Registered XML-RPC over HTTP")
+
class OerpAuthProxy(AuthProxy):
- """ Require basic authentication..
-
- This is a copy of the BasicAuthProxy, which however checks/caches the db
- as well.
- """
- def __init__(self,provider):
- AuthProxy.__init__(self,provider)
- self.auth_creds = {}
- self.auth_tries = 0
- self.last_auth = None
-
- def checkRequest(self,handler,path = '/'):
- if self.auth_creds:
- return True
- auth_str = handler.headers.get('Authorization',False)
- try:
- db = handler.get_db_from_path(path)
- print "Got db:",db
- except:
- if path.startswith('/'):
- path = path[1:]
- psp= path.split('/')
- if len(psp)>1:
- db = psp[0]
- else:
- #FIXME!
- self.provider.log("Wrong path: %s, failing auth" %path)
- raise AuthRejectedExc("Authorization failed. Wrong sub-path.")
-
- if auth_str and auth_str.startswith('Basic '):
- auth_str=auth_str[len('Basic '):]
- (user,passwd) = base64.decodestring(auth_str).split(':')
- self.provider.log("Found user=\"%s\", passwd=\"***\" for db=\"%s\"" %(user,db))
- acd = self.provider.authenticate(db,user,passwd,handler.client_address)
- if acd != False:
- self.auth_creds[db] = acd
- self.last_auth=db
- return True
- if self.auth_tries > 5:
- self.provider.log("Failing authorization after 5 requests w/o password")
- raise AuthRejectedExc("Authorization failed.")
- self.auth_tries += 1
- raise AuthRequiredExc(atype = 'Basic', realm=self.provider.realm)
+ """ Require basic authentication..
+
+ This is a copy of the BasicAuthProxy, which however checks/caches the db
+ as well.
+ """
+ def __init__(self,provider):
+ AuthProxy.__init__(self,provider)
+ self.auth_creds = {}
+ self.auth_tries = 0
+ self.last_auth = None
+
+ def checkRequest(self,handler,path = '/'):
+ if self.auth_creds:
+ return True
+ auth_str = handler.headers.get('Authorization',False)
+ try:
+ db = handler.get_db_from_path(path)
+ print "Got db:",db
+ except:
+ if path.startswith('/'):
+ path = path[1:]
+ psp= path.split('/')
+ if len(psp)>1:
+ db = psp[0]
+ else:
+ #FIXME!
+ self.provider.log("Wrong path: %s, failing auth" %path)
+ raise AuthRejectedExc("Authorization failed. Wrong sub-path.")
+
+ if auth_str and auth_str.startswith('Basic '):
+ auth_str=auth_str[len('Basic '):]
+ (user,passwd) = base64.decodestring(auth_str).split(':')
+ self.provider.log("Found user=\"%s\", passwd=\"***\" for db=\"%s\"" %(user,db))
+ acd = self.provider.authenticate(db,user,passwd,handler.client_address)
+ if acd != False:
+ self.auth_creds[db] = acd
+ self.last_auth=db
+ return True
+ if self.auth_tries > 5:
+ self.provider.log("Failing authorization after 5 requests w/o password")
+ raise AuthRejectedExc("Authorization failed.")
+ self.auth_tries += 1
+ raise AuthRequiredExc(atype = 'Basic', realm=self.provider.realm)
import security
class OpenERPAuthProvider(AuthProvider):
- def __init__(self,realm = 'OpenERP User'):
- self.realm = realm
-
- def setupAuth(self, multi, handler):
- if not multi.sec_realms.has_key(self.realm):
- multi.sec_realms[self.realm] = OerpAuthProxy(self)
- handler.auth_proxy = multi.sec_realms[self.realm]
-
- def authenticate(self, db, user, passwd, client_address):
- try:
- uid = security.login(db,user,passwd)
- if uid is False:
- return False
- return (user, passwd, db, uid)
- except Exception,e:
- netsvc.Logger().notifyChannel("auth",netsvc.LOG_DEBUG,"Fail auth:"+ str(e))
- return False
-
- def log(self, msg):
- netsvc.Logger().notifyChannel("auth",netsvc.LOG_INFO,msg)
+ def __init__(self,realm = 'OpenERP User'):
+ self.realm = realm
+
+ def setupAuth(self, multi, handler):
+ if not multi.sec_realms.has_key(self.realm):
+ multi.sec_realms[self.realm] = OerpAuthProxy(self)
+ handler.auth_proxy = multi.sec_realms[self.realm]
+
+ def authenticate(self, db, user, passwd, client_address):
+ try:
+ uid = security.login(db,user,passwd)
+ if uid is False:
+ return False
+ return (user, passwd, db, uid)
+ except Exception,e:
+ netsvc.Logger().notifyChannel("auth",netsvc.LOG_DEBUG,"Fail auth:"+ str(e))
+ return False
+
+ def log(self, msg):
+ netsvc.Logger().notifyChannel("auth",netsvc.LOG_INFO,msg)
#eof
diff --git a/bin/service/netrpc_server.py b/bin/service/netrpc_server.py
index 50679eed2db..a126eb77907 100644
--- a/bin/service/netrpc_server.py
+++ b/bin/service/netrpc_server.py
@@ -141,23 +141,23 @@ class TinySocketServerThread(threading.Thread,netsvc.Server):
return False
def stats(self):
- res = "Net-RPC: " + ( (self.running and "running") or "stopped")
- i = 0
- for t in self.threads:
- i += 1
- res += "\nNet-RPC #%d: %s " % (i, t.name)
- if t.isAlive():
- res += "running"
- else:
- res += "finished"
- if t.sock:
- res += ", socket"
- return res
+ res = "Net-RPC: " + ( (self.running and "running") or "stopped")
+ i = 0
+ for t in self.threads:
+ i += 1
+ res += "\nNet-RPC #%d: %s " % (i, t.name)
+ if t.isAlive():
+ res += "running"
+ else:
+ res += "finished"
+ if t.sock:
+ res += ", socket"
+ return res
netrpcd = None
def init_servers():
- global netrpcd
- if tools.config.get_misc('netrpcd','enable', True):
- netrpcd = TinySocketServerThread(tools.config.get_misc('netrpcd','interface', ''), \
- tools.config.get_misc('netrpcd','port', 8070))
+ global netrpcd
+ if tools.config.get_misc('netrpcd','enable', True):
+ netrpcd = TinySocketServerThread(tools.config.get_misc('netrpcd','interface', ''), \
+ tools.config.get_misc('netrpcd','port', 8070))
diff --git a/bin/service/web_services.py b/bin/service/web_services.py
index 907091e51db..42fc5c0e37c 100644
--- a/bin/service/web_services.py
+++ b/bin/service/web_services.py
@@ -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
def dispatch(self, method, auth, params):
- if method in [ 'create', 'get_progress', 'drop', 'dump',
- 'restore', 'rename',
- 'change_admin_password', 'migrate_databases' ]:
- passwd = params[0]
- params = params[1:]
- security.check_super(passwd)
- elif method in [ 'db_exist', 'list', 'list_lang', 'server_version' ]:
- # params = params
- # No security check for these methods
- pass
- else:
- raise KeyError("Method not found: %s" % method)
- fn = getattr(self, 'exp_'+method)
- return fn(*params)
-
+ if method in [ 'create', 'get_progress', 'drop', 'dump',
+ 'restore', 'rename',
+ 'change_admin_password', 'migrate_databases' ]:
+ passwd = params[0]
+ params = params[1:]
+ security.check_super(passwd)
+ elif method in [ 'db_exist', 'list', 'list_lang', 'server_version' ]:
+ # params = params
+ # No security check for these methods
+ pass
+ else:
+ raise KeyError("Method not found: %s" % method)
+ fn = getattr(self, 'exp_'+method)
+ return fn(*params)
+
def new_dispatch(self,method,auth,params):
- pass
+ pass
def exp_create(self, db_name, demo, lang, user_password='admin'):
self.id_protect.acquire()
@@ -366,15 +366,15 @@ class _ObjectService(netsvc.ExportService):
"A common base class for those who have fn(db, uid, password,...) "
def common_dispatch(self, method, auth, params):
- (db, uid, passwd ) = params[0:3]
- params = params[3:]
- security.check(db,uid,passwd)
- cr = pooler.get_db(db).cursor()
- fn = getattr(self, 'exp_'+method)
- res = fn(cr, uid, *params)
- cr.commit()
- cr.close()
- return res
+ (db, uid, passwd ) = params[0:3]
+ params = params[3:]
+ security.check(db,uid,passwd)
+ cr = pooler.get_db(db).cursor()
+ fn = getattr(self, 'exp_'+method)
+ res = fn(cr, uid, *params)
+ cr.commit()
+ cr.close()
+ return res
class common(_ObjectService):
def __init__(self,name="common"):
@@ -382,36 +382,36 @@ class common(_ObjectService):
self.joinGroup("web-services")
def dispatch(self, method, auth, params):
- logger = netsvc.Logger()
- if method in [ 'ir_set','ir_del', 'ir_get' ]:
- return self.common_dispatch(method,auth,params)
- if method == 'login':
- # At this old dispatcher, we do NOT update the auth proxy
- res = security.login(params[0], params[1], params[2])
- msg = res and 'successful login' or 'bad login or password'
- # 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()))
- return res or False
- elif method == 'logout':
- if auth:
- auth.logout(params[1])
- logger.notifyChannel("web-service", netsvc.LOG_INFO,'Logout %s from database %s'%(login,db))
- return True
- elif method in ['about', 'timezone_get', 'get_server_environment', 'login_message', 'get_stats' ]:
- pass
- elif method in ['get_available_updates', 'get_migration_scripts', 'set_loglevel']:
- passwd = params[0]
- params = params[1:]
- security.check_super(passwd)
- else:
- raise Exception("Method not found: %s" % method)
-
- fn = getattr(self, 'exp_'+method)
- return fn(*params)
+ logger = netsvc.Logger()
+ if method in [ 'ir_set','ir_del', 'ir_get' ]:
+ return self.common_dispatch(method,auth,params)
+ if method == 'login':
+ # At this old dispatcher, we do NOT update the auth proxy
+ res = security.login(params[0], params[1], params[2])
+ msg = res and 'successful login' or 'bad login or password'
+ # 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()))
+ return res or False
+ elif method == 'logout':
+ if auth:
+ auth.logout(params[1])
+ logger.notifyChannel("web-service", netsvc.LOG_INFO,'Logout %s from database %s'%(login,db))
+ return True
+ elif method in ['about', 'timezone_get', 'get_server_environment', 'login_message', 'get_stats' ]:
+ pass
+ elif method in ['get_available_updates', 'get_migration_scripts', 'set_loglevel']:
+ passwd = params[0]
+ params = params[1:]
+ security.check_super(passwd)
+ else:
+ raise Exception("Method not found: %s" % method)
+
+ fn = getattr(self, 'exp_'+method)
+ return fn(*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):
res = ir.ir_set(cr,uid, keys, args, name, value, replace, isobject)
@@ -574,7 +574,7 @@ GNU Public Licence.
def exp_get_stats(self):
import threading
res = "OpenERP server: %d threads\n" % threading.active_count()
- res += netsvc.Server.allStats()
+ res += netsvc.Server.allStats()
return res
common()
@@ -585,19 +585,19 @@ class objects_proxy(netsvc.ExportService):
self.joinGroup('web-services')
def dispatch(self, method, auth, params):
- (db, uid, passwd ) = params[0:3]
- params = params[3:]
- if method not in ['execute','exec_workflow','obj_list']:
- raise KeyError("Method not supported %s" % method)
- security.check(db,uid,passwd)
- ls = netsvc.LocalService('object_proxy')
- fn = getattr(ls, method)
- res = fn(db, uid, *params)
- return res
-
-
+ (db, uid, passwd ) = params[0:3]
+ params = params[3:]
+ if method not in ['execute','exec_workflow','obj_list']:
+ raise KeyError("Method not supported %s" % method)
+ security.check(db,uid,passwd)
+ ls = netsvc.LocalService('object_proxy')
+ fn = getattr(ls, method)
+ res = fn(db, uid, *params)
+ return res
+
+
def new_dispatch(self,method,auth,params):
- pass
+ pass
objects_proxy()
@@ -623,17 +623,17 @@ class wizard(netsvc.ExportService):
self.wiz_uid = {}
def dispatch(self, method, auth, params):
- (db, uid, passwd ) = params[0:3]
- params = params[3:]
- if method not in ['execute','create']:
- raise KeyError("Method not supported %s" % method)
- security.check(db,uid,passwd)
- fn = getattr(self, 'exp_'+method)
- res = fn(db, uid, *params)
- return res
-
+ (db, uid, passwd ) = params[0:3]
+ params = params[3:]
+ if method not in ['execute','create']:
+ raise KeyError("Method not supported %s" % method)
+ security.check(db,uid,passwd)
+ fn = getattr(self, 'exp_'+method)
+ res = fn(db, uid, *params)
+ return res
+
def new_dispatch(self,method,auth,params):
- pass
+ pass
def _execute(self, db, uid, wiz_id, datas, action, context):
self.wiz_datas[wiz_id].update(datas)
@@ -685,18 +685,18 @@ class report_spool(netsvc.ExportService):
self.id_protect = threading.Semaphore()
def dispatch(self, method, auth, params):
- (db, uid, passwd ) = params[0:3]
- params = params[3:]
- if method not in ['report','report_get']:
- raise KeyError("Method not supported %s" % method)
- security.check(db,uid,passwd)
- fn = getattr(self, 'exp_' + method)
- res = fn(db, uid, *params)
- return res
-
-
+ (db, uid, passwd ) = params[0:3]
+ params = params[3:]
+ if method not in ['report','report_get']:
+ raise KeyError("Method not supported %s" % method)
+ security.check(db,uid,passwd)
+ fn = getattr(self, 'exp_' + method)
+ res = fn(db, uid, *params)
+ return res
+
+
def new_dispatch(self,method,auth,params):
- pass
+ pass
def exp_report(self, db, uid, object, ids, datas=None, context=None):
if not datas:
diff --git a/bin/service/websrv_lib.py b/bin/service/websrv_lib.py
index 759b7b6f3c3..1913b5d5102 100644
--- a/bin/service/websrv_lib.py
+++ b/bin/service/websrv_lib.py
@@ -37,115 +37,115 @@ from BaseHTTPServer import *
from SimpleHTTPServer import SimpleHTTPRequestHandler
class AuthRequiredExc(Exception):
- def __init__(self,atype,realm):
- Exception.__init__(self)
- self.atype = atype
- self.realm = realm
-
+ def __init__(self,atype,realm):
+ Exception.__init__(self)
+ self.atype = atype
+ self.realm = realm
+
class AuthRejectedExc(Exception):
- pass
+ pass
class AuthProvider:
- def __init__(self,realm):
- self.realm = realm
+ def __init__(self,realm):
+ self.realm = realm
- def setupAuth(self, multi,handler):
- """ Attach an AuthProxy object to handler
- """
- pass
+ def setupAuth(self, multi,handler):
+ """ Attach an AuthProxy object to handler
+ """
+ pass
- def authenticate(self, user, passwd, client_address):
- return False
-
- def log(self, msg):
- print msg
+ def authenticate(self, user, passwd, client_address):
+ return False
+
+ def log(self, msg):
+ print msg
class BasicAuthProvider(AuthProvider):
- def setupAuth(self, multi, handler):
- if not multi.sec_realms.has_key(self.realm):
- multi.sec_realms[self.realm] = BasicAuthProxy(self)
-
+ def setupAuth(self, multi, handler):
+ if not multi.sec_realms.has_key(self.realm):
+ multi.sec_realms[self.realm] = BasicAuthProxy(self)
+
class AuthProxy:
- """ This class will hold authentication information for a handler,
- i.e. a connection
- """
- def __init__(self, provider):
- self.provider = provider
+ """ This class will hold authentication information for a handler,
+ i.e. a connection
+ """
+ def __init__(self, provider):
+ self.provider = provider
- def checkRequest(self,handler,path = '/'):
- """ Check if we are allowed to process that request
- """
- pass
+ def checkRequest(self,handler,path = '/'):
+ """ Check if we are allowed to process that request
+ """
+ pass
class BasicAuthProxy(AuthProxy):
- """ Require basic authentication..
- """
- def __init__(self,provider):
- AuthProxy.__init__(self,provider)
- self.auth_creds = None
- self.auth_tries = 0
-
- def checkRequest(self,handler,path = '/'):
- if self.auth_creds:
- return True
- auth_str = handler.headers.get('Authorization',False)
- if auth_str and auth_str.startswith('Basic '):
- auth_str=auth_str[len('Basic '):]
- (user,passwd) = base64.decodestring(auth_str).split(':')
- self.provider.log("Found user=\"%s\", passwd=\"%s\"" %(user,passwd))
- self.auth_creds = self.provider.authenticate(user,passwd,handler.client_address)
- if self.auth_creds:
- return True
- if self.auth_tries > 5:
- self.provider.log("Failing authorization after 5 requests w/o password")
- raise AuthRejectedExc("Authorization failed.")
- self.auth_tries += 1
- raise AuthRequiredExc(atype = 'Basic', realm=self.provider.realm)
+ """ Require basic authentication..
+ """
+ def __init__(self,provider):
+ AuthProxy.__init__(self,provider)
+ self.auth_creds = None
+ self.auth_tries = 0
+
+ def checkRequest(self,handler,path = '/'):
+ if self.auth_creds:
+ return True
+ auth_str = handler.headers.get('Authorization',False)
+ if auth_str and auth_str.startswith('Basic '):
+ auth_str=auth_str[len('Basic '):]
+ (user,passwd) = base64.decodestring(auth_str).split(':')
+ self.provider.log("Found user=\"%s\", passwd=\"%s\"" %(user,passwd))
+ self.auth_creds = self.provider.authenticate(user,passwd,handler.client_address)
+ if self.auth_creds:
+ return True
+ if self.auth_tries > 5:
+ self.provider.log("Failing authorization after 5 requests w/o password")
+ raise AuthRejectedExc("Authorization failed.")
+ self.auth_tries += 1
+ raise AuthRequiredExc(atype = 'Basic', realm=self.provider.realm)
class HTTPHandler(SimpleHTTPRequestHandler):
- def __init__(self,request, client_address, server):
- SimpleHTTPRequestHandler.__init__(self,request,client_address,server)
- # print "Handler for %s inited" % str(client_address)
- self.protocol_version = 'HTTP/1.1'
- self.connection = dummyconn()
-
- def handle(self):
- """ Classes here should NOT handle inside their constructor
- """
- pass
-
- def finish(self):
- pass
-
- def setup(self):
- pass
+ def __init__(self,request, client_address, server):
+ SimpleHTTPRequestHandler.__init__(self,request,client_address,server)
+ # print "Handler for %s inited" % str(client_address)
+ self.protocol_version = 'HTTP/1.1'
+ self.connection = dummyconn()
+
+ def handle(self):
+ """ Classes here should NOT handle inside their constructor
+ """
+ pass
+
+ def finish(self):
+ pass
+
+ def setup(self):
+ pass
class HTTPDir:
- """ A dispatcher class, like a virtual folder in httpd
- """
- def __init__(self,path,handler, auth_provider = None):
- self.path = path
- self.handler = handler
- self.auth_provider = auth_provider
-
- def matches(self, request):
- """ Test if some request matches us. If so, return
- the matched path. """
- if request.startswith(self.path):
- return self.path
- return False
+ """ A dispatcher class, like a virtual folder in httpd
+ """
+ def __init__(self,path,handler, auth_provider = None):
+ self.path = path
+ self.handler = handler
+ self.auth_provider = auth_provider
+
+ def matches(self, request):
+ """ Test if some request matches us. If so, return
+ the matched path. """
+ if request.startswith(self.path):
+ return self.path
+ return False
class noconnection:
- """ a class to use instead of the real connection
- """
- def makefile(self, mode, bufsize):
- return None
+ """ a class to use instead of the real connection
+ """
+ def makefile(self, mode, bufsize):
+ return None
class dummyconn:
- def shutdown(self, tru):
- pass
+ def shutdown(self, tru):
+ pass
def _quote_html(html):
return html.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
@@ -168,7 +168,7 @@ class FixSendError:
self.send_response(code, message)
self.send_header("Content-Type", self.error_content_type)
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()
if self.command != 'HEAD' and code >= 200 and code not in (204, 304):
self.wfile.write(content)
@@ -176,65 +176,65 @@ class FixSendError:
class MultiHTTPHandler(FixSendError,BaseHTTPRequestHandler):
""" this is a multiple handler, that will dispatch each request
to a nested handler, iff it matches
-
- The handler will also have *one* dict of authentication proxies,
- groupped by their realm.
+
+ The handler will also have *one* dict of authentication proxies,
+ groupped by their realm.
"""
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>
<body>You must authenticate to use this service</body><html>\r\r"""
def __init__(self, request, client_address, server):
- self.in_handlers = {}
- self.sec_realms = {}
- SocketServer.StreamRequestHandler.__init__(self,request,client_address,server)
- self.log_message("MultiHttpHandler init for %s" %(str(client_address)))
+ self.in_handlers = {}
+ self.sec_realms = {}
+ SocketServer.StreamRequestHandler.__init__(self,request,client_address,server)
+ self.log_message("MultiHttpHandler init for %s" %(str(client_address)))
def _handle_one_foreign(self,fore, path, auth_provider):
""" This method overrides the handle_one_request for *children*
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)
if not fore.parse_request(): # An error code has been sent, just exit
return
- self.request_version = fore.request_version
- if auth_provider and auth_provider.realm:
- try:
- self.sec_realms[auth_provider.realm].checkRequest(fore,path)
- except AuthRequiredExc,ae:
- if self.request_version != 'HTTP/1.1':
- self.log_error("Cannot require auth at %s",self.request_version)
- self.send_error(401)
- return
- self._get_ignore_body(fore) # consume any body that came, not loose sync with input
- self.send_response(401,'Authorization required')
- self.send_header('WWW-Authenticate','%s realm="%s"' % (ae.atype,ae.realm))
- self.send_header('Connection', 'keep-alive')
- self.send_header('Content-Type','text/html')
- self.send_header('Content-Length',len(self.auth_required_msg))
- self.end_headers()
- self.wfile.write(self.auth_required_msg)
- return
- except AuthRejectedExc,e:
- self.log_error("Rejected auth: %s" % e.args[0])
- self.send_error(401,e.args[0])
- self.close_connection = 1
- return
+ self.request_version = fore.request_version
+ if auth_provider and auth_provider.realm:
+ try:
+ self.sec_realms[auth_provider.realm].checkRequest(fore,path)
+ except AuthRequiredExc,ae:
+ if self.request_version != 'HTTP/1.1':
+ self.log_error("Cannot require auth at %s",self.request_version)
+ self.send_error(401)
+ return
+ self._get_ignore_body(fore) # consume any body that came, not loose sync with input
+ self.send_response(401,'Authorization required')
+ self.send_header('WWW-Authenticate','%s realm="%s"' % (ae.atype,ae.realm))
+ self.send_header('Connection', 'keep-alive')
+ self.send_header('Content-Type','text/html')
+ self.send_header('Content-Length',len(self.auth_required_msg))
+ self.end_headers()
+ self.wfile.write(self.auth_required_msg)
+ return
+ except AuthRejectedExc,e:
+ self.log_error("Rejected auth: %s" % e.args[0])
+ self.send_error(401,e.args[0])
+ self.close_connection = 1
+ return
mname = 'do_' + fore.command
if not hasattr(fore, mname):
fore.send_error(501, "Unsupported method (%r)" % fore.command)
return
- fore.close_connection = 0
+ fore.close_connection = 0
method = getattr(fore, mname)
method()
- if fore.close_connection:
- # print "Closing connection because of handler"
- self.close_connection = fore.close_connection
+ if fore.close_connection:
+ # print "Closing connection because of handler"
+ self.close_connection = fore.close_connection
def parse_rawline(self):
"""Parse a request (internal).
@@ -295,67 +295,67 @@ class MultiHTTPHandler(FixSendError,BaseHTTPRequestHandler):
else:
self.send_error(400, "Bad request syntax (%r)" % requestline)
return False
- self.request_version = version
- self.command, self.path, self.version = command, path, version
- return True
+ self.request_version = version
+ self.command, self.path, self.version = command, path, version
+ return True
def handle_one_request(self):
"""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()
- if not self.raw_requestline:
- self.close_connection = 1
- # self.log_message("no requestline, connection closed?")
- return
- if not self.parse_rawline():
- self.log_message("Could not parse rawline.")
- return
+ if not self.raw_requestline:
+ self.close_connection = 1
+ # self.log_message("no requestline, connection closed?")
+ return
+ if not self.parse_rawline():
+ self.log_message("Could not parse rawline.")
+ return
# self.parse_request(): # Do NOT parse here. the first line should be the only
- for vdir in self.server.vdirs:
- p = vdir.matches(self.path)
- if p == False:
- continue
- npath = self.path[len(p):]
- if not npath.startswith('/'):
- npath = '/' + npath
-
- if not self.in_handlers.has_key(p):
- self.in_handlers[p] = vdir.handler(noconnection(),self.client_address,self.server)
- if vdir.auth_provider:
- vdir.auth_provider.setupAuth(self, self.in_handlers[p])
- hnd = self.in_handlers[p]
- hnd.rfile = self.rfile
- hnd.wfile = self.wfile
- self.rlpath = self.raw_requestline
- self._handle_one_foreign(hnd,npath, vdir.auth_provider)
- # print "Handled, closing = ", self.close_connection
- return
- # if no match:
+ for vdir in self.server.vdirs:
+ p = vdir.matches(self.path)
+ if p == False:
+ continue
+ npath = self.path[len(p):]
+ if not npath.startswith('/'):
+ npath = '/' + npath
+
+ if not self.in_handlers.has_key(p):
+ self.in_handlers[p] = vdir.handler(noconnection(),self.client_address,self.server)
+ if vdir.auth_provider:
+ vdir.auth_provider.setupAuth(self, self.in_handlers[p])
+ hnd = self.in_handlers[p]
+ hnd.rfile = self.rfile
+ hnd.wfile = self.wfile
+ self.rlpath = self.raw_requestline
+ self._handle_one_foreign(hnd,npath, vdir.auth_provider)
+ # print "Handled, closing = ", self.close_connection
+ return
+ # if no match:
self.send_error(404, "Path not found: %s" % self.path)
return
def _get_ignore_body(self,fore):
- if not fore.headers.has_key("content-length"):
- return
- max_chunk_size = 10*1024*1024
- size_remaining = int(fore.headers["content-length"])
- got = ''
- while size_remaining:
- chunk_size = min(size_remaining, max_chunk_size)
- got = fore.rfile.read(chunk_size)
- size_remaining -= len(got)
+ if not fore.headers.has_key("content-length"):
+ return
+ max_chunk_size = 10*1024*1024
+ size_remaining = int(fore.headers["content-length"])
+ got = ''
+ while size_remaining:
+ chunk_size = min(size_remaining, max_chunk_size)
+ got = fore.rfile.read(chunk_size)
+ size_remaining -= len(got)
class SecureMultiHTTPHandler(MultiHTTPHandler):
def getcert_fnames(self):
- """ Return a pair with the filenames of ssl cert,key
-
- Override this to direct to other filenames
- """
- return ('server.cert','server.key')
-
+ """ Return a pair with the filenames of ssl cert,key
+
+ Override this to direct to other filenames
+ """
+ return ('server.cert','server.key')
+
def setup(self):
import ssl
certfile, keyfile = self.getcert_fnames()
@@ -386,10 +386,10 @@ import threading
class ConnThreadingMixIn:
"""Mix-in class to handle each _connection_ in a new thread.
- This is necessary for persistent connections, where multiple
- requests should be handled synchronously at each connection, but
- multiple connections can run in parallel.
- """
+ This is necessary for persistent connections, where multiple
+ requests should be handled synchronously at each connection, but
+ multiple connections can run in parallel.
+ """
# Decides how threads will act upon termination of the
# main process
@@ -401,7 +401,7 @@ class ConnThreadingMixIn:
if self.daemon_threads:
t.setDaemon (1)
t.start()
-
+
def _handle_request2(self):
"""Handle one request, without blocking.
diff --git a/bin/sql_db.py b/bin/sql_db.py
index 4973aaa221e..42d11e78f0e 100644
--- a/bin/sql_db.py
+++ b/bin/sql_db.py
@@ -119,14 +119,14 @@ class Cursor(object):
try:
params = params or None
res = self._obj.execute(query, params)
- except psycopg2.ProgrammingError, pe:
- logger= netsvc.Logger()
- logger.notifyChannel('sql_db', netsvc.LOG_ERROR, "Programming error: %s, in query %s" % (pe, query))
- raise
+ except psycopg2.ProgrammingError, pe:
+ logger= netsvc.Logger()
+ logger.notifyChannel('sql_db', netsvc.LOG_ERROR, "Programming error: %s, in query %s" % (pe, query))
+ raise
except Exception, e:
log("bad query: %s" % self._obj.query)
log(e)
- raise
+ raise
if self.sql_log:
log("query: %s" % self._obj.query)
@@ -144,8 +144,8 @@ class Cursor(object):
return res
def print_log(self):
- global sql_counter
- sql_counter += self.count
+ global sql_counter
+ sql_counter += self.count
def process(type):
sqllogs = {'from':self.sql_from_log, 'into':self.sql_into_log}
sum = 0
diff --git a/bin/tools/config.py b/bin/tools/config.py
index 770fdea7de1..2dd6b1131bf 100644
--- a/bin/tools/config.py
+++ b/bin/tools/config.py
@@ -66,7 +66,7 @@ class configmanager(object):
'import_partial': "",
'pidfile': None,
'logfile': None,
- 'logrotate': '1',
+ 'logrotate': '1',
'smtp_server': 'localhost',
'smtp_user': False,
'smtp_port':25,
@@ -82,8 +82,8 @@ class configmanager(object):
'login_message': False,
'list_db' : True,
}
-
- self.misc = {}
+
+ self.misc = {}
hasSSL = check_ssl()
@@ -135,7 +135,7 @@ class configmanager(object):
group = optparse.OptionGroup(parser, "Logging Configuration")
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",
- 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",
default=False, help="Send the log to the syslog server")
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',
'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy',
'netinterface', 'netport', 'db_maxconn', 'import_partial', 'addons_path',
- 'netrpc', 'xmlrpc', 'syslog', 'without_demo']
+ 'netrpc', 'xmlrpc', 'syslog', 'without_demo']
if hasSSL:
keys.extend(['smtp_ssl', 'secure_cert_file', 'secure_pkey_file'])
@@ -341,18 +341,18 @@ class configmanager(object):
if value=='False' or value=='false':
value = False
self.options[name] = value
- #parse the other sections, as well
- for sec in p.sections():
- if sec == 'options':
- continue
- if not self.misc.has_key(sec):
- self.misc[sec]= {}
- for (name, value) in p.items(sec):
- if value=='True' or value=='true':
- value = True
- if value=='False' or value=='false':
- value = False
- self.misc[sec][name] = value
+ #parse the other sections, as well
+ for sec in p.sections():
+ if sec == 'options':
+ continue
+ if not self.misc.has_key(sec):
+ self.misc[sec]= {}
+ for (name, value) in p.items(sec):
+ if value=='True' or value=='true':
+ value = True
+ if value=='False' or value=='false':
+ value = False
+ self.misc[sec][name] = value
except IOError:
pass
except ConfigParser.NoSectionError:
@@ -369,10 +369,10 @@ class configmanager(object):
p.set('options', opt, loglevelnames.get(self.options[opt], self.options[opt]))
else:
p.set('options', opt, self.options[opt])
-
- for sec in self.misc.keys():
- for opt in self.misc[sec].keys():
- p.set(sec,opt,self.misc[sec][opt])
+
+ for sec in self.misc.keys():
+ for opt in self.misc[sec].keys():
+ p.set(sec,opt,self.misc[sec][opt])
# try to create the directories and write the file
try:
diff --git a/bin/tools/misc.py b/bin/tools/misc.py
index 9e65a47031a..982287c0864 100644
--- a/bin/tools/misc.py
+++ b/bin/tools/misc.py
@@ -386,15 +386,15 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
smtp_server = config['smtp_server']
if smtp_server.startswith('maildir:/'):
from mailbox import Maildir
- maildir_path = smtp_server[8:]
- try:
- mdir = Maildir(maildir_path,factory=None, create = True)
- mdir.add(msg.as_string(True))
- return True
- except Exception,e:
- netsvc.Logger().notifyChannel('email_send (maildir)', netsvc.LOG_ERROR, e)
- return False
-
+ maildir_path = smtp_server[8:]
+ try:
+ mdir = Maildir(maildir_path,factory=None, create = True)
+ mdir.add(msg.as_string(True))
+ return True
+ except Exception,e:
+ netsvc.Logger().notifyChannel('email_send (maildir)', netsvc.LOG_ERROR, e)
+ return False
+
try:
oldstderr = smtplib.stderr
s = smtplib.SMTP()
diff --git a/bin/tools/safe_eval.py b/bin/tools/safe_eval.py
index 7c4da78375c..bfbc0b34fe9 100644
--- a/bin/tools/safe_eval.py
+++ b/bin/tools/safe_eval.py
@@ -29,38 +29,38 @@ __export_bis = {}
import sys
def __init_ebis():
- global __export_bis
-
- _evars = [ 'abs', 'all', 'any', 'basestring' , 'bool',
- 'chr', 'cmp','complex', 'dict', 'divmod', 'enumerate',
- 'float', 'frozenset', 'getattr', 'hasattr', 'hash',
- 'hex', 'id','int', 'iter', 'len', 'list', 'long', 'map', 'max',
- 'min', 'oct', 'ord','pow', 'range', 'reduce', 'repr',
- 'reversed', 'round', 'set', 'setattr', 'slice','sorted', 'str',
- 'sum', 'tuple','type', 'unichr','unicode', 'xrange',
- 'True','False', 'None', 'NotImplemented', 'Ellipsis', ]
-
- if sys.version_info[0:2] >= (2,6):
- _evars.extend(['bin', 'format', 'next'])
- for v in _evars:
- __export_bis[v] = __builtins__[v]
-
+ global __export_bis
+
+ _evars = [ 'abs', 'all', 'any', 'basestring' , 'bool',
+ 'chr', 'cmp','complex', 'dict', 'divmod', 'enumerate',
+ 'float', 'frozenset', 'getattr', 'hasattr', 'hash',
+ 'hex', 'id','int', 'iter', 'len', 'list', 'long', 'map', 'max',
+ 'min', 'oct', 'ord','pow', 'range', 'reduce', 'repr',
+ 'reversed', 'round', 'set', 'setattr', 'slice','sorted', 'str',
+ 'sum', 'tuple','type', 'unichr','unicode', 'xrange',
+ 'True','False', 'None', 'NotImplemented', 'Ellipsis', ]
+
+ if sys.version_info[0:2] >= (2,6):
+ _evars.extend(['bin', 'format', 'next'])
+ for v in _evars:
+ __export_bis[v] = __builtins__[v]
+
__init_ebis()
def safe_eval(expr,sglobals,slocals = None):
- """ A little safer version of eval().
- This one, will use fewer builtin functions, so that only
- arithmetic and logic expressions can really work """
-
- global __export_bis
+ """ A little safer version of eval().
+ This one, will use fewer builtin functions, so that only
+ arithmetic and logic expressions can really work """
+
+ global __export_bis
- if not sglobals.has_key('__builtins__'):
- # we copy, because we wouldn't want successive calls to safe_eval
- # to be able to alter the builtins.
- sglobals['__builtins__'] = __export_bis.copy()
-
- return eval(expr,sglobals,slocals)
-
-#eof \ No newline at end of file
+ if not sglobals.has_key('__builtins__'):
+ # we copy, because we wouldn't want successive calls to safe_eval
+ # to be able to alter the builtins.
+ sglobals['__builtins__'] = __export_bis.copy()
+
+ return eval(expr,sglobals,slocals)
+
+#eof
diff --git a/bin/tools/translate.py b/bin/tools/translate.py
index dcd7afbcff4..57b15002a4e 100644
--- a/bin/tools/translate.py
+++ b/bin/tools/translate.py
@@ -133,12 +133,12 @@ class GettextAlias(object):
return source
cr = frame.f_locals.get('cr')
- try:
- lang = (frame.f_locals.get('context') or {}).get('lang', False)
- if not (lang and cr):
- return source
- except:
- return source
+ try:
+ lang = (frame.f_locals.get('context') or {}).get('lang', False)
+ if not (lang and cr):
+ return source
+ except:
+ return source
cr.execute('select value from ir_translation where lang=%s and type=%s and src=%s', (lang, 'code', source))
res_trans = cr.fetchone()
@@ -154,7 +154,7 @@ class TinyPoFile(object):
def __iter__(self):
self.buffer.seek(0)
self.lines = self._get_lines()
- self.lines_count = len(self.lines);
+ self.lines_count = len(self.lines);
self.first = True
self.tnrs= []
@@ -170,7 +170,7 @@ class TinyPoFile(object):
return lines
def cur_line(self):
- return (self.lines_count - len(self.lines))
+ return (self.lines_count - len(self.lines))
def next(self):
def unquote(str):
@@ -185,30 +185,30 @@ class TinyPoFile(object):
else:
tmp_tnrs = []
line = None
- fuzzy = False
+ fuzzy = False
while (not line):
if 0 == len(self.lines):
raise StopIteration()
line = self.lines.pop(0).strip()
if line.startswith('#:'):
- if ' ' in line[2:].strip():
- for lpart in line[2:].strip().split(' '):
- tmp_tnrs.append(lpart.strip().split(':',2))
- else:
+ if ' ' in line[2:].strip():
+ for lpart in line[2:].strip().split(' '):
+ tmp_tnrs.append(lpart.strip().split(':',2))
+ else:
tmp_tnrs.append( line[2:].strip().split(':',2) )
- elif line.startswith('#,') and (line[2:].strip() == 'fuzzy'):
- fuzzy = True
+ elif line.startswith('#,') and (line[2:].strip() == 'fuzzy'):
+ fuzzy = True
line = self.lines.pop(0).strip()
while not line:
# allow empty lines between comments and msgid
line = self.lines.pop(0).strip()
- if line.startswith('#~ '):
- while line.startswith('#~ ') or not line.strip():
- if 0 == len(self.lines):
+ if line.startswith('#~ '):
+ while line.startswith('#~ ') or not line.strip():
+ if 0 == len(self.lines):
raise StopIteration()
- line = self.lines.pop(0)
- # This has been a deprecated entry, don't return anything
- return self.next()
+ line = self.lines.pop(0)
+ # This has been a deprecated entry, don't return anything
+ return self.next()
if not line.startswith('msgid'):
@@ -242,9 +242,9 @@ class TinyPoFile(object):
self.tnrs.append((t, n, r, source, trad))
self.first = False
-
- if name == None:
- return self.next()
+
+ if name == None:
+ return self.next()
return type, name, res_id, source, trad
def write_infos(self, modules):
@@ -279,7 +279,7 @@ class TinyPoFile(object):
def quote(s):
return '"%s"' % s.replace('"','\\"') \
.replace('\n', '\\n"\n"') \
- .replace(' \\ ',' \\\\ ')
+ .replace(' \\ ',' \\\\ ')
plurial = len(modules) > 1 and 's' or ''
@@ -490,9 +490,9 @@ def trans_generate(lang, modules, dbname=None):
}
# export fields
- if not result.has_key('fields'):
- logger.notifyChannel("db",netsvc.LOG_WARNING,"res has no fields: %r" % result)
- continue
+ if not result.has_key('fields'):
+ logger.notifyChannel("db",netsvc.LOG_WARNING,"res has no fields: %r" % result)
+ continue
for field_name, field_def in result['fields'].iteritems():
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)
elif model=='ir.model.fields':
- try:
+ try:
field_name = encode(obj.name)
- except AttributeError, exc:
- logger.notifyChannel("db", netsvc.LOG_ERROR, "name error in %s: %s" % (xml_name,str(exc)))
- continue
+ except AttributeError, exc:
+ logger.notifyChannel("db", netsvc.LOG_ERROR, "name error in %s: %s" % (xml_name,str(exc)))
+ continue
objmodel = pool.get(obj.model)
if not objmodel or not field_name in objmodel._columns:
continue
@@ -578,28 +578,28 @@ def trans_generate(lang, modules, dbname=None):
for field_name,field_def in pool.get(model)._columns.items():
if field_def.translate:
name = model + "," + field_name
- try:
+ try:
trad = getattr(obj, field_name) or ''
- except:
- trad = ''
+ except:
+ trad = ''
push_translation(module, 'model', name, xml_name, encode(trad))
# parse source code for _() calls
def get_module_from_path(path,mod_paths=None):
- if not mod_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)
- ad_paths= map(lambda m: os.path.abspath(m.strip()),tools.config['addons_path'].split(','))
- mod_paths=[def_path]
- for adp in ad_paths:
- mod_paths.append(adp)
- if not adp.startswith('/'):
- mod_paths.append(os.path.join(def_path,adp))
- elif adp.startswith(def_path):
- mod_paths.append(adp[len(def_path)+1:])
-
- for mp in mod_paths:
- if path.startswith(mp) and (os.path.dirname(path) != mp):
+ if not mod_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)
+ ad_paths= map(lambda m: os.path.abspath(m.strip()),tools.config['addons_path'].split(','))
+ mod_paths=[def_path]
+ for adp in ad_paths:
+ mod_paths.append(adp)
+ if not adp.startswith('/'):
+ mod_paths.append(os.path.join(def_path,adp))
+ elif adp.startswith(def_path):
+ mod_paths.append(adp[len(def_path)+1:])
+
+ for mp in mod_paths:
+ if path.startswith(mp) and (os.path.dirname(path) != mp):
path = path[len(mp)+1:]
return path.split(os.path.sep)[0]
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,
# otherwise use the whole list
- if not ids:
- ids = []
+ if not ids:
+ ids = []
ids = (dic['res_id'] in ids) and [dic['res_id']] or ids
for id in ids:
dic['res_id'] = id