2012-02-12 11:45:09 +00:00
# -*- coding: utf-8 -*-
2011-09-14 10:43:00 +00:00
import threading
2010-03-04 09:44:58 +00:00
import types
import time # used to eval time.strftime expressions
2010-07-13 08:40:57 +00:00
from datetime import datetime , timedelta
2010-03-04 09:44:58 +00:00
import logging
2011-02-07 12:57:23 +00:00
import openerp . pooler as pooler
2011-09-14 10:43:00 +00:00
import openerp . sql_db as sql_db
2010-03-05 10:42:04 +00:00
import misc
2010-03-04 09:44:58 +00:00
from config import config
2010-03-30 15:20:31 +00:00
import yaml_tag
2010-03-08 11:29:28 +00:00
import yaml
2011-11-13 22:30:56 +00:00
import re
from lxml import etree
2012-08-31 13:53:09 +00:00
from openerp import SUPERUSER_ID
2010-03-08 08:55:32 +00:00
2010-06-04 00:39:40 +00:00
# YAML import needs both safe and unsafe eval, but let's
# default to /safe/.
unsafe_eval = eval
2011-02-07 12:57:23 +00:00
from safe_eval import safe_eval as eval
2010-06-04 00:39:40 +00:00
2012-03-02 11:02:27 +00:00
import assertion_report
2012-01-24 14:00:56 +00:00
_logger = logging . getLogger ( __name__ )
2010-03-04 09:44:58 +00:00
class YamlImportException ( Exception ) :
pass
class YamlImportAbortion ( Exception ) :
pass
def _is_yaml_mapping ( node , tag_constructor ) :
value = isinstance ( node , types . DictionaryType ) \
and len ( node . keys ( ) ) == 1 \
and isinstance ( node . keys ( ) [ 0 ] , tag_constructor )
return value
def is_comment ( node ) :
return isinstance ( node , types . StringTypes )
def is_assert ( node ) :
2010-12-03 14:20:35 +00:00
return isinstance ( node , yaml_tag . Assert ) \
or _is_yaml_mapping ( node , yaml_tag . Assert )
2010-03-04 09:44:58 +00:00
def is_record ( node ) :
2010-03-30 15:20:31 +00:00
return _is_yaml_mapping ( node , yaml_tag . Record )
2010-03-04 09:44:58 +00:00
def is_python ( node ) :
2010-03-30 15:20:31 +00:00
return _is_yaml_mapping ( node , yaml_tag . Python )
2010-03-04 09:44:58 +00:00
2010-03-05 09:12:18 +00:00
def is_menuitem ( node ) :
2010-03-30 15:20:31 +00:00
return isinstance ( node , yaml_tag . Menuitem ) \
or _is_yaml_mapping ( node , yaml_tag . Menuitem )
2010-03-05 09:12:18 +00:00
def is_function ( node ) :
2010-03-30 15:20:31 +00:00
return isinstance ( node , yaml_tag . Function ) \
or _is_yaml_mapping ( node , yaml_tag . Function )
2010-03-05 09:12:18 +00:00
2010-03-05 10:42:04 +00:00
def is_report ( node ) :
2010-03-30 15:20:31 +00:00
return isinstance ( node , yaml_tag . Report )
2010-03-05 10:42:04 +00:00
2010-03-04 09:44:58 +00:00
def is_workflow ( node ) :
2010-03-30 15:20:31 +00:00
return isinstance ( node , yaml_tag . Workflow )
2010-03-05 09:12:18 +00:00
def is_act_window ( node ) :
2010-03-30 15:20:31 +00:00
return isinstance ( node , yaml_tag . ActWindow )
2010-03-05 09:12:18 +00:00
def is_delete ( node ) :
2010-03-30 15:20:31 +00:00
return isinstance ( node , yaml_tag . Delete )
2010-03-04 09:44:58 +00:00
def is_context ( node ) :
2010-03-30 15:20:31 +00:00
return isinstance ( node , yaml_tag . Context )
2010-03-04 09:44:58 +00:00
2010-03-05 09:12:18 +00:00
def is_url ( node ) :
2010-03-30 15:20:31 +00:00
return isinstance ( node , yaml_tag . Url )
2010-03-05 09:12:18 +00:00
2010-03-04 09:44:58 +00:00
def is_eval ( node ) :
2010-03-30 15:20:31 +00:00
return isinstance ( node , yaml_tag . Eval )
2010-09-17 09:41:00 +00:00
2010-03-31 16:55:26 +00:00
def is_ref ( node ) :
return isinstance ( node , yaml_tag . Ref ) \
or _is_yaml_mapping ( node , yaml_tag . Ref )
2010-09-17 09:41:00 +00:00
2010-03-05 09:37:22 +00:00
def is_ir_set ( node ) :
2010-03-30 15:20:31 +00:00
return _is_yaml_mapping ( node , yaml_tag . IrSet )
2010-03-04 09:44:58 +00:00
2010-09-17 09:41:00 +00:00
def is_string ( node ) :
return isinstance ( node , basestring )
2010-03-04 09:44:58 +00:00
2010-03-09 09:23:46 +00:00
class RecordDictWrapper ( dict ) :
"""
Used to pass a record as locals in eval :
records do not strictly behave like dict , so we force them to .
"""
def __init__ ( self , record ) :
2011-05-13 09:44:05 +00:00
self . record = record
2010-03-09 09:23:46 +00:00
def __getitem__ ( self , key ) :
if key in self . record :
return self . record [ key ]
return dict . __getitem__ ( self , key )
2010-07-13 08:40:57 +00:00
2010-03-04 09:44:58 +00:00
class YamlInterpreter ( object ) :
2012-08-22 10:11:56 +00:00
def __init__ ( self , cr , module , id_map , mode , filename , report = None , noupdate = False , loglevel = logging . DEBUG ) :
2010-03-04 09:44:58 +00:00
self . cr = cr
self . module = module
self . id_map = id_map
self . mode = mode
self . filename = filename
2012-03-02 11:02:27 +00:00
if report is None :
report = assertion_report . assertion_report ( )
self . assertion_report = report
2010-03-04 09:44:58 +00:00
self . noupdate = noupdate
2012-08-22 10:11:56 +00:00
self . loglevel = loglevel
2010-03-04 09:44:58 +00:00
self . pool = pooler . get_pool ( cr . dbname )
self . uid = 1
2010-03-09 09:23:46 +00:00
self . context = { } # opererp context
2010-07-13 08:40:57 +00:00
self . eval_context = { ' ref ' : self . _ref ( ) ,
' _ref ' : self . _ref ( ) , # added '_ref' so that record['ref'] is possible
' time ' : time ,
' datetime ' : datetime ,
' timedelta ' : timedelta }
2010-03-04 09:44:58 +00:00
2012-08-22 10:11:56 +00:00
def _log ( self , * args , * * kwargs ) :
_logger . log ( self . loglevel , * args , * * kwargs )
2010-03-04 09:44:58 +00:00
def _ref ( self ) :
return lambda xml_id : self . get_id ( xml_id )
def get_model ( self , model_name ) :
model = self . pool . get ( model_name )
assert model , " The model %s does not exist. " % ( model_name , )
return model
2010-07-13 08:40:57 +00:00
2010-03-04 09:44:58 +00:00
def validate_xml_id ( self , xml_id ) :
id = xml_id
if ' . ' in xml_id :
module , id = xml_id . split ( ' . ' , 1 )
assert ' . ' not in id , " The ID reference ' %s ' must contains maximum one dot. \n " \
" It is used to refer to other modules ID, in the form: module.record_id " \
% ( xml_id , )
if module != self . module :
module_count = self . pool . get ( ' ir.module.module ' ) . search_count ( self . cr , self . uid , \
[ ' & ' , ( ' name ' , ' = ' , module ) , ( ' state ' , ' in ' , [ ' installed ' ] ) ] )
2010-03-09 09:23:46 +00:00
assert module_count == 1 , ' The ID " %s " refers to an uninstalled module. ' % ( xml_id , )
2010-03-04 09:44:58 +00:00
if len ( id ) > 64 : # TODO where does 64 come from (DB is 128)? should be a constant or loaded form DB
2012-01-24 14:00:56 +00:00
_logger . error ( ' id: %s is to long (max: 64) ' , id )
2010-03-04 09:44:58 +00:00
def get_id ( self , xml_id ) :
2011-11-24 15:32:33 +00:00
if xml_id is False or xml_id is None :
2011-11-13 22:30:56 +00:00
return False
#if not xml_id:
# raise YamlImportException("The xml_id should be a non empty string.")
elif isinstance ( xml_id , types . IntType ) :
2010-03-04 09:44:58 +00:00
id = xml_id
elif xml_id in self . id_map :
id = self . id_map [ xml_id ]
else :
if ' . ' in xml_id :
2010-03-31 16:55:26 +00:00
module , checked_xml_id = xml_id . split ( ' . ' , 1 )
2010-03-04 09:44:58 +00:00
else :
module = self . module
2010-03-31 16:55:26 +00:00
checked_xml_id = xml_id
2011-05-13 09:44:05 +00:00
try :
_ , id = self . pool . get ( ' ir.model.data ' ) . get_object_reference ( self . cr , self . uid , module , checked_xml_id )
self . id_map [ xml_id ] = id
2011-06-24 13:33:35 +00:00
except ValueError :
2011-05-13 12:52:18 +00:00
raise ValueError ( """ %s not found when processing %s .
This Yaml file appears to depend on missing data . This often happens for
tests that belong to a module ' s test suite and depend on each other. " " " % (checked_xml_id, self.filename))
2011-05-13 09:44:05 +00:00
2010-03-04 09:44:58 +00:00
return id
2011-05-13 09:44:05 +00:00
2010-03-09 09:23:46 +00:00
def get_context ( self , node , eval_dict ) :
2010-03-05 09:12:18 +00:00
context = self . context . copy ( )
if node . context :
2010-03-09 09:23:46 +00:00
context . update ( eval ( node . context , eval_dict ) )
2010-03-05 09:12:18 +00:00
return context
2010-03-05 10:05:37 +00:00
def isnoupdate ( self , node ) :
return self . noupdate or node . noupdate or False
2011-05-13 09:44:05 +00:00
2010-04-01 19:25:02 +00:00
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
2011-05-13 09:44:05 +00:00
2010-03-04 09:44:58 +00:00
def process_comment ( self , node ) :
return node
2012-03-02 12:35:35 +00:00
def _log_assert_failure ( self , msg , * args ) :
2012-03-02 11:02:27 +00:00
self . assertion_report . record_failure ( )
2012-03-02 11:28:34 +00:00
_logger . error ( msg , * args )
2010-03-04 09:44:58 +00:00
def _get_assertion_id ( self , assertion ) :
if assertion . id :
ids = [ self . get_id ( assertion . id ) ]
elif assertion . search :
2010-03-09 09:23:46 +00:00
q = eval ( assertion . search , self . eval_context )
2010-03-04 09:44:58 +00:00
ids = self . pool . get ( assertion . model ) . search ( self . cr , self . uid , q , context = assertion . context )
2010-12-03 14:20:35 +00:00
else :
2010-03-04 09:44:58 +00:00
raise YamlImportException ( ' Nothing to assert: you must give either an id or a search criteria. ' )
return ids
def process_assert ( self , node ) :
2010-12-03 14:20:35 +00:00
if isinstance ( node , dict ) :
assertion , expressions = node . items ( ) [ 0 ]
else :
assertion , expressions = node , [ ]
2010-03-04 09:44:58 +00:00
2010-03-05 10:05:37 +00:00
if self . isnoupdate ( assertion ) and self . mode != ' init ' :
2012-01-24 14:00:56 +00:00
_logger . warning ( ' This assertion was not evaluated ( " %s " ). ' , assertion . string )
2010-03-05 10:05:37 +00:00
return
2010-03-04 09:44:58 +00:00
model = self . get_model ( assertion . model )
ids = self . _get_assertion_id ( assertion )
2010-12-03 14:20:35 +00:00
if assertion . count is not None and len ( ids ) != assertion . count :
2010-03-04 09:44:58 +00:00
msg = ' assertion " %s " failed! \n ' \
' Incorrect search count: \n ' \
' expected count: %d \n ' \
' obtained count: %d \n '
args = ( assertion . string , assertion . count , len ( ids ) )
2012-03-02 11:28:34 +00:00
self . _log_assert_failure ( msg , * args )
2010-03-04 09:44:58 +00:00
else :
2010-03-09 09:23:46 +00:00
context = self . get_context ( assertion , self . eval_context )
2010-03-04 09:44:58 +00:00
for id in ids :
2010-03-05 10:05:37 +00:00
record = model . browse ( self . cr , self . uid , id , context )
2010-04-01 13:26:03 +00:00
for test in expressions :
2010-03-09 09:23:46 +00:00
try :
2010-06-04 00:39:40 +00:00
success = unsafe_eval ( test , self . eval_context , RecordDictWrapper ( record ) )
2010-03-09 09:23:46 +00:00
except Exception , e :
2012-01-24 14:00:56 +00:00
_logger . debug ( ' Exception during evaluation of !assert block in yaml_file %s . ' , self . filename , exc_info = True )
2010-03-09 09:23:46 +00:00
raise YamlImportAbortion ( e )
2010-03-04 09:44:58 +00:00
if not success :
msg = ' Assertion " %s " FAILED \n test: %s \n '
args = ( assertion . string , test )
2010-09-02 11:30:25 +00:00
for aop in ( ' == ' , ' != ' , ' <> ' , ' in ' , ' not in ' , ' >= ' , ' <= ' , ' > ' , ' < ' ) :
if aop in test :
left , right = test . split ( aop , 1 )
lmsg = ' '
rmsg = ' '
try :
lmsg = unsafe_eval ( left , self . eval_context , RecordDictWrapper ( record ) )
except Exception , e :
lmsg = ' <exc> '
try :
rmsg = unsafe_eval ( right , self . eval_context , RecordDictWrapper ( record ) )
except Exception , e :
rmsg = ' <exc> '
msg + = ' values: ! %s %s %s '
args + = ( lmsg , aop , rmsg )
break
2012-03-02 11:28:34 +00:00
self . _log_assert_failure ( msg , * args )
2010-03-04 09:44:58 +00:00
return
else : # all tests were successful for this assertion tag (no break)
2012-03-02 11:02:27 +00:00
self . assertion_report . record_success ( )
2010-03-04 09:44:58 +00:00
2010-03-31 16:55:26 +00:00
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
2010-05-03 23:35:16 +00:00
return b
2010-04-30 14:18:10 +00:00
def create_osv_memory_record ( self , record , fields ) :
model = self . get_model ( record . model )
2011-10-12 06:31:45 +00:00
context = self . get_context ( record , self . eval_context )
2010-04-30 14:18:10 +00:00
record_dict = self . _create_record ( model , fields )
2011-10-12 06:31:45 +00:00
id_new = model . create ( self . cr , self . uid , record_dict , context = context )
2010-04-30 14:18:10 +00:00
self . id_map [ record . id ] = int ( id_new )
return record_dict
2010-05-03 23:35:16 +00:00
2010-03-04 09:44:58 +00:00
def process_record ( self , node ) :
2011-02-07 12:57:23 +00:00
import openerp . osv as osv
2010-03-04 09:44:58 +00:00
record , fields = node . items ( ) [ 0 ]
2010-03-31 16:55:26 +00:00
model = self . get_model ( record . model )
2011-11-13 22:30:56 +00:00
view_id = record . view
2012-10-30 15:28:24 +00:00
if view_id and ( view_id is not True ) and isinstance ( view_id , basestring ) :
module = self . module
if ' . ' in view_id :
module , view_id = view_id . split ( ' . ' , 1 )
view_id = self . pool . get ( ' ir.model.data ' ) . get_object_reference ( self . cr , SUPERUSER_ID , module , view_id ) [ 1 ]
2011-11-13 22:30:56 +00:00
2011-08-16 09:57:55 +00:00
if model . is_transient ( ) :
2010-04-30 14:18:10 +00:00
record_dict = self . create_osv_memory_record ( record , fields )
else :
self . validate_xml_id ( record . id )
2011-11-14 21:26:27 +00:00
try :
2012-08-31 13:53:09 +00:00
self . pool . get ( ' ir.model.data ' ) . _get_id ( self . cr , SUPERUSER_ID , self . module , record . id )
2011-11-14 21:26:27 +00:00
default = False
except ValueError :
default = True
2010-04-30 14:18:10 +00:00
if self . isnoupdate ( record ) and self . mode != ' init ' :
2012-08-31 13:53:09 +00:00
id = self . pool . get ( ' ir.model.data ' ) . _update_dummy ( self . cr , SUPERUSER_ID , record . model , self . module , record . id )
2010-04-30 14:18:10 +00:00
# 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
2010-05-03 23:35:16 +00:00
2011-11-13 22:30:56 +00:00
2010-09-01 08:57:07 +00:00
#context = self.get_context(record, self.eval_context)
2011-11-14 21:26:27 +00:00
#TOFIX: record.context like {'withoutemployee':True} should pass from self.eval_context. example: test_project.yml in project module
context = record . context
2012-10-01 15:38:06 +00:00
view_info = False
2011-11-14 21:26:27 +00:00
if view_id :
varg = view_id
if view_id is True : varg = False
2012-10-01 15:38:06 +00:00
view_info = model . fields_view_get ( self . cr , SUPERUSER_ID , varg , ' form ' , context )
2011-11-13 22:30:56 +00:00
2012-10-01 15:38:06 +00:00
record_dict = self . _create_record ( model , fields , view_info , default = default )
2012-01-24 14:00:56 +00:00
_logger . debug ( " RECORD_DICT %s " % record_dict )
2012-08-31 13:53:09 +00:00
id = self . pool . get ( ' ir.model.data ' ) . _update ( self . cr , SUPERUSER_ID , record . model , \
2010-09-01 08:57:07 +00:00
self . module , record_dict , record . id , noupdate = self . isnoupdate ( record ) , mode = self . mode , context = context )
2010-05-03 23:35:16 +00:00
self . id_map [ record . id ] = int ( id )
if config . get ( ' import_partial ' ) :
self . cr . commit ( )
2012-10-01 15:38:06 +00:00
def _create_record ( self , model , fields , view_info = False , parent = { } , default = True ) :
2012-10-05 12:06:53 +00:00
""" This function processes the !record tag in yalm files. It simulates the record creation through an xml
view ( either specified on the ! record tag or the default one for this object ) , including the calls to
2012-10-19 11:06:04 +00:00
on_change ( ) functions , and sending only values for fields that aren ' t set as readonly.
2012-10-05 12:06:53 +00:00
: param model : model instance
: param fields : dictonary mapping the field names and their values
: param view_info : result of fields_view_get ( ) called on the object
: param parent : dictionary containing the values already computed for the parent , in case of one2many fields
: param default : if True , the default values must be processed too or not
: return : dictionary mapping the field names and their values , ready to use when calling the create ( ) function
: rtype : dict
2012-10-04 12:15:22 +00:00
"""
2012-10-19 11:06:04 +00:00
def _get_right_one2many_view ( fg , field_name , view_type ) :
one2many_view = fg [ field_name ] [ ' views ' ] . get ( view_type )
# if the view is not defined inline, we call fields_view_get()
if not one2many_view :
one2many_view = self . pool . get ( fg [ field_name ] [ ' relation ' ] ) . fields_view_get ( self . cr , SUPERUSER_ID , False , view_type , self . context )
return one2many_view
2011-11-14 21:26:27 +00:00
def process_val ( key , val ) :
if fg [ key ] [ ' type ' ] == ' many2one ' :
if type ( val ) in ( tuple , list ) :
val = val [ 0 ]
2011-11-14 22:19:54 +00:00
elif ( fg [ key ] [ ' type ' ] == ' one2many ' ) :
if val is False :
val = [ ]
if len ( val ) and type ( val [ 0 ] ) == dict :
2012-10-19 11:06:04 +00:00
#we want to return only the fields that aren't readonly
#For that, we need to first get the right tree view to consider for the field `key´
one2many_tree_view = _get_right_one2many_view ( fg , key , ' tree ' )
for rec in val :
#make a copy for the iteration, as we will alterate the size of `rec´ dictionary
rec_copy = rec . copy ( )
for field_key in rec_copy :
#seek in the view for the field `field_key´ and removing it from `key´ values, as this column is readonly in the tree view
subfield_obj = etree . fromstring ( one2many_tree_view [ ' arch ' ] . encode ( ' utf-8 ' ) ) . xpath ( " //field[@name= ' %s ' ] " % ( field_key ) )
if subfield_obj and ( subfield_obj [ 0 ] . get ( ' modifiers ' , ' {} ' ) . find ( ' " readonly " : true ' ) > = 0 ) :
#TODO: currently we only support if readonly is True in the modifiers. Some improvement may be done in
#order to support also modifiers that look like {"readonly": [["state", "not in", ["draft", "confirm"]]]}
del ( rec [ field_key ] )
#now that unwanted values have been removed from val, we can encapsulate it in a tuple as returned value
2011-11-14 21:26:27 +00:00
val = map ( lambda x : ( 0 , 0 , x ) , val )
2012-10-19 11:06:04 +00:00
#we want to return only the fields that aren't readonly
if el . get ( ' modifiers ' , ' {} ' ) . find ( ' " readonly " : true ' ) > = 0 :
#TODO: currently we only support if readonly is True in the modifiers. Some improvement may be done in
#order to support also modifiers that look like {"readonly": [["state", "not in", ["draft", "confirm"]]]}
return False
2011-11-14 21:26:27 +00:00
return val
2012-10-04 11:56:17 +00:00
view = view_info and etree . fromstring ( view_info [ ' arch ' ] . encode ( ' utf-8 ' ) ) or False
fields = fields or { }
if view is not False :
fg = view_info [ ' fields ' ]
2012-10-04 15:40:32 +00:00
# gather the default values on the object. (Can't use `fields´ as parameter instead of {} because we may
# have references like `base.main_company´ in the yaml file and it's not compatible with the function)
defaults = default and model . _add_missing_default_values ( self . cr , SUPERUSER_ID , { } , context = self . context ) or { }
2012-10-05 12:06:53 +00:00
2012-10-04 11:56:17 +00:00
# copy the default values in record_dict, only if they are in the view (because that's what the client does)
# the other default values will be added later on by the create().
record_dict = dict ( [ ( key , val ) for key , val in defaults . items ( ) if key in fg ] )
2012-10-04 12:15:22 +00:00
2012-10-04 11:56:17 +00:00
# Process all on_change calls
nodes = [ view ]
while nodes :
el = nodes . pop ( 0 )
if el . tag == ' field ' :
field_name = el . attrib [ ' name ' ]
assert field_name in fg , " The field ' %s ' is defined in the form view but not on the object ' %s ' ! " % ( field_name , model . _name )
if field_name in fields :
one2many_form_view = None
if ( view is not False ) and ( fg [ field_name ] [ ' type ' ] == ' one2many ' ) :
2012-10-04 12:15:22 +00:00
# for one2many fields, we want to eval them using the inline form view defined on the parent
2012-10-19 11:06:04 +00:00
one2many_form_view = _get_right_one2many_view ( fg , field_name , ' form ' )
2012-10-04 11:56:17 +00:00
field_value = self . _eval_field ( model , field_name , fields [ field_name ] , one2many_form_view or view_info , parent = record_dict , default = default )
2012-10-19 11:06:04 +00:00
#call process_val to not update record_dict if values were given for readonly fields
val = process_val ( field_name , field_value )
if val :
record_dict [ field_name ] = val
2012-10-04 11:56:17 +00:00
#if (field_name in defaults) and defaults[field_name] == field_value:
# print '*** You can remove these lines:', field_name, field_value
#if field_name has a default value or a value is given in the yaml file, we must call its on_change()
elif field_name not in defaults :
continue
if not el . attrib . get ( ' on_change ' , False ) :
continue
match = re . match ( " ([a-z_1-9A-Z]+) \ ((.*) \ ) " , el . attrib [ ' on_change ' ] )
assert match , " Unable to parse the on_change ' %s ' ! " % ( el . attrib [ ' on_change ' ] , )
# creating the context
class parent2 ( object ) :
def __init__ ( self , d ) :
self . d = d
def __getattr__ ( self , name ) :
return self . d . get ( name , False )
ctx = record_dict . copy ( )
ctx [ ' context ' ] = self . context
ctx [ ' uid ' ] = SUPERUSER_ID
ctx [ ' parent ' ] = parent2 ( parent )
for a in fg :
if a not in ctx :
2012-10-19 11:06:04 +00:00
ctx [ a ] = process_val ( a , defaults . get ( a , False ) )
2012-10-04 11:56:17 +00:00
# Evaluation args
args = map ( lambda x : eval ( x , ctx ) , match . group ( 2 ) . split ( ' , ' ) )
result = getattr ( model , match . group ( 1 ) ) ( self . cr , SUPERUSER_ID , [ ] , * args )
for key , val in ( result or { } ) . get ( ' value ' , { } ) . items ( ) :
2012-10-04 12:24:18 +00:00
assert key in fg , " The returning field ' %s ' from your on_change call ' %s ' does not exist either on the object ' %s ' , either in the view ' %s ' used for the creation " % ( key , match . group ( 1 ) , model . _name , view_info [ ' name ' ] )
2011-11-14 21:26:27 +00:00
record_dict [ key ] = process_val ( key , val )
2011-11-15 00:14:26 +00:00
#if (key in fields) and record_dict[key] == process_val(key, val):
# print '*** You can remove these lines:', key, val
2012-10-04 11:56:17 +00:00
else :
nodes = list ( el ) + nodes
else :
record_dict = { }
2011-11-13 22:30:56 +00:00
2010-03-04 09:44:58 +00:00
for field_name , expression in fields . items ( ) :
2011-11-13 22:30:56 +00:00
if field_name in record_dict :
continue
2012-10-01 15:38:06 +00:00
field_value = self . _eval_field ( model , field_name , expression , default = False )
2010-03-04 09:44:58 +00:00
record_dict [ field_name ] = field_value
2010-05-03 23:35:16 +00:00
return record_dict
2010-04-02 14:03:23 +00:00
def process_ref ( self , node , column = None ) :
2011-10-03 17:13:02 +00:00
assert node . search or node . id , ' !ref node should have a `search` attribute or `id` attribute '
2010-04-02 14:03:23 +00:00
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
2010-05-03 23:35:16 +00:00
2010-04-02 14:03:23 +00:00
def process_eval ( self , node ) :
return eval ( node . expression , self . eval_context )
2010-05-03 23:35:16 +00:00
2012-10-01 15:38:06 +00:00
def _eval_field ( self , model , field_name , expression , view_info = False , parent = { } , default = True ) :
2010-04-21 21:55:05 +00:00
# TODO this should be refactored as something like model.get_field() in bin/osv
if field_name in model . _columns :
column = model . _columns [ field_name ]
elif field_name in model . _inherit_fields :
column = model . _inherit_fields [ field_name ] [ 2 ]
else :
raise KeyError ( " Object ' %s ' does not contain field ' %s ' " % ( model , field_name ) )
2010-03-31 16:55:26 +00:00
if is_ref ( expression ) :
2010-06-08 12:34:59 +00:00
elements = self . process_ref ( expression , column )
2010-04-02 14:03:23 +00:00
if column . _type in ( " many2many " , " one2many " ) :
value = [ ( 6 , 0 , elements ) ]
else : # many2one
2011-10-03 17:13:02 +00:00
if isinstance ( elements , ( list , tuple ) ) :
value = self . _get_first_result ( elements )
else :
value = elements
2010-03-31 16:55:26 +00:00
elif column . _type == " many2one " :
2010-03-04 09:44:58 +00:00
value = self . get_id ( expression )
elif column . _type == " one2many " :
other_model = self . get_model ( column . _obj )
2012-10-01 15:38:06 +00:00
value = [ ( 0 , 0 , self . _create_record ( other_model , fields , view_info , parent , default = default ) ) for fields in expression ]
2010-03-04 09:44:58 +00:00
elif column . _type == " many2many " :
ids = [ self . get_id ( xml_id ) for xml_id in expression ]
2010-03-31 16:55:26 +00:00
value = [ ( 6 , 0 , ids ) ]
2010-09-17 09:41:00 +00:00
elif column . _type == " date " and is_string ( expression ) :
# enforce ISO format for string date values, to be locale-agnostic during tests
2010-09-16 15:08:05 +00:00
time . strptime ( expression , misc . DEFAULT_SERVER_DATE_FORMAT )
2010-09-16 14:46:44 +00:00
value = expression
2010-09-17 09:41:00 +00:00
elif column . _type == " datetime " and is_string ( expression ) :
# enforce ISO format for string datetime values, to be locale-agnostic during tests
2010-09-16 15:08:05 +00:00
time . strptime ( expression , misc . DEFAULT_SERVER_DATETIME_FORMAT )
2010-09-16 14:46:44 +00:00
value = expression
2010-03-04 09:44:58 +00:00
else : # scalar field
2010-03-31 16:55:26 +00:00
if is_eval ( expression ) :
2010-04-02 14:03:23 +00:00
value = self . process_eval ( expression )
2010-03-04 09:44:58 +00:00
else :
value = expression
# raise YamlImportException('Unsupported column "%s" or value %s:%s' % (field_name, type(expression), expression))
return value
2010-09-01 16:42:07 +00:00
2010-03-04 09:44:58 +00:00
def process_context ( self , node ) :
self . context = node . __dict__
2010-03-09 12:27:46 +00:00
if node . uid :
self . uid = self . get_id ( node . uid )
if node . noupdate :
self . noupdate = node . noupdate
2010-09-01 16:42:07 +00:00
2010-03-04 09:44:58 +00:00
def process_python ( self , node ) :
python , statements = node . items ( ) [ 0 ]
model = self . get_model ( python . model )
2010-03-05 13:46:41 +00:00
statements = statements . replace ( " \r \n " , " \n " )
2012-08-31 13:53:09 +00:00
code_context = { ' model ' : model , ' cr ' : self . cr , ' uid ' : self . uid , ' log ' : self . _log , ' context ' : self . context }
2010-04-08 20:18:54 +00:00
code_context . update ( { ' self ' : model } ) # remove me when no !python block test uses 'self' anymore
2010-03-04 09:44:58 +00:00
try :
2010-06-04 00:39:40 +00:00
code_obj = compile ( statements , self . filename , ' exec ' )
unsafe_eval ( code_obj , { ' ref ' : self . get_id } , code_context )
2010-03-04 15:41:59 +00:00
except AssertionError , e :
2012-03-02 11:28:34 +00:00
self . _log_assert_failure ( ' AssertionError in Python code %s : %s ' , python . name , e )
2010-03-04 15:41:59 +00:00
return
2010-03-04 09:44:58 +00:00
except Exception , e :
2012-01-24 14:00:56 +00:00
_logger . debug ( ' Exception during evaluation of !python block in yaml_file %s . ' , self . filename , exc_info = True )
2010-09-01 16:42:07 +00:00
raise
2010-03-04 15:41:59 +00:00
else :
2012-03-02 11:02:27 +00:00
self . assertion_report . record_success ( )
2011-05-13 09:44:05 +00:00
2010-03-04 09:44:58 +00:00
def process_workflow ( self , node ) :
workflow , values = node . items ( ) [ 0 ]
2010-03-05 10:05:37 +00:00
if self . isnoupdate ( workflow ) and self . mode != ' init ' :
return
2010-03-04 09:44:58 +00:00
if workflow . ref :
id = self . get_id ( workflow . ref )
else :
if not values :
raise YamlImportException ( ' You must define a child node if you do not give a ref. ' )
if not len ( values ) == 1 :
raise YamlImportException ( ' Only one child node is accepted ( %d given). ' % len ( values ) )
value = values [ 0 ]
2010-03-05 09:12:18 +00:00
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. ' )
2010-03-04 09:44:58 +00:00
value_model = self . get_model ( value [ ' model ' ] )
2010-03-09 09:23:46 +00:00
local_context = { ' obj ' : lambda x : value_model . browse ( self . cr , self . uid , x , context = self . context ) }
2010-03-04 09:44:58 +00:00
local_context . update ( self . id_map )
2010-03-09 09:23:46 +00:00
id = eval ( value [ ' eval ' ] , self . eval_context , local_context )
2011-05-13 09:44:05 +00:00
2010-03-04 09:44:58 +00:00
if workflow . uid is not None :
uid = workflow . uid
else :
uid = self . uid
2010-04-30 14:18:10 +00:00
self . cr . execute ( ' select distinct signal from wkf_transition ' )
signals = [ x [ ' signal ' ] for x in self . cr . dictfetchall ( ) ]
if workflow . action not in signals :
raise YamlImportException ( ' Incorrect action %s . No such action defined ' % workflow . action )
2011-02-07 12:57:23 +00:00
import openerp . netsvc as netsvc
2010-03-04 09:44:58 +00:00
wf_service = netsvc . LocalService ( " workflow " )
2010-04-01 13:27:09 +00:00
wf_service . trg_validate ( uid , workflow . model , id , workflow . action , self . cr )
2011-05-13 09:44:05 +00:00
2010-04-02 14:03:23 +00:00
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 )
2010-04-08 13:44:04 +00:00
ids = param_model . search ( self . cr , self . uid , q )
2010-04-02 14:03:23 +00:00
value = self . _get_first_result ( ids )
elif ' eval ' in param :
2010-04-08 13:44:04 +00:00
local_context = { ' obj ' : lambda x : param_model . browse ( self . cr , self . uid , x , self . context ) }
2010-04-02 14:03:23 +00:00
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
2011-05-13 09:44:05 +00:00
2010-03-05 09:12:18 +00:00
def process_function ( self , node ) :
2010-04-01 19:26:47 +00:00
function , params = node . items ( ) [ 0 ]
2010-03-05 10:05:37 +00:00
if self . isnoupdate ( function ) and self . mode != ' init ' :
return
2010-04-01 19:26:47 +00:00
model = self . get_model ( function . model )
2010-03-05 09:12:18 +00:00
if function . eval :
2010-04-02 14:03:23 +00:00
args = self . process_eval ( function . eval )
else :
args = self . _eval_params ( function . model , params )
2010-03-05 09:12:18 +00:00
method = function . name
getattr ( model , method ) ( self . cr , self . uid , * args )
2011-05-13 09:44:05 +00:00
2010-03-05 09:12:18 +00:00
def _set_group_values ( self , node , values ) :
if node . groups :
group_names = node . groups . split ( ' , ' )
groups_value = [ ]
for group in group_names :
if group . startswith ( ' - ' ) :
group_id = self . get_id ( group [ 1 : ] )
groups_value . append ( ( 3 , group_id ) )
else :
group_id = self . get_id ( group )
groups_value . append ( ( 4 , group_id ) )
values [ ' groups_id ' ] = groups_value
def process_menuitem ( self , node ) :
self . validate_xml_id ( node . id )
if not node . parent :
parent_id = False
self . cr . execute ( ' select id from ir_ui_menu where parent_id is null and name= %s ' , ( node . name , ) )
res = self . cr . fetchone ( )
values = { ' parent_id ' : parent_id , ' name ' : node . name }
else :
parent_id = self . get_id ( node . parent )
values = { ' parent_id ' : parent_id }
if node . name :
values [ ' name ' ] = node . name
try :
res = [ self . get_id ( node . id ) ]
except : # which exception ?
res = None
if node . action :
action_type = node . type or ' act_window '
icons = {
" act_window " : ' STOCK_NEW ' ,
" report.xml " : ' STOCK_PASTE ' ,
" wizard " : ' STOCK_EXECUTE ' ,
" url " : ' STOCK_JUMP_TO ' ,
}
values [ ' icon ' ] = icons . get ( action_type , ' STOCK_NEW ' )
if action_type == ' act_window ' :
action_id = self . get_id ( node . action )
self . cr . execute ( ' select view_type,view_mode,name,view_id,target from ir_act_window where id= %s ' , ( action_id , ) )
ir_act_window_result = self . cr . fetchone ( )
assert ir_act_window_result , " No window action defined for this id %s ! \n " \
" Verify that this is a window action or add a type argument. " % ( node . action , )
action_type , action_mode , action_name , view_id , target = ir_act_window_result
if view_id :
self . cr . execute ( ' SELECT type FROM ir_ui_view WHERE id= %s ' , ( view_id , ) )
# TODO guess why action_mode is ir_act_window.view_mode above and ir_ui_view.type here
action_mode = self . cr . fetchone ( )
self . cr . execute ( ' SELECT view_mode FROM ir_act_window_view WHERE act_window_id= %s ORDER BY sequence LIMIT 1 ' , ( action_id , ) )
if self . cr . rowcount :
action_mode = self . cr . fetchone ( )
if action_type == ' tree ' :
values [ ' icon ' ] = ' STOCK_INDENT '
elif action_mode and action_mode . startswith ( ' tree ' ) :
values [ ' icon ' ] = ' STOCK_JUSTIFY_FILL '
elif action_mode and action_mode . startswith ( ' graph ' ) :
values [ ' icon ' ] = ' terp-graph '
elif action_mode and action_mode . startswith ( ' calendar ' ) :
values [ ' icon ' ] = ' terp-calendar '
if target == ' new ' :
values [ ' icon ' ] = ' STOCK_EXECUTE '
if not values . get ( ' name ' , False ) :
values [ ' name ' ] = action_name
elif action_type == ' wizard ' :
action_id = self . get_id ( node . action )
self . cr . execute ( ' select name from ir_act_wizard where id= %s ' , ( action_id , ) )
ir_act_wizard_result = self . cr . fetchone ( )
if ( not values . get ( ' name ' , False ) ) and ir_act_wizard_result :
values [ ' name ' ] = ir_act_wizard_result [ 0 ]
else :
raise YamlImportException ( " Unsupported type ' %s ' in menuitem tag. " % action_type )
if node . sequence :
values [ ' sequence ' ] = node . sequence
if node . icon :
values [ ' icon ' ] = node . icon
self . _set_group_values ( node , values )
2011-05-13 09:44:05 +00:00
2012-08-31 13:53:09 +00:00
pid = self . pool . get ( ' ir.model.data ' ) . _update ( self . cr , SUPERUSER_ID , \
2010-03-05 09:12:18 +00:00
' ir.ui.menu ' , self . module , values , node . id , mode = self . mode , \
2010-03-05 10:05:37 +00:00
noupdate = self . isnoupdate ( node ) , res_id = res and res [ 0 ] or False )
2010-03-05 09:12:18 +00:00
if node . id and parent_id :
self . id_map [ node . id ] = int ( parent_id )
if node . action and pid :
action_type = node . type or ' act_window '
action_id = self . get_id ( node . action )
action = " ir.actions. %s , %d " % ( action_type , action_id )
2012-08-31 13:53:09 +00:00
self . pool . get ( ' ir.model.data ' ) . ir_set ( self . cr , SUPERUSER_ID , ' action ' , \
2010-03-05 09:12:18 +00:00
' tree_but_open ' , ' Menuitem ' , [ ( ' ir.ui.menu ' , int ( parent_id ) ) ] , action , True , True , xml_id = node . id )
def process_act_window ( self , node ) :
2010-04-30 14:18:10 +00:00
assert getattr ( node , ' id ' ) , " Attribute %s of act_window is empty ! " % ( ' id ' , )
assert getattr ( node , ' name ' ) , " Attribute %s of act_window is empty ! " % ( ' name ' , )
assert getattr ( node , ' res_model ' ) , " Attribute %s of act_window is empty ! " % ( ' res_model ' , )
2010-03-05 09:12:18 +00:00
self . validate_xml_id ( node . id )
view_id = False
if node . view :
view_id = self . get_id ( node . view )
2010-04-30 14:18:10 +00:00
if not node . context :
node . context = { }
context = eval ( str ( node . context ) , self . eval_context )
2010-03-05 09:12:18 +00:00
values = {
' name ' : node . name ,
2010-04-30 14:18:10 +00:00
' type ' : node . type or ' ir.actions.act_window ' ,
2010-03-05 09:12:18 +00:00
' view_id ' : view_id ,
' domain ' : node . domain ,
' context ' : context ,
' res_model ' : node . res_model ,
' src_model ' : node . src_model ,
' view_type ' : node . view_type or ' form ' ,
' view_mode ' : node . view_mode or ' tree,form ' ,
' usage ' : node . usage ,
' limit ' : node . limit ,
' auto_refresh ' : node . auto_refresh ,
2010-10-15 14:07:29 +00:00
' multi ' : getattr ( node , ' multi ' , False ) ,
2010-03-05 09:12:18 +00:00
}
self . _set_group_values ( node , values )
if node . target :
values [ ' target ' ] = node . target
2012-08-31 13:53:09 +00:00
id = self . pool . get ( ' ir.model.data ' ) . _update ( self . cr , SUPERUSER_ID , \
2010-03-05 09:12:18 +00:00
' ir.actions.act_window ' , self . module , values , node . id , mode = self . mode )
self . id_map [ node . id ] = int ( id )
if node . src_model :
keyword = ' client_action_relate '
value = ' ir.actions.act_window, %s ' % id
replace = node . replace or True
2012-08-31 13:53:09 +00:00
self . pool . get ( ' ir.model.data ' ) . ir_set ( self . cr , SUPERUSER_ID , ' action ' , keyword , \
2010-03-05 10:05:37 +00:00
node . id , [ node . src_model ] , value , replace = replace , noupdate = self . isnoupdate ( node ) , isobject = True , xml_id = node . id )
2010-03-05 09:12:18 +00:00
# TODO add remove ir.model.data
def process_delete ( self , node ) :
2010-04-30 14:18:10 +00:00
assert getattr ( node , ' model ' ) , " Attribute %s of delete tag is empty ! " % ( ' model ' , )
if self . pool . get ( node . model ) :
2011-11-02 12:46:14 +00:00
if node . search :
2010-04-30 14:18:10 +00:00
ids = self . pool . get ( node . model ) . search ( self . cr , self . uid , eval ( node . search , self . eval_context ) )
else :
ids = [ self . get_id ( node . id ) ]
if len ( ids ) :
self . pool . get ( node . model ) . unlink ( self . cr , self . uid , ids )
2010-04-02 08:08:55 +00:00
else :
2012-08-22 10:11:56 +00:00
self . _log ( " Record not deleted. " )
2011-05-13 09:44:05 +00:00
2010-03-05 09:12:18 +00:00
def process_url ( self , node ) :
self . validate_xml_id ( node . id )
res = { ' name ' : node . name , ' url ' : node . url , ' target ' : node . target }
2012-08-31 13:53:09 +00:00
id = self . pool . get ( ' ir.model.data ' ) . _update ( self . cr , SUPERUSER_ID , \
2012-06-08 10:17:10 +00:00
" ir.actions.act_url " , self . module , res , node . id , mode = self . mode )
2010-03-05 09:12:18 +00:00
self . id_map [ node . id ] = int ( id )
# ir_set
if ( not node . menu or eval ( node . menu ) ) and id :
keyword = node . keyword or ' client_action_multi '
2012-06-08 10:17:10 +00:00
value = ' ir.actions.act_url, %s ' % id
2010-03-05 09:12:18 +00:00
replace = node . replace or True
2012-08-31 13:53:09 +00:00
self . pool . get ( ' ir.model.data ' ) . ir_set ( self . cr , SUPERUSER_ID , ' action ' , \
2012-06-08 10:17:10 +00:00
keyword , node . url , [ " ir.actions.act_url " ] , value , replace = replace , \
2010-03-05 10:05:37 +00:00
noupdate = self . isnoupdate ( node ) , isobject = True , xml_id = node . id )
2011-05-13 09:44:05 +00:00
2010-03-05 09:37:22 +00:00
def process_ir_set ( self , node ) :
if not self . mode == ' init ' :
return False
_ , fields = node . items ( ) [ 0 ]
res = { }
for fieldname , expression in fields . items ( ) :
2010-04-08 13:52:00 +00:00
if is_eval ( expression ) :
2010-03-09 09:23:46 +00:00
value = eval ( expression . expression , self . eval_context )
2010-03-05 09:37:22 +00:00
else :
value = expression
res [ fieldname ] = value
2012-08-31 13:53:09 +00:00
self . pool . get ( ' ir.model.data ' ) . ir_set ( self . cr , SUPERUSER_ID , res [ ' key ' ] , res [ ' key2 ' ] , \
2010-03-05 09:37:22 +00:00
res [ ' name ' ] , res [ ' models ' ] , res [ ' value ' ] , replace = res . get ( ' replace ' , True ) , \
isobject = res . get ( ' isobject ' , False ) , meta = res . get ( ' meta ' , None ) )
2010-03-05 09:12:18 +00:00
2010-03-05 10:42:04 +00:00
def process_report ( self , node ) :
values = { }
for dest , f in ( ( ' name ' , ' string ' ) , ( ' model ' , ' model ' ) , ( ' report_name ' , ' name ' ) ) :
values [ dest ] = getattr ( node , f )
assert values [ dest ] , " Attribute %s of report is empty ! " % ( f , )
2010-10-12 09:58:04 +00:00
for field , dest in ( ( ' rml ' , ' report_rml ' ) , ( ' file ' , ' report_rml ' ) , ( ' xml ' , ' report_xml ' ) , ( ' xsl ' , ' report_xsl ' ) , ( ' attachment ' , ' attachment ' ) , ( ' attachment_use ' , ' attachment_use ' ) ) :
2010-03-05 10:42:04 +00:00
if getattr ( node , field ) :
values [ dest ] = getattr ( node , field )
if node . auto :
values [ ' auto ' ] = eval ( node . auto )
if node . sxw :
2011-01-04 10:13:35 +00:00
sxw_file = misc . file_open ( node . sxw )
try :
sxw_content = sxw_file . read ( )
values [ ' report_sxw_content ' ] = sxw_content
finally :
sxw_file . close ( )
2010-03-05 10:42:04 +00:00
if node . header :
values [ ' header ' ] = eval ( node . header )
values [ ' multi ' ] = node . multi and eval ( node . multi )
xml_id = node . id
self . validate_xml_id ( xml_id )
self . _set_group_values ( node , values )
2012-08-31 13:53:09 +00:00
id = self . pool . get ( ' ir.model.data ' ) . _update ( self . cr , SUPERUSER_ID , " ir.actions.report.xml " , \
2010-03-05 10:42:04 +00:00
self . module , values , xml_id , noupdate = self . isnoupdate ( node ) , mode = self . mode )
self . id_map [ xml_id ] = int ( id )
if not node . menu or eval ( node . menu ) :
keyword = node . keyword or ' client_print_multi '
value = ' ir.actions.report.xml, %s ' % id
replace = node . replace or True
2012-08-31 13:53:09 +00:00
self . pool . get ( ' ir.model.data ' ) . ir_set ( self . cr , SUPERUSER_ID , ' action ' , \
2010-03-05 10:42:04 +00:00
keyword , values [ ' name ' ] , [ values [ ' model ' ] ] , value , replace = replace , isobject = True , xml_id = xml_id )
2011-05-13 09:44:05 +00:00
2010-03-09 09:23:46 +00:00
def process_none ( self ) :
"""
Empty node or commented node should not pass silently .
"""
2012-03-02 11:28:34 +00:00
self . _log_assert_failure ( " You have an empty block in your tests. " )
2011-05-13 09:44:05 +00:00
2010-03-05 10:42:04 +00:00
2010-03-04 09:44:58 +00:00
def process ( self , yaml_string ) :
2010-03-09 09:23:46 +00:00
"""
Processes a Yaml string . Custom tags are interpreted by ' process_ ' instance methods .
"""
2010-04-30 14:18:10 +00:00
yaml_tag . add_constructors ( )
2010-03-04 09:44:58 +00:00
is_preceded_by_comment = False
for node in yaml . load ( yaml_string ) :
2012-08-22 10:11:56 +00:00
is_preceded_by_comment = self . _log_node ( node , is_preceded_by_comment )
2010-03-04 09:44:58 +00:00
try :
self . _process_node ( node )
2010-03-09 09:23:46 +00:00
except Exception , e :
2012-01-24 14:00:56 +00:00
_logger . exception ( e )
2010-05-19 18:32:10 +00:00
raise
2011-05-13 09:44:05 +00:00
2010-03-04 09:44:58 +00:00
def _process_node ( self , node ) :
if is_comment ( node ) :
self . process_comment ( node )
elif is_assert ( node ) :
self . process_assert ( node )
elif is_record ( node ) :
self . process_record ( node )
elif is_python ( node ) :
self . process_python ( node )
2010-03-05 09:12:18 +00:00
elif is_menuitem ( node ) :
self . process_menuitem ( node )
elif is_delete ( node ) :
self . process_delete ( node )
elif is_url ( node ) :
self . process_url ( node )
2010-03-04 09:44:58 +00:00
elif is_context ( node ) :
self . process_context ( node )
2010-03-05 09:37:22 +00:00
elif is_ir_set ( node ) :
self . process_ir_set ( node )
2010-03-05 09:12:18 +00:00
elif is_act_window ( node ) :
self . process_act_window ( node )
2010-03-05 10:42:04 +00:00
elif is_report ( node ) :
self . process_report ( node )
2010-03-04 09:44:58 +00:00
elif is_workflow ( node ) :
if isinstance ( node , types . DictionaryType ) :
self . process_workflow ( node )
else :
self . process_workflow ( { node : [ ] } )
2010-03-05 09:12:18 +00:00
elif is_function ( node ) :
if isinstance ( node , types . DictionaryType ) :
self . process_function ( node )
else :
self . process_function ( { node : [ ] } )
2010-03-09 09:23:46 +00:00
elif node is None :
self . process_none ( )
2010-03-04 09:44:58 +00:00
else :
raise YamlImportException ( " Can not process YAML block: %s " % node )
2011-05-13 09:44:05 +00:00
2012-08-22 10:11:56 +00:00
def _log_node ( self , node , is_preceded_by_comment ) :
2010-03-04 09:44:58 +00:00
if is_comment ( node ) :
is_preceded_by_comment = True
2012-08-22 10:11:56 +00:00
self . _log ( node )
2010-03-04 09:44:58 +00:00
elif not is_preceded_by_comment :
if isinstance ( node , types . DictionaryType ) :
2010-03-07 21:18:33 +00:00
msg = " Creating %s \n with %s "
args = node . items ( ) [ 0 ]
2012-08-22 10:11:56 +00:00
self . _log ( msg , * args )
2010-03-04 09:44:58 +00:00
else :
2012-08-22 10:11:56 +00:00
self . _log ( node )
2010-03-04 09:44:58 +00:00
else :
is_preceded_by_comment = False
return is_preceded_by_comment
2012-08-22 10:11:56 +00:00
def yaml_import ( cr , module , yamlfile , kind , idref = None , mode = ' init ' , noupdate = False , report = None ) :
2010-03-04 09:44:58 +00:00
if idref is None :
idref = { }
2012-08-22 10:11:56 +00:00
loglevel = logging . TEST if kind == ' test ' else logging . DEBUG
2010-03-04 09:44:58 +00:00
yaml_string = yamlfile . read ( )
2012-08-22 10:11:56 +00:00
yaml_interpreter = YamlInterpreter ( cr , module , idref , mode , filename = yamlfile . name , report = report , noupdate = noupdate , loglevel = loglevel )
2010-03-04 09:44:58 +00:00
yaml_interpreter . process ( yaml_string )
# keeps convention of convert.py
convert_yaml_import = yaml_import
2011-09-14 10:43:00 +00:00
def threaded_yaml_import ( db_name , module_name , file_name , delay = 0 ) :
def f ( ) :
time . sleep ( delay )
cr = None
fp = None
try :
cr = sql_db . db_connect ( db_name ) . cursor ( )
fp = misc . file_open ( file_name )
convert_yaml_import ( cr , module_name , fp , { } , ' update ' , True )
finally :
if cr : cr . close ( )
if fp : fp . close ( )
threading . Thread ( target = f ) . start ( )
2010-03-04 09:44:58 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: