diff --git a/.bzrignore b/.bzrignore
index 1f9c25fe409..9b867797a34 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -1,3 +1,5 @@
-./bin/addons/*
-./bin/filestore*
-
+*.pyc
+.*.swp
+.bzrignore
+bin/addons/*
+bin/filestore*
diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py
index 00a12ee784b..02475e02bd3 100644
--- a/bin/addons/__init__.py
+++ b/bin/addons/__init__.py
@@ -23,7 +23,6 @@
import os, sys, imp
from os.path import join as opj
import itertools
-from sets import Set
import zipimport
import osv
@@ -69,20 +68,56 @@ class Graph(dict):
father.addChild(name)
else:
Node(name, self)
+
+ def update_from_db(self, cr):
+ # update the graph with values from the database (if exist)
+ ## First, we set the default values for each package in graph
+ additional_data = dict.fromkeys(self.keys(), {'id': 0, 'state': 'uninstalled', 'dbdemo': False, 'installed_version': None})
+ ## Then we get the values from the database
+ cr.execute('SELECT name, id, state, demo AS dbdemo, latest_version AS installed_version'
+ ' FROM ir_module_module'
+ ' WHERE name in (%s)' % (','.join(['%s'] * len(self))),
+ additional_data.keys()
+ )
+
+ ## and we update the default values with values from the database
+ additional_data.update(dict([(x.pop('name'), x) for x in cr.dictfetchall()]))
+
+ for package in self.values():
+ for k, v in additional_data[package.name].items():
+ setattr(package, k, v)
+
+
def __iter__(self):
- level = 0
- done = Set(self.keys())
- while done:
- level_modules = [(name, module) for name, module in self.items() if module.depth==level]
- for name, module in level_modules:
- done.remove(name)
- yield module
- level += 1
+ done = set()
+ # first pass: all modules that doesn't have a depend module (or
+ # themself) in 'to install' state.
+ first_pass = []
+ for name, mod in self.items():
+ if all(m.state != 'to install' for m in mod.depends(True)):
+ first_pass.append(mod)
+
+ first_pass.sort(key=lambda m: m.depth)
+ for m in first_pass:
+ done.add(m.name)
+ yield m
+
+ # second pass: all modules in 'to install' state
+ second_pass = [m for m in self.values() if m.state == 'to install']
+ second_pass.sort(key=lambda m: m.depth)
+ for m in second_pass:
+ done.add(m.name)
+ yield m
+
+ # third pass: all other modules
+ third_pass = [m for m in self.values() if m.name not in done]
+ third_pass.sort(key=lambda m: m.depth)
+ for m in third_pass:
+ yield m
class Singleton(object):
-
def __new__(cls, name, graph):
if name in graph:
inst = graph[name]
@@ -97,57 +132,70 @@ class Node(Singleton):
def __init__(self, name, graph):
self.graph = graph
- if not hasattr(self, 'childs'):
- self.childs = []
+ if not hasattr(self, 'children'):
+ self.children = []
if not hasattr(self, 'depth'):
self.depth = 0
def addChild(self, name):
node = Node(name, self.graph)
node.depth = self.depth + 1
- if node not in self.childs:
- self.childs.append(node)
+ if node not in self.children:
+ self.children.append(node)
for attr in ('init', 'update', 'demo'):
if hasattr(self, attr):
setattr(node, attr, True)
- self.childs.sort(lambda x, y: cmp(x.name, y.name))
-
- def hasChild(self, name):
- return Node(name, self.graph) in self.childs or \
- bool([c for c in self.childs if c.hasChild(name)])
+ self.children.sort(lambda x, y: cmp(x.name, y.name))
def __setattr__(self, name, value):
super(Singleton, self).__setattr__(name, value)
if name in ('init', 'update', 'demo'):
tools.config[name][self.name] = 1
- for child in self.childs:
+ for child in self.children:
setattr(child, name, value)
if name == 'depth':
- for child in self.childs:
+ for child in self.children:
setattr(child, name, value + 1)
def __iter__(self):
- return itertools.chain(iter(self.childs), *map(iter, self.childs))
+ return itertools.chain(iter(self.children), *map(iter, self.children))
+
+ def _depends(self):
+ """direct depends"""
+ return list(self.data.get('depends', []))
+
+ def depends(self, include_self=False):
+ deps = self._depends()
+ res = set()
+ if include_self:
+ res.add(self)
+ while deps:
+ dep = Node(deps.pop(0), self.graph)
+ res.add(dep)
+ for d in dep._depends():
+ if d not in res:
+ deps.append(d)
+ return res
def __str__(self):
return self._pprint()
def _pprint(self, depth=0):
s = '%s\n' % self.name
- for c in self.childs:
+ for c in self.children:
s += '%s`-> %s' % (' ' * depth, c._pprint(depth+1))
return s
-def get_module_path(module):
+def get_module_path(module, downloaded=False):
"""Return the path of the given module."""
-
if os.path.exists(opj(ad, module)) or os.path.exists(opj(ad, '%s.zip' % module)):
return opj(ad, module)
if os.path.exists(opj(_ad, module)) or os.path.exists(opj(_ad, '%s.zip' % module)):
return opj(_ad, module)
-
+ if downloaded:
+ return opj(_ad, module)
logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: module not found' % (module,))
return False
@@ -311,7 +359,7 @@ def upgrade_graph(graph, cr, module_list, force=None):
packages.append((module, info.get('depends', []), info))
dependencies = dict([(p, deps) for p, deps, data in packages])
- current, later = Set([p for p, dep, data in packages]), Set()
+ current, later = set([p for p, dep, data in packages]), set()
while packages and current > later:
package, deps, data = packages[0]
@@ -333,6 +381,8 @@ def upgrade_graph(graph, cr, module_list, force=None):
packages.append((package, deps, data))
packages.pop(0)
+ graph.update_from_db(cr)
+
for package in later:
unmet_deps = filter(lambda p: p not in graph, dependencies[package])
logger.notifyChannel('init', netsvc.LOG_ERROR, 'module %s: Unmet dependencies: %s' % (package, ', '.join(unmet_deps)))
@@ -551,24 +601,6 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
statusi = 0
pool = pooler.get_pool(cr.dbname)
-
- # update the graph with values from the database (if exist)
- ## First, we set the default values for each package in graph
- additional_data = dict.fromkeys([p.name for p in graph], {'id': 0, 'state': 'uninstalled', 'dbdemo': False, 'installed_version': None})
- ## Then we get the values from the database
- cr.execute('SELECT name, id, state, demo AS dbdemo, latest_version AS installed_version'
- ' FROM ir_module_module'
- ' WHERE name in (%s)' % (','.join(['%s'] * len(graph))),
- additional_data.keys()
- )
-
- ## and we update the default values with values from the database
- additional_data.update(dict([(x.pop('name'), x) for x in cr.dictfetchall()]))
-
- for package in graph:
- for k, v in additional_data[package.name].items():
- setattr(package, k, v)
-
migrations = MigrationManager(cr, graph)
has_updates = False
@@ -603,9 +635,6 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
init_module_objects(cr, m, modules)
for kind in ('init', 'update'):
for filename in package.data.get('%s_xml' % kind, []):
-# mode = 'update'
-# if hasattr(package, 'init') or package.state == 'to install':
-# mode = 'init'
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: loading %s' % (m, filename))
name, ext = os.path.splitext(filename)
fp = tools.file_open(opj(m, filename))
@@ -650,9 +679,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
if hasattr(package, kind):
delattr(package, kind)
-
statusi += 1
-
cr.execute('select model from ir_model where state=%s', ('manual',))
for model in cr.dictfetchall():
@@ -748,7 +775,7 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
cr.execute('delete from ir_model_data where noupdate=%s and module=%s', (False, mod_name,))
cr.commit()
#
- # TODO: remove menu without actions of childs
+ # TODO: remove menu without actions of children
#
while True:
cr.execute('''delete from
@@ -772,4 +799,3 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/bin/addons/base/base.sql b/bin/addons/base/base.sql
index 50d793b6dd5..8dfc8d8f765 100644
--- a/bin/addons/base/base.sql
+++ b/bin/addons/base/base.sql
@@ -11,7 +11,7 @@ create table ir_values
id serial,
name varchar(128) not null,
key varchar(128) not null,
- key2 varchar(128) not null,
+ key2 varchar(256) not null,
model varchar(128) not null,
value text,
meta text default NULL,
@@ -55,7 +55,7 @@ CREATE TABLE ir_model_fields (
CREATE TABLE ir_actions (
id serial NOT NULL,
name varchar(64) DEFAULT ''::varchar NOT NULL,
- "type" varchar(64) DEFAULT 'window'::varchar NOT NULL,
+ "type" varchar(32) DEFAULT 'window'::varchar NOT NULL,
usage varchar(32) DEFAULT null,
primary key(id)
);
@@ -64,7 +64,7 @@ CREATE TABLE ir_act_window (
view_id integer,
res_model varchar(64),
view_type varchar(16),
- "domain" varchar(127),
+ "domain" varchar(250),
primary key(id)
)
INHERITS (ir_actions);
@@ -72,8 +72,8 @@ INHERITS (ir_actions);
CREATE TABLE ir_act_report_xml (
model varchar(64) NOT NULL,
report_name varchar(64) NOT NULL,
- report_xsl varchar(64),
- report_xml varchar(64),
+ report_xsl varchar(256),
+ report_xml varchar(256),
auto boolean default true,
primary key(id)
)
@@ -140,7 +140,7 @@ CREATE TABLE res_users (
name varchar(64) not null,
active boolean default True,
login varchar(64) NOT NULL UNIQUE,
- password varchar(32) default null,
+ password varchar(64) default null,
context_tz varchar(64) default null,
signature text,
-- action_id int references ir_act_window on delete set null,
@@ -151,14 +151,14 @@ alter table res_users add constraint res_users_login_uniq unique (login);
CREATE TABLE res_groups (
id serial NOT NULL,
- name varchar(32) NOT NULL,
+ name varchar(64) NOT NULL,
primary key(id)
);
create table res_roles (
id serial NOT NULL,
parent_id int references res_roles on delete set null,
- name varchar(32) NOT NULL,
+ name varchar(64) NOT NULL,
primary key(id)
);
diff --git a/bin/addons/base/base_data.xml b/bin/addons/base/base_data.xml
index 442147434bd..b75b39f2c9e 100644
--- a/bin/addons/base/base_data.xml
+++ b/bin/addons/base/base_data.xml
@@ -2748,7 +2748,6 @@
COP0.014
-
@@ -2756,7 +2755,6 @@
CZK0.014
-
@@ -2777,7 +2775,6 @@
HUF0.014
-
@@ -2785,7 +2782,6 @@
IDR0.014
-
@@ -2832,7 +2828,6 @@
PLN0.014
-
@@ -2840,7 +2835,6 @@
SEK0.014
-
@@ -2860,9 +2854,20 @@
ARS0.014
-
-
+
+
+ INR
+ Rs
+ 0.01
+ 4
+
+
+ 0.634
+
+
+
+
Tiny sprl
diff --git a/bin/addons/base/ir/ir_cron.py b/bin/addons/base/ir/ir_cron.py
index 18f853a0d83..8772cd52120 100644
--- a/bin/addons/base/ir/ir_cron.py
+++ b/bin/addons/base/ir/ir_cron.py
@@ -77,45 +77,45 @@ class ir_cron(osv.osv, netsvc.Agent):
def _poolJobs(self, db_name, check=False):
try:
db, pool = pooler.get_db_and_pool(db_name)
- if pool._init:
- # retry in a few minutes
- self.setAlarm(self._poolJobs, int(time.time())+10*60, [db_name])
- cr = db.cursor()
except:
return False
-
- now = DateTime.now()
- #FIXME: multidb. Solution: a l'instanciation d'une nouvelle connection bd (ds pooler) fo que j'instancie
- # un nouveau pooljob avec comme parametre la bd
- try:
- cr.execute('select * from ir_cron where numbercall<>0 and active and nextcall<=now() order by priority')
- for job in cr.dictfetchall():
- nextcall = DateTime.strptime(job['nextcall'], '%Y-%m-%d %H:%M:%S')
- numbercall = job['numbercall']
+ if pool._init:
+ # retry in a few minutes
+ next_call = 600
+ else:
+ next_call = next_wait
+ cr = db.cursor()
+ now = DateTime.now()
+ try:
+ cr.execute('select * from ir_cron where numbercall<>0 and active and nextcall<=now() order by priority')
+ for job in cr.dictfetchall():
+ nextcall = DateTime.strptime(job['nextcall'], '%Y-%m-%d %H:%M:%S')
+ numbercall = job['numbercall']
- ok = False
- while nextcall 0:
- numbercall -= 1
- if not ok or job['doall']:
- self._callback(cr, job['user_id'], job['model'], job['function'], job['args'])
- if numbercall:
- nextcall += _intervalTypes[job['interval_type']](job['interval_number'])
- ok = True
- addsql=''
- if not numbercall:
- addsql = ', active=False'
- cr.execute("update ir_cron set nextcall=%s, numbercall=%s"+addsql+" where id=%s", (nextcall.strftime('%Y-%m-%d %H:%M:%S'), numbercall, job['id']))
- cr.commit()
- finally:
- cr.close()
+ ok = False
+ while nextcall < now and numbercall:
+ if numbercall > 0:
+ numbercall -= 1
+ if not ok or job['doall']:
+ self._callback(cr, job['user_id'], job['model'], job['function'], job['args'])
+ if numbercall:
+ nextcall += _intervalTypes[job['interval_type']](job['interval_number'])
+ ok = True
+ addsql=''
+ if not numbercall:
+ addsql = ', active=False'
+ cr.execute("update ir_cron set nextcall=%s, numbercall=%s"+addsql+" where id=%s", (nextcall.strftime('%Y-%m-%d %H:%M:%S'), numbercall, job['id']))
+ cr.commit()
+ finally:
+ cr.close()
+
#
- # Can be improved to do at the min(min(nextcalls), time()+next_wait)
+ # Can be improved to do at the min(min(nextcalls), time()+next_call)
# But is this an improvement ?
#
if not check:
- self.setAlarm(self._poolJobs, int(time.time())+next_wait, [db_name])
+ self.setAlarm(self._poolJobs, int(time.time()) + next_call, db_name, db_name)
ir_cron()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/bin/addons/base/ir/ir_model.py b/bin/addons/base/ir/ir_model.py
index 25507e2496e..958dd4845db 100644
--- a/bin/addons/base/ir/ir_model.py
+++ b/bin/addons/base/ir/ir_model.py
@@ -437,14 +437,16 @@ class ir_model_data(osv.osv):
if (not xml_id) and (not self.doinit):
return False
action_id = False
+
if xml_id:
cr.execute('select id,res_id from ir_model_data where module=%s and name=%s', (module,xml_id))
results = cr.fetchall()
for action_id2,res_id2 in results:
- cr.execute('select id from '+self.pool.get(model)._table+' where id=%s', (res_id2,))
+ cr.execute('select id from '+model_obj._table+' where id=%s', (res_id2,))
result3 = cr.fetchone()
if not result3:
cr.execute('delete from ir_model_data where id=%s', (action_id2,))
+ res_id = False
else:
res_id,action_id = res_id2,action_id2
@@ -512,7 +514,7 @@ class ir_model_data(osv.osv):
#self.pool.get(model).unlink(cr, uid, ids)
for id in ids:
self.unlink_mark[(model, id)]=False
- cr.execute('delete from ir_model_data where res_id=%s and model=\'%s\'', (id,model))
+ cr.execute('delete from ir_model_data where res_id=%s and model=%s', (id, model))
return True
def ir_set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=None, xml_id=False):
@@ -563,18 +565,20 @@ class ir_model_data(osv.osv):
cr.commit()
if not config.get('import_partial', False):
- for (model,id) in self.unlink_mark.keys():
+ logger = netsvc.Logger()
+ for (model, res_id) in self.unlink_mark.keys():
if self.pool.get(model):
- logger = netsvc.Logger()
- logger.notifyChannel('init', netsvc.LOG_INFO, 'Deleting %s@%s' % (id, model))
+ logger.notifyChannel('init', netsvc.LOG_INFO, 'Deleting %s@%s' % (res_id, model))
try:
- self.pool.get(model).unlink(cr, uid, [id])
- if self.unlink_mark[(model,id)]:
- self.unlink(cr, uid, [self.unlink_mark[(model,id)]])
- cr.execute('DELETE FROM ir_values WHERE value=%s', (model+','+str(id),))
+ self.pool.get(model).unlink(cr, uid, [res_id])
+ id = self.unlink_mark[(model, res_id)]
+ if id:
+ self.unlink(cr, uid, [id])
+ cr.execute('DELETE FROM ir_values WHERE value=%s', ('%s,%s' % (model, res_id),))
cr.commit()
except:
- logger.notifyChannel('init', netsvc.LOG_ERROR, 'Could not delete id: %d of model %s\tThere should be some relation that points to this resource\tYou should manually fix this and restart --update=module' % (id, model))
+ cr.rollback()
+ logger.notifyChannel('init', netsvc.LOG_ERROR, 'Could not delete id: %d of model %s\nThere should be some relation that points to this resource\nYou should manually fix this and restart --update=module' % (res_id, model))
return True
ir_model_data()
diff --git a/bin/addons/base/ir/ir_ui_view.py b/bin/addons/base/ir/ir_ui_view.py
index f80b865db1b..b1e15b34cf4 100644
--- a/bin/addons/base/ir/ir_ui_view.py
+++ b/bin/addons/base/ir/ir_ui_view.py
@@ -57,6 +57,7 @@ class view(osv.osv):
'type': fields.selection((
('tree','Tree'),
('form','Form'),
+ ('mdx','mdx'),
('graph', 'Graph'),
('calendar', 'Calendar'),
('gantt', 'Gantt')), 'View Type', required=True),
diff --git a/bin/addons/base/module/module.py b/bin/addons/base/module/module.py
index e5e764184c5..7867afa7b92 100644
--- a/bin/addons/base/module/module.py
+++ b/bin/addons/base/module/module.py
@@ -398,12 +398,12 @@ class module(osv.osv):
if not download:
continue
zipfile = urllib.urlopen(mod.url).read()
- fname = addons.get_module_path(mod.name+'.zip')
+ fname = addons.get_module_path(str(mod.name)+'.zip', downloaded=True)
try:
fp = file(fname, 'wb')
fp.write(zipfile)
fp.close()
- except IOError, e:
+ except Exception, e:
raise orm.except_orm(_('Error'), _('Can not create the module file:\n %s') % (fname,))
terp = self.get_module_info(mod.name)
self.write(cr, uid, mod.id, {
diff --git a/bin/addons/base/res/partner/partner.py b/bin/addons/base/res/partner/partner.py
index cfe1cb41710..97c2ed45ac3 100644
--- a/bin/addons/base/res/partner/partner.py
+++ b/bin/addons/base/res/partner/partner.py
@@ -163,10 +163,6 @@ class res_partner(osv.osv):
'customer': lambda *a: 1,
'category_id': _default_category,
}
- _sql_constraints = [
- ('name_uniq', 'unique (name)', 'The name of the partner must be unique !')
- ]
-
def copy(self, cr, uid, id, default=None, context={}):
name = self.read(cr, uid, [id], ['name'])[0]['name']
default.update({'name': name+' (copy)'})
diff --git a/bin/addons/base/res/partner/wizard/wizard_spam.py b/bin/addons/base/res/partner/wizard/wizard_spam.py
index 435bc2a9e94..aa10b08c73e 100644
--- a/bin/addons/base/res/partner/wizard/wizard_spam.py
+++ b/bin/addons/base/res/partner/wizard/wizard_spam.py
@@ -30,7 +30,7 @@ email_send_form = '''
-
+
'''
email_send_fields = {
diff --git a/bin/addons/base/rng/view.rng b/bin/addons/base/rng/view.rng
index 40db5265c92..beb1a2487a4 100644
--- a/bin/addons/base/rng/view.rng
+++ b/bin/addons/base/rng/view.rng
@@ -191,15 +191,7 @@
-
-
-
-
-
-
-
-
-
+
diff --git a/bin/import_xml.rng b/bin/import_xml.rng
index 3ad2f2feff0..0dc844b59df 100644
--- a/bin/import_xml.rng
+++ b/bin/import_xml.rng
@@ -141,6 +141,14 @@
+
+
+
+
+
+
+
+
@@ -194,6 +202,7 @@
+
diff --git a/bin/netsvc.py b/bin/netsvc.py
index 75246e981b8..1a806d53766 100644
--- a/bin/netsvc.py
+++ b/bin/netsvc.py
@@ -182,29 +182,33 @@ import tools
init_logger()
class Agent(object):
- _timers = []
+ _timers = {}
_logger = Logger()
- def setAlarm(self, fn, dt, args=None, kwargs=None):
- if not args:
- args = []
- if not kwargs:
- kwargs = {}
+ def setAlarm(self, fn, dt, db_name, *args, **kwargs):
wait = dt - time.time()
if wait > 0:
self._logger.notifyChannel('timers', LOG_DEBUG, "Job scheduled in %s seconds for %s.%s" % (wait, fn.im_class.__name__, fn.func_name))
timer = threading.Timer(wait, fn, args, kwargs)
timer.start()
- self._timers.append(timer)
- for timer in self._timers[:]:
- if not timer.isAlive():
- self._timers.remove(timer)
+ self._timers.setdefault(db_name, []).append(timer)
+ for db in self._timers:
+ for timer in self._timers[db]:
+ if not timer.isAlive():
+ self._timers[db].remove(timer)
+
+ @classmethod
+ def cancel(cls, db_name):
+ """Cancel all timers for a given database. If None passed, all timers are cancelled"""
+ for db in cls._timers:
+ if db_name is None or db == db_name:
+ for timer in cls._timers[db]:
+ timer.cancel()
+
+ @classmethod
def quit(cls):
- for timer in cls._timers:
- timer.cancel()
- quit = classmethod(quit)
-
+ cls.cancel(None)
import traceback
diff --git a/bin/osv/fields.py b/bin/osv/fields.py
index b44579957c4..bfd1adeef9e 100644
--- a/bin/osv/fields.py
+++ b/bin/osv/fields.py
@@ -308,11 +308,9 @@ class many2one(_column):
names = dict(obj.name_get(cr, user, filter(None, res.values()), context))
except except_orm:
names = {}
-
iids = filter(None, res.values())
- cr.execute('select id,'+obj._rec_name+' from '+obj._table+' where id in ('+','.join(map(str, iids))+')')
- for res22 in cr.fetchall():
- names[res22[0]] = res22[1]
+ for iiid in iids:
+ names[iiid] = '// Access Denied //'
for r in res.keys():
if res[r] and res[r] in names:
@@ -626,7 +624,7 @@ 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(lambda (x, y): (x, tools.human_size(len(y))), res.items()))
+ res = dict(map(lambda (x, y): (x, tools.human_size(len(y or ''))), res.items()))
return res
def set(self, cr, obj, id, name, value, user=None, context=None):
diff --git a/bin/osv/orm.py b/bin/osv/orm.py
index 6644142517c..719b4cdf857 100644
--- a/bin/osv/orm.py
+++ b/bin/osv/orm.py
@@ -61,7 +61,7 @@ except ImportError:
from tools.config import config
-regex_order = re.compile('^([a-zA-Z0-9_]+( desc)?( asc)?,?)+$', re.I)
+regex_order = re.compile('^([a-z0-9_]+( *desc| *asc)?( *, *|))+$', re.I)
def last_day_of_current_month():
import datetime
@@ -465,7 +465,7 @@ class orm_template(object):
datas += self.__export_row(cr, uid, row, fields, context)
return datas
- def import_data(self, cr, uid, fields, datas, mode='init', current_module=None, noupdate=False, context=None, filename=None):
+ def import_data(self, cr, uid, fields, datas, mode='init', current_module='', noupdate=False, context=None, filename=None):
if not context:
context = {}
fields = map(lambda x: x.split('/'), fields)
@@ -872,7 +872,7 @@ class orm_template(object):
rolesobj = self.pool.get('res.roles')
usersobj = self.pool.get('res.users')
- buttons = xpath.Evaluate("//button[@type != 'object']", node)
+ buttons = (n for n in node.getElementsByTagName('button') if n.getAttribute('type') != 'object')
for button in buttons:
ok = True
if user != 1: # admin user has all roles
@@ -1773,7 +1773,7 @@ class orm(orm_template):
import random
_rel1 = field['relation'].replace('.', '_')
_rel2 = field['model'].replace('.', '_')
- _rel_name = 'x_%s_%s_%s_rel' %(_rel1, _rel2, random.randint(0, 10000))
+ _rel_name = 'x_%s_%s_%s_rel' %(_rel1, _rel2, field['name'])
self._columns[field['name']] = getattr(fields, field['ttype'])(field['relation'], _rel_name, 'id1', 'id2', **attrs)
else:
self._columns[field['name']] = getattr(fields, field['ttype'])(**attrs)
@@ -2130,10 +2130,11 @@ class orm(orm_template):
for order, object, ids, fields in result_store:
if object<>self._name:
- cr.execute('select id from '+self._table+' where id in ('+','.join(map(str, ids))+')')
+ obj = self.pool.get(object)
+ cr.execute('select id from '+obj._table+' where id in ('+','.join(map(str, ids))+')')
ids = map(lambda x: x[0], cr.fetchall())
if ids:
- self.pool.get(object)._store_set_values(cr, uid, ids, fields, context)
+ obj._store_set_values(cr, uid, ids, fields, context)
return True
#
@@ -2285,60 +2286,42 @@ class orm(orm_template):
self.pool._init_parent[self._name]=True
else:
for id in ids:
+ # Find Position of the element
if vals[self._parent_name]:
cr.execute('select parent_left,parent_right,id from '+self._table+' where '+self._parent_name+'=%s order by '+(self._parent_order or self._order), (vals[self._parent_name],))
- pleft_old = pright_old = None
- result_p = cr.fetchall()
- for (pleft,pright,pid) in result_p:
- if pid == id:
- break
- pleft_old = pleft
- pright_old = pright
- if not pleft_old:
- cr.execute('select parent_left,parent_right from '+self._table+' where id=%s', (vals[self._parent_name],))
- pleft_old,pright_old = cr.fetchone()
- res = (pleft_old, pright_old)
else:
- cr.execute('SELECT parent_left,parent_right FROM '+self._table+' WHERE id IS NULL')
- res = cr.fetchone()
- if res:
- pleft,pright = res
- else:
- cr.execute('select max(parent_right),max(parent_right)+1 from '+self._table)
- pleft,pright = cr.fetchone()
- cr.execute('select parent_left,parent_right,id from '+self._table+' where id in ('+','.join(map(lambda x:'%s',ids))+')', ids)
- dest = pleft + 1
- for cleft,cright,cid in cr.fetchall():
- if cleft > pleft:
- treeshift = pleft - cleft + 1
- leftbound = pleft+1
- rightbound = cleft-1
- cwidth = cright-cleft+1
- leftrange = cright
- rightrange = pleft
+ cr.execute('select parent_left,parent_right,id from '+self._table+' where '+self._parent_name+' is null order by '+(self._parent_order or self._order))
+ result_p = cr.fetchall()
+ position = None
+ for (pleft,pright,pid) in result_p:
+ if pid == id:
+ break
+ position = pright+1
+
+ # It's the first node of the parent: position = parent_left+1
+ if not position:
+ if not vals[self._parent_name]:
+ position = 1
else:
- treeshift = pleft - cright
- leftbound = cright + 1
- rightbound = pleft
- cwidth = cleft-cright-1
- leftrange = pleft+1
- rightrange = cleft
- cr.execute('UPDATE '+self._table+'''
- SET
- parent_left = CASE
- WHEN parent_left BETWEEN %s AND %s THEN parent_left + %s
- WHEN parent_left BETWEEN %s AND %s THEN parent_left + %s
- ELSE parent_left
- END,
- parent_right = CASE
- WHEN parent_right BETWEEN %s AND %s THEN parent_right + %s
- WHEN parent_right BETWEEN %s AND %s THEN parent_right + %s
- ELSE parent_right
- END
- WHERE
- parent_left<%s OR parent_right>%s;
- ''', (leftbound,rightbound,cwidth,cleft,cright,treeshift,leftbound,rightbound,
- cwidth,cleft,cright,treeshift,leftrange,rightrange))
+ cr.execute('select parent_left from '+self._table+' where id=%s', (vals[self._parent_name],))
+ position = cr.fetchone()[0]+1
+
+ # We have the new position !
+ cr.execute('select parent_left,parent_right from '+self._table+' where id=%s', (id,))
+ pleft,pright = cr.fetchone()
+ distance = pright - pleft + 1
+
+ if position>pleft and position<=pright:
+ raise except_orm(_('UserError'), _('Recursivity Detected.'))
+
+ if pleft=%s', (distance, position))
+ cr.execute('update '+self._table+' set parent_right=parent_right+%s where parent_right>=%s', (distance, position))
+ cr.execute('update '+self._table+' set parent_left=parent_left+%s, parent_right=parent_right+%s where parent_left>=%s and parent_left<%s', (position-pleft,position-pleft, pleft, pright))
+ else:
+ cr.execute('update '+self._table+' set parent_left=parent_left+%s where parent_left>=%s', (distance, position))
+ cr.execute('update '+self._table+' set parent_right=parent_right+%s where parent_right>=%s', (distance, position))
+ cr.execute('update '+self._table+' set parent_left=parent_left-%s, parent_right=parent_right-%s where parent_left>=%s and parent_left<%s', (pleft-position+distance,pleft-position+distance, pleft+distance, pright+distance))
result = self._store_get_values(cr, user, ids, vals.keys(), context)
for order, object, ids, fields in result:
diff --git a/bin/pooler.py b/bin/pooler.py
index 0064e2397b6..32b45dbd170 100644
--- a/bin/pooler.py
+++ b/bin/pooler.py
@@ -57,6 +57,7 @@ def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False)
def restart_pool(db_name, force_demo=False, status=None, update_module=False):
if db_name in pool_dic:
+ pool_dic[db_name].get('ir.cron').cancel(db_name)
del pool_dic[db_name]
return get_db_and_pool(db_name, force_demo, status, update_module=update_module)
diff --git a/bin/report/render/rml2html/rml2html.py b/bin/report/render/rml2html/rml2html.py
index 5d005cc45a6..1033c64d454 100644
--- a/bin/report/render/rml2html/rml2html.py
+++ b/bin/report/render/rml2html/rml2html.py
@@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
-# OpenERP, Open Source Management Solution
+# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
# $Id$
#
@@ -94,7 +94,6 @@ class _flowable(object):
if node.hasAttribute('style'):
node.setAttribute('class', node.getAttribute('style'))
return node.toxml()
-
def render(self, node):
result = self.template.start()
result += self.template.frame_start()
@@ -107,8 +106,7 @@ class _flowable(object):
#print 'tag', n.localName, 'not yet implemented!'
result += self.template.frame_stop()
result += self.template.end()
- return result
-
+ return result.encode('utf-8').replace('"',"\'").replace('°','°')
class _rml_tmpl_tag(object):
def __init__(self, *args):
pass
@@ -126,7 +124,7 @@ class _rml_tmpl_frame(_rml_tmpl_tag):
self.width = width
self.posx = posx
def tag_start(self):
- return '