diff --git a/bin/addons/base/base_update.xml b/bin/addons/base/base_update.xml index a3bc710e857..99ec3f7a250 100644 --- a/bin/addons/base/base_update.xml +++ b/bin/addons/base/base_update.xml @@ -78,7 +78,7 @@
diff --git a/bin/addons/base/res/res_currency.py b/bin/addons/base/res/res_currency.py index 0cd80c141c6..50a6679c46f 100644 --- a/bin/addons/base/res/res_currency.py +++ b/bin/addons/base/res/res_currency.py @@ -63,7 +63,7 @@ class res_currency(osv.osv): } _defaults = { 'active': lambda *a: 1, - 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'res.currency', c) + 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'res.currency', context=c) } _order = "code" diff --git a/bin/addons/base/res/res_user.py b/bin/addons/base/res/res_user.py index 40be4a43392..3a8d9fa3753 100644 --- a/bin/addons/base/res/res_user.py +++ b/bin/addons/base/res/res_user.py @@ -207,7 +207,7 @@ class users(osv.osv): if (ids == [uid]): ok = True for k in values.keys(): - if k not in ('password','signature','action_id', 'context_lang', 'context_tz'): + if k not in ('password','signature','action_id', 'context_lang', 'context_tz','company_id'): ok=False if ok: uid = 1 diff --git a/bin/addons/quality_integration_server/base_quality_interrogation.py b/bin/addons/quality_integration_server/base_quality_interrogation.py index 8806ff0e2b9..96c04e72ca6 100755 --- a/bin/addons/quality_integration_server/base_quality_interrogation.py +++ b/bin/addons/quality_integration_server/base_quality_interrogation.py @@ -171,9 +171,10 @@ def create_db(uri, dbname, user='admin', pwd='admin', lang='en_US'): wiz_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard') login_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common') db_list = execute(conn, 'list') - if dbname not in db_list: - id = execute(conn,'create',admin_passwd, dbname, True, lang) - wait(id,uri) + if dbname in db_list: + drop_db(uri, dbname) + id = execute(conn,'create',admin_passwd, dbname, True, lang) + wait(id,uri) uid = login_conn.login(dbname, user, pwd) wiz_id = execute(wiz_conn,'create', dbname, uid, user, 'base_setup.base_setup') diff --git a/bin/osv/expression.py b/bin/osv/expression.py index d1fdfedf464..9b4b01d3fe9 100644 --- a/bin/osv/expression.py +++ b/bin/osv/expression.py @@ -115,14 +115,14 @@ class expression(object): main_table = table fargs = left.split('.', 1) index = i - if left in table._inherit_fields: + if fargs[0] in table._inherit_fields: while True: field = main_table._columns.get(fargs[0], False) if field: working_table = main_table self.__tables[i] = working_table break - working_table = main_table.pool.get(main_table._inherit_fields[left][0]) + working_table = main_table.pool.get(main_table._inherit_fields[fargs[0]][0]) if working_table not in self.__tables.values(): self.__joins.append(('%s.%s=%s.%s' % (working_table._table, 'id', main_table._table, main_table._inherits[working_table._name]), working_table._table)) self.__tables[index] = working_table @@ -145,25 +145,23 @@ class expression(object): if field._type in ['many2many','one2many']: right = field_obj.search(cr, uid, [(fargs[1], operator, right)], context=context) right1 = table.search(cr, uid, [(fargs[0],'in', right)], context=context) - self.__exp[i] = ('id', 'in', right1) - + self.__exp[i] = ('id', 'in', right1) continue - if field._properties: + if field._properties and not field.store: # this is a function field - if not field.store: - if not field._fnct_search: - # the function field doesn't provide a search function and doesn't store - # values in the database, so we must ignore it : we generate a dummy leaf - self.__exp[i] = self.__DUMMY_LEAF - else: - subexp = field.search(cr, uid, table, left, [self.__exp[i]]) - # we assume that the expression is valid - # we create a dummy leaf for forcing the parsing of the resulting expression - self.__exp[i] = '&' - self.__exp.insert(i + 1, self.__DUMMY_LEAF) - for j, se in enumerate(subexp): - self.__exp.insert(i + 2 + j, se) + if not field._fnct_search: + # the function field doesn't provide a search function and doesn't store + # values in the database, so we must ignore it : we generate a dummy leaf + self.__exp[i] = self.__DUMMY_LEAF + else: + subexp = field.search(cr, uid, table, left, [self.__exp[i]]) + # we assume that the expression is valid + # we create a dummy leaf for forcing the parsing of the resulting expression + self.__exp[i] = '&' + self.__exp.insert(i + 1, self.__DUMMY_LEAF) + for j, se in enumerate(subexp): + self.__exp.insert(i + 2 + j, se) # else, the value of the field is store in the database, so we search on it diff --git a/bin/osv/fields.py b/bin/osv/fields.py index 09d51e6bd82..f56f700596c 100644 --- a/bin/osv/fields.py +++ b/bin/osv/fields.py @@ -506,12 +506,13 @@ class many2many(_column): limit_str = self._limit is not None and ' limit %d' % self._limit or '' obj = obj.pool.get(self._obj) - d1, d2 = obj.pool.get('ir.rule').domain_get(cr, user, obj._name) + d1, d2, tables = obj.pool.get('ir.rule').domain_get(cr, user, obj._name, context=context) if d1: - d1 = ' and ' + d1 + d1 = ' and ' + ' and '.join(d1) + else: d1 = '' cr.execute('SELECT '+self._rel+'.'+self._id2+','+self._rel+'.'+self._id1+' \ - FROM '+self._rel+' , '+obj._table+' \ + FROM '+self._rel+' , '+(','.join(tables))+' \ WHERE '+self._rel+'.'+self._id1+' = ANY (%s) \ AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+d1 +limit_str+' order by '+obj._table+'.'+obj._order+' offset %s', @@ -544,10 +545,12 @@ class many2many(_column): cr.execute('update '+self._rel+' set '+self._id2+'=null where '+self._id2+'=%s', (id,)) elif act[0] == 6: - d1, d2 = obj.pool.get('ir.rule').domain_get(cr, user, obj._name) + d1, d2,tables = obj.pool.get('ir.rule').domain_get(cr, user, obj._name, context=context) if d1: - d1 = ' and ' + d1 - cr.execute('delete from '+self._rel+' where '+self._id1+'=%s AND '+self._id2+' IN (SELECT '+self._rel+'.'+self._id2+' FROM '+self._rel+', '+obj._table+' WHERE '+self._rel+'.'+self._id1+'=%s AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2) + d1 = ' and ' + ' and '.join(d1) + else: + d1 = '' + cr.execute('delete from '+self._rel+' where '+self._id1+'=%s AND '+self._id2+' IN (SELECT '+self._rel+'.'+self._id2+' FROM '+self._rel+', '+','.join(tables)+' WHERE '+self._rel+'.'+self._id1+'=%s AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2) for act_nbr in act[2]: cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s, %s)', (id, act_nbr)) @@ -676,6 +679,10 @@ class function(_column): if self._type == 'binary' and context.get('bin_size', False): # convert the data returned by the function with the size of that data... res = dict(map( get_nice_size, res.items())) + if self._type == "integer": + for r in res.keys(): + # Converting value into string so that it does not affect XML-RPC Limits + res[r] = str(res[r]) return res get_memory = get @@ -741,7 +748,8 @@ class related(function): if not ids: return {} relation = obj._name res = {}.fromkeys(ids, False) - objlst = obj.browse(cr, uid, ids) + + objlst = obj.browse(cr, uid, ids, context=context) for data in objlst: if not data: continue @@ -778,7 +786,6 @@ class related(function): if res[r]: res[r] = [x.id for x in res[r]] - return res def __init__(self, *arg, **args): @@ -856,9 +863,12 @@ class property(function): if nid: default_val = property.browse(cr, uid, nid[0], context).value - company_id = obj.pool.get('res.users').company_get(cr, uid, uid) + company_id = obj.pool.get('res.company')._company_default_get(cr, uid, obj._name, prop, context=context) res = False - newval = (id_val and obj_dest+','+str(id_val)) or False + if val[0]: + newval = (id_val and obj_dest+','+str(id_val)) or False + else: + newval = id_val or False if (newval != default_val) and newval: propdef = obj.pool.get('ir.model.fields').browse(cr, uid, definition_id, context=context) @@ -892,27 +902,28 @@ class property(function): for id in ids: res[id] = default_val for prop in property.browse(cr, uid, nids): - res[int(prop.res_id.split(',')[1])] = (prop.value and \ - int(prop.value.split(',')[1])) or False - - obj = obj.pool.get(self._obj) - - to_check = res.values() - if default_val and default_val not in to_check: - to_check += [default_val] - existing_ids = obj.search(cr, uid, [('id', 'in', to_check)]) - - for id, res_id in res.items(): - if res_id not in existing_ids: - cr.execute('DELETE FROM ir_property WHERE value=%s', ((obj._name+','+str(res_id)),)) - res[id] = default_val - - names = dict(obj.name_get(cr, uid, existing_ids, context)) - for r in res.keys(): - if res[r] and res[r] in names: - res[r] = (res[r], names[res[r]]) + if prop.value.find(',') >= 0: + res[int(prop.res_id.split(',')[1])] = (prop.value and \ + int(prop.value.split(',')[1])) or False else: - res[r] = False + res[int(prop.res_id.split(',')[1])] = prop.value or '' + + if self._obj: + obj = obj.pool.get(self._obj) + to_check = res.values() + if default_val and default_val not in to_check: + to_check += [default_val] + existing_ids = obj.search(cr, uid, [('id', 'in', to_check)]) + for id, res_id in res.items(): + if res_id not in existing_ids: + cr.execute('DELETE FROM ir_property WHERE value=%s', ((obj._name+','+str(res_id)),)) + res[id] = default_val + names = dict(obj.name_get(cr, uid, existing_ids, context)) + for r in res.keys(): + if res[r] and res[r] in names: + res[r] = (res[r], names[res[r]]) + else: + res[r] = False return res def _field_get(self, cr, uid, model_name, prop): diff --git a/bin/osv/orm.py b/bin/osv/orm.py index a326b6b23e3..f1c36026c32 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1860,7 +1860,8 @@ class orm(orm_template): if not hasattr(self, "_auto") or self._auto: cr.execute("SELECT relname FROM pg_class WHERE relkind in ('r','v') AND relname='%s'" % self._table) if not cr.rowcount: - cr.execute("CREATE TABLE \"%s\" (id SERIAL NOT NULL, PRIMARY KEY(id)) WITH OIDS" % self._table) + cr.execute("CREATE TABLE \"%s\" (id SERIAL NOT NULL, PRIMARY KEY(id)) WITHOUT OIDS" % self._table) + cr.execute("COMMENT ON TABLE \"%s\" IS '%s'" % (self._table, self._description.replace("'","''"))) create = True cr.commit() if self._parent_store: @@ -1922,9 +1923,10 @@ class orm(orm_template): ref = self.pool.get(f._obj)._table except AttributeError: ref = f._obj.replace('.', '_') - cr.execute('CREATE TABLE "%s" ("%s" INTEGER NOT NULL REFERENCES "%s" ON DELETE CASCADE, "%s" INTEGER NOT NULL REFERENCES "%s" ON DELETE CASCADE) WITH OIDS' % (f._rel, f._id1, self._table, f._id2, ref)) + cr.execute('CREATE TABLE "%s" ("%s" INTEGER NOT NULL REFERENCES "%s" ON DELETE CASCADE, "%s" INTEGER NOT NULL REFERENCES "%s" ON DELETE CASCADE) WITHOUT OIDS' % (f._rel, f._id1, self._table, f._id2, ref)) cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (f._rel, f._id1, f._rel, f._id1)) cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (f._rel, f._id2, f._rel, f._id2)) + cr.execute("COMMENT ON TABLE \"%s\" IS 'RELATION BETWEEN %s AND %s'" % (f._rel, self._table, ref)) cr.commit() else: 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 " \ @@ -1953,6 +1955,7 @@ class orm(orm_template): # add the missing field cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, get_pg_type(f)[1])) + cr.execute("COMMENT ON COLUMN %s.%s IS '%s'" % (self._table, k, f.string.replace("'","''"))) # initialize it if not create and k in self._defaults: @@ -2340,7 +2343,6 @@ class orm(orm_template): select = map(lambda x: isinstance(x,dict) and x['id'] or x, select) result = self._read_flat(cr, user, select, fields, context, load) - for r in result: for key, v in r.items(): if v == None: @@ -2358,8 +2360,7 @@ class orm(orm_template): id_exist = cr.fetchone() if not id_exist: cr.execute('update "'+self._table+'" set "'+key+'"=NULL where "%s"=%s' %(key,''.join("'"+str(v)+"'"))) - r[key] = '' - + r[key] = '' if isinstance(ids, (int, long, dict)): return result and result[0] or False return result @@ -2374,7 +2375,7 @@ class orm(orm_template): fields_to_read = self._columns.keys() # construct a clause for the rules : - d1, d2 = self.pool.get('ir.rule').domain_get(cr, user, self._name) + d1, d2, tables = self.pool.get('ir.rule').domain_get(cr, user, self._name, context=context) # all inherited fields + all non inherited fields for which the attribute whose name is in load is True fields_pre = [f for f in fields_to_read if @@ -2389,7 +2390,7 @@ class orm(orm_template): return "date_trunc('second', %s) as %s" % (f, f) if f == self.CONCURRENCY_CHECK_FIELD: if self._log_access: - return "COALESCE(write_date, create_date, now())::timestamp AS %s" % (f,) + return "COALESCE(%s.write_date, %s.create_date, now())::timestamp AS %s" % (self._table, self._table, f,) return "now()::timestamp AS %s" % (f,) if isinstance(self._columns[f], fields.binary) and context.get('bin_size', False): return 'length("%s") as "%s"' % (f, f) @@ -2398,12 +2399,12 @@ class orm(orm_template): for i in range(0, len(ids), cr.IN_MAX): sub_ids = ids[i:i+cr.IN_MAX] if d1: - cr.execute('SELECT %s FROM \"%s\" WHERE id = ANY (%%s) AND %s ORDER BY %s' % \ - (','.join(fields_pre2 + ['id']), self._table, d1, + cr.execute('SELECT %s FROM %s WHERE %s.id = ANY (%%s) AND %s ORDER BY %s' % \ + (','.join(fields_pre2 + [self._table + '.id']), ','.join(tables), self._table, ' and '.join(d1), self._order),[sub_ids,]+d2) if not cr.rowcount == len({}.fromkeys(sub_ids)): raise except_orm(_('AccessError'), - _('You try to bypass an access rule (Document type: %s).') % self._description) + _('You try to bypass an access rule while reading (Document type: %s).') % self._description) else: cr.execute('SELECT %s FROM \"%s\" WHERE id = ANY (%%s) ORDER BY %s' % \ (','.join(fields_pre2 + ['id']), self._table, @@ -2585,27 +2586,23 @@ class orm(orm_template): # ids2 = [x[self._inherits[key]] for x in res] # self.pool.get(key).unlink(cr, uid, ids2) - d1, d2 = self.pool.get('ir.rule').domain_get(cr, uid, self._name) + d1, d2,tables = self.pool.get('ir.rule').domain_get(cr, uid, self._name, context=context) if d1: - d1 = ' AND '+d1 + d1 = ' AND '+' and '.join(d1) for i in range(0, len(ids), cr.IN_MAX): sub_ids = ids[i:i+cr.IN_MAX] str_d = string.join(('%s',)*len(sub_ids), ',') if d1: - cr.execute('SELECT id FROM "'+self._table+'" ' \ - 'WHERE id IN ('+str_d+')'+d1, sub_ids+d2) + cr.execute('SELECT '+self._table+'.id FROM '+','.join(tables)+' ' \ + 'WHERE '+self._table+'.id IN ('+str_d+')'+d1, sub_ids+d2) if not cr.rowcount == len(sub_ids): raise except_orm(_('AccessError'), _('You try to bypass an access rule (Document type: %s).') % \ self._description) - if d1: - cr.execute('delete from "'+self._table+'" ' \ - 'where id in ('+str_d+')'+d1, sub_ids+d2) - else: - cr.execute('delete from "'+self._table+'" ' \ - 'where id in ('+str_d+')', sub_ids) + cr.execute('delete from '+self._table+' ' \ + 'where id in ('+str_d+')', sub_ids) for order, object, store_ids, fields in result_store: if object<>self._name: @@ -2705,19 +2702,19 @@ class orm(orm_template): if len(upd0): - d1, d2 = self.pool.get('ir.rule').domain_get(cr, user, self._name) + d1, d2,tables = self.pool.get('ir.rule').domain_get(cr, user, self._name, context=context) if d1: - d1 = ' and '+d1 + d1 = ' and '+' and '.join(d1) for i in range(0, len(ids), cr.IN_MAX): sub_ids = ids[i:i+cr.IN_MAX] ids_str = string.join(map(str, sub_ids), ',') if d1: - cr.execute('SELECT id FROM "'+self._table+'" ' \ - 'WHERE id IN ('+ids_str+')'+d1, d2) + cr.execute('SELECT '+self._table+'.id FROM '+','.join(tables)+' ' \ + 'WHERE '+self._table+'.id IN ('+ids_str+')'+d1, d2) if not cr.rowcount == len({}.fromkeys(sub_ids)): raise except_orm(_('AccessError'), - _('You try to bypass an access rule (Document type: %s).') % \ + _('You try to bypass an access rule while writing (Document type: %s).') % \ self._description) else: cr.execute('SELECT id FROM "'+self._table+'" WHERE id IN ('+ids_str+')') @@ -2725,12 +2722,8 @@ class orm(orm_template): raise except_orm(_('AccessError'), _('You try to write on an record that doesn\'t exist ' \ '(Document type: %s).') % self._description) - if d1: - cr.execute('update "'+self._table+'" set '+string.join(upd0, ',')+' ' \ - 'where id in ('+ids_str+')'+d1, upd1+ d2) - else: - cr.execute('update "'+self._table+'" set '+string.join(upd0, ',')+' ' \ - 'where id in ('+ids_str+')', upd1) + cr.execute('update '+self._table+' set '+string.join(upd0, ',')+' ' \ + 'where id in ('+ids_str+')', upd1) if totranslate: # TODO: optimize @@ -3023,7 +3016,9 @@ class orm(orm_template): continue result.setdefault(fncts[fnct][0], {}) - ids2 = fncts[fnct][2](self,cr, uid, ids, context) + + # uid == 1 for accessing objects having rules defined on store fields + ids2 = fncts[fnct][2](self,cr, 1, ids, context) for id in filter(None, ids2): result[fncts[fnct][0]].setdefault(id, []) result[fncts[fnct][0]][id].append(fnct) @@ -3072,7 +3067,8 @@ class orm(orm_template): for key in keys: val = todo[key] if key: - result = self._columns[val[0]].get(cr, self, ids, val, uid, context=context) + # uid == 1 for accessing objects having rules defined on store fields + result = self._columns[val[0]].get(cr, self, ids, val, 1, context=context) for id,value in result.items(): if field_flag: for f in value.keys(): @@ -3096,7 +3092,8 @@ class orm(orm_template): else: for f in val: - result = self._columns[f].get(cr, self, ids, f, uid, context=context) + # uid == 1 for accessing objects having rules defined on store fields + result = self._columns[f].get(cr, self, ids, f, 1, context=context) for r in result.keys(): if field_flag: if r in field_dict.keys(): @@ -3159,12 +3156,19 @@ class orm(orm_template): context = {} # compute the where, order by, limit and offset clauses (qu1, qu2, tables) = self._where_calc(cr, user, args, context=context) + dom = self.pool.get('ir.rule').domain_get(cr, user, self._name, context=context) + qu1 = qu1 + dom[0] + qu2 = qu2 + dom[1] + for t in dom[2]: + if t not in tables: + tables.append(t) if len(qu1): qu1 = ' where '+string.join(qu1, ' and ') else: qu1 = '' + if order: self._check_qorder(order) order_by = order or self._order @@ -3173,12 +3177,6 @@ class orm(orm_template): offset_str = offset and ' offset %d' % offset or '' - # construct a clause for the rules : - d1, d2 = self.pool.get('ir.rule').domain_get(cr, user, self._name) - if d1: - qu1 = qu1 and qu1+' and '+d1 or ' where '+d1 - qu2 += d2 - if count: cr.execute('select count(%s.id) from ' % self._table + ','.join(tables) +qu1 + limit_str + offset_str, qu2) diff --git a/bin/sql_db.py b/bin/sql_db.py index a84547b0b7c..b4ce8347f43 100644 --- a/bin/sql_db.py +++ b/bin/sql_db.py @@ -82,7 +82,6 @@ class Cursor(object): self.sql_into_log = {} self.sql_log = False self.sql_log_count = 0 - self.__closed = True # avoid the call of close() (by __del__) if an exception # is raised by any of the following initialisations self._pool = pool diff --git a/bin/tools/misc.py b/bin/tools/misc.py index c3394c2ed4f..001f62e0968 100644 --- a/bin/tools/misc.py +++ b/bin/tools/misc.py @@ -31,6 +31,7 @@ from config import config import zipfile import release import socket +import re if sys.version_info[:2] < (2, 4): from threadinglocal import local @@ -302,8 +303,103 @@ def reverse_enumerate(l): #---------------------------------------------------------- # Emails #---------------------------------------------------------- +email_re = re.compile(r""" + ([a-zA-Z][\w\.-]*[a-zA-Z0-9] # username part + @ # mandatory @ sign + [a-zA-Z0-9][\w\.-]* # domain must start with a letter ... Ged> why do we include a 0-9 then? + \. + [a-z]{2,3} # TLD + ) + """, re.VERBOSE) +res_re = re.compile(r"\[([0-9]+)\]", re.UNICODE) +command_re = re.compile("^Set-([a-z]+) *: *(.+)$", re.I + re.UNICODE) +reference_re = re.compile("<.*-openobject-(\\d+)@(.*)>", re.UNICODE) + +priorities = { + '1': '1 (Highest)', + '2': '2 (High)', + '3': '3 (Normal)', + '4': '4 (Low)', + '5': '5 (Lowest)', + } + +def html2plaintext(html, body_id=None, encoding='utf-8'): + ## (c) Fry-IT, www.fry-it.com, 2007 + ##