bzr revid: hda@tinyerp.com-20100408130532-fu53hdza1o2jettc
This commit is contained in:
HDA (OpenERP)
2010-04-08 18:35:32 +05:30
23 changed files with 497 additions and 293 deletions
+74 -31
View File
@@ -592,8 +592,75 @@ class MigrationManager(object):
if mod:
del mod
log = logging.getLogger('init')
def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
def process_sql_file(cr, file):
queries = fp.read().split(';')
for query in queries:
new_query = ' '.join(query.split())
if new_query:
cr.execute(new_query)
def load_init_update_xml(cr, m, idref, mode, kind):
for filename in package.data.get('%s_xml' % kind, []):
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: loading %s' % (m, filename))
_, ext = os.path.splitext(filename)
fp = tools.file_open(opj(m, filename))
if ext == '.csv':
noupdate = (kind == 'init')
tools.convert_csv_import(cr, m, os.path.basename(filename), fp.read(), idref, mode=mode, noupdate=noupdate)
elif ext == '.sql':
process_sql_file(cr, fp)
elif ext == '.yml':
tools.convert_yaml_import(cr, m, fp, idref, mode=mode, **kwargs)
else:
tools.convert_xml_import(cr, m, fp, idref, mode=mode, **kwargs)
fp.close()
def load_demo_xml(cr, m, idref, mode):
for xml in package.data.get('demo_xml', []):
name, ext = os.path.splitext(xml)
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: loading %s' % (m, xml))
fp = tools.file_open(opj(m, xml))
if ext == '.csv':
tools.convert_csv_import(cr, m, os.path.basename(xml), fp.read(), idref, mode=mode, noupdate=True)
elif ext == '.yml':
tools.convert_yaml_import(cr, m, fp, idref, mode=mode, noupdate=True, **kwargs)
else:
tools.convert_xml_import(cr, m, fp, idref, mode=mode, noupdate=True, **kwargs)
fp.close()
def load_data(cr, module_name, id_map, mode):
_load_data(cr, module_name, id_map, mode, 'data')
def load_demo(cr, module_name, id_map, mode):
_load_data(cr, module_name, id_map, mode, 'demo')
def load_test(cr, module_name, id_map, mode):
cr.commit()
try:
_load_data(cr, module_name, id_map, mode, 'test')
finally:
cr.rollback()
def _load_data(cr, module_name, id_map, mode, kind):
noupdate = (kind == 'demo')
for filename in package.data.get(kind, []):
_, ext = os.path.splitext(filename)
log.info("module %s: loading %s", module_name, filename)
pathname = os.path.join(module_name, filename)
file = tools.file_open(pathname)
# TODO manage .csv file with noupdate == (kind == 'init')
if ext == '.sql':
process_sql_file(cr, fp)
elif ext == '.yml':
tools.convert_yaml_import(cr, module_name, file, id_map, mode, noupdate)
else:
tools.convert_xml_import(cr, module_name, file, id_map, mode, noupdate)
file.close()
# **kwargs is passed directly to convert_xml_import
if not status:
status = {}
@@ -650,40 +717,16 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
'license': package.data.get('license', 'GPL-2'),
'certificate': package.data.get('certificate') or None,
})
for filename in package.data.get('%s_xml' % kind, []):
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))
if ext == '.csv':
noupdate=False
if kind == 'init':
noupdate=True
tools.convert_csv_import(cr, m, os.path.basename(filename), fp.read(), idref, mode=mode, noupdate=noupdate)
elif ext == '.sql':
queries = fp.read().split(';')
for query in queries:
new_query = ' '.join(query.split())
if new_query:
cr.execute(new_query)
elif ext == '.yml':
tools.convert_yaml_import(cr, m, fp, idref, mode=mode, **kwargs)
else:
tools.convert_xml_import(cr, m, fp, idref, mode=mode, **kwargs)
fp.close()
load_init_update_xml(cr, m, idref, mode, kind)
load_data(cr, m, idref, mode)
if hasattr(package, 'demo') or (package.dbdemo and package.state != 'installed'):
status['progress'] = (float(statusi)+0.75) / len(graph)
for xml in package.data.get('demo_xml', []):
name, ext = os.path.splitext(xml)
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: loading %s' % (m, xml))
fp = tools.file_open(opj(m, xml))
if ext == '.csv':
tools.convert_csv_import(cr, m, os.path.basename(xml), fp.read(), idref, mode=mode, noupdate=True)
elif ext == '.yml':
tools.convert_yaml_import(cr, m, fp, idref, mode=mode, **kwargs)
else:
tools.convert_xml_import(cr, m, fp, idref, mode=mode, noupdate=True, **kwargs)
fp.close()
load_demo_xml(cr, m, idref, mode)
load_demo(cr, m, idref, mode)
cr.execute('update ir_module_module set demo=%s where id=%s', (True, mid))
load_test(cr, m, idref, mode)
package_todo.append(package.name)
migrations.migrate_module(package, 'post')
+2 -1
View File
@@ -34,7 +34,8 @@
'security/base_security.xml',
'res/res_security.xml',
'res/res_config.xml',
'maintenance/maintenance_security.xml'
'maintenance/maintenance_security.xml',
'data/res.country.state.csv'
],
'update_xml': [
'base_update.xml',
@@ -0,0 +1,52 @@
"country_id:id","name","code"
us,"Alabama","AL"
us,"Alaska","AK"
us,"Arizona","AZ"
us,"Arkansas","AR"
us,"California","CA"
us,"Colorado","CO"
us,"Connecticut","CT"
us,"Delaware","DE"
us,"District of Columbia","DC"
us,"Florida","FL"
us,"Georgia","GA"
us,"Hawaii","HI"
us,"Idaho","ID"
us,"Illinois","IL"
us,"Indiana","IN"
us,"Iowa","IA"
us,"Kansas","KS"
us,"Kentucky","KY"
us,"Louisiana","LA"
us,"Maine","ME"
us,"Montana","MT"
us,"Nebraska","NE"
us,"Nevada","NV"
us,"New Hampshire","NH"
us,"New Jersey","NJ"
us,"New Mexico","NM"
us,"New York","NY"
us,"North Carolina","NC"
us,"North Dakota","ND"
us,"Ohio","OH"
us,"Oklahoma","OK"
us,"Oregon","OR"
us,"Maryland","MD"
us,"Massachusetts","MA"
us,"Michigan","MI"
us,"Minnesota","MN"
us,"Mississippi","MS"
us,"Missouri","MO"
us,"Pennsylvania","PA"
us,"Rhode Island","RI"
us,"South Carolina","SC"
us,"South Dakota","SD"
us,"Tennessee","TN"
us,"Texas","TX"
us,"Utah","UT"
us,"Vermont","VT"
us,"Virginia","VA"
us,"Washington","WA"
us,"West Virginia","WV"
us,"Wisconsin","WI"
us,"Wyoming","WY"
1 country_id:id name code
2 us Alabama AL
3 us Alaska AK
4 us Arizona AZ
5 us Arkansas AR
6 us California CA
7 us Colorado CO
8 us Connecticut CT
9 us Delaware DE
10 us District of Columbia DC
11 us Florida FL
12 us Georgia GA
13 us Hawaii HI
14 us Idaho ID
15 us Illinois IL
16 us Indiana IN
17 us Iowa IA
18 us Kansas KS
19 us Kentucky KY
20 us Louisiana LA
21 us Maine ME
22 us Montana MT
23 us Nebraska NE
24 us Nevada NV
25 us New Hampshire NH
26 us New Jersey NJ
27 us New Mexico NM
28 us New York NY
29 us North Carolina NC
30 us North Dakota ND
31 us Ohio OH
32 us Oklahoma OK
33 us Oregon OR
34 us Maryland MD
35 us Massachusetts MA
36 us Michigan MI
37 us Minnesota MN
38 us Mississippi MS
39 us Missouri MO
40 us Pennsylvania PA
41 us Rhode Island RI
42 us South Carolina SC
43 us South Dakota SD
44 us Tennessee TN
45 us Texas TX
46 us Utah UT
47 us Vermont VT
48 us Virginia VA
49 us Washington WA
50 us West Virginia WV
51 us Wisconsin WI
52 us Wyoming WY
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-04-06 04:00+0000\n"
"X-Launchpad-Export-Date: 2010-04-08 07:18+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+2 -2
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-04-05 04:33+0000\n"
"PO-Revision-Date: 2010-04-07 04:18+0000\n"
"Last-Translator: goranc <goranc@gmail.com>\n"
"Language-Team: openerp-translators\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-04-06 04:00+0000\n"
"X-Launchpad-Export-Date: 2010-04-08 07:18+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
+2 -2
View File
@@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-server\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-04-05 04:34+0000\n"
"PO-Revision-Date: 2010-04-07 04:14+0000\n"
"Last-Translator: Harry (Open ERP) <hmo@tinyerp.com>\n"
"Language-Team: Japanese <ja@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-04-06 04:00+0000\n"
"X-Launchpad-Export-Date: 2010-04-08 07:18+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+2 -2
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-04-05 04:37+0000\n"
"PO-Revision-Date: 2010-04-07 04:19+0000\n"
"Last-Translator: Anders Wallenquist <anders.wallenquist@vertel.se>\n"
"Language-Team: <>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-04-06 04:01+0000\n"
"X-Launchpad-Export-Date: 2010-04-08 07:18+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+2 -2
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-04-05 04:31+0000\n"
"PO-Revision-Date: 2010-04-07 04:12+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-04-06 04:01+0000\n"
"X-Launchpad-Export-Date: 2010-04-08 07:18+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+2 -2
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-04-05 04:30+0000\n"
"PO-Revision-Date: 2010-04-07 04:21+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-04-06 04:01+0000\n"
"X-Launchpad-Export-Date: 2010-04-08 07:18+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+4 -4
View File
@@ -548,10 +548,10 @@ class ir_model_data(osv.osv):
table.replace('.', '_'))] = (table, inherit_id)
return res_id
def _unlink(self, cr, uid, model, ids, direct=False):
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))
def _unlink(self, cr, uid, model, res_ids):
for res_id in res_ids:
self.unlink_mark[(model, res_id)] = False
cr.execute('delete from ir_model_data where res_id=%s and model=%s', (res_id, model))
return True
def ir_set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=None, xml_id=False):
+9 -12
View File
@@ -73,18 +73,15 @@ class ir_sequence(osv.osv):
}
def get_id(self, cr, uid, sequence_id, test='id', context=None):
try:
assert test in ('code','id')
cr.execute('SELECT id, number_next, prefix, suffix, padding FROM ir_sequence WHERE '+test+'=%s AND active=%s FOR UPDATE', (sequence_id, True))
res = cr.dictfetchone()
if res:
cr.execute('UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s AND active=%s', (res['id'], True))
if res['number_next']:
return self._process(res['prefix']) + '%%0%sd' % res['padding'] % res['number_next'] + self._process(res['suffix'])
else:
return self._process(res['prefix']) + self._process(res['suffix'])
finally:
cr.commit()
assert test in ('code','id')
cr.execute('SELECT id, number_next, prefix, suffix, padding FROM ir_sequence WHERE '+test+'=%s AND active=%s FOR UPDATE NOWAIT', (sequence_id, True))
res = cr.dictfetchone()
if res:
cr.execute('UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s AND active=%s', (res['id'], True))
if res['number_next']:
return self._process(res['prefix']) + '%%0%sd' % res['padding'] % res['number_next'] + self._process(res['suffix'])
else:
return self._process(res['prefix']) + self._process(res['suffix'])
return False
def get(self, cr, uid, code):
+5 -3
View File
@@ -50,10 +50,12 @@
<filter icon="terp-sale" string="Uninstalled" domain="[('state', 'in', ['uninstalled', 'uninstallable'])]"/>
<filter icon="terp-sale" string="To be upgraded" domain="[('state','in', ['to upgrade', 'to remove', 'to install'])]"/>
<separator orientation="vertical"/>
<field name="name" select="1"/>
<field name="state" readonly="1" select="1"/>
<filter icon="terp-sale" string="Certified" domain="[('certificate','&lt;&gt;', False)]"/>
<separator orientation="vertical"/>
<field name="name" select="1"/>
<field name="state" readonly="1" select="1"/>
</group>
</group>
</search>
</field>
+1 -1
View File
@@ -50,9 +50,9 @@
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="State">
<field name="country_id"/>
<field name="name"/>
<field name="code"/>
<field name="country_id"/>
</tree>
</field>
</record>
+1 -1
View File
@@ -136,7 +136,7 @@ class res_partner(osv.osv):
'child_ids': fields.one2many('res.partner', 'parent_id', 'Partner Ref.'),
'ref': fields.char('Code', size=64),
'lang': fields.selection(_lang_get, 'Language', size=5, help="If the selected language is loaded in the system, all documents related to this partner will be printed in this language. If not, it will be english."),
'user_id': fields.many2one('res.users', 'Dedicated Salesman', help='The internal user that is in charge of communicating with this partner if any.'),
'user_id': fields.many2one('res.users', 'Salesman', help='The internal user that is in charge of communicating with this partner if any.'),
'vat': fields.char('VAT',size=32 ,help="Value Added Tax number. Check the box if the partner is subjected to the VAT. Used by the VAT legal statement."),
'bank_ids': fields.one2many('res.partner.bank', 'partner_id', 'Banks'),
'website': fields.char('Website',size=64),
+1 -2
View File
@@ -329,7 +329,6 @@
<field colspan="4" name="events" nolabel="1" widget="one2many_list"/>
</page>
<page string="Notes">
<separator string="Description" colspan="4"/>
<field colspan="4" name="comment" nolabel="1"/>
</page>
</notebook>
@@ -344,7 +343,7 @@
<field name="arch" type="xml">
<search string="Search Partner">
<group col='10' colspan='4'>
<filter string="My Partners" icon="terp-partner" domain="[('parent_id','!=',False)]"/>
<filter string="My Partners" icon="terp-partner" domain="[('user_id','=',uid)]"/>
<separator orientation="vertical"/>
<filter string="Customers" icon="terp-partner" domain="[('customer','=',1)]" help="Customer Partners"/>
<filter string="Suppliers" icon="terp-partner" domain="[('supplier','=',1)]" help="Supplier Partners" name='supplier'/>
+4 -2
View File
@@ -148,8 +148,10 @@
<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:choice>
<rng:attribute name="id" />
<rng:attribute name="search" />
</rng:choice>
</rng:element>
</rng:define>
+4 -1
View File
@@ -205,7 +205,10 @@ def init_logger():
for level, (fg, bg) in mapping.items():
msg = "\x1b[%dm\x1b[%dm%s\x1b[0m" % (foreground(fg), background(bg), level)
logging.addLevelName(getattr(logging, level), msg)
# jth: we should not override default level name
# jth: use this instead http://stackoverflow.com/questions/384076/how-can-i-make-the-python-logging-output-to-be-colored
# jth: also, do not output ANSI if terminal doesn't support it (test it in Eclipse console and on windows)
#logging.addLevelName(getattr(logging, level), msg)
class Logger(object):
-1
View File
@@ -2937,7 +2937,6 @@ class orm(orm_template):
for sub_ids in cr.split_for_in_conditions(ids):
cr.execute('delete from ' + self._table + ' ' \
'where id in %s', (sub_ids,))
for order, object, store_ids, fields in result_store:
if object != self._name:
obj = self.pool.get(object)
+7 -7
View File
@@ -251,12 +251,11 @@ class OerpAuthProxy(AuthProxy):
self.auth_tries = 0
self.last_auth = None
def checkRequest(self,handler,path = '/'):
if self.auth_creds:
return True
def checkRequest(self,handler,path, db=False):
auth_str = handler.headers.get('Authorization',False)
try:
db = handler.get_db_from_path(path)
if not db:
db = handler.get_db_from_path(path)
print "Got db:",db
except:
if path.startswith('/'):
@@ -267,8 +266,9 @@ class OerpAuthProxy(AuthProxy):
else:
#FIXME!
self.provider.log("Wrong path: %s, failing auth" %path)
raise AuthRejectedExc("Authorization failed. Wrong sub-path.")
raise AuthRejectedExc("Authorization failed. Wrong sub-path.")
if self.auth_creds.get(db):
return True
if auth_str and auth_str.startswith('Basic '):
auth_str=auth_str[len('Basic '):]
(user,passwd) = base64.decodestring(auth_str).split(':')
@@ -276,7 +276,7 @@ class OerpAuthProxy(AuthProxy):
acd = self.provider.authenticate(db,user,passwd,handler.client_address)
if acd != False:
self.auth_creds[db] = acd
self.last_auth=db
self.last_auth = db
return True
if self.auth_tries > 5:
self.provider.log("Failing authorization after 5 requests w/o password")
+3
View File
@@ -234,6 +234,9 @@ class MultiHTTPHandler(FixSendError,BaseHTTPRequestHandler):
if fore.close_connection:
# print "Closing connection because of handler"
self.close_connection = fore.close_connection
if hasattr(fore, '_flush'):
fore._flush()
def parse_rawline(self):
"""Parse a request (internal).
+1 -1
View File
@@ -251,7 +251,7 @@ form: module.record_id""" % (xml_id,)
pass
if ids:
self.pool.get(d_model).unlink(cr, self.uid, ids)
self.pool.get('ir.model.data')._unlink(cr, self.uid, d_model, ids, direct=True)
self.pool.get('ir.model.data')._unlink(cr, self.uid, d_model, ids)
def _tag_report(self, cr, rec, data_node=None):
res = {}
+146 -215
View File
@@ -7,6 +7,7 @@ import pooler
import netsvc
import misc
from config import config
import yaml_tag
import yaml
@@ -18,161 +19,6 @@ class YamlImportException(Exception):
class YamlImportAbortion(Exception):
pass
class YamlTag(object):
"""
Superclass for constructors of custom tags defined in yaml file.
"""
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __getitem__(self, key):
return getattr(self, key)
def __getattr__(self, attr):
return None
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, sorted(self.__dict__.items()))
class Assert(YamlTag):
def __init__(self, model, id, severity=logging.ERROR, string="NONAME", **kwargs):
self.model = model
self.id = id
self.severity = severity
self.string = string
super(Assert, self).__init__(**kwargs)
class Record(YamlTag):
def __init__(self, model, id, **kwargs):
self.model = model
self.id = id
super(Record, self).__init__(**kwargs)
class Python(YamlTag):
def __init__(self, model, severity=logging.ERROR, name="", **kwargs):
self.model= model
self.severity = severity
self.name = name
super(Python, self).__init__(**kwargs)
class Menuitem(YamlTag):
def __init__(self, id, name, **kwargs):
self.id = id
self.name = name
super(Menuitem, self).__init__(**kwargs)
class Workflow(YamlTag):
def __init__(self, model, action, **kwargs):
self.model = model
self.action = action
super(Workflow, self).__init__(**kwargs)
class ActWindow(YamlTag):
def __init__(self, model, action, **kwargs):
self.model = model
self.action = action
super(ActWindow, self).__init__(**kwargs)
class Function(YamlTag):
def __init__(self, model, name, **kwargs):
self.model = model
self.name = name
super(Function, self).__init__(**kwargs)
class Report(YamlTag):
def __init__(self, model, name, string, **kwargs):
self.model = model
self.name = name
self.string = string
super(Report, self).__init__(**kwargs)
class Delete(YamlTag):
def __init__(self, model, id, search, **kwargs):
self.model = model
self.id = id
self.search = search
super(Delete, self).__init__(**kwargs)
class Context(YamlTag):
def __init__(self, **kwargs):
super(Context, self).__init__(**kwargs)
class Url(YamlTag):
def __init__(self, **kwargs):
super(Url, self).__init__(**kwargs)
class Eval(YamlTag):
def __init__(self, expression):
self.expression = expression
super(Eval, self).__init__()
class IrSet(YamlTag):
def __init__(self):
super(IrSet, self).__init__()
def assert_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Assert(**kwargs)
def record_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Record(**kwargs)
def python_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Python(**kwargs)
def menuitem_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Menuitem(**kwargs)
def workflow_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Workflow(**kwargs)
def act_window_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return ActWindow(**kwargs)
def function_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Function(**kwargs)
def report_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Report(**kwargs)
def delete_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Delete(**kwargs)
def context_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Context(**kwargs)
def url_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Url(**kwargs)
def eval_constructor(loader, node):
expression = loader.construct_scalar(node)
return Eval(expression)
def ir_set_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return IrSet(**kwargs)
yaml.add_constructor(u"!assert", assert_constructor)
yaml.add_constructor(u"!record", record_constructor)
yaml.add_constructor(u"!python", python_constructor)
yaml.add_constructor(u"!menuitem", menuitem_constructor)
yaml.add_constructor(u"!workflow", workflow_constructor)
yaml.add_constructor(u"!act_window", act_window_constructor)
yaml.add_constructor(u"!function", function_constructor)
yaml.add_constructor(u"!report", report_constructor)
yaml.add_constructor(u"!context", context_constructor)
yaml.add_constructor(u"!delete", delete_constructor)
yaml.add_constructor(u"!url", url_constructor)
yaml.add_constructor(u"!eval", eval_constructor)
yaml.add_constructor(u"!ir_set", ir_set_constructor)
def _is_yaml_mapping(node, tag_constructor):
value = isinstance(node, types.DictionaryType) \
and len(node.keys()) == 1 \
@@ -183,45 +29,49 @@ def is_comment(node):
return isinstance(node, types.StringTypes)
def is_assert(node):
return _is_yaml_mapping(node, Assert)
return _is_yaml_mapping(node, yaml_tag.Assert)
def is_record(node):
return _is_yaml_mapping(node, Record)
return _is_yaml_mapping(node, yaml_tag.Record)
def is_python(node):
return _is_yaml_mapping(node, Python)
return _is_yaml_mapping(node, yaml_tag.Python)
def is_menuitem(node):
return isinstance(node, Menuitem) \
or _is_yaml_mapping(node, Menuitem)
return isinstance(node, yaml_tag.Menuitem) \
or _is_yaml_mapping(node, yaml_tag.Menuitem)
def is_function(node):
return isinstance(node, Function) \
or _is_yaml_mapping(node, Function)
return isinstance(node, yaml_tag.Function) \
or _is_yaml_mapping(node, yaml_tag.Function)
def is_report(node):
return isinstance(node, Report)
return isinstance(node, yaml_tag.Report)
def is_workflow(node):
return isinstance(node, Workflow)
return isinstance(node, yaml_tag.Workflow)
def is_act_window(node):
return isinstance(node, ActWindow)
return isinstance(node, yaml_tag.ActWindow)
def is_delete(node):
return isinstance(node, Delete)
return isinstance(node, yaml_tag.Delete)
def is_context(node):
return isinstance(node, Context)
return isinstance(node, yaml_tag.Context)
def is_url(node):
return isinstance(node, Url)
return isinstance(node, yaml_tag.Url)
def is_eval(node):
return isinstance(node, Eval)
return isinstance(node, yaml_tag.Eval)
def is_ref(node):
return isinstance(node, yaml_tag.Ref) \
or _is_yaml_mapping(node, yaml_tag.Ref)
def is_ir_set(node):
return _is_yaml_mapping(node, IrSet)
return _is_yaml_mapping(node, yaml_tag.IrSet)
class TestReport(object):
@@ -276,7 +126,7 @@ class YamlInterpreter(object):
self.pool = pooler.get_pool(cr.dbname)
self.uid = 1
self.context = {} # opererp context
self.eval_context = {'ref': self._ref, '_ref': self._ref} # added '_ref' so that record['ref'] is possible
self.eval_context = {'ref': self._ref(), '_ref': self._ref(), 'time': time} # added '_ref' so that record['ref'] is possible
def _ref(self):
return lambda xml_id: self.get_id(xml_id)
@@ -309,10 +159,11 @@ class YamlInterpreter(object):
id = self.id_map[xml_id]
else:
if '.' in xml_id:
module, xml_id = xml_id.split('.', 1)
module, checked_xml_id = xml_id.split('.', 1)
else:
module = self.module
ir_id = self.pool.get('ir.model.data')._get_id(self.cr, self.uid, module, xml_id)
checked_xml_id = xml_id
ir_id = self.pool.get('ir.model.data')._get_id(self.cr, self.uid, module, checked_xml_id)
obj = self.pool.get('ir.model.data').read(self.cr, self.uid, ir_id, ['res_id'])
id = int(obj['res_id'])
self.id_map[xml_id] = id
@@ -327,14 +178,29 @@ class YamlInterpreter(object):
def isnoupdate(self, node):
return self.noupdate or node.noupdate or False
def _get_first_result(self, results, default=False):
if len(results):
value = results[0]
if isinstance(value, types.TupleType):
value = value[0]
else:
value = default
return value
def process_comment(self, node):
return node
def _log_assert_failure(self, severity, msg, *args):
self.assert_report.record(False, severity)
self.logger.log(severity, msg, *args)
if severity >= config['assert_exit_level']:
raise YamlImportAbortion('Severe assertion failure (%s), aborting.' % logging.getLevelName(severity))
if isinstance(severity, types.StringTypes):
levelname = severity.strip().upper()
level = logging.getLevelName(levelname)
else:
level = severity
levelname = logging.getLevelName(level)
self.assert_report.record(False, levelname)
self.logger.log(level, msg, *args)
if level >= config['assert_exit_level']:
raise YamlImportAbortion('Severe assertion failure (%s), aborting.' % levelname)
return
def _get_assertion_id(self, assertion):
@@ -351,6 +217,7 @@ class YamlInterpreter(object):
assertion, expressions = node.items()[0]
if self.isnoupdate(assertion) and self.mode != 'init':
self.logger.warn('This assertion was not evaluated ("%s").' % assertion.string)
return
model = self.get_model(assertion.model)
ids = self._get_assertion_id(assertion)
@@ -365,7 +232,7 @@ class YamlInterpreter(object):
context = self.get_context(assertion, self.eval_context)
for id in ids:
record = model.browse(self.cr, self.uid, id, context)
for test in expressions.get('test', ''):
for test in expressions:
try:
success = eval(test, self.eval_context, RecordDictWrapper(record))
except Exception, e:
@@ -378,19 +245,39 @@ class YamlInterpreter(object):
else: # all tests were successful for this assertion tag (no break)
self.assert_report.record(True, assertion.severity)
def _coerce_bool(self, value, default=False):
if isinstance(value, types.BooleanType):
b = value
if isinstance(value, types.StringTypes):
b = value.strip().lower() not in ('0', 'false', 'off', 'no')
elif isinstance(value, types.IntType):
b = bool(value)
else:
b = default
return b
def process_record(self, node):
record, fields = node.items()[0]
self.validate_xml_id(record.id)
if self.isnoupdate(record) and self.mode != 'init':
model = self.get_model(record.model)
record_dict = self._create_record(model, fields)
self.logger.debug("RECORD_DICT %s" % record_dict)
id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \
self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode)
self.id_map[record.id] = int(id)
if config.get('import_partial', False):
self.cr.commit()
id = self.pool.get('ir.model.data')._update_dummy(self.cr, self.uid, record.model, self.module, record.id)
# check if the resource already existed at the last update
if id:
self.id_map[record] = int(id)
return None
else:
if not self._coerce_bool(record.forcecreate):
return None
model = self.get_model(record.model)
record_dict = self._create_record(model, fields)
self.logger.debug("RECORD_DICT %s" % record_dict)
id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \
self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode)
self.id_map[record.id] = int(id)
if config.get('import_partial', False):
self.cr.commit()
def _create_record(self, model, fields):
record_dict = {}
@@ -399,19 +286,50 @@ class YamlInterpreter(object):
record_dict[field_name] = field_value
return record_dict
def process_ref(self, node, column=None):
if node.search:
if node.model:
model_name = node.model
elif column:
model_name = column._obj
else:
raise YamlImportException('You need to give a model for the search, or a column to infer it.')
model = self.get_model(model_name)
q = eval(node.search, self.eval_context)
ids = model.search(self.cr, self.uid, q)
if node.use:
instances = model.browse(self.cr, self.uid, ids)
value = [inst[node.use] for inst in instances]
else:
value = ids
elif node.id:
value = self.get_id(node.id)
else:
value = None
return value
def process_eval(self, node):
return eval(node.expression, self.eval_context)
def _eval_field(self, model, field_name, expression):
column = model._columns[field_name]
if column._type == "many2one":
if is_ref(expression):
elements = self.process_ref(expression)
if column._type in ("many2many", "one2many"):
value = [(6, 0, elements)]
else: # many2one
value = self._get_first_result(elements)
elif column._type == "many2one":
value = self.get_id(expression)
elif column._type == "one2many":
other_model = self.get_model(column._obj)
value = [(0, 0, self._create_record(other_model, fields)) for fields in expression]
elif column._type == "many2many":
ids = [self.get_id(xml_id) for xml_id in expression]
value= [(6, 0, ids)]
value = [(6, 0, ids)]
else: # scalar field
if isinstance(expression, Eval):
value = eval(expression.expression)
if is_eval(expression):
value = self.process_eval(expression)
else:
value = expression
# raise YamlImportException('Unsupported column "%s" or value %s:%s' % (field_name, type(expression), expression))
@@ -446,7 +364,6 @@ class YamlInterpreter(object):
workflow, values = node.items()[0]
if self.isnoupdate(workflow) and self.mode != 'init':
return
model = self.get_model(workflow.model)
if workflow.ref:
id = self.get_id(workflow.ref)
else:
@@ -467,26 +384,44 @@ class YamlInterpreter(object):
else:
uid = self.uid
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, model, id, workflow.action, self.cr)
wf_service.trg_validate(uid, workflow.model, id, workflow.action, self.cr)
def _eval_params(self, model, params):
args = []
for i, param in enumerate(params):
if isinstance(param, types.ListType):
value = self._eval_params(model, param)
elif is_ref(param):
value = self.process_ref(param)
elif is_eval(param):
value = self.process_eval(param)
elif isinstance(param, types.DictionaryType): # supports XML syntax
param_model = self.get_model(param.get('model', model))
if 'search' in param:
q = eval(param['search'], self.eval_context)
ids = param_model.search(cr, uid, q)
value = self._get_first_result(ids)
elif 'eval' in param:
local_context = {'obj': lambda x: param_model.browse(self.cr, self.uid, x, context)}
local_context.update(self.id_map)
value = eval(param['eval'], self.eval_context, local_context)
else:
raise YamlImportException('You must provide either a !ref or at least a "eval" or a "search" to function parameter #%d.' % i)
else:
value = param # scalar value
args.append(value)
return args
def process_function(self, node):
function, values = node.items()[0]
function, params = node.items()[0]
if self.isnoupdate(function) and self.mode != 'init':
return
context = self.get_context(function, self.eval_context)
args = []
if function.eval:
args = eval(function.eval, self.eval_context)
for value in values:
if not 'model' in value and (not 'eval' in value or not 'search' in value):
raise YamlImportException('You must provide a "model" and an "eval" or "search" to evaluate.')
value_model = self.get_model(value['model'])
local_context = {'obj': lambda x: value_model.browse(self.cr, self.uid, x, context=context)}
local_context.update(self.id_map)
id = eval(value['eval'], self.eval_context, local_context)
if id != None:
args.append(id)
model = self.get_model(function.model)
context = self.get_context(function, self.eval_context)
if function.eval:
args = self.process_eval(function.eval)
else:
args = self._eval_params(function.model, params)
method = function.name
getattr(model, method)(self.cr, self.uid, *args)
@@ -624,17 +559,13 @@ class YamlInterpreter(object):
# TODO add remove ir.model.data
def process_delete(self, node):
ids = []
if len(node.search):
ids = self.pool.get(node.model).search(self.cr, self.uid, eval(node.search, self.eval_context))
if len(node.id):
try:
ids.append(self.get_id(node.id))
except:
pass
else:
ids = [self.get_id(node.id)]
if len(ids):
self.pool.get(node.model).unlink(self.cr, self.uid, ids)
self.pool.get('ir.model.data')._unlink(self.cr, self.uid, node.model, ids, direct=True)
self.pool.get('ir.model.data')._unlink(self.cr, self.uid, node.model, ids)
def process_url(self, node):
self.validate_xml_id(node.id)
@@ -717,9 +648,9 @@ class YamlInterpreter(object):
try:
self._process_node(node)
except YamlImportException, e:
self.logger.log(logging.ERROR, e)
self.logger.exception(e)
except Exception, e:
self.logger.log(logging.ERROR, e)
self.logger.exception(e)
raise e
def _process_node(self, node):
+172
View File
@@ -0,0 +1,172 @@
import yaml
import logging
class YamlTag(object):
"""
Superclass for constructors of custom tags defined in yaml file.
"""
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __getitem__(self, key):
return getattr(self, key)
def __getattr__(self, attr):
return None
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, sorted(self.__dict__.items()))
class Assert(YamlTag):
def __init__(self, model, id, severity=logging.ERROR, string="NONAME", **kwargs):
self.model = model
self.id = id
self.severity = severity
self.string = string
super(Assert, self).__init__(**kwargs)
class Record(YamlTag):
def __init__(self, model, id, use='id', **kwargs):
self.model = model
self.id = id
super(Record, self).__init__(**kwargs)
class Python(YamlTag):
def __init__(self, model, severity=logging.ERROR, name="", **kwargs):
self.model= model
self.severity = severity
self.name = name
super(Python, self).__init__(**kwargs)
class Menuitem(YamlTag):
def __init__(self, id, name, **kwargs):
self.id = id
self.name = name
super(Menuitem, self).__init__(**kwargs)
class Workflow(YamlTag):
def __init__(self, model, action, **kwargs):
self.model = model
self.action = action
super(Workflow, self).__init__(**kwargs)
class ActWindow(YamlTag):
def __init__(self, model, action, **kwargs):
self.model = model
self.action = action
super(ActWindow, self).__init__(**kwargs)
class Function(YamlTag):
def __init__(self, model, name, **kwargs):
self.model = model
self.name = name
super(Function, self).__init__(**kwargs)
class Report(YamlTag):
def __init__(self, model, name, string, **kwargs):
self.model = model
self.name = name
self.string = string
super(Report, self).__init__(**kwargs)
class Delete(YamlTag):
def __init__(self, model, id, search, **kwargs):
self.model = model
self.id = id
self.search = search
super(Delete, self).__init__(**kwargs)
class Context(YamlTag):
def __init__(self, **kwargs):
super(Context, self).__init__(**kwargs)
class Url(YamlTag):
def __init__(self, **kwargs):
super(Url, self).__init__(**kwargs)
class Eval(YamlTag):
def __init__(self, expression):
self.expression = expression
super(Eval, self).__init__()
class Ref(YamlTag):
def __init__(self, *args, **kwargs):
super(Ref, self).__init__(*args, **kwargs)
class IrSet(YamlTag):
def __init__(self):
super(IrSet, self).__init__()
def assert_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Assert(**kwargs)
def record_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Record(**kwargs)
def python_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Python(**kwargs)
def menuitem_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Menuitem(**kwargs)
def workflow_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Workflow(**kwargs)
def act_window_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return ActWindow(**kwargs)
def function_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Function(**kwargs)
def report_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Report(**kwargs)
def delete_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Delete(**kwargs)
def context_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Context(**kwargs)
def url_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return Url(**kwargs)
def eval_constructor(loader, node):
expression = loader.construct_scalar(node)
return Eval(expression)
def ref_constructor(loader, tag_suffix, node):
if tag_suffix == "id":
kwargs = {"id": loader.construct_scalar(node)}
else:
kwargs = loader.construct_mapping(node)
return Ref(**kwargs)
def ir_set_constructor(loader, node):
kwargs = loader.construct_mapping(node)
return IrSet(**kwargs)
# Registers constructors for custom tags.
# Constructors are actually defined globally: do not redefined them in another
# class/file/package. This means that module recorder need import this file.
yaml.add_constructor(u"!assert", assert_constructor)
yaml.add_constructor(u"!record", record_constructor)
yaml.add_constructor(u"!python", python_constructor)
yaml.add_constructor(u"!menuitem", menuitem_constructor)
yaml.add_constructor(u"!workflow", workflow_constructor)
yaml.add_constructor(u"!act_window", act_window_constructor)
yaml.add_constructor(u"!function", function_constructor)
yaml.add_constructor(u"!report", report_constructor)
yaml.add_constructor(u"!context", context_constructor)
yaml.add_constructor(u"!delete", delete_constructor)
yaml.add_constructor(u"!url", url_constructor)
yaml.add_constructor(u"!eval", eval_constructor)
yaml.add_multi_constructor(u"!ref", ref_constructor)
yaml.add_constructor(u"!ir_set", ir_set_constructor)