def readdir(self, path, offset): """ Return content of a directory : - List models for root path - List records for a model - List attachments for a record We don't have to check for the path, because getattr already returns -ENOENT if the model/record/attachment doesn't exist """ yield fuse.Direntry('.') yield fuse.Direntry('..') paths = path.split('/')[1:] # List models if path == '/': model_obj = Object(self.oerp_connection, 'ir.model') model_ids = model_obj.search([]) for model_data in model_obj.read(model_ids, ['model']): yield fuse.Direntry(model_data['model']) # List records elif len(paths) == 1: element_obj = Object(self.oerp_connection, paths[0]) element_ids = element_obj.search([]) for element_data in element_obj.read(element_ids, ['id']): yield fuse.Direntry(str(element_data['id'])) # List attachments else: attachment_obj = Object(self.oerp_connection, 'ir.attachment') attachment_ids = attachment_obj.search([('res_model', '=', paths[0]), ('res_id', '=', int(paths[1]))]) for attachment_data in attachment_obj.read(attachment_ids, ['name']): yield fuse.Direntry('%d-%s' % (attachment_data['id'], attachment_data['name']))
def readdir(self, path, offset): """ Return content of a directory : - List models for root path - List records for a model - List attachments for a record We don't have to check for the path, because getattr already returns -ENOENT if the model/record/attachment doesn't exist """ yield fuse.Direntry('.') yield fuse.Direntry('..') paths = path.split('/')[1:] # List models if path == '/': model_obj = Object(self.oerp_connection, 'ir.model') model_ids = model_obj.search([]) for model_data in model_obj.read(model_ids, ['model']): yield fuse.Direntry(model_data['model']) # List records elif len(paths) == 1: element_obj = Object(self.oerp_connection, paths[0]) element_ids = element_obj.search([]) for element_data in element_obj.read(element_ids, ['id']): yield fuse.Direntry(str(element_data['id'])) # List attachments else: attachment_obj = Object(self.oerp_connection, 'ir.attachment') attachment_ids = attachment_obj.search([ ('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])) ]) for attachment_data in attachment_obj.read(attachment_ids, ['name']): yield fuse.Direntry( '%d-%s' % (attachment_data['id'], attachment_data['name']))
def getattr(self, path): """ Return attributes for the specified path : - Search for the model as first part - Search for an existing record as second part - Search for an existing attachment as third part - There cannot be more than 3 parts in the path """ fakeStat = fuse.Stat() fakeStat.st_mode = stat.S_IFDIR | 0400 fakeStat.st_nlink = 0 if path == '/': return fakeStat paths = path.split('/')[1:] if len(paths) > 3: return -ENOENT # Check for model existence model_obj = Object(self.oerp_connection, 'ir.model') model_ids = model_obj.search([('model', '=', paths[0])]) if not model_ids: return -ENOENT elif len(paths) == 1: return fakeStat # Check for record existence element_obj = Object(self.oerp_connection, paths[0]) element_ids = element_obj.search([('id', '=', int(paths[1]))]) if not element_ids: return -ENOENT elif len(paths) == 2: return fakeStat # Chech for attachement existence attachment_obj = Object(self.oerp_connection, 'ir.attachment') attachment_ids = attachment_obj.search([ ('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])), ('id', '=', self.id_from_label(paths[2])) ]) if not attachment_ids: return -ENOENT # Common stats fakeStat.st_mode = stat.S_IFREG | 0400 fakeStat.st_nlink = 2 # TODO : Read the file size from a dedicated field (created in a specific module) attachment_obj = Object(self.oerp_connection, 'ir.attachment') attachment_ids = attachment_obj.search([ ('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])), ('id', '=', self.id_from_label(paths[2])) ]) attachment_data = attachment_obj.read(attachment_ids, ['datas']) fakeStat.st_size = len(base64.b64decode(attachment_data[0]['datas'])) return fakeStat
def read(self, path, size, offset): """ Return the specified slide of a file Note : Only the beginning of the name is required (the ID of the attachment), we can put anything after the first '-', it will be ignored """ paths = path.split('/')[1:] # TODO : Create a module that allows to read files by slides attachment_obj = Object(self.oerp_connection, 'ir.attachment') attachment_ids = attachment_obj.search([('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])), ('id', '=', self.id_from_label(paths[2]))]) attachment_data = attachment_obj.read(attachment_ids, ['datas']) return base64.b64decode(attachment_data[0]['datas'])[offset:offset + size]
def _get_attr(self, searchTuples, objectName, attribute): """ returns value of the attribute """ obj = Object(self.cnx, objectName) results = obj.search(searchTuples) if len(results) != 1: raise ValueError("We did not get a single " + \ self.common[objectName] + " back. " + \ str(results)) else: return obj.read(results[0])[attribute]
def getattr(self, path): """ Return attributes for the specified path : - Search for the model as first part - Search for an existing record as second part - Search for an existing attachment as third part - There cannot be more than 3 parts in the path """ fakeStat = fuse.Stat() fakeStat.st_mode = stat.S_IFDIR | 0400 fakeStat.st_nlink = 0 if path == '/': return fakeStat paths = path.split('/')[1:] if len(paths) > 3: return -ENOENT # Check for model existence model_obj = Object(self.oerp_connection, 'ir.model') model_ids = model_obj.search([('model', '=', paths[0])]) if not model_ids: return -ENOENT elif len(paths) == 1: return fakeStat # Check for record existence element_obj = Object(self.oerp_connection, paths[0]) element_ids = element_obj.search([('id', '=', int(paths[1]))]) if not element_ids: return -ENOENT elif len(paths) == 2: return fakeStat # Chech for attachement existence attachment_obj = Object(self.oerp_connection, 'ir.attachment') attachment_ids = attachment_obj.search([('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])), ('id', '=', self.id_from_label(paths[2]))]) if not attachment_ids: return -ENOENT # Common stats fakeStat.st_mode = stat.S_IFREG | 0400 fakeStat.st_nlink = 2 # TODO : Read the file size from a dedicated field (created in a specific module) attachment_obj = Object(self.oerp_connection, 'ir.attachment') attachment_ids = attachment_obj.search([('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])), ('id', '=', self.id_from_label(paths[2]))]) attachment_data = attachment_obj.read(attachment_ids, ['datas']) fakeStat.st_size = len(base64.b64decode(attachment_data[0]['datas'])) return fakeStat
def read(self, path, size, offset): """ Return the specified slide of a file Note : Only the beginning of the name is required (the ID of the attachment), we can put anything after the first '-', it will be ignored """ paths = path.split('/')[1:] # TODO : Create a module that allows to read files by slides attachment_obj = Object(self.oerp_connection, 'ir.attachment') attachment_ids = attachment_obj.search([ ('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])), ('id', '=', self.id_from_label(paths[2])) ]) attachment_data = attachment_obj.read(attachment_ids, ['datas']) return base64.b64decode(attachment_data[0]['datas'])[offset:offset + size]
password=opts.passwd, port=opts.port) except Exception, e: logger.error('Fail to connect to the server') logger.error('%s' % str(e)) sys.exit(1) model = Object(cnx, opts.model) mod_count = model.search_count([]) logger.info('There are %d record to export' % mod_count) fields = model.fields_get() fields_name = fields.keys() result = model.read(model.search([])) from odf.opendocument import OpenDocumentSpreadsheet from odf.style import Style, TextProperties, ParagraphProperties, TableColumnProperties from odf.text import P from odf.table import Table, TableColumn, TableRow, TableCell textdoc = OpenDocumentSpreadsheet() tablecontents = Style(name="Table Contents", family="paragraph") tablecontents.addElement(ParagraphProperties(numberlines="false", linenumber="0")) tablecontents.addElement(TextProperties(fontweight="bold")) textdoc.styles.addElement(tablecontents) table = Table(name=opts.model) if opts.title:
elif opts.inactive: count = model.search_count([], {'active_test': False}) model_ids = model.search([], 0, count, 0, {'active_test': False}) else: count = model.search_count([]) model_ids = model.search([], 0, count) root = Element('openerp') data = SubElement(root, 'data') for m_id in model_ids: ## # Read the current id # mod = model.read(m_id) record = SubElement(data, 'record') record.set('model', opts.model) record.set('id', Ir_Model_Data(opts.model, m_id)) o2m_dict = {} for fld in f_list: f_type = fields[fld]['type'] if fld in ('parent_left', 'parent_right'): continue if mod[fld] or opts.all or f_type == 'boolean' or fld == 'active': field = SubElement(record, 'field') field.set('name', fld) if f_type in('char', 'text'): field.text = unicode(mod[fld]) or '' elif f_type in ('int', 'integer'): field.set('eval', mod[fld] and str(mod[fld]) or '0')
if opts.oerp_version == '5': print 'version 5' model = mod.search([]) else: print 'version 6' model = mod.search([('osv_memory', '=', False)]) print 80 * '-' print '| Model | Search | Read | View XML |' print 80 * '-' footer = '--- FOOTER REPORT ---\n' for m in mod.read(model): if m['model'].startswith('ir_') or m['model'].find('wizard') >= 0: continue t = Object(cnx, m['model']) try: t_ids = t.search([]) search = ('%d' % len(t_ids)).zfill(4) except Exception, e: search = 'ERR' footer += 'Objet: %s\n' % m['model'] footer += 'Message: %s\n' % str(e) try: read = 'NA ' if t_ids: end_id = min(10, len(t_ids)) - 1
password=opts.passwd) except Exception, e: print '%s' % str(e) exit(1) user = Object(cnx, 'res.users') rule = Object(cnx, 'ir.rule') user_id = user.search([('login', '=', opts.user)])[0] if opts.legend: comp = Object(cnx, 'res.company') company_ids = comp.search([]) print 'List all company' print 80 * '*' for compa in comp.read(company_ids, ['name']): print '%s -> %d' % (compa['name'].ljust(20), compa['id']) print 80 * '*' company_id = user.read(user_id, ['company_id'])['company_id'] try: dest = rule.domain_get(opts.model) except Exception, e: print "Object %s doesn't exists" % opts.model exit(1) print '\nUser: %s (id %d) => %s (id %d)' % (opts.user, user_id, company_id[1], company_id[0]) if dest[0] or dest[1]: where = ' AND '.join(dest[0])
try: logger.info('Open connection to "%s:%s" on "%s" with user "%s" ' % (opts.server, opts.port, opts.dbname, opts.user)) cnx = Connection( server=opts.server, dbname=opts.dbname, login=opts.user, password=opts.passwd, port=opts.port) except Exception, e: logger.error('Fail to connect to the server') logger.error('%s' % str(e)) sys.exit(1) model = Object(cnx, opts.model) model_ids = model.search([]) model_lists = model.read(model_ids, [opts.field,'parent_left','parent_right']) models = dict(map(lambda x: (x['id'],x), model_lists)) try: for a in model_lists: logger.debug('id: %d' % a['id']) if a[opts.field]: assert a['parent_left'] > models[a[opts.field][0]]['parent_left'], '%s > %s' % (a['parent_left'], models[a[opts.field][0]]['parent_left']) assert a['parent_right'] < models[a[opts.field][0]]['parent_right'], '%s > %s' % (a['parent_right'], models[a[opts.field][0]]['parent_right']) assert a['parent_left'] < a['parent_right'] for a2 in model_lists: assert not ((a2['parent_right']>a['parent_left']) and (a2['parent_left']<a['parent_left']) and (a2['parent_right']<a['parent_right'])) if a2[opts.field]==a['id']: assert (a2['parent_left']>a['parent_left']) and (a2['parent_right']<a['parent_right']) logger.info('No problem found')
#root.set('name', 'to_be_defined') #root.set('language', 'groovy') #root.set('pageWidth', '595') #root.set('pageHeight', '842') #root.set('columnWidth', '555') #root.set('leftMargin', '20') #root.set('rightMargin', '20') #root.set('topMargin', '20') #root.set('bottomMargin', '20') jasper_ids = jasper_obj.search([('service', '=', opts.service)]) if not jasper_ids: print 'Service %s not found' % opts.service exit(1) jasper = jasper_obj.read(jasper_ids[0]) if isinstance(jasper, list): jasper = jasper[0] #print jasper for lab in label_obj.read(jasper['label_ids'], ['name', 'value']): #print lab #<parameter name="I18N_TITLE" class="java.lang.String" isForPrompting="false"> # <defaultValueExpression><![CDATA["BON DE RETOUR S.A.V."]]></defaultValueExpression> #</parameter> parameter = SubElement(root, 'parameter') parameter.set('name', 'I18N_' + lab['name'].upper()) parameter.set('class', 'java.lang.String')
""" Replace all non alphanumeric characters by underscores """ return re.sub(r'[^\w\d]', '_', name).lower() resid = {} opts.directory = os.path.expanduser(opts.directory) # extract scenario scenario_obj = Object(cnx, 'scanner.scenario') model_obj = Object(cnx, 'ir.model') warehouse_obj = Object(cnx, 'stock.warehouse') user_obj = Object(cnx, 'res.users') group_obj = Object(cnx, 'res.groups') scen_read = scenario_obj.read(int(opts.scenario_id), [], '_classic_read', {'active_test': False}) scen_read = scen_read and scen_read[0] if not scen_read: logger.error('Scenario ID %s not found' % opts.scenario_id) sys.exit(1) del scen_read['step_ids'] field_to_remove = [ 'create_uid', 'create_date', 'write_uid', 'write_date', '__last_update', 'display_name' ] for field in field_to_remove: del scen_read[field] scenario_xml_id = scenario_obj.get_metadata(opts.scenario_id)[0]['xmlid'] if not scenario_xml_id:
try: cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user, port=opts.port, password=opts.passwd) except Exception, e: print '%s' % str(e) exit(1) def generate_tracking_message_id(openobject_id): """Returns a string that can be used in the Message-ID RFC822 header field so we can track the replies related to a given object thanks to the "In-Reply-To" or "References" fields that Mail User Agents will set. """ s = hashlib.sha1() s.update(str(time.time())) return "<%s-openobject-%s@%s>" % (s.hexdigest(), openobject_id, 'syleam6.syleam.fr') message = Object(cnx, 'mailgate.message') message_ids = message.search([('model','=','project.issue'),('message_id','=', False)]) print '%d message to update' % len(message_ids) for m in message.read(message_ids, ['name', 'res_id']): args = {'message_id': generate_tracking_message_id(m['res_id'])} message.write([m['id']], args) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
password=opts.passwd) except Exception, e: print '%s' % str(e) exit(1) user = Object(cnx, 'res.users') rule = Object(cnx, 'ir.rule') user_id = user.search([('login','=', opts.user)])[0] if opts.legend: comp = Object(cnx, 'res.company') company_ids = comp.search([]) print 'List all company' print 80 * '*' for compa in comp.read(company_ids, ['name']): print '%s -> %d' % (compa['name'].ljust(20), compa['id']) print 80 * '*' company_id = user.read(user_id, ['company_id'])['company_id'] try: dest = rule.domain_get(opts.model) except Exception, e: print "Object %s doesn't exists" % opts.model exit(1) print '\nUser: %s (id %d) => %s (id %d)' % (opts.user, user_id, company_id[1], company_id[0]) if dest[0] or dest[1]: where = ' AND '.join(dest[0]) where = where % tuple(dest[1])
try: cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user, password=opts.passwd) except Exception, e: print '%s' % str(e) exit(1) user = Object(cnx, 'res.users') multi = Object(cnx, 'res.company') user_id = user.search([('login', '=', opts.user)])[0] # save company_id to restore it after curr = user.read(user_id, ['company_ids', 'company_id']) c_save_id = curr['company_id'] print 'User: %d => %s (id %d)' % (user_id, c_save_id[1], c_save_id[0]) ## # If the company argument is missing, retrieve all companies in the user form # if opts.company: companies = opts.company.split(',') else: companies = curr['company_ids'] s = 23 header = ('Main Company'.ljust(s), 'Object'.ljust(s), 'Dest Company'.ljust(s)) print 80 * '-'
try: logger.info('Open connection to "%s:%s" on "%s" with user "%s" ' % (opts.server, opts.port, opts.dbname, opts.user)) cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user, password=opts.passwd, port=opts.port) except Exception, e: logger.error('Fail to connect to the server') logger.error('%s' % str(e)) sys.exit(1) model = Object(cnx, opts.model) model_ids = model.search([]) model_lists = model.read(model_ids, [opts.field, 'parent_left', 'parent_right']) models = dict(map(lambda x: (x['id'], x), model_lists)) try: for a in model_lists: logger.debug('id: %d' % a['id']) if a[opts.field]: assert a['parent_left'] > models[a[ opts.field][0]]['parent_left'], '%s > %s' % ( a['parent_left'], models[a[opts.field][0]]['parent_left']) assert a['parent_right'] < models[a[ opts.field][0]]['parent_right'], '%s > %s' % ( a['parent_right'], models[a[opts.field][0]]['parent_right']) assert a['parent_left'] < a['parent_right'] for a2 in model_lists: assert not ((a2['parent_right'] > a['parent_left']) and
#root.set('name', 'to_be_defined') #root.set('language', 'groovy') #root.set('pageWidth', '595') #root.set('pageHeight', '842') #root.set('columnWidth', '555') #root.set('leftMargin', '20') #root.set('rightMargin', '20') #root.set('topMargin', '20') #root.set('bottomMargin', '20') jasper_ids = jasper_obj.search([('service','=',opts.service)]) if not jasper_ids: print 'Service %s not found' % opts.service exit(1) jasper = jasper_obj.read(jasper_ids[0]) if isinstance(jasper, list): jasper = jasper[0] #print jasper for lab in label_obj.read(jasper['label_ids'], ['name','value']): #print lab #<parameter name="I18N_TITLE" class="java.lang.String" isForPrompting="false"> # <defaultValueExpression><![CDATA["BON DE RETOUR S.A.V."]]></defaultValueExpression> #</parameter> parameter = SubElement(root, 'parameter') parameter.set('name', 'I18N_' + lab['name'].upper()) parameter.set('class', 'java.lang.String')
def _return_object(self, objectName, id): obj = Object(self.cnx, objectName) r = obj.search([("id", "=", id)]) return obj.read(r)[0]
args = [ ('model', '=', model), ('res_id', '=', id) ] ret = '%s_%d' % (model.replace('.', '_'), id) res = model_data.search(args) if res: r = model_data.read(res, ['module', 'name'])[0] ret = '%s.%s' % (r['module'], r['name']) return ret root = Element('record') root.set('model','ir.ui.view') root.set('id', Ir_Model_Data('ir.ui.view', opts.id)) view = model_view.read(opts.id) if isinstance(view, list): view = view[0] for f in ['name','model','type','priority','inherit_id','arch']: if f == 'inherit_id' and not view[f]: continue field = SubElement(root ,'field') if f == 'inherit_id': field.set('name', f) field.set('ref', Ir_Model_Data('ir.ui.view', view[f][0])) elif f == 'arch': field.set('name', f) field.set('type', 'xml')
sys.path.append('../') from oobjlib.connection import Connection from oobjlib.component import Object from oobjlib.common import GetParser parser = GetParser('Module List', '0.1') opts, args = parser.parse_args() try: cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user, password=opts.passwd, port=opts.port) except Exception, e: print '%s' % str(e) exit(1) modules = Object(cnx, "ir.module.module") print '--[Connection Object]---------------------' print '%s' % str(modules) ids = modules.search([('state', '=', 'installed')]) print '--[Module list]---------------------------' for p in modules.read(ids, ['name']): print '* %s' % p['name'] print '--[End]-----------------------------------' # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
""" import sys sys.path.append("../") from oobjlib.connection import Connection from oobjlib.component import Object from oobjlib.common import GetParser parser = GetParser("Module List", "0.1") opts, args = parser.parse_args() try: cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user, password=opts.passwd, port=opts.port) except Exception, e: print "%s" % str(e) exit(1) modules = Object(cnx, "ir.module.module") print "--[Connection Object]---------------------" print "%s" % str(modules) ids = modules.search([("state", "=", "installed")]) print "--[Module list]---------------------------" for p in modules.read(ids, ["name"]): print "* %s" % p["name"] print "--[End]-----------------------------------" # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
opts, args = parser.parse_args() try: cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user, password=opts.passwd) except Exception, e: print '%s' % str(e) exit(1) user = Object(cnx, 'res.users') multi = Object(cnx, 'res.company') user_id = user.search([('login','=',opts.user)])[0] # save company_id to restore it after curr = user.read(user_id, ['company_ids','company_id']) c_save_id = curr['company_id'] print 'User: %d => %s (id %d)' % (user_id, c_save_id[1], c_save_id[0]) ## # If the company argument is missing, retrieve all companies in the user form # if opts.company: companies = opts.company.split(',') else: companies = curr['company_ids'] s = 23 header = ('Main Company'.ljust(s), 'Object'.ljust(s), 'Dest Company'.ljust(s)) print 80 * '-'
# create or update scenario_ids = scenario_obj.search( [('reference_res_id', '=', scen_vals['reference_res_id'])], 0, None, None, {'active_test': False}) if scenario_ids: logger.info('Scenario exists, update it') del scen_vals['reference_res_id'] scenario_obj.write(scenario_ids, scen_vals) scenario_id = scenario_ids[0] else: logger.info('Scenario not exists, create it') scenario_id = scenario_obj.create(scen_vals) # List scenario steps and transitions, to be able to remove deleted data scenario_data = scenario_obj.read(scenario_id, ['step_ids']) all_step_ids = set(scenario_data['step_ids']) step_data = step_obj.read(list(all_step_ids), ['in_transition_ids', 'out_transition_ids']) all_transition_ids = set( sum([ data['in_transition_ids'] + data['out_transition_ids'] for data in step_data ], [])) # parse step logger.info('Update steps') resid = {} for node in step: step_vals = {} for key, item in node.items():
{'active_test': False}) elif opts.inactive: count = model.search_count([], {'active_test': False}) model_ids = model.search([], 0, count, 0, {'active_test': False}) else: count = model.search_count([]) model_ids = model.search([], 0, count) root = Element('openerp') data = SubElement(root, 'data') for m_id in model_ids: ## # Read the current id # mod = model.read(m_id) record = SubElement(data, 'record') record.set('model', opts.model) record.set('id', Ir_Model_Data(opts.model, m_id)) o2m_dict = {} for fld in f_list: f_type = fields[fld]['type'] if fld in ('parent_left', 'parent_right'): continue if mod[fld] or opts.all or f_type == 'boolean' or fld == 'active': field = SubElement(record, 'field') field.set('name', fld) if f_type in ('char', 'text'): field.text = unicode(mod[fld]) or '' elif f_type in ('int', 'integer'): field.set('eval', mod[fld] and str(mod[fld]) or '0')
login=opts.user, password=opts.passwd, port=opts.port) except Exception, e: logger.error('Fail to connect to the server') logger.error('%s' % str(e)) sys.exit(1) resid = {} opts.directory = os.path.expanduser(opts.directory) # extract scenario scenario_obj = Object(cnx, 'scanner.scenario') model_obj = Object(cnx, 'ir.model') warehouse_obj = Object(cnx, 'stock.warehouse') scen_read = scenario_obj.read(int(opts.scenario_id), [], {'active_test': False}) if not scen_read: logger.error('Scenario ID %s not found' % opts.scenario_id) sys.exit(1) del scen_read['step_ids'] del scen_read['id'] # create node and attributs root = Element('scenario') for field in scen_read: node = SubElement(root, field) if field == 'model_id': if scen_read[field]: node.text = model_obj.read( scen_read.get('model_id', [0])[0], ['model']).get('model') elif field == 'company_id': if scen_read[field]:
opts, args = parser.parse_args() try: cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user, port=opts.port, password=opts.passwd) except Exception, e: print "%s" % str(e) exit(1) def generate_tracking_message_id(openobject_id): """Returns a string that can be used in the Message-ID RFC822 header field so we can track the replies related to a given object thanks to the "In-Reply-To" or "References" fields that Mail User Agents will set. """ s = hashlib.sha1() s.update(str(time.time())) return "<%s-openobject-%s@%s>" % (s.hexdigest(), openobject_id, "syleam6.syleam.fr") message = Object(cnx, "mailgate.message") message_ids = message.search([("model", "=", "project.issue"), ("message_id", "=", False)]) print "%d message to update" % len(message_ids) for m in message.read(message_ids, ["name", "res_id"]): args = {"message_id": generate_tracking_message_id(m["res_id"])} message.write([m["id"]], args) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: