Merge commit 'origin/master' into mdv-gpl3-py26

Conflicts:
	bin/addons/__init__.py
	bin/addons/base/ir/ir_cron.py
	bin/addons/base/rng/view.rng

bzr revid: p_christ@hol.gr-20090304073610-2ss5ju4lyyue79qv
bzr revid: p_christ@hol.gr-20090308214750-0bgr6yj85f8ixpjp
bzr revid: p_christ@hol.gr-20090312075024-1rqeqam5ipfofb9m
This commit is contained in:
P. Christeas 2009-03-12 09:50:24 +02:00
commit 7cb394f380
26 changed files with 447 additions and 288 deletions

View File

@ -1,3 +1,5 @@
./bin/addons/*
./bin/filestore*
*.pyc
.*.swp
.bzrignore
bin/addons/*
bin/filestore*

View File

@ -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,6 +68,26 @@ 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
@ -80,9 +99,7 @@ class Graph(dict):
yield module
level += 1
class Singleton(object):
def __new__(cls, name, graph):
if name in graph:
inst = graph[name]
@ -97,57 +114,53 @@ 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 __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
@ -334,6 +347,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)))
@ -552,24 +567,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
@ -596,14 +593,16 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
idref = {}
status['progress'] = (float(statusi)+0.4) / len(graph)
mode = 'update'
if hasattr(package, 'init') or package.state == 'to install':
mode = 'init'
if hasattr(package, 'init') or hasattr(package, 'update') or package.state in ('to install', 'to upgrade'):
has_updates = True
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))
@ -648,9 +647,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():
@ -750,7 +747,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
@ -774,4 +771,3 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -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)
);

View File

@ -2748,7 +2748,6 @@
<field name="code">COP</field>
<field name="rounding">0.01</field>
<field name="accuracy">4</field>
<field eval="False" name="active"/>
</record>
<record id="CZK" model="res.currency">
@ -2756,7 +2755,6 @@
<field name="code">CZK</field>
<field name="rounding">0.01</field>
<field name="accuracy">4</field>
<field eval="False" name="active"/>
</record>
<record id="DKK" model="res.currency">
@ -2777,7 +2775,6 @@
<field name="code">HUF</field>
<field name="rounding">0.01</field>
<field name="accuracy">4</field>
<field eval="False" name="active"/>
</record>
<record id="IDR" model="res.currency">
@ -2785,7 +2782,6 @@
<field name="code">IDR</field>
<field name="rounding">0.01</field>
<field name="accuracy">4</field>
<field eval="False" name="active"/>
</record>
<record id="LVL" model="res.currency">
@ -2832,7 +2828,6 @@
<field name="code">PLN</field>
<field name="rounding">0.01</field>
<field name="accuracy">4</field>
<field eval="False" name="active"/>
</record>
<record id="SEK" model="res.currency">
@ -2840,7 +2835,6 @@
<field name="code">SEK</field>
<field name="rounding">0.01</field>
<field name="accuracy">4</field>
<field eval="False" name="active"/>
</record>
<record id="GBP" model="res.currency">
@ -2860,9 +2854,20 @@
<field name="code">ARS</field>
<field name="rounding">0.01</field>
<field name="accuracy">4</field>
<field eval="False" name="active"/>
</record>
<record id="INR" model="res.currency">
<field name="name">INR</field>
<field name="code">Rs</field>
<field name="rounding">0.01</field>
<field name="accuracy">4</field>
</record>
<record id="rateINR" model="res.currency.rate">
<field name="rate">0.634</field>
<field name="currency_id" ref="INR"/>
<field eval="time.strftime('%Y-01-01')" name="name"/>
</record>
<!-- Basic Company -->
<record id="main_company" model="res.company">
<field name="name">Tiny sprl</field>

View File

@ -1234,8 +1234,8 @@
</page>
<page string="SMS Configuration" attrs="{'invisible':[('state','!=','sms')]}">
<separator colspan="4" string="SMS Configuration"/>
<field name="mobile" domain="[('model_id','=',model_id)]" attrs="{'required':[('state','=','email')]}"/>
<field name="sms" colspan="4" attrs="{'required':[('state','=','email')]}"/>
<field name="mobile" domain="[('model_id','=',model_id)]" attrs="{'required':[('state','=','sms')]}"/>
<field name="sms" colspan="4" attrs="{'required':[('state','=','sms')]}"/>
<newline/>
<label colspan="4" string="Access all the fields related to the current object using expression in double brackets, i.e. [[ object.partner_id.name ]]" align="0.0"/>
</page>

View File

@ -77,47 +77,47 @@ 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<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()
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()
except:
print "Exception!"
finally:
cr.close()
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)
return None
ir_cron()

View File

@ -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()

View File

@ -105,18 +105,17 @@ class ir_rule(osv.osv):
def _domain_force_get(self, cr, uid, ids, field_name, arg, context={}):
res = {}
for rule in self.browse(cr, uid, ids, context):
eval_user_data = {'user': self.pool.get('res.users').browse(cr, 1, uid),
'time':time}
if rule.domain_force:
res[rule.id] = eval(rule.domain_force, {'user': self.pool.get('res.users').browse(cr, 1, uid),
'time':time})
res[rule.id] = eval(rule.domain_force, eval_user_data)
else:
if rule.operator in ('in', 'child_of'):
dom = eval("[('%s', '%s', [%s])]" % (rule.field_id.name, rule.operator,
rule.operand), {'user': self.pool.get('res.users').browse(cr, 1, uid),
'time':time})
eval(rule.operand,eval_user_data)), eval_user_data)
else:
dom = eval("[('%s', '%s', %s)]" % (rule.field_id.name, rule.operator,
rule.operand), {'user': self.pool.get('res.users').browse(cr, 1, uid),
'time':time})
rule.operand), eval_user_data)
res[rule.id] = dom
return res

View File

@ -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),

View File

@ -21,6 +21,7 @@
##############################################################################
from osv import osv,fields
from osv.orm import except_orm
import pickle
from tools.translate import _
@ -225,7 +226,10 @@ class ir_values(osv.osv):
del fields[pos]
else:
pos+=1
datas = self.pool.get(model).read(cr, uid, [id], fields, context)
try:
datas = self.pool.get(model).read(cr, uid, [id], fields, context)
except except_orm:
return False
datas= datas and datas[0] or None
if not datas:
#ir_del(cr, uid, x[0])

View File

@ -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, {

View File

@ -0,0 +1,96 @@
<?xml version = '1.0' encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:variable name="signature" select="//corporate-header/user/signature"/>
<xsl:variable name="title">Open ERP Report</xsl:variable>
<xsl:variable name="leftMargin">1cm</xsl:variable>
<xsl:variable name="rightMargin">1cm</xsl:variable>
<xsl:variable name="topMargin">1cm</xsl:variable>
<xsl:variable name="bottomMargin">1cm</xsl:variable>
<xsl:variable name="pageSize">21cm,29.7cm</xsl:variable>
<xsl:variable name="page_format">a4_letter</xsl:variable>
<xsl:template name="first_page_graphics_corporation">
<!--logo-->
<setFont name="Helvetica" size="14"/>
<fill color="black"/>
<stroke color="black"/>
<drawString x="1cm" y="27.6cm"><xsl:value-of select="//corporate-header/corporation/name"/></drawString>
<lines>1cm 25.4cm 20cm 25.4cm</lines>
<!-- <lines>1cm 25.7cm 7cm 25.7cm</lines>-->
<setFont name="Helvetica" size="10"/>
<drawRightString x="1cm" y="27.5cm"><xsl:value-of select="//corporate-header/corporation/rml_header1"/></drawRightString>
<drawString x="1cm" y="27cm"><xsl:value-of select="//corporate-header/corporation/address/street"/></drawString>
<drawString x="1cm" y="26.5cm">
<xsl:value-of select="//corporate-header/corporation/address/zip"/>
<xsl:text> </xsl:text>
<xsl:value-of select="//corporate-header/corporation/address/city"/>
<xsl:text> - </xsl:text>
<xsl:value-of select="//corporate-header/corporation/address/country"/>
</drawString>
<drawString x="1cm" y="26cm">Phone:</drawString>
<drawRightString x="7cm" y="26cm"><xsl:value-of select="//corporate-header/corporation/address/phone"/></drawRightString>
<drawString x="1cm" y="25.5cm">Mail:</drawString>
<drawRightString x="7cm" y="25.5cm"><xsl:value-of select="//corporate-header/corporation/address/email"/></drawRightString>
<!--page bottom-->
<lines>1.5cm 1.2cm 19.9cm 1.2cm</lines>
<drawCentredString x="10.5cm" y="1.7cm"><xsl:value-of select="//corporate-header/corporation/rml_footer1"/></drawCentredString>
<drawCentredString x="10.5cm" y="1.25cm"><xsl:value-of select="//corporate-header/corporation/rml_footer2"/></drawCentredString>
<drawCentredString x="10.5cm" y="0.8cm">Your contact : <xsl:value-of select="//corporate-header/user/name"/></drawCentredString>
</xsl:template>
<xsl:template name="other_pages_graphics_corporation">
<!--logo-->
<setFont name="Helvetica" size="14"/>
<fill color="black"/>
<stroke color="black"/>
<drawString x="1cm" y="27.6cm"><xsl:value-of select="//corporate-header/corporation/name"/></drawString>
<lines>1cm 25.4cm 20cm 25.4cm</lines>
<!-- <lines>1cm 25.7cm 7cm 25.7cm</lines>-->
<setFont name="Helvetica" size="10"/>
<drawRightString x="1cm" y="27.5cm"><xsl:value-of select="//corporate-header/corporation/rml_header1"/></drawRightString>
<drawString x="1cm" y="27cm"><xsl:value-of select="//corporate-header/corporation/address/street"/></drawString>
<drawString x="1cm" y="26.5cm">
<xsl:value-of select="//corporate-header/corporation/address/zip"/>
<xsl:text> </xsl:text>
<xsl:value-of select="//corporate-header/corporation/address/city"/>
<xsl:text> - </xsl:text>
<xsl:value-of select="//corporate-header/corporation/address/country"/>
</drawString>
<drawString x="1cm" y="26cm">Phone:</drawString>
<drawRightString x="7cm" y="26cm"><xsl:value-of select="//corporate-header/corporation/address/phone"/></drawRightString>
<drawString x="1cm" y="25.5cm">Mail:</drawString>
<drawRightString x="7cm" y="25.5cm"><xsl:value-of select="//corporate-header/corporation/address/email"/></drawRightString>
<!--page bottom-->
<lines>1.5cm 1.2cm 19.9cm 1.2cm</lines>
<drawCentredString x="10.5cm" y="1.7cm"><xsl:value-of select="//corporate-header/corporation/rml_footer1"/></drawCentredString>
<drawCentredString x="10.5cm" y="1.25cm"><xsl:value-of select="//corporate-header/corporation/rml_footer2"/></drawCentredString>
<!-- <drawCentredString x="10.5cm" y="0.8cm">Your contact : <xsl:value-of select="//corporate-header/user/name"/></drawCentredString>-->
</xsl:template>
<xsl:template name="first_page_frames">
<xsl:if test="$page_format='a4_normal'">
<frame id="main" x1="1cm" y1="2.5cm" width="19.0cm" height="22.0cm"/>
</xsl:if>
<xsl:if test="$page_format='a4_letter'">
<frame id="address" x1="11cm" y1="21.5cm" width="6cm" height="4cm"/>
<frame id="main" x1="1cm" y1="2.5cm" width="19.0cm" height="17.5cm"/>
</xsl:if>
</xsl:template>
<xsl:template name="other_pages_frames">
<frame id="main" x1="1cm" y1="2.5cm" width="19.0cm" height="22cm"/>
</xsl:template>
</xsl:stylesheet>

View File

@ -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)'})

View File

@ -30,7 +30,7 @@ email_send_form = '''<?xml version="1.0"?>
<newline/>
<field name="subject"/>
<newline/>
<field name="text"/>
<field name="text" widget="text_html"/>
</form>'''
email_send_fields = {

View File

@ -191,15 +191,7 @@
<rng:optional><rng:attribute name="position"/></rng:optional>
<rng:zeroOrMore>
<rng:choice>
<rng:ref name="notebook" />
<rng:ref name="graph" />
<rng:ref name="calendar" />
<rng:ref name="gantt" />
<rng:ref name="form"/>
<rng:ref name="tree"/>
<rng:ref name="field"/>
<rng:ref name="separator"/>
<rng:ref name="page"/>
<rng:ref name="any"/>
<rng:ref name="button"/>
</rng:choice>
</rng:zeroOrMore>

View File

@ -143,6 +143,14 @@
</rng:element>
</rng:define>
<rng:define name="delete">
<rng:element name="delete">
<rng:attribute name="model" />
<rng:optional><rng:attribute name="id" /> </rng:optional>
<rng:optional><rng:attribute name="search" /></rng:optional>
</rng:element>
</rng:define>
<rng:define name="ir_set">
<rng:element name="ir_set">
<rng:oneOrMore>
@ -196,6 +204,7 @@
<rng:text/>
<rng:ref name="menuitem" />
<rng:ref name="record" />
<rng:ref name="delete" />
<rng:ref name="wizard" />
<rng:ref name="act_window" />
<rng:ref name="assert" />

View File

@ -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

View File

@ -72,7 +72,7 @@ class expression(object):
if not self.__exp:
return self
def _rec_get(ids, table, parent, left='id', prefix=''):
def _rec_get(ids, table, parent=None, left='id', prefix=''):
if table._parent_store and (not table.pool._init):
# TODO: Improve where joins are implemented for many with '.', replace by:
# doms += ['&',(prefix+'.parent_left','<',o.parent_right),(prefix+'.parent_left','>=',o.parent_left)]
@ -90,7 +90,7 @@ class expression(object):
return []
ids2 = table.search(cr, uid, [(parent, 'in', ids)], context=context)
return ids + rg(ids2, table, parent)
return [(left, 'in', rg(ids, table, parent))]
return [(left, 'in', rg(ids, table, parent or table._parent_name))]
self.__main_table = table
@ -114,7 +114,7 @@ class expression(object):
field = working_table._columns.get(fargs[0], False)
if not field:
if left == 'id' and operator == 'child_of':
dom = _rec_get(right, working_table, working_table._parent_name)
dom = _rec_get(right, working_table)
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
continue
@ -167,7 +167,7 @@ class expression(object):
return ids
return self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, ids)
dom = _rec_get(ids2, field_obj, working_table._parent_name)
dom = _rec_get(ids2, field_obj)
ids2 = field_obj.search(cr, uid, dom, context=context)
self.__exp[i] = ('id', 'in', _rec_convert(ids2))
else:
@ -185,9 +185,9 @@ class expression(object):
self.__operator = 'in'
if field._obj != working_table._name:
dom = _rec_get(ids2, field_obj, working_table._parent_name, left=left, prefix=field._obj)
dom = _rec_get(ids2, field_obj, left=left, prefix=field._obj)
else:
dom = _rec_get(ids2, working_table, left)
dom = _rec_get(ids2, working_table, parent=left)
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
else:
if isinstance(right, basestring): # and not isinstance(field, fields.related):

View File

@ -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):

View File

@ -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
@ -101,7 +101,7 @@ class browse_null(object):
def __nonzero__(self):
return False
def __unicode__(self):
return u''
@ -323,7 +323,7 @@ class orm_template(object):
_inherits = {}
_table = None
_invalids = set()
CONCURRENCY_CHECK_FIELD = '__last_update'
def _field_create(self, cr, context={}):
@ -474,7 +474,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)
@ -735,7 +735,7 @@ class orm_template(object):
model_access_obj = self.pool.get('ir.model.access')
for parent in self._inherits:
res.update(self.pool.get(parent).fields_get(cr, user, fields, context))
if self._columns.keys():
for f in self._columns.keys():
if fields and f not in fields:
@ -752,14 +752,14 @@ class orm_template(object):
if hasattr(self._columns[f], arg) \
and getattr(self._columns[f], arg):
res[f][arg] = getattr(self._columns[f], arg)
res_trans = translation_obj._get_source(cr, user, self._name + ',' + f, 'field', context.get('lang', False) or 'en_US')
if res_trans:
res[f]['string'] = res_trans
help_trans = translation_obj._get_source(cr, user, self._name + ',' + f, 'help', context.get('lang', False) or 'en_US')
if help_trans:
res[f]['help'] = help_trans
if hasattr(self._columns[f], 'selection'):
if isinstance(self._columns[f].selection, (tuple, list)):
sel = self._columns[f].selection
@ -781,9 +781,9 @@ class orm_template(object):
res[f]['domain'] = self._columns[f]._domain
res[f]['context'] = self._columns[f]._context
else:
#TODO : read the fields from the database
#TODO : read the fields from the database
pass
if fields:
# filter out fields which aren't in the fields list
for r in res.keys():
@ -883,7 +883,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
@ -953,11 +953,11 @@ class orm_template(object):
def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False):
if not context:
context = {}
def encode(s):
if isinstance(s, unicode):
return s.encode('utf8')
return s
return s
def _inherit_apply(src, inherit):
def _find(node, node2):
@ -981,7 +981,7 @@ class orm_template(object):
if res:
return res
return None
doc_src = dom.minidom.parseString(encode(src))
doc_dest = dom.minidom.parseString(encode(inherit))
@ -1390,7 +1390,7 @@ class orm_memory(orm_template):
'id': id
})
return result
def _check_removed_columns(self, cr, log=False):
# nothing to check in memory...
pass
@ -1458,7 +1458,7 @@ class orm(orm_template):
" AND c.oid=a.attrelid"
" AND a.attisdropped=%%s"
" AND pg_catalog.format_type(a.atttypid, a.atttypmod) NOT IN ('cid', 'tid', 'oid', 'xid')"
" AND a.attname NOT IN (%s)" % ",".join(['%s']*len(columns)),
" AND a.attname NOT IN (%s)" % ",".join(['%s']*len(columns)),
[self._table, False] + columns)
for column in cr.dictfetchall():
if log:
@ -1511,7 +1511,7 @@ class orm(orm_template):
if not cr.rowcount:
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, logs[k]))
cr.commit()
self._check_removed_columns(cr, log=False)
# iterate on the "object columns"
@ -1665,20 +1665,20 @@ class orm(orm_template):
if isinstance(f, fields.many2one):
ref = self.pool.get(f._obj)._table
if ref != 'ir_actions':
cr.execute('SELECT confdeltype, conname FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, '
'pg_attribute as att1, pg_attribute as att2 '
'WHERE con.conrelid = cl1.oid '
'AND cl1.relname = %s '
'AND con.confrelid = cl2.oid '
'AND cl2.relname = %s '
'AND array_lower(con.conkey, 1) = 1 '
'AND con.conkey[1] = att1.attnum '
'AND att1.attrelid = cl1.oid '
'AND att1.attname = %s '
'AND array_lower(con.confkey, 1) = 1 '
'AND con.confkey[1] = att2.attnum '
'AND att2.attrelid = cl2.oid '
'AND att2.attname = %s '
cr.execute('SELECT confdeltype, conname FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, '
'pg_attribute as att1, pg_attribute as att2 '
'WHERE con.conrelid = cl1.oid '
'AND cl1.relname = %s '
'AND con.confrelid = cl2.oid '
'AND cl2.relname = %s '
'AND array_lower(con.conkey, 1) = 1 '
'AND con.conkey[1] = att1.attnum '
'AND att1.attrelid = cl1.oid '
'AND att1.attname = %s '
'AND array_lower(con.confkey, 1) = 1 '
'AND con.confkey[1] = att2.attnum '
'AND att2.attrelid = cl2.oid '
'AND att2.attname = %s '
"AND con.contype = 'f'", (self._table, ref, k, 'id'))
res = cr.dictfetchall()
if res:
@ -1725,7 +1725,7 @@ class orm(orm_template):
def __init__(self, cr):
super(orm, self).__init__(cr)
if not hasattr(self, '_log_access'):
# if not access is not specify, it is the same value as _auto
self._log_access = not hasattr(self, "_auto") or self._auto
@ -1790,7 +1790,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)
@ -1925,7 +1925,7 @@ class orm(orm_template):
# 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
f == self.CONCURRENCY_CHECK_FIELD
f == self.CONCURRENCY_CHECK_FIELD
or (f in self._columns and getattr(self._columns[f], '_classic_write'))
] + self._inherits.values()
@ -2092,8 +2092,8 @@ class orm(orm_template):
return "%s,%s" % (self._name, oid)
santa = "(id = %s AND %s < COALESCE(write_date, create_date, now())::timestamp)"
for i in range(0, len(ids), cr.IN_MAX):
sub_ids = tools.flatten(((oid, context[self.CONCURRENCY_CHECK_FIELD][key(oid)])
for oid in ids[i:i+cr.IN_MAX]
sub_ids = tools.flatten(((oid, context[self.CONCURRENCY_CHECK_FIELD][key(oid)])
for oid in ids[i:i+cr.IN_MAX]
if key(oid) in context[self.CONCURRENCY_CHECK_FIELD]))
if sub_ids:
cr.execute("SELECT count(1) FROM %s WHERE %s" % (self._table, " OR ".join([santa]*(len(sub_ids)/2))), sub_ids)
@ -2108,7 +2108,7 @@ class orm(orm_template):
ids = [ids]
result_store = self._store_get_values(cr, uid, ids, None, context)
self._check_concurrency(cr, ids, context)
self.pool.get('ir.model.access').check(cr, uid, self._name, 'unlink')
@ -2147,10 +2147,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
#
@ -2302,60 +2303,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<position:
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', (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:
@ -2418,12 +2401,12 @@ class orm(orm_template):
# Try-except added to filter the creation of those records whose filds are readonly.
# Example : any dashboard which has all the fields readonly.(due to Views(database views))
try:
try:
cr.execute("SELECT nextval('"+self._sequence+"')")
except:
raise except_orm(_('UserError'),
_('You cannot perform this operation.'))
_('You cannot perform this operation.'))
id_new = cr.fetchone()[0]
for table in tocreate:
id = self.pool.get(table).create(cr, user, tocreate[table])
@ -2508,15 +2491,20 @@ class orm(orm_template):
for id in filter(None, ids2):
result[fncts[fnct][0]].setdefault(id, [])
result[fncts[fnct][0]][id].append(fnct)
result2 = []
dict = {}
for object in result:
k2 = {}
for id,fnct in result[object].items():
k2.setdefault(tuple(fnct), [])
k2[tuple(fnct)].append(id)
for fnct,id in k2.items():
result2.append((fncts[fnct[0]][4],object,id,map(lambda x: fncts[x][1], fnct)))
result2.sort()
dict.setdefault(fncts[fnct[0]][4],[])
dict[fncts[fnct[0]][4]].append((fncts[fnct[0]][4],object,id,map(lambda x: fncts[x][1], fnct)))
result2 = []
tmp = dict.keys()
tmp.sort()
for k in tmp:
result2+=dict[k]
return result2
def _store_set_values(self, cr, uid, ids, fields, context):
@ -2737,6 +2725,7 @@ class orm(orm_template):
return data, trans_data
def copy(self, cr, uid, id, default=None, context=None):
trans_obj = self.pool.get('ir.translation')
data, trans_data = self.copy_data(cr, uid, id, default, context)
new_id=self.create(cr, uid, data)
for record in trans_data:

View File

@ -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)

View File

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
@ -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('°','&deg;')
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 '<table border="0" width="%d"><tr><td width="%d">&nbsp;</td><td>' % (self.width+self.posx,self.posx)
return "<table border=\'0\' width=\'%d\'><tr><td width=\'%d\'>&nbsp;</td><td>" % (self.width+self.posx,self.posx)
def tag_end(self):
return True
def tag_stop(self):
@ -152,19 +150,19 @@ class _rml_tmpl_draw_string(_rml_tmpl_tag):
def tag_start(self):
self.pos.sort()
res = '<table border="0" cellpadding="0" cellspacing="0"><tr>'
res = "<table border='0' cellpadding='0' cellspacing='0'><tr>"
posx = 0
i = 0
for (x,y,align,txt, style, fs) in self.pos:
if align=="left":
pos2 = len(txt)*fs
res+='<td width="%d"></td><td style="%s" width="%d">%s</td>' % (x - posx, style, pos2, txt)
res+="<td width=\'%d\'></td><td style=\'%s\' width=\'%d\'>%s</td>" % (x - posx, style, pos2, txt)
posx = x+pos2
if align=="right":
res+='<td width="%d" align="right" style="%s">%s</td>' % (x - posx, style, txt)
res+="<td width=\'%d\' align=\'right\' style=\'%s\'>%s</td>" % (x - posx, style, txt)
posx = x
if align=="center":
res+='<td width="%d" align="center" style="%s">%s</td>' % ((x - posx)*2, style, txt)
res+="<td width=\'%d\' align=\'center\' style=\'%s\'>%s</td>" % ((x - posx)*2, style, txt)
posx = 2*x-posx
i+=1
res+='</tr></table>'
@ -185,7 +183,7 @@ class _rml_tmpl_draw_lines(_rml_tmpl_tag):
def tag_start(self):
if self.ok:
return '<table border="0" cellpadding="0" cellspacing="0" width="%d"><tr><td width="%d"></td><td><hr width="100%%" style="margin:0px; %s"></td></tr></table>' % (self.posx+self.width,self.posx,self.style)
return "<table border=\'0\' cellpadding=\'0\' cellspacing=\'0\' width=\'%d\'><tr><td width=\'%d\'></td><td><hr width=\'100%%\' style=\'margin:0px; %s\'></td></tr></table>" % (self.posx+self.width,self.posx,self.style)
else:
return ''
@ -207,9 +205,9 @@ class _rml_stylesheet(object):
attrs = []
for a in attr:
if a in self._tags:
attrs.append("%s:%s" % self._tags[a](attr[a]))
attrs.append('%s:%s' % self._tags[a](attr[a]))
if len(attrs):
result += "p."+attr['name']+" {"+'; '.join(attrs)+"}\n"
result += 'p.'+attr['name']+' {'+'; '.join(attrs)+'}\n'
self.result = result
def render(self):
@ -338,6 +336,7 @@ class _rml_doc(object):
self.result += '''<!DOCTYPE HTML PUBLIC "-//w3c//DTD HTML 4.0 Frameset//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
p {margin:0px; font-size:12px;}
td {font-size:14px;}
@ -347,14 +346,50 @@ class _rml_doc(object):
self.result += s.render()
self.result+='''
</style>
</head>
<body>'''
'''
template = _rml_template(self.dom.documentElement.getElementsByTagName('template')[0])
f = _flowable(template, self.dom)
self.result += f.render(self.dom.documentElement.getElementsByTagName('story')[0])
# f = _flowable(template, self.dom)
list_story =[]
storys= self.dom.documentElement.getElementsByTagName('story')
for story in storys :
template = _rml_template(self.dom.documentElement.getElementsByTagName('template')[0])
f = _flowable(template, self.dom)
story_text = f.render(story)
list_story.append(story_text)
del f
self.result += '</body></html>'
self.result +='''
<script type="text/javascript">
var indexer = 0;
var aryTest = %s ;
function nextData()
{
if(indexer < aryTest.length -1)
{
indexer += 1;
document.getElementById("tiny_data").innerHTML=aryTest[indexer];
}
}
function prevData()
{
if (indexer > 0)
{
indexer -= 1;
document.getElementById("tiny_data").innerHTML=aryTest[indexer];
}
}
</script>
</head>
<body>
<div id="tiny_data">
%s
</div>
<br>
<input type="button" value="next" onclick="nextData();">
<input type="button" value="prev" onclick="prevData();">
</body></html>'''%(list_story,list_story[0])
out.write( self.result)
def parseString(data, fout=None):
@ -383,5 +418,4 @@ if __name__=="__main__":
print 'Usage: trml2pdf input.rml >output.pdf'
print 'Try \'trml2pdf --help\' for more information.'
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -519,8 +519,8 @@ class rml_parse(object):
if not self.logo and rml_head.find('company.logo')>=0:
rml_head = rml_head.replace('<image','<!--image')
rml_head = rml_head.replace('</image>','</image-->')
head_dom = xml.dom.minidom.parseString(rml_head)
head_dom = xml.dom.minidom.parseString(rml_head.encode('utf-8'))
#for frame in head_dom.getElementsByTagName('frame'):
# frame.parentNode.removeChild(frame)
node2 = head_dom.documentElement

View File

@ -40,11 +40,10 @@ def check_super(passwd):
return True
else:
raise Exception('AccessDenied')
def check(db, uid, passwd):
if _uid_cache.get(db, {}).get(uid) == passwd:
return True
cr = pooler.get_db(db).cursor()
cr.execute('select count(*) from res_users where id=%s and password=%s', (int(uid), passwd))
res = cr.fetchone()[0]

View File

@ -82,7 +82,7 @@ class configmanager(object):
hasSSL = check_ssl()
loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x))
self._LOGLEVELS = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x))
for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC', 'NOTSET')])
version = "%s %s" % (release.description, release.version)
@ -111,8 +111,8 @@ class configmanager(object):
parser.add_option("--stop-after-init", action="store_true", dest="stop_after_init", default=False,
help="stop the server after it initializes")
parser.add_option('--debug', dest='debug_mode', action='store_true', default=False, help='enable debug mode')
parser.add_option("--assert-exit-level", dest='assert_exit_level', type="choice", choices=loglevels.keys(),
help="specify the level at which a failed assertion will stop the server. Accepted values: %s" % (loglevels.keys(),))
parser.add_option("--assert-exit-level", dest='assert_exit_level', type="choice", choices=self._LOGLEVELS.keys(),
help="specify the level at which a failed assertion will stop the server. Accepted values: %s" % (self._LOGLEVELS.keys(),))
if hasSSL:
group = optparse.OptionGroup(parser, "SSL Configuration")
group.add_option("-S", "--secure", dest="secure", action="store_true",
@ -130,8 +130,8 @@ class configmanager(object):
group.add_option("--logfile", dest="logfile", help="file where the server log will be stored")
group.add_option("--syslog", action="store_true", dest="syslog",
default=False, help="Send the log to the syslog server")
group.add_option('--log-level', dest='log_level', type='choice', choices=loglevels.keys(),
help='specify the level of the logging. Accepted values: ' + str(loglevels.keys()))
group.add_option('--log-level', dest='log_level', type='choice', choices=self._LOGLEVELS.keys(),
help='specify the level of the logging. Accepted values: ' + str(self._LOGLEVELS.keys()))
parser.add_option_group(group)
# SMTP Group
@ -235,10 +235,14 @@ class configmanager(object):
self.options[arg] = getattr(opt, arg)
if opt.assert_exit_level:
self.options['assert_exit_level'] = loglevels[opt.assert_exit_level]
self.options['assert_exit_level'] = self._LOGLEVELS[opt.assert_exit_level]
else:
self.options['assert_exit_level'] = self._LOGLEVELS.get(self.options['assert_exit_level']) or int(self.options['assert_exit_level'])
if opt.log_level:
self.options['log_level'] = loglevels[opt.log_level]
self.options['log_level'] = self._LOGLEVELS[opt.log_level]
else:
self.options['log_level'] = self._LOGLEVELS.get(self.options['log_level']) or int(self.options['log_level'])
if not self.options['root_path'] or self.options['root_path']=='None':
self.options['root_path'] = os.path.abspath(os.path.dirname(sys.argv[0]))
@ -335,9 +339,15 @@ class configmanager(object):
def save(self):
p = ConfigParser.ConfigParser()
loglevelnames = dict(zip(self._LOGLEVELS.values(), self._LOGLEVELS.keys()))
p.add_section('options')
for o in [opt for opt in self.options.keys() if opt not in ('version','language','translate_out','translate_in','init','update')]:
p.set('options', o, self.options[o])
for opt in self.options.keys():
if opt in ('version', 'language', 'translate_out', 'translate_in', 'init', 'update'):
continue
if opt in ('log_level', 'assert_exit_level'):
p.set('options', opt, loglevelnames.get(self.options[opt], self.options[opt]))
else:
p.set('options', opt, self.options[opt])
# try to create the directories and write the file
try:
@ -345,6 +355,7 @@ class configmanager(object):
os.makedirs(os.path.dirname(self.rcfile))
try:
p.write(file(self.rcfile, 'w'))
os.chmod(self.rcfile, 0600)
except IOError:
sys.stderr.write("ERROR: couldn't write the config file\n")

View File

@ -302,7 +302,8 @@ def reverse_enumerate(l):
#----------------------------------------------------------
# Emails
#----------------------------------------------------------
def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False, attach=None, tinycrm=False, ssl=False, debug=False, subtype='plain'):
def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False,
attach=None, tinycrm=False, ssl=False, debug=False, subtype='plain', x_headers=None):
"""Send an email."""
import smtplib
from email.MIMEText import MIMEText
@ -313,9 +314,15 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
from email.Utils import formatdate, COMMASPACE
from email import Encoders
if x_headers is None:
x_headers = {}
if not ssl:
ssl = config.get('smtp_ssl', False)
if not email_from and not config['email_from']:
raise Exception("No Email sender by default, see config file")
if not email_cc:
email_cc = []
if not email_bcc:
@ -326,11 +333,13 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
else:
msg = MIMEMultipart()
msg['Subject'] = Header(subject.decode('utf8'), 'utf-8')
msg['Subject'] = Header(ustr(subject), 'utf-8')
msg['From'] = email_from
del msg['Reply-To']
if reply_to:
msg['Reply-To'] = msg['From']+', '+reply_to
msg['Reply-To'] = reply_to
else:
msg['Reply-To'] = msg['From']
msg['To'] = COMMASPACE.join(email_to)
if email_cc:
msg['Cc'] = COMMASPACE.join(email_cc)
@ -338,6 +347,15 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
msg['Bcc'] = COMMASPACE.join(email_bcc)
msg['Date'] = formatdate(localtime=True)
# Add OpenERP Server information
msg['X-Generated-By'] = 'OpenERP (http://www.openerp.com)'
msg['X-OpenERP-Server-Host'] = socket.gethostname()
msg['X-OpenERP-Server-Version'] = release.version
# Add dynamic X Header
for key, value in x_headers.items():
msg['X-OpenERP-%s' % key] = str(value)
if tinycrm:
msg['Message-Id'] = "<%s-tinycrm-%s@%s>" % (time.time(), tinycrm, socket.gethostname())
@ -381,9 +399,10 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
# text must be latin-1 encoded
def sms_send(user, password, api_id, text, to):
import urllib
params = urllib.urlencode({'user': user, 'password': password, 'api_id': api_id, 'text': text, 'to':to})
#f = urllib.urlopen("http://api.clickatell.com/http/sendmsg", params)
f = urllib.urlopen("http://196.7.150.220/http/sendmsg", params)
url = "http://api.urlsms.com/SendSMS.aspx"
#url = "http://196.7.150.220/http/sendmsg"
params = urllib.urlencode({'UserID': user, 'Password': password, 'SenderID': api_id, 'MsgText': text, 'RecipientMobileNo':to})
f = urllib.urlopen(url+"?"+params)
# FIXME: Use the logger if there is an error
return True