/src/boinc-6.12.38/py/Boinc/add_util.py
Python | 179 lines | 141 code | 18 blank | 20 comment | 19 complexity | eb6d4025a03a23164c699b1ba78e4f73 MD5 | raw file
- #!/usr/bin/env python
- # $Id: add_util.py 12027 2007-02-02 20:14:18Z boincadm $
- # add_util.py - code shared between add and xadd
- import database, tools
- import time, pprint
- import MySQLdb
- CREATE_TIME = ['?create_time', int(time.time())]
- TRANSITION_TIME = ['?transition_time', int(time.time())]
- class XAppVersion(database.AppVersion):
- def __init__(self,**kwargs):
- kwargs['xml_doc'] = tools.process_app_version(
- app = kwargs['app'],
- version_num = int(kwargs['version_num']),
- exec_files = kwargs['exec_files'],
- signature_files = kwargs.setdefault('signature_files',{}))
- del kwargs['signature_files']
- del kwargs['exec_files']
- del kwargs['exec_file']
- database.AppVersion.__init__(self,**kwargs)
- # format: [ database.Object, args, ...]
- # arg format:
- # 'arg'
- # '?arg' optional
- # [ 'arg', default_value ]
- # NOTE TO KARL: If cross_project_id is not supplied, the default value
- # should be a random 32 character script obtained by doing the md5sum
- # hash of (say) 512 bytes from /dev/urandom or similar.
- list_objects_to_add = [
- [ database.Platform, 'name', 'user_friendly_name', CREATE_TIME ],
- [ database.App, 'name', 'user_friendly_name', ['?min_version',0], CREATE_TIME],
- [ XAppVersion, 'app', 'platform', 'version_num', 'exec_file', '?signature_file',
- CREATE_TIME ],
- [ database.User, 'name', 'email_addr', 'authenticator',
- ['?country','United States'], ['?postal_code','0'], ['?cross_project_id', '0'],
- '?global_prefs', '?global_prefs_file',
- CREATE_TIME ],
- # [ database.Workunit, 'zzzz' ],
- ]
- class AddObject:
- pass
- add_objects = {}
- for o in list_objects_to_add:
- add_object = AddObject()
- add_object.DatabaseObject = o[0]
- add_object.name = add_object.DatabaseObject._table.table
- add_object.args = []
- add_object.optional_args = []
- add_object.default_values = {}
- for arg in o[1:]:
- if isinstance(arg, list):
- default_value = arg[1]
- arg = arg[0]
- else:
- default_value = None
- if arg.startswith('?'):
- optional = True
- arg = arg[1:]
- else:
- optional = False
- if optional:
- add_object.optional_args.append(arg)
- else:
- add_object.args.append(arg)
- if default_value:
- add_object.default_values[arg] = default_value
- add_objects[add_object.name] = add_object
- most_recent_exec_file = None
- def translate_arg(object, arg, value, args_dict):
- '''Translate various user argument values, for adding given ``object``.
- Modifies ``args_dict``.'''
- database_table = None
- try:
- database_table = database.__dict__[arg.capitalize()]._table
- except:
- pass
- if database_table:
- args_dict[arg] = translate_database_arg(database_table, arg, value)
- return
- if arg == 'global_prefs_file':
- args_dict['global_prefs'] = open(value).read()
- return
- if object.DatabaseObject == XAppVersion:
- # 'add app_version' accepts multiple '-exec_file's with
- # '-signature_file' applying to the most recent exec_file
- if arg == 'exec_file':
- global most_recent_exec_file
- most_recent_exec_file = value
- args_dict.setdefault('exec_files',[]).append(value)
- # since 'exec_file' (without 's') is required, set it to None so
- # that argument checker knows we got one; we'll delete it later.
- args_dict[arg] = None
- return
- if arg == 'signature_file':
- args_dict.setdefault('signature_files',{})[most_recent_exec_file] = value
- return
- if arg == 'cross_project_id':
- if not value:
- value = tools.make_uuid()
- args_dict[arg] = value
- def translate_database_arg(database_table, arg, value):
- '''Look up an object ``value`` either as a database ID or string.
- This allows us to accept e.g. either --app Astropulse or --app 1'''
- try:
- id = int(value)
- results = database_table.find(id=id)
- if not results:
- raise Exception("")
- except:
- results = database_table.find(name=value)
- if len(results) == 0:
- raise SystemExit('No %s "%s" found' %(arg,value))
- if len(results) > 1:
- print >>sys.stderr, 'Too many %ss match "%s": '%(arg,value)
- for result in results:
- print >>sys.stderr, ' ', result.name
- raise SystemExit
- return results[0]
- class AddObjectException(Exception): pass
- def check_required_arguments(add_object, args_dict):
- for arg in add_object.args:
- if not arg in args_dict:
- raise AddObjectException('required value for %s not given'%arg)
- def translate_args_dict(add_object, untranslated_args_dict):
- args_dict = add_object.default_values.copy()
- for arg,value in untranslated_args_dict.items():
- translate_arg(add_object,arg,value,args_dict)
- return args_dict
- def exception_is_duplicate_entry(exception):
- '''Checks a MySQLdb.IntegrityError for whether the error is Duplicate
- Entry. Kludgy.'''
- return (isinstance(exception, MySQLdb.IntegrityError) and
- str(exception).find('Duplicate entry')!=-1)
- def do_add_object(add_object, untranslated_args_dict, skip_old=False):
- '''Input ```args_dict``` must have been translated already.'''
- args_dict = translate_args_dict(add_object, untranslated_args_dict)
- check_required_arguments(add_object, args_dict)
- dbobject = add_object.DatabaseObject(**args_dict)
- print "Processing", dbobject, "..."
- # print "Commiting", dbobject, "with args:"
- # pprint.pprint(dbobject.__dict__)
- try:
- dbobject.commit()
- except MySQLdb.MySQLError, e:
- if skip_old and exception_is_duplicate_entry(e):
- print " Skipped existing", dbobject
- return
- else:
- raise SystemExit('Error committing %s: %s' %(dbobject, e))
- # delete object and re-select it from database to allow user to check
- # consistency
- id = dbobject.id
- del dbobject
- dbobject = add_object.DatabaseObject._table[id]
- print " Committed", dbobject, "; values:"
- pprint.pprint(dbobject.__dict__)