summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Dony <odo@openerp.com>2010-12-15 12:40:19 +0100
committerOlivier Dony <odo@openerp.com>2010-12-15 12:40:19 +0100
commit650490d61dac7d20fd7ecb6ecfa551652469c5b2 (patch)
tree3315d91e39dc96f0258d10e285f1fb1c143e849a
parent516dc572c4e8daaa51ff9fd0cf59018683f83079 (diff)
[IMP] ir.translation,tools.translate._(): cleanup and speedup if translations via _()
- Removed expensive inspect.stack() (courtesy of xrg) - Improved heuristics for detection of context/lang and cursor - Switch to using ir.translation when possible instead of direct DB hit to benefit from cache - Cleanup lp bug: https://launchpad.net/bugs/624114 fixed bzr revid: odo@openerp.com-20101215114019-psrsu998inw6cksu
-rw-r--r--bin/addons/base/ir/ir_translation.py29
-rw-r--r--bin/tools/translate.py89
2 files changed, 77 insertions, 41 deletions
diff --git a/bin/addons/base/ir/ir_translation.py b/bin/addons/base/ir/ir_translation.py
index 8efeac8a0f8..417fe7c9848 100644
--- a/bin/addons/base/ir/ir_translation.py
+++ b/bin/addons/base/ir/ir_translation.py
@@ -138,7 +138,7 @@ class ir_translation(osv.osv):
and source. All values passed to this method should be unicode (not byte strings),
especially ``source``.
- :param name: identification of the term to translate, such as field name
+ :param name: identification of the term to translate, such as field name (optional if source is passed)
:param types: single string defining type of term to translate (see ``type`` field on ir.translation), or sequence of allowed types (strings)
:param lang: language code of the desired translation
:param source: optional source term to translate (should be unicode)
@@ -153,19 +153,22 @@ class ir_translation(osv.osv):
if isinstance(types, basestring):
types = (types,)
if source:
- cr.execute('select value ' \
- 'from ir_translation ' \
- 'where lang=%s ' \
- 'and type in %s ' \
- 'and name=%s ' \
- 'and src=%s',
- (lang or '', types, tools.ustr(name), source))
+ query = """SELECT value
+ FROM ir_translation
+ WHERE lang=%s
+ AND type in %s
+ AND src=%s"""
+ params = (lang or '', types, source)
+ if name:
+ query += " AND name=%s"
+ params += (tools.ustr(name),)
+ cr.execute(query, params)
else:
- cr.execute('select value ' \
- 'from ir_translation ' \
- 'where lang=%s ' \
- 'and type in %s ' \
- 'and name=%s',
+ cr.execute("""SELECT value
+ FROM ir_translation
+ WHERE lang=%s
+ AND type in %s
+ AND name=%s"""
(lang or '', types, tools.ustr(name)))
res = cr.fetchone()
trad = res and res[0] or u''
diff --git a/bin/tools/translate.py b/bin/tools/translate.py
index fff7f707555..629d51ac1b0 100644
--- a/bin/tools/translate.py
+++ b/bin/tools/translate.py
@@ -26,10 +26,12 @@ import inspect
import itertools
import locale
import os
+import pooler
import re
import logging
import tarfile
import tempfile
+import threading
from os.path import join
import logging
@@ -153,48 +155,79 @@ logger = logging.getLogger('translate')
class GettextAlias(object):
+ def _get_db_pool(self):
+ # find current DB based on thread/worker db name (see netsvc)
+ db_name = getattr(threading.currentThread(), 'dbname', None)
+ if db_name:
+ dbname = getattr(threading.currentThread(), 'dbname')
+ return pooler.get_db_and_pool(dbname)
+ return (None, None)
+
def _get_cr(self, frame):
- is_new_cr = False
- cr = frame.f_locals.get('cr')
+ new_cr = False
+ cr = frame.f_locals.get('cr', frame.f_locals.get('cursor'))
if not cr:
s = frame.f_locals.get('self', {})
- cr = getattr(s, 'cr', False)
- if not cr:
- if frame.f_globals.get('pooler', False):
- # TODO: we should probably get rid of the 'is_new_cr' case: no cr in locals -> no translation for you
- dbs = frame.f_globals['pooler'].pool_dic.keys()
- if len(dbs) == 1:
- cr = pooler.get_db(dbs[0]).cursor()
- is_new_cr = True
- return cr, is_new_cr
+ cr = getattr(s, 'cr', None)
+ if not cr:
+ db, _ = self._get_db_pool()
+ if db:
+ cr = db.cursor()
+ new_cr = True
+ return cr, new_cr
def _get_lang(self, frame):
- lang = frame.f_locals.get('context', {}).get('lang', False)
+ lang = None
+ ctx = frame.f_locals.get('context')
+ if not ctx:
+ kwargs = frame.f_locals.get('kwargs')
+ if kwargs is None:
+ args = frame.f_locals.get('args')
+ if args and isinstance(args, (list, tuple)) \
+ and isinstance(args[-1], dict):
+ ctx = args[-1]
+ elif isinstance(kwargs, dict):
+ ctx = kwargs.get('context')
+ if ctx:
+ lang = ctx.get('lang')
if not lang:
- args = frame.f_locals.get('args', False)
- if args:
- lang = args[-1].get('lang', False)
- if not lang:
- s = frame.f_locals.get('self', {})
- c = getattr(s, 'localcontext', {})
- lang = c.get('lang', False)
+ s = frame.f_locals.get('self', {})
+ c = getattr(s, 'localcontext', None)
+ if c:
+ lang = c.get('lang')
return lang
def __call__(self, source):
- is_new_cr = False
res = source
+ cr = None
+ new_cr = False
try:
- frame = inspect.stack()[1][0]
- cr, is_new_cr = self._get_cr(frame)
+ frame = inspect.currentframe()
+ if frame is None:
+ return source
+ frame = frame.f_back
+ if not frame:
+ return source
lang = self._get_lang(frame)
- if lang and cr:
- cr.execute('SELECT value FROM ir_translation WHERE lang=%s AND type IN (%s, %s) AND src=%s', (lang, 'code','sql_constraint', source))
- res_trans = cr.fetchone()
- res = res_trans and res_trans[0] or source
+ if lang:
+ cr, new_cr = self._get_cr(frame)
+ if cr:
+ # Try to use ir.translation to benefit from global cache if possible
+ _, pool = self._get_db_pool()
+ if pool:
+ res = pool.get('ir.translation')._get_source(cr, 1, None, ('code','sql_constraint'), lang, source)
+ else:
+ cr.execute('SELECT value FROM ir_translation WHERE lang=%s AND type IN (%s, %s) AND src=%s', (lang, 'code','sql_constraint', source))
+ res_trans = cr.fetchone()
+ res = res_trans and res_trans[0] or source
+ else:
+ logger.debug('no context cursor detected, skipping translation for "%r"', source)
+ else:
+ logger.debug('no translation language detected, skipping translation for "%r" ', source)
except Exception:
- logger.debug('translation went wrong for string %s', repr(source))
+ logger.debug('translation went wrong for "%r", skipped', source)
finally:
- if is_new_cr:
+ if cr and new_cr:
cr.close()
return res