[MERGE] with trunk

bzr revid: tfr@openerp.com-20101119133226-g04bvgnyr0jp7psz
This commit is contained in:
Thibault Francois
2010-11-19 14:32:26 +01:00
31 changed files with 7797 additions and 4335 deletions
+2 -2
View File
@@ -30,7 +30,7 @@ import tools
import tools.osutil
from tools.safe_eval import safe_eval as eval
import pooler
from tools.translate import _
import netsvc
@@ -806,7 +806,7 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
graph = create_graph(cr, ['base'], force)
if not graph:
logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'module base cannot be loaded! (hint: verify addons-path)')
raise osv.osv.except_osv('Could not load base module', 'module base cannot be loaded! (hint: verify addons-path)')
raise osv.osv.except_osv(_('Could not load base module'), _('module base cannot be loaded! (hint: verify addons-path)'))
has_updates = load_module_graph(cr, graph, status, perform_checks=(not update_module), report=report)
if update_module:
+14
View File
@@ -1378,5 +1378,19 @@
<field name="name">Reserve</field>
<field name="code">RSV</field>
</record>
<record id="CRC" model="res.currency">
<field name="name">CRC</field>
<field name="code">CRC</field>
<field name="rounding">0.01</field>
<field name="accuracy">4</field>
<field name="symbol">¢</field>
</record>
<record id="rateCRC" model="res.currency.rate">
<field name="rate">691.3153</field>
<field name="currency_id" ref="CRC"/>
<field eval="time.strftime('%Y-01-01')" name="name"/>
</record>
</data>
</openerp>
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -6,13 +6,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2010-10-18 17:46+0000\n"
"PO-Revision-Date: 2010-11-11 19:17+0000\n"
"PO-Revision-Date: 2010-11-12 06:39+0000\n"
"Last-Translator: Dimitris Andavoglou <dimitrisand@gmail.com>\n"
"Language-Team: nls@hellug.gr <nls@hellug.gr>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-11-12 04:45+0000\n"
"X-Launchpad-Export-Date: 2010-11-13 04:55+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+36 -33
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2010-10-18 17:46+0000\n"
"PO-Revision-Date: 2010-10-20 07:13+0000\n"
"Last-Translator: Quentin THEURET <quentin@theuret.net>\n"
"PO-Revision-Date: 2010-11-17 07:14+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-10-21 05:01+0000\n"
"X-Launchpad-Export-Date: 2010-11-18 04:45+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
@@ -38,12 +38,12 @@ msgstr "Autre configuration"
#. module: base
#: view:res.lang:0
msgid "%j - Day of the year as a decimal number [001,366]."
msgstr "%j - Jour de l'année comme un nombre décimal [001,366]."
msgstr "%j - Numéro du Jour dans l'année [001,366]."
#. module: base
#: selection:ir.property,type:0
msgid "DateTime"
msgstr ""
msgstr "Horodatage"
#. module: base
#: view:ir.values:0
@@ -106,7 +106,7 @@ msgstr "Vues créées"
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "terp-emblem-important"
msgstr ""
msgstr "terp-emblem-important"
#. module: base
#: field:res.partner,ref:0
@@ -148,7 +148,7 @@ msgstr "STOCK_CANCEL"
#. module: base
#: model:res.partner.category,name:base.res_partner_category_woodsuppliers0
msgid "Wood Suppliers"
msgstr ""
msgstr "Fournisseurs de bois"
#. module: base
#: field:ir.sequence,number_increment:0
@@ -198,7 +198,7 @@ msgstr "Nombre de modules"
#. module: base
#: help:multi_company.default,company_dest_id:0
msgid "Company to store the current record"
msgstr "Société physique ou sera stocké cet enregistrement"
msgstr "Société pour laquelle est fait cet enregistrement"
#. module: base
#: field:res.partner.bank.type.field,size:0
@@ -238,7 +238,7 @@ msgstr "Nom de l'assistant"
#. module: base
#: view:res.lang:0
msgid "%y - Year without century as a decimal number [00,99]."
msgstr "%y - Année dans le siècle comme un nombre décimal [00,99]."
msgstr "%y - Année dans le siècle [00,99]."
#. module: base
#: selection:maintenance.contract.wizard,state:0
@@ -360,7 +360,7 @@ msgstr "Serbe / Serbie"
#. module: base
#: help:res.lang,iso_code:0
msgid "This ISO code is the name of po files to use for translations"
msgstr "Ce code ISO est le nom des fichiers po utiliser pour les traductions"
msgstr "Ce code ISO est le nom des fichiers po utilisés pour les traductions"
#. module: base
#: selection:ir.ui.menu,icon:0
@@ -399,7 +399,7 @@ msgid ""
"The ISO country code in two chars.\n"
"You can use this field for quick search."
msgstr ""
"Le code ISO du pays en deux caractères.\n"
"Le code ISO du pays, sur deux caractères.\n"
"Vous pouvez utiliser ce champ pour effectuer une recherche rapide."
#. module: base
@@ -445,7 +445,7 @@ msgstr "Assistants"
#. module: base
#: model:res.partner.category,name:base.res_partner_category_miscellaneoussuppliers0
msgid "Miscellaneous Suppliers"
msgstr ""
msgstr "Fournisseurs divers"
#. module: base
#: code:addons/base/ir/ir_model.py:0
@@ -462,7 +462,7 @@ msgstr ""
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "terp-gtk-jump-to-ltr"
msgstr ""
msgstr "terp-gtk-jump-to-ltr"
#. module: base
#: view:base.language.export:0
@@ -513,7 +513,7 @@ msgstr "Bulgare / български"
#. module: base
#: model:ir.ui.menu,name:base.menu_base_action_rule
msgid "Automated Actions"
msgstr ""
msgstr "Actions automatisées"
#. module: base
#: model:ir.model,name:base.model_ir_actions_actions
@@ -579,17 +579,17 @@ msgstr "Séquences"
#. module: base
#: model:ir.model,name:base.model_base_language_import
msgid "Language Import"
msgstr ""
msgstr "Importation de langue"
#. module: base
#: model:ir.model,name:base.model_res_config_users
msgid "res.config.users"
msgstr ""
msgstr "res.config.users"
#. module: base
#: model:ir.model,name:base.model_base_language_export
msgid "base.language.export"
msgstr ""
msgstr "base.language.export"
#. module: base
#: selection:ir.ui.menu,icon:0
@@ -609,7 +609,7 @@ msgstr ""
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "terp-folder-yellow"
msgstr ""
msgstr "terp-folder-yellow"
#. module: base
#: model:res.partner.category,name:base.res_partner_category_4
@@ -629,7 +629,7 @@ msgstr "Mes partenaires"
#. module: base
#: view:ir.actions.report.xml:0
msgid "XML Report"
msgstr ""
msgstr "Rapport XML"
#. module: base
#: model:res.country,name:base.es
@@ -651,7 +651,7 @@ msgstr ""
#: model:ir.actions.act_window,name:base.action_view_base_module_upgrade
#: model:ir.model,name:base.model_base_module_upgrade
msgid "Module Upgrade"
msgstr ""
msgstr "Mise à jour de module"
#. module: base
#: view:res.config.users:0
@@ -685,6 +685,9 @@ msgid ""
"\n"
"This addon is already installed on your system"
msgstr ""
"\n"
"\n"
"Ce module est déjà installé sur votre système"
#. module: base
#: model:res.country,name:base.nu
@@ -729,7 +732,7 @@ msgstr "Modules du contrat de maintenance"
#: model:ir.actions.act_window,name:base.res_request_link-act
#: model:ir.ui.menu,name:base.menu_res_request_link_act
msgid "Request Reference Types"
msgstr ""
msgstr "Types de référence des requêtes"
#. module: base
#: view:ir.values:0
@@ -791,7 +794,7 @@ msgstr "STOCK_EDIT"
#. module: base
#: model:ir.ui.menu,name:base.menu_hr_project
msgid "Human Resources Dashboard"
msgstr ""
msgstr "Tableau de bord ressources humaines"
#. module: base
#: selection:ir.ui.menu,icon:0
@@ -822,7 +825,7 @@ msgstr "Îles Caïmans"
#. module: base
#: field:ir.module.module,contributors:0
msgid "Contributors"
msgstr ""
msgstr "Contributeurs"
#. module: base
#: selection:ir.property,type:0
@@ -852,7 +855,7 @@ msgstr "Niger"
#. module: base
#: selection:base.language.install,lang:0
msgid "Chinese (HK)"
msgstr ""
msgstr "Chinois (Hong Kong)"
#. module: base
#: model:res.country,name:base.ba
@@ -934,17 +937,17 @@ msgstr "Pour exporter une langue, ne sélectionnez aucune langue."
#. module: base
#: view:res.request:0
msgid "Request Date"
msgstr ""
msgstr "Date de la requête"
#. module: base
#: model:ir.ui.menu,name:base.menu_hr_dasboard
msgid "Dashboard"
msgstr ""
msgstr "Tableau de bord"
#. module: base
#: model:ir.ui.menu,name:base.menu_purchase_root
msgid "Purchases"
msgstr ""
msgstr "Achats"
#. module: base
#: model:res.country,name:base.md
@@ -1330,7 +1333,7 @@ msgstr "Malawi"
#: code:addons/base/res/res_user.py:0
#, python-format
msgid "%s (copy)"
msgstr ""
msgstr "%s (copie)"
#. module: base
#: field:res.partner.address,type:0
@@ -1419,7 +1422,7 @@ msgstr ""
#. module: base
#: view:base.language.export:0
msgid "https://help.launchpad.net/Translations"
msgstr ""
msgstr "https://help.launchpad.net/Translations"
#. module: base
#: field:ir.actions.act_window,view_mode:0
@@ -1522,7 +1525,7 @@ msgstr ""
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "terp-stock_align_left_24"
msgstr ""
msgstr "terp-stock_align_left_24"
#. module: base
#: field:ir.actions.act_window,groups_id:0
@@ -1679,7 +1682,7 @@ msgstr "Vue originale"
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "terp-camera_test"
msgstr ""
msgstr "terp-camera_test"
#. module: base
#: code:addons/base/res/res_user.py:0
@@ -1840,12 +1843,12 @@ msgstr "Slovénie"
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "terp-stock_format-default"
msgstr ""
msgstr "terp-stock_format-default"
#. module: base
#: view:res.lang:0
msgid "%p - Equivalent of either AM or PM."
msgstr "%p - Soit AM soit à PM."
msgstr "%p - AM ou PM"
#. module: base
#: view:ir.actions.server:0
+3 -3
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2010-10-18 17:46+0000\n"
"PO-Revision-Date: 2010-11-01 08:31+0000\n"
"PO-Revision-Date: 2010-11-14 07:36+0000\n"
"Last-Translator: Chertykov Denis <chertykov@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-11-02 04:49+0000\n"
"X-Launchpad-Export-Date: 2010-11-15 04:59+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
@@ -96,7 +96,7 @@ msgstr "Рабочий процесс включен"
#. module: base
#: field:ir.actions.act_window,display_menu_tip:0
msgid "Display Menu Tips"
msgstr ""
msgstr "Выводить советы"
#. module: base
#: view:ir.module.module:0
+3891 -2013
View File
File diff suppressed because it is too large Load Diff
+2982 -1785
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -705,6 +705,7 @@
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.company</field>
<field name="view_type">form</field>
<field name="help">Create and manage the companies that will be managed by OpenERP from here. Shops or subsidiaries can be created and maintained from here.</field>
</record>
<menuitem action="action_res_company_form" id="menu_action_res_company_form" parent="base.menu_res_company_global"/>
@@ -716,6 +717,7 @@
<field name="view_type">form</field>
<field name="view_id" ref="view_users_tree"/>
<field name="search_view_id" ref="view_users_search"/>
<field name="help">Create and manage users that will connect to the system. Users can be deactivated should there be a period of time during which they will/should not connect to the system. You can assign them groups in order to give them specific access to the applications they need to use in the system.</field>
</record>
<record id="action_res_users_view1" model="ir.actions.act_window.view">
<field eval="10" name="sequence"/>
@@ -757,6 +759,7 @@
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.groups</field>
<field name="view_type">form</field>
<field name="help">A group is a set of functional areas that will be assigned to the user in order to give them access and rights to specific applications and tasks in the system. You can create custom groups or edit the ones existing by default in order to customize the view of the menu that users will be able to see. Whether they can have a read, write, create and delete access right can be managed from here.</field>
</record>
<menuitem action="action_res_groups" id="menu_action_res_groups" parent="base.menu_users"
groups="base.group_extended"/>
@@ -844,6 +847,7 @@
<field name="type">ir.actions.act_window</field>
<field name="res_model">ir.ui.view</field>
<field name="view_id" ref="view_view_tree"/>
<field name="help">Views allows you to personalize each view of OpenERP. You can add new fields, move fields, rename them or delete the ones that you do not need.</field>
</record>
<menuitem action="action_ui_view" id="menu_action_ui_view" parent="base.next_id_2"/>
@@ -1403,6 +1407,7 @@
<field name="view_type">form</field>
<field name="view_id" ref="edit_menu"/>
<field name="search_view_id" ref="edit_menu_access_search"/>
<field name="help">Manage and customize the items available and displayed in your OpenERP system menu. You can delete an item by clicking on the box at the beginning of each line and then delete it through the button that appeared. Items can be assigned to specific groups in order to make them accessible to some users within the system.</field>
</record>
<menuitem action="grant_menu_access" id="menu_grant_menu_access" parent="base.next_id_2" sequence="1"/>
+2 -3
View File
@@ -485,7 +485,7 @@ class actions_server(osv.osv):
for field in fields:
try:
obj = getattr(obj, field)
except Exception,e :
except Exception:
logger.notifyChannel('Workflow', netsvc.LOG_ERROR, 'Failed to parse : %s' % (field))
return obj
@@ -506,7 +506,7 @@ class actions_server(osv.osv):
for field in fields:
try:
obj = getattr(obj, field)
except Exception,e :
except Exception:
logger.notifyChannel('Workflow', netsvc.LOG_ERROR, 'Failed to parse : %s' % (field))
return obj
@@ -514,7 +514,6 @@ class actions_server(osv.osv):
def merge_message(self, cr, uid, keystr, action, context=None):
if context is None:
context = {}
logger = netsvc.Logger()
def merge(match):
obj_pool = self.pool.get(action.model_id.model)
id = context.get('active_id')
+1 -1
View File
@@ -57,7 +57,7 @@ class ir_model(osv.osv):
return []
field, operator, value = domain[0]
if operator not in ['=', '!=']:
raise osv.except_osv('Invalid search criterions','The osv_memory field can only be compared with = and != operator.')
raise osv.except_osv(_('Invalid search criterions'), _('The osv_memory field can only be compared with = and != operator.'))
value = bool(value) if operator == '=' else not bool(value)
all_model_ids = self.search(cr, uid, [], context=context)
is_osv_mem = self._is_osv_memory(cr, uid, all_model_ids, 'osv_memory', arg=None, context=context)
+2 -2
View File
@@ -53,8 +53,8 @@ class module_category(osv.osv):
result = dict(cr.fetchall())
for id in ids:
cr.execute('select id from ir_module_category where parent_id=%s', (id,))
childs = [c for c, in cr.fetchall()]
result[id] = reduce(lambda x,y:x+y, [result.get(c, 0) for c in childs], result.get(id, 0))
result[id] = sum([result.get(c, 0) for (c,) in cr.fetchall()],
result.get(id, 0))
return result
_columns = {
+2 -2
View File
@@ -68,7 +68,6 @@
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('category_id','=',active_id)]</field>
</record>
<record id="ir_action_module_category" model="ir.values">
<field eval="'tree_but_open'" name="key2"/>
@@ -169,7 +168,8 @@
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain"/>
<field name="search_view_id" ref="view_module_filter"/>
<field name="search_view_id" ref="view_module_filter"/>
<field name="help">List all certified modules available to configure your OpenERP. Modules that are installed are flagged as such. You can search for a specific module using the name or the description of the module. You do not need to install modules one by one, you can install many at the same time by clicking on the schedule button in this list. Then, apply the schedule upgrade from Action menu once for all the ones you have scheduled for installation.</field>
</record>
<menuitem action="open_module_tree" id="menu_module_tree" parent="base.menu_management"/>
@@ -22,6 +22,8 @@
<separator orientation="vertical" rowspan="15"/>
<group colspan="4" col="4">
<separator string="Import Translation" colspan="4"/>
<label colspan="4" nolabel="1" string="If you need another language than the official ones available, you can import a language pack from here. Other OpenERP languages than the official ones can be found on launchpad."/>
<newline/>
<field name="name" width="200"/>
<field name="code"/>
<field name="data" colspan="4"/>
@@ -93,7 +93,7 @@ class base_module_upgrade(osv.osv_memory):
if dep_mod.state in ('unknown','uninstalled'):
unmet_packages.append(dep_mod.name)
if len(unmet_packages):
raise osv.except_osv('Unmet dependency !', 'Following modules are uninstalled or unknown. \n\n'+'\n'.join(unmet_packages))
raise osv.except_osv(_('Unmet dependency !'), _('Following modules are not installed or unknown: %s') % ('\n\n' + '\n'.join(unmet_packages)))
mod_obj.download(cr, uid, ids, context=context)
cr.commit()
_, pool = pooler.restart_pool(cr.dbname, update_module=True)
-1
View File
@@ -23,7 +23,6 @@ import math
from osv import fields,osv
import tools
import ir
import pooler
from tools.translate import _
+2 -1
View File
@@ -33,6 +33,7 @@ import time
class groups(osv.osv):
_name = "res.groups"
_order = 'name'
_description = "Access Groups"
_columns = {
'name': fields.char('Group Name', size=64, required=True),
'model_access': fields.one2many('ir.model.access', 'group_id', 'Access Controls'),
@@ -264,7 +265,7 @@ class users(osv.osv):
]
_sql_constraints = [
('login_key', 'UNIQUE (login)', _('You can not have two users with the same login !'))
('login_key', 'UNIQUE (login)', 'You can not have two users with the same login !')
]
def _get_email_from(self, cr, uid, ids, context=None):
+1 -1
View File
@@ -31,7 +31,7 @@ def ir_del(cr, uid, id):
obj = pooler.get_pool(cr.dbname).get('ir.values')
return obj.unlink(cr, uid, [id])
def ir_get(cr, uid, key, key2, models, meta=False, context={}, res_id_req=False):
def ir_get(cr, uid, key, key2, models, meta=False, context=None, res_id_req=False):
obj = pooler.get_pool(cr.dbname).get('ir.values')
res = obj.get(cr, uid, key, key2, models, meta=meta, context=context, res_id_req=res_id_req)
return res
+11 -9
View File
@@ -63,8 +63,10 @@ class _column(object):
_symbol_set = (_symbol_c, _symbol_f)
_symbol_get = None
def __init__(self, string='unknown', required=False, readonly=False, domain=None, context={}, states=None, priority=0, change_default=False, size=None, ondelete="set null", translate=False, select=False, **args):
if not context:
def __init__(self, string='unknown', required=False, readonly=False, domain=None, context=None, states=None, priority=0, change_default=False, size=None, ondelete="set null", translate=False, select=False, **args):
if domain is None:
domain = []
if context is None:
context = {}
self.states = states or {}
self.string = string
@@ -76,7 +78,7 @@ class _column(object):
self.change_default = change_default
self.ondelete = ondelete
self.translate = translate
self._domain = domain or []
self._domain = domain
self._context = context
self.write = False
self.read = False
@@ -403,7 +405,7 @@ class one2many(_column):
assert(self.change_default != True)
def get_memory(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
if not context:
if context is None:
context = {}
if self._context:
context = context.copy()
@@ -786,7 +788,7 @@ class function(_column):
class related(function):
def _fnct_search(self, tobj, cr, uid, obj=None, name=None, domain=None, context={}):
def _fnct_search(self, tobj, cr, uid, obj=None, name=None, domain=None, context=None):
self._field_get2(cr, uid, obj, context)
i = len(self._arg)-1
sarg = name
@@ -803,7 +805,7 @@ class related(function):
return [(self._arg[0], 'in', sarg)]
def _fnct_write(self,obj,cr, uid, ids, field_name, values, args, context=None):
self._field_get2(cr, uid, obj, context)
self._field_get2(cr, uid, obj, context=context)
if type(ids) != type([]):
ids=[ids]
objlst = obj.browse(cr, uid, ids)
@@ -884,7 +886,7 @@ class related(function):
# TODO: improve here to change self.store = {...} according to related objects
pass
def _field_get2(self, cr, uid, obj, context={}):
def _field_get2(self, cr, uid, obj, context=None):
if self._relations:
return
obj_name = obj._name
@@ -904,10 +906,10 @@ class related(function):
# ---------------------------------------------------------
class dummy(function):
def _fnct_search(self, tobj, cr, uid, obj=None, name=None, domain=None, context={}):
def _fnct_search(self, tobj, cr, uid, obj=None, name=None, domain=None, context=None):
return []
def _fnct_write(self,obj,cr, uid, ids, field_name, values, args, context=None):
def _fnct_write(self, obj, cr, uid, ids, field_name, values, args, context=None):
return False
def _fnct_read(self, obj, cr, uid, ids, field_name, args, context=None):
+27 -23
View File
@@ -126,12 +126,14 @@ class browse_record_list(list):
class browse_record(object):
logger = netsvc.Logger()
def __init__(self, cr, uid, id, table, cache, context=None, list_class = None, fields_process={}):
def __init__(self, cr, uid, id, table, cache, context=None, list_class=None, fields_process=None):
'''
table : the object (inherited from orm)
context : dictionary with an optional context
'''
if not context:
if fields_process is None:
fields_process = {}
if context is None:
context = {}
self._list_class = list_class or browse_record_list
self._cr = cr
@@ -404,7 +406,9 @@ class orm_template(object):
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None):
raise NotImplementedError(_('The read_group method is not implemented on this object !'))
def _field_create(self, cr, context={}):
def _field_create(self, cr, context=None):
if context is None:
context = {}
cr.execute("SELECT id FROM ir_model WHERE model=%s", (self._name,))
if not cr.rowcount:
cr.execute('SELECT nextval(%s)', ('ir_model_id_seq',))
@@ -489,8 +493,8 @@ class orm_template(object):
break
cr.commit()
def _auto_init(self, cr, context={}):
self._field_create(cr, context)
def _auto_init(self, cr, context=None):
self._field_create(cr, context=context)
def __init__(self, cr):
if not self._name and not hasattr(self, '_inherit'):
@@ -506,7 +510,7 @@ class orm_template(object):
if not self._table:
self._table = self._name.replace('.', '_')
def browse(self, cr, uid, select, context=None, list_class=None, fields_process={}):
def browse(self, cr, uid, select, context=None, list_class=None, fields_process=None):
"""
Fetch records as objects allowing to use dot notation to browse fields and relations
@@ -517,8 +521,6 @@ class orm_template(object):
:rtype: object or list of objects requested
"""
if not context:
context = {}
self._list_class = list_class or browse_record_list
cache = {}
# need to accepts ints and longs because ids coming from a method
@@ -526,7 +528,7 @@ class orm_template(object):
if isinstance(select, (int, long)):
return browse_record(cr, uid, select, self, cache, context=context, list_class=self._list_class, fields_process=fields_process)
elif isinstance(select, list):
return self._list_class([browse_record(cr, uid, id, self, cache, context=context, list_class=self._list_class, fields_process=fields_process) for id in select], context)
return self._list_class([browse_record(cr, uid, id, self, cache, context=context, list_class=self._list_class, fields_process=fields_process) for id in select], context=context)
else:
return browse_null()
@@ -554,8 +556,8 @@ class orm_template(object):
lines = []
data = map(lambda x: '', range(len(fields)))
done = []
for fpos in range(len(fields)):
done = []
f = fields[fpos]
if f:
r = row
@@ -600,7 +602,8 @@ class orm_template(object):
fields2 = map(lambda x: (x[:i+1]==f[:i+1] and x[i+1:]) \
or [], fields)
if fields2 in done:
break
if [x for x in fields2 if x]:
break
done.append(fields2)
for row2 in r:
lines2 = self.__export_row(cr, uid, row2, fields2,
@@ -1274,7 +1277,7 @@ class orm_template(object):
context = {}
result = False
fields = {}
childs = True
children = True
def encode(s):
if isinstance(s, unicode):
@@ -1328,7 +1331,7 @@ class orm_template(object):
if column:
relation = self.pool.get(column._obj)
childs = False
children = False
views = {}
for f in node:
if f.tag in ('form', 'tree', 'graph'):
@@ -1390,7 +1393,7 @@ class orm_template(object):
node.set('sum', trans)
for f in node:
if childs or (node.tag == 'field' and f.tag in ('filter','separator')):
if children or (node.tag == 'field' and f.tag in ('filter','separator')):
fields.update(self.__view_look_dom(cr, user, f, view_id, context))
return fields
@@ -1437,7 +1440,7 @@ class orm_template(object):
fields = self.fields_get(cr, user, fields_def.keys(), context)
for field in fields_def:
if field == 'id':
# sometime, the view may containt the (invisible) field 'id' needed for a domain (when 2 objects have cross references)
# sometime, the view may contain the (invisible) field 'id' needed for a domain (when 2 objects have cross references)
fields['id'] = {'readonly': True, 'type': 'integer', 'string': 'ID'}
elif field in fields:
fields[field].update(fields_def[field])
@@ -1498,14 +1501,14 @@ class orm_template(object):
return arch
def __get_default_search_view(self, cr, uid, context={}):
def __get_default_search_view(self, cr, uid, context=None):
def encode(s):
if isinstance(s, unicode):
return s.encode('utf8')
return s
view = self.fields_view_get(cr, uid, False, 'form', context)
view = self.fields_view_get(cr, uid, False, 'form', context=context)
root = etree.fromstring(encode(view['arch']))
res = etree.XML("""<search string="%s"></search>""" % root.get("string", ""))
@@ -2357,8 +2360,7 @@ class orm(orm_template):
where += ' order by '+self._parent_order
cr.execute('SELECT id FROM '+self._table+' WHERE '+where)
pos2 = pos + 1
childs = cr.fetchall()
for id in childs:
for id in cr.fetchall():
pos2 = browse_rec(id[0], pos2)
cr.execute('update '+self._table+' set parent_left=%s, parent_right=%s where id=%s', (pos, pos2, root))
return pos2 + 1
@@ -2413,7 +2415,9 @@ class orm(orm_template):
self.__schema.debug("Table '%s': column '%s': dropped NOT NULL constraint",
self._table, column['attname'])
def _auto_init(self, cr, context={}):
def _auto_init(self, cr, context=None):
if context is None:
context = {}
store_compute = False
create = False
todo_end = []
@@ -4156,9 +4160,9 @@ class orm(orm_template):
old_record, new_record = self.read(cr, uid, [old_id, new_id], [field_name], context=context)
# here we rely on the order of the ids to match the translations
# as foreseen in copy_data()
old_childs = sorted(old_record[field_name])
new_childs = sorted(new_record[field_name])
for (old_child, new_child) in zip(old_childs, new_childs):
old_children = sorted(old_record[field_name])
new_children = sorted(new_record[field_name])
for (old_child, new_child) in zip(old_children, new_children):
# recursive copy of translations here
target_obj.copy_translations(cr, uid, old_child, new_child, context=context)
# and for translatable fields we keep them for copy
+1 -1
View File
@@ -254,7 +254,7 @@ class document(object):
for el_cld in node:
self.parse_node(el_cld, el, v)
else:
# if there is no "type" attribute in the node, copy it to the xml data and parse its childs
# if there is no "type" attribute in the node, copy it to the xml data and parse its children
if not node.tag == etree.Comment:
if node.tag == parent.tag:
el = parent
-1
View File
@@ -139,7 +139,6 @@ class report_printscreen_list(report_int):
_append_node('header-date', str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M")))
l = []
t = 0
rowcount = 0;
strmax = (pageSize[0]-40) * 2.8346
temp = []
tsum = []
+3 -3
View File
@@ -552,8 +552,8 @@ class _rml_flowable(object):
return rc1
def _table(self, node):
childs = utils._child_get(node,self,'tr')
if not childs:
children = utils._child_get(node,self,'tr')
if not children:
return None
length = 0
colwidths = None
@@ -561,7 +561,7 @@ class _rml_flowable(object):
data = []
styles = []
posy = 0
for tr in childs:
for tr in children:
paraStyle = None
if tr.get('style'):
st = copy.deepcopy(self.styles.table_styles[tr.get('style')])
+1 -5
View File
@@ -204,13 +204,10 @@ class rml_parse(object):
return res['datas']
else :
return ''
except Exception,e:
except Exception:
return ''
def setLang(self, lang):
if not lang or self.default_lang.has_key(lang):
if not lang:
key = 'en_US'
self.localcontext['lang'] = lang
self.lang_dict_called = False
for obj in self.objects:
@@ -519,7 +516,6 @@ class report_sxw(report_rml, preprocess.report):
xml_declaration=True)
rml_dom = etree.XML(rml)
body = rml_dom[-1]
elements = []
key1 = rml_parser.localcontext['name_space']["text"]+"p"
key2 = rml_parser.localcontext['name_space']["text"]+"drop-down"
+1
View File
@@ -20,3 +20,4 @@
##############################################################################
from test_osv import *
from test_translate import *
+48
View File
@@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2010 OpenERP S.A. http://www.openerp.com
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import unittest
from tools.translate import quote, unquote
class TranslationToolsTestCase(unittest.TestCase):
def test_quote_unquote(self):
def test_string(str):
quoted = quote(str)
#print "\n1:", repr(str)
#print "2:", repr(quoted)
unquoted = unquote("".join(quoted.split('"\n"')))
#print "3:", repr(unquoted)
self.assertEquals(str, unquoted)
test_string("""test \nall kinds\n \n o\r
\\\\ nope\n\n"
""")
# The ones with 1+ backslashes directly followed by
# a newline or literal N can fail... we would need a
# state-machine parser to handle these, but this would
# be much slower so it's better to avoid them at the moment
self.assertRaises(AssertionError, quote, """test \nall kinds\n\no\r
\\\\nope\n\n"
""")
+79 -69
View File
@@ -68,6 +68,18 @@ def _obj(pool, cr, uid, model_str, context=None):
model = pool.get(model_str)
return lambda x: model.browse(cr, uid, x, context=context)
def _get_idref(self, cr, uid, model_str, context, idref):
idref2 = dict(idref,
time=time,
DateTime=datetime,
timedelta=timedelta,
version=release.major_version,
ref=_ref(self, cr),
pytz=pytz)
if len(model_str):
idref2['obj'] = _obj(self.pool, cr, uid, model_str, context=context)
return idref2
def _fix_multiple_roots(node):
"""
Surround the children of the ``node`` element of an XML field with a
@@ -90,72 +102,68 @@ def _eval_xml(self, node, pool, cr, uid, idref, context=None):
if context is None:
context = {}
if node.tag in ('field','value'):
t = node.get('type','char')
f_model = node.get('model', '').encode('utf-8')
if node.get('search'):
f_search = node.get("search",'').encode('utf-8')
f_use = node.get("use",'id').encode('utf-8')
f_name = node.get("name",'').encode('utf-8')
q = unsafe_eval(f_search, idref)
ids = pool.get(f_model).search(cr, uid, q)
if f_use != 'id':
ids = map(lambda x: x[f_use], pool.get(f_model).read(cr, uid, ids, [f_use]))
_cols = pool.get(f_model)._columns
if (f_name in _cols) and _cols[f_name]._type=='many2many':
return ids
f_val = False
if len(ids):
f_val = ids[0]
if isinstance(f_val, tuple):
f_val = f_val[0]
return f_val
a_eval = node.get('eval','')
if a_eval:
idref2 = dict(idref,
time=time,
DateTime=datetime,
timedelta=timedelta,
version=release.major_version,
ref=lambda x: self.id_get(cr, False, x),
pytz=pytz)
if len(f_model):
idref2['obj'] = _obj(self.pool, cr, uid, f_model, context=context)
try:
return unsafe_eval(a_eval, idref2)
except Exception:
logger = logging.getLogger('init')
logger.warning('could not eval(%s) for %s in %s' % (a_eval, node.get('name'), context), exc_info=True)
return ""
if t == 'xml':
def _process(s, idref):
m = re.findall('[^%]%\((.*?)\)[ds]', s)
for id in m:
if not id in idref:
idref[id]=self.id_get(cr, False, id)
return s % idref
_fix_multiple_roots(node)
return '<?xml version="1.0"?>\n'\
+_process("".join([etree.tostring(n, encoding='utf-8')
for n in node]),
idref)
if t in ('char', 'int', 'float'):
d = node.text
if t == 'int':
d = d.strip()
if d == 'None':
return None
else:
return int(d.strip())
elif t == 'float':
return float(d.strip())
return d
elif t in ('list','tuple'):
res=[]
for n in node.findall('./value'):
res.append(_eval_xml(self,n,pool,cr,uid,idref))
if t=='tuple':
return tuple(res)
return res
t = node.get('type','char')
f_model = node.get('model', '').encode('utf-8')
if node.get('search'):
f_search = node.get("search",'').encode('utf-8')
f_use = node.get("use",'id').encode('utf-8')
f_name = node.get("name",'').encode('utf-8')
idref2 = {}
if f_search:
idref2 = _get_idref(self, cr, uid, f_model, context, idref)
q = unsafe_eval(f_search, idref2)
ids = pool.get(f_model).search(cr, uid, q)
if f_use != 'id':
ids = map(lambda x: x[f_use], pool.get(f_model).read(cr, uid, ids, [f_use]))
_cols = pool.get(f_model)._columns
if (f_name in _cols) and _cols[f_name]._type=='many2many':
return ids
f_val = False
if len(ids):
f_val = ids[0]
if isinstance(f_val, tuple):
f_val = f_val[0]
return f_val
a_eval = node.get('eval','')
idref2 = {}
if a_eval:
idref2 = _get_idref(self, cr, uid, f_model, context, idref)
try:
return unsafe_eval(a_eval, idref2)
except Exception:
logger = logging.getLogger('init')
logger.warning('could not eval(%s) for %s in %s' % (a_eval, node.get('name'), context), exc_info=True)
return ""
if t == 'xml':
def _process(s, idref):
m = re.findall('[^%]%\((.*?)\)[ds]', s)
for id in m:
if not id in idref:
idref[id]=self.id_get(cr, False, id)
return s % idref
_fix_multiple_roots(node)
return '<?xml version="1.0"?>\n'\
+_process("".join([etree.tostring(n, encoding='utf-8')
for n in node]),
idref)
if t in ('char', 'int', 'float'):
d = node.text
if t == 'int':
d = d.strip()
if d == 'None':
return None
else:
return int(d.strip())
elif t == 'float':
return float(d.strip())
return d
elif t in ('list','tuple'):
res=[]
for n in node.findall('./value'):
res.append(_eval_xml(self,n,pool,cr,uid,idref))
if t=='tuple':
return tuple(res)
return res
elif node.tag == "getitem":
for n in node:
res=_eval_xml(self,n,pool,cr,uid,idref)
@@ -273,11 +281,13 @@ form: module.record_id""" % (xml_id,)
def _tag_delete(self, cr, rec, data_node=None):
d_model = rec.get("model",'')
d_search = rec.get("search",'')
d_search = rec.get("search",'').encode('utf-8')
d_id = rec.get("id",'')
ids = []
if d_search:
ids = self.pool.get(d_model).search(cr, self.uid, unsafe_eval(d_search))
idref = _get_idref(self, cr, self.uid, d_model, context={}, idref={})
ids = self.pool.get(d_model).search(cr, self.uid, unsafe_eval(d_search, idref))
if d_id:
try:
ids.append(self.id_get(cr, d_model, d_id))
@@ -655,7 +665,7 @@ form: module.record_id""" % (xml_id,)
self.pool.get('ir.model.data').ir_set(cr, self.uid, 'action', 'tree_but_open', 'Menuitem', [('ir.ui.menu', int(pid))], action, True, True, xml_id=rec_id)
return ('ir.ui.menu', pid)
def _assert_equals(self, f1, f2, prec = 4):
def _assert_equals(self, f1, f2, prec=4):
return not round(f1 - f2, prec)
def _tag_assert(self, cr, rec, data_node=None):
+3 -1
View File
@@ -164,7 +164,7 @@ d[types.InstanceType] = _copy_inst
del d
def deepcopy(x, memo=None, _nil=[]):
def deepcopy(x, memo=None, _nil=None):
"""Deep copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
@@ -172,6 +172,8 @@ def deepcopy(x, memo=None, _nil=[]):
if memo is None:
memo = {}
if _nil is None:
_nil = {}
d = id(x)
y = memo.get(d, _nil)
+1 -1
View File
@@ -60,7 +60,7 @@ trailer
%%EOF
"""
def output_field( f ):
def output_field(f):
return "\xfe\xff" + "".join( [ "\x00"+c for c in f ] )
def extract_keys(lines):
+69 -40
View File
@@ -200,6 +200,23 @@ class GettextAlias(object):
_ = GettextAlias()
def quote(s):
"""Returns quoted PO term string, with special PO characters escaped"""
assert r"\n" not in s, "Translation terms may not include escaped newlines ('\\n'), please use only literal newlines! (in '%s')" % s
return '"%s"' % s.replace('\\','\\\\') \
.replace('"','\\"') \
.replace('\n', '\\n"\n"')
re_escaped_char = re.compile(r"(\\.)")
re_escaped_replacements = {'n': '\n', }
def _sub_replacement(match_obj):
return re_escaped_replacements.get(match_obj.group(1)[1], match_obj.group(1)[1])
def unquote(str):
"""Returns unquoted PO term string, with special PO characters unescaped"""
return re_escaped_char.sub(_sub_replacement, str[1:-1])
# class to handle po files
class TinyPoFile(object):
def __init__(self, buffer):
@@ -231,11 +248,6 @@ class TinyPoFile(object):
return (self.lines_count - len(self.lines))
def next(self):
def unquote(str):
return str[1:-1].replace("\\n", "\n") \
.replace("\\\\ ", "\\ ") \
.replace('\\"', '"')
type = name = res_id = source = trad = None
if self.tnrs:
@@ -337,11 +349,6 @@ class TinyPoFile(object):
)
def write(self, modules, tnrs, source, trad):
def quote(s):
return '"%s"' % s.replace('"','\\"') \
.replace('\n', '\\n"\n"') \
.replace(' \\ ',' \\\\ ')
plurial = len(modules) > 1 and 's' or ''
self.buffer.write("#. module%s: %s\n" % (plurial, ', '.join(modules)))
@@ -654,29 +661,21 @@ def trans_generate(lang, modules, dbname=None):
# 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):
# path = path[len(mp)+1:]
# return path.split(os.path.sep)[0]
path_dir = os.path.dirname(path[1:])
if path_dir:
if os.path.exists(os.path.join(tools.config['addons_path'],path[1:])):
return path.split(os.path.sep)[1]
else:
root_addons = os.path.join(tools.config['root_path'], 'addons')
if os.path.exists(os.path.join(root_addons,path[1:])):
return path.split(os.path.sep)[1]
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 os.path.isabs(adp):
mod_paths.append(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
modobj = pool.get('ir.module.module')
@@ -685,25 +684,55 @@ def trans_generate(lang, modules, dbname=None):
root_path = os.path.join(tools.config['root_path'], 'addons')
if root_path in tools.config['addons_path'] :
path_list = [root_path]
apaths = map(os.path.abspath, map(str.strip, tools.config['addons_path'].split(',')))
if root_path in apaths:
path_list = apaths
else :
path_list = [root_path,tools.config['addons_path']]
path_list = [root_path,] + apaths
logger.notifyChannel("i18n", netsvc.LOG_DEBUG, "Scanning modules at paths: %s" % (' '.join(path_list),))
mod_paths = []
join_dquotes = re.compile(r'([^\\])"[\s\\]*"', re.DOTALL)
join_quotes = re.compile(r'([^\\])\'[\s\\]*\'', re.DOTALL)
re_dquotes = re.compile(r'[^a-zA-Z0-9_]_\([\s]*"(.+?)"[\s]*?\)', re.DOTALL)
re_quotes = re.compile(r'[^a-zA-Z0-9_]_\([\s]*\'(.+?)\'[\s]*?\)', re.DOTALL)
def export_code_terms_from_file(fname, path, root, terms_type):
fabsolutepath = join(root, fname)
frelativepath = fabsolutepath[len(path):]
module = get_module_from_path(frelativepath)
module = get_module_from_path(fabsolutepath, mod_paths=mod_paths)
is_mod_installed = module in installed_modules
if (('all' in modules) or (module in modules)) and is_mod_installed:
logger.notifyChannel("i18n", netsvc.LOG_DEBUG, "Scanning code of %s at module: %s" % (frelativepath, module))
code_string = tools.file_open(fabsolutepath, subdir='').read()
iter = re.finditer('[^a-zA-Z0-9_]_\([\s]*["\'](.+?)["\'][\s]*\)', code_string, re.S)
if module in installed_modules:
frelativepath = str("addons" + frelativepath)
for i in iter:
push_translation(module, terms_type, frelativepath, 0, encode(i.group(1)))
ite = re_dquotes.finditer(code_string)
for i in ite:
src = i.group(1)
if src.startswith('""'):
assert src.endswith('""'), "Incorrect usage of _(..) function (should contain only literal strings!) in file %s near: %s" % (frelativepath, src[:30])
src = src[2:-2]
else:
src = join_dquotes.sub(r'\1', src)
# now, since we did a binary read of a python source file, we
# have to expand pythonic escapes like the interpreter does.
src = src.decode('string_escape')
push_translation(module, terms_type, frelativepath, 0, encode(src))
ite = re_quotes.finditer(code_string)
for i in ite:
src = i.group(1)
if src.startswith("''"):
assert src.endswith("''"), "Incorrect usage of _(..) function (should contain only literal strings!) in file %s near: %s" % (frelativepath, src[:30])
src = src[2:-2]
else:
src = join_quotes.sub(r'\1', src)
src = src.decode('string_escape')
push_translation(module, terms_type, frelativepath, 0, encode(src))
for path in path_list:
logger.notifyChannel("i18n", netsvc.LOG_DEBUG, "Scanning files of modules at %s" % path)
for root, dummy, files in tools.osutil.walksymlinks(path):
for fname in itertools.chain(fnmatch.filter(files, '*.py')):
export_code_terms_from_file(fname, path, root, 'code')
+7 -5
View File
@@ -8,20 +8,20 @@ msgstr ""
"Project-Id-Version: openobject-server\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-08-24 22:41+0300\n"
"PO-Revision-Date: 2010-07-21 07:32+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"PO-Revision-Date: 2010-11-15 08:27+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\n"
"Language-Team: Serbian <sr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-09-29 04:47+0000\n"
"X-Launchpad-Export-Date: 2010-11-16 05:05+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. Type: string
#. Description
#: ../openerp-server.templates:1001
msgid "Dedicated system account for the Open ERP server:"
msgstr ""
msgstr "Namenski sistem naloga za OpenERP Server:"
#. Type: string
#. Description
@@ -31,9 +31,11 @@ msgid ""
"the system's security is not compromised by running it with superuser "
"privileges."
msgstr ""
"OpenERP server mora koristiti namenski nalog ya svoje operacije tako da "
"sigurnosni sistem nije kompromitovan pri radu sa superUser privilegijama."
#. Type: string
#. Description
#: ../openerp-server.templates:1001
msgid "Please choose that account's username."
msgstr ""
msgstr "Molim vas izaberite korisničko ime naloga."