def call_bz(self, method, params): """Attempt to call method with args. """ if self.bz_token is not None: params['Bugzilla_token'] = self.bz_token try: return method(params) except xmlrpc.client.Fault as fault: raise BugzError('Bugzilla error: {0}'.format(fault.faultString)) except xmlrpc.client.ProtocolError as e: raise BugzError(e) except urllib.error.URLError as e: raise BugzError(e)
def call_bz(self, method, params): """Attempt to call method with args. """ if hasattr(self, 'key'): params['Bugzilla_api_key'] = self.key else: if hasattr(self, 'user'): params['Bugzilla_login'] = self.user if hasattr(self, 'password'): params['Bugzilla_password'] = self.password try: return method(params) except xmlrpc.client.Fault as fault: raise BugzError('Bugzilla error: {0}'.format(fault.faultString)) except xmlrpc.client.ProtocolError as error: raise BugzError(error) except urllib.error.URLError as error: raise BugzError(error)
def search(conn): """Performs a search on the bugzilla database with the keywords given on the title (or the body if specified). """ valid_keys = [ 'alias', 'assigned_to', 'component', 'creator', 'limit', 'offset', 'op_sys', 'platform', 'priority', 'product', 'resolution', 'severity', 'version', 'whiteboard' ] params = {} d = vars(conn) for key in d: if key in valid_keys: params[key] = d[key] if 'status' in d: if 'all' not in d['status']: params['status'] = d['status'] elif 'search_statuses' in d: params['status'] = d['search_statuses'] if 'terms' in d: params['summary'] = d['terms'] search_term = ' '.join(d['terms']).strip() if not params: raise BugzError('Please give search terms or options.') log_info('Searching for bugs meeting the following criteria:') for key in params: log_info(' {0:<20} = {1}'.format(key, params[key])) if not conn.skip_auth: login(conn) result = conn.call_bz(conn.bz.Bug.search, params)['bugs'] if not len(result): log_info('No bugs found.') else: list_bugs(result, conn)
def attach(settings): """ Attach a file to a bug given a filename. """ filename = getattr(settings, 'filename', None) content_type = getattr(settings, 'content_type', None) bugid = getattr(settings, 'bugid', None) summary = getattr(settings, 'summary', None) is_patch = getattr(settings, 'is_patch', None) comment = getattr(settings, 'comment', None) if not os.path.exists(filename): raise BugzError('File not found: %s' % filename) if content_type is None: content_type = get_content_type(filename) if comment is None: comment = block_edit('Enter optional long description of attachment') if summary is None: summary = os.path.basename(filename) params = {} params['ids'] = [bugid] fd = open(filename, 'rb') params['data'] = xmlrpc.client.Binary(fd.read()) fd.close() params['file_name'] = os.path.basename(filename) params['summary'] = summary params['content_type'] = content_type params['comment'] = comment if is_patch is not None: params['is_patch'] = is_patch login(settings) result = settings.call_bz(settings.bz.Bug.add_attachment, params) attachid = result['ids'][0] log_info('{0} ({1}) has been attached to bug {2}'.format( filename, attachid, bugid))
def post(settings): """Post a new bug""" login(settings) # load description from file if possible if hasattr(settings, 'description_from'): try: if settings.description_from == '-': settings.description = sys.stdin.read() else: settings.description = \ open(settings.description_from, 'r').read() except IOError as error: raise BugzError('Unable to read from file: %s: %s' % (settings.description_from, error)) if not hasattr(settings, 'batch') and not hasattr(settings, 'template'): prompt_for_bug(settings) params = {} if hasattr(settings, 'template'): tmpl = configparser.ConfigParser() try: tmpl.read(settings.template) msection = tmpl['Default']['type'] for key in tmpl[msection]: params[key] = tmpl[msection][key] print('%-12s: %s' % (key, params[key])) except configparser.DuplicateOptionError as error: log_error(error) sys.exit(1) except configparser.DuplicateSectionError as error: log_error(error) sys.exit(1) except configparser.MissingSectionHeaderError as error: log_error(error) sys.exit(1) except configparser.ParsingError as error: log_error(error) sys.exit(1) else: # raise an exception if mandatory fields are not specified. if not hasattr(settings, 'product'): raise RuntimeError('Product not specified') if not hasattr(settings, 'component'): raise RuntimeError('Component not specified') if not hasattr(settings, 'summary'): raise RuntimeError('Title not specified') if not hasattr(settings, 'description'): raise RuntimeError('Description not specified') print('-' * (settings.columns - 1)) print('%-12s: %s' % ('Product', settings.product)) print('%-12s: %s' % ('Component', settings.component)) print('%-12s: %s' % ('Title', settings.summary)) if hasattr(settings, 'version'): print('%-12s: %s' % ('Version', settings.version)) print('%-12s: %s' % ('Description', settings.description)) if hasattr(settings, 'op_sys'): print('%-12s: %s' % ('Operating System', settings.op_sys)) if hasattr(settings, 'platform'): print('%-12s: %s' % ('Platform', settings.platform)) if hasattr(settings, 'priority'): print('%-12s: %s' % ('Priority', settings.priority)) if hasattr(settings, 'severity'): print('%-12s: %s' % ('Severity', settings.severity)) if hasattr(settings, 'alias'): print('%-12s: %s' % ('Alias', settings.alias)) if hasattr(settings, 'assigned_to'): print('%-12s: %s' % ('Assigned to', settings.assigned_to)) if hasattr(settings, 'cc'): print('%-12s: %s' % ('CC', settings.cc)) if hasattr(settings, 'url'): print('%-12s: %s' % ('URL', settings.url)) print('-' * (settings.columns - 1)) params['product'] = settings.product params['component'] = settings.component if hasattr(settings, 'version'): params['version'] = settings.version params['summary'] = settings.summary if hasattr(settings, 'description'): params['description'] = settings.description if hasattr(settings, 'op_sys'): params['op_sys'] = settings.op_sys if hasattr(settings, 'platform'): params['platform'] = settings.platform if hasattr(settings, 'priority'): params['priority'] = settings.priority if hasattr(settings, 'severity'): params['severity'] = settings.severity if hasattr(settings, 'alias'): params['alias'] = settings.alias if hasattr(settings, 'assigned_to'): params['assigned_to'] = settings.assigned_to if hasattr(settings, 'cc'): params['cc'] = settings.cc if hasattr(settings, 'url'): params['url'] = settings.url # append the output from append_command to the description append_command = getattr(settings, 'append_command', None) if append_command is not None and append_command != '': append_command_output = subprocess.getoutput(append_command) settings.description = settings.description + '\n\n' + \ '$ ' + append_command + '\n' + \ append_command_output if not hasattr(settings, 'batch'): if settings.default_confirm in ['Y', 'y']: confirm = input('Confirm bug submission (Y/n)? ') else: confirm = input('Confirm bug submission (y/N)? ') if len(confirm) < 1: confirm = settings.default_confirm if confirm[0] not in ('y', 'Y'): log_info('Submission aborted') return result = settings.call_bz(settings.bz.Bug.create, params) log_info('Bug %d submitted' % result['id'])
def modify(settings): """Modify an existing bug (eg. adding a comment or changing resolution.)""" if hasattr(settings, 'comment_from'): try: if settings.comment_from == '-': settings.comment = sys.stdin.read() else: settings.comment = open(settings.comment_from, 'r').read() except IOError as error: raise BugzError('unable to read file: %s: %s' % (settings.comment_from, error)) if hasattr(settings, 'assigned_to') and \ hasattr(settings, 'reset_assigned_to'): raise BugzError('--assigned-to and --unassign cannot be used together') if hasattr(settings, 'comment_editor'): settings.comment = block_edit('Enter comment:') params = {} params['ids'] = [settings.bugid] if hasattr(settings, 'alias'): params['alias'] = settings.alias if hasattr(settings, 'assigned_to'): params['assigned_to'] = settings.assigned_to if hasattr(settings, 'blocks_add'): if 'blocks' not in params: params['blocks'] = {} params['blocks']['add'] = settings.blocks_add if hasattr(settings, 'blocks_remove'): if 'blocks' not in params: params['blocks'] = {} params['blocks']['remove'] = settings.blocks_remove if hasattr(settings, 'depends_on_add'): if 'depends_on' not in params: params['depends_on'] = {} params['depends_on']['add'] = settings.depends_on_add if hasattr(settings, 'depends_on_remove'): if 'depends_on' not in params: params['depends_on'] = {} params['depends_on']['remove'] = settings.depends_on_remove if hasattr(settings, 'cc_add'): if 'cc' not in params: params['cc'] = {} params['cc']['add'] = settings.cc_add if hasattr(settings, 'cc_remove'): if 'cc' not in params: params['cc'] = {} params['cc']['remove'] = settings.cc_remove if hasattr(settings, 'comment'): if 'comment' not in params: params['comment'] = {} params['comment']['body'] = settings.comment if hasattr(settings, 'component'): params['component'] = settings.component if hasattr(settings, 'dupe_of'): params['dupe_of'] = settings.dupe_of if hasattr(settings, 'deadline'): params['deadline'] = settings.deadline if hasattr(settings, 'estimated_time'): params['estimated_time'] = settings.estimated_time if hasattr(settings, 'remaining_time'): params['remaining_time'] = settings.remaining_time if hasattr(settings, 'work_time'): params['work_time'] = settings.work_time if hasattr(settings, 'groups_add'): if 'groups' not in params: params['groups'] = {} params['groups']['add'] = settings.groups_add if hasattr(settings, 'groups_remove'): if 'groups' not in params: params['groups'] = {} params['groups']['remove'] = settings.groups_remove if hasattr(settings, 'keywords_set'): if 'keywords' not in params: params['keywords'] = {} params['keywords']['set'] = settings.keywords_set if hasattr(settings, 'op_sys'): params['op_sys'] = settings.op_sys if hasattr(settings, 'platform'): params['platform'] = settings.platform if hasattr(settings, 'priority'): params['priority'] = settings.priority if hasattr(settings, 'product'): params['product'] = settings.product if hasattr(settings, 'resolution'): if not hasattr(settings, 'dupe_of'): params['resolution'] = settings.resolution if hasattr(settings, 'see_also_add'): if 'see_also' not in params: params['see_also'] = {} params['see_also']['add'] = settings.see_also_add if hasattr(settings, 'see_also_remove'): if 'see_also' not in params: params['see_also'] = {} params['see_also']['remove'] = settings.see_also_remove if hasattr(settings, 'severity'): params['severity'] = settings.severity if hasattr(settings, 'status'): if not hasattr(settings, 'dupe_of'): params['status'] = settings.status if hasattr(settings, 'summary'): params['summary'] = settings.summary if hasattr(settings, 'url'): params['url'] = settings.url if hasattr(settings, 'version'): params['version'] = settings.version if hasattr(settings, 'whiteboard'): params['whiteboard'] = settings.whiteboard if hasattr(settings, 'custom'): custom_options = settings.custom.split(':') for custom_option in custom_options: try: key, value = custom_option.split('=', 1) params[key] = value except: print("Badly formatted option :{}".format(custom_option)) pass if hasattr(settings, 'fixed'): params['status'] = 'RESOLVED' params['resolution'] = 'FIXED' if hasattr(settings, 'invalid'): params['status'] = 'RESOLVED' params['resolution'] = 'INVALID' if len(params) < 2: raise BugzError('No changes were specified') login(settings) result = settings.call_bz(settings.bz.Bug.update, params) for bug in result['bugs']: changes = bug['changes'] if not len(changes): log_info('Added comment to bug %s' % bug['id']) else: log_info('Modified the following fields in bug %s' % bug['id']) for key in changes: log_info('%-12s: removed %s' % (key, changes[key]['removed'])) log_info('%-12s: added %s' % (key, changes[key]['added']))
def post(settings): """Post a new bug""" login(settings) # load description from file if possible if hasattr(settings, 'description_from'): try: if settings.description_from == '-': settings.description = sys.stdin.read() else: settings.description = open(settings.description_from, 'r').read() except IOError as error: raise BugzError('Unable to read from file: %s: %s' % (settings.description_from, error)) if not hasattr(settings, 'batch'): prompt_for_bug(settings) # raise an exception if mandatory fields are not specified. if not hasattr(settings, 'product'): raise RuntimeError('Product not specified') if not hasattr(settings, 'component'): raise RuntimeError('Component not specified') if not hasattr(settings, 'summary'): raise RuntimeError('Title not specified') if not hasattr(settings, 'description'): raise RuntimeError('Description not specified') # append the output from append_command to the description append_command = getattr(settings, 'append_command', None) if append_command is not None and append_command != '': append_command_output = subprocess.getoutput(append_command) settings.description = settings.description + '\n\n' + \ '$ ' + append_command + '\n' + \ append_command_output # print submission confirmation write('-' * (settings.columns - 1)) write('%-12s: %s' % ('Product', settings.product)) write('%-12s: %s' % ('Component', settings.component)) write('%-12s: %s' % ('Title', settings.summary)) if hasattr(settings, 'version'): write('%-12s: %s' % ('Version', settings.version)) write('%-12s: %s' % ('Description', settings.description)) if hasattr(settings, 'op_sys'): write('%-12s: %s' % ('Operating System', settings.op_sys)) if hasattr(settings, 'platform'): write('%-12s: %s' % ('Platform', settings.platform)) if hasattr(settings, 'priority'): write('%-12s: %s' % ('Priority', settings.priority)) if hasattr(settings, 'severity'): write('%-12s: %s' % ('Severity', settings.severity)) if hasattr(settings, 'alias'): write('%-12s: %s' % ('Alias', settings.alias)) if hasattr(settings, 'assigned_to'): write('%-12s: %s' % ('Assigned to', settings.assigned_to)) if hasattr(settings, 'cc'): write('%-12s: %s' % ('CC', settings.cc)) if hasattr(settings, 'url'): write('%-12s: %s' % ('URL', settings.url)) # fixme: groups # fixme: status # fixme: Milestone write('-' * (settings.columns - 1)) if not hasattr(settings, 'batch'): if settings.default_confirm in ['Y', 'y']: confirm = input('Confirm bug submission (Y/n)? ') else: confirm = input('Confirm bug submission (y/N)? ') if len(confirm) < 1: confirm = settings.default_confirm if confirm[0] not in ('y', 'Y'): log_info('Submission aborted') return params = {} params['product'] = settings.product params['component'] = settings.component if hasattr(settings, 'version'): params['version'] = settings.version params['summary'] = settings.summary if hasattr(settings, 'description'): params['description'] = settings.description if hasattr(settings, 'op_sys'): params['op_sys'] = settings.op_sys if hasattr(settings, 'platform'): params['platform'] = settings.platform if hasattr(settings, 'priority'): params['priority'] = settings.priority if hasattr(settings, 'severity'): params['severity'] = settings.severity if hasattr(settings, 'alias'): params['alias'] = settings.alias if hasattr(settings, 'assigned_to'): params['assigned_to'] = settings.assigned_to if hasattr(settings, 'cc'): params['cc'] = settings.cc if hasattr(settings, 'url'): params['url'] = settings.url result = settings.call_bz(settings.bz.Bug.create, params) log_info('Bug %d submitted' % result['id'])
def modify(conn): """Modify an existing bug (eg. adding a comment or changing resolution.)""" if hasattr(conn, 'comment_from'): try: if conn.comment_from == '-': conn.comment = sys.stdin.read() else: conn.comment = open(conn.comment_from, 'r').read() except IOError as e: raise BugzError('unable to read file: %s: %s' % (conn.comment_from, e)) if hasattr(conn, 'comment_editor'): conn.comment = block_edit('Enter comment:') params = {} params['ids'] = [conn.bugid] if hasattr(conn, 'alias'): params['alias'] = conn.alias if hasattr(conn, 'assigned_to'): params['assigned_to'] = conn.assigned_to if hasattr(conn, 'blocks_add'): if 'blocks' not in params: params['blocks'] = {} params['blocks']['add'] = conn.blocks_add if hasattr(conn, 'blocks_remove'): if 'blocks' not in params: params['blocks'] = {} params['blocks']['remove'] = conn.blocks_remove if hasattr(conn, 'depends_on_add'): if 'depends_on' not in params: params['depends_on'] = {} params['depends_on']['add'] = conn.depends_on_add if hasattr(conn, 'depends_on_remove'): if 'depends_on' not in params: params['depends_on'] = {} params['depends_on']['remove'] = conn.depends_on_remove if hasattr(conn, 'cc_add'): if 'cc' not in params: params['cc'] = {} params['cc']['add'] = conn.cc_add if hasattr(conn, 'cc_remove'): if 'cc' not in params: params['cc'] = {} params['cc']['remove'] = conn.cc_remove if hasattr(conn, 'comment'): if 'comment' not in params: params['comment'] = {} params['comment']['body'] = conn.comment if hasattr(conn, 'component'): params['component'] = conn.component if hasattr(conn, 'dupe_of'): params['dupe_of'] = conn.dupe_of if hasattr(conn, 'groups_add'): if 'groups' not in params: params['groups'] = {} params['groups']['add'] = conn.groups_add if hasattr(conn, 'groups_remove'): if 'groups' not in params: params['groups'] = {} params['groups']['remove'] = conn.groups_remove if hasattr(conn, 'keywords_set'): if 'keywords' not in params: params['keywords'] = {} params['keywords']['set'] = conn.keywords_set if hasattr(conn, 'op_sys'): params['op_sys'] = conn.op_sys if hasattr(conn, 'platform'): params['platform'] = conn.platform if hasattr(conn, 'priority'): params['priority'] = conn.priority if hasattr(conn, 'product'): params['product'] = conn.product if hasattr(conn, 'resolution'): if not hasattr(conn, 'dupe_of'): params['resolution'] = conn.resolution if hasattr(conn, 'see_also_add'): if 'see_also' not in params: params['see_also'] = {} params['see_also']['add'] = conn.see_also_add if hasattr(conn, 'see_also_remove'): if 'see_also' not in params: params['see_also'] = {} params['see_also']['remove'] = conn.see_also_remove if hasattr(conn, 'severity'): params['severity'] = conn.severity if hasattr(conn, 'status'): if not hasattr(conn, 'dupe_of'): params['status'] = conn.status if hasattr(conn, 'summary'): params['summary'] = conn.summary if hasattr(conn, 'url'): params['url'] = conn.url if hasattr(conn, 'version'): params['version'] = conn.version if hasattr(conn, 'whiteboard'): params['whiteboard'] = conn.whiteboard if hasattr(conn, 'fixed'): params['status'] = 'RESOLVED' params['resolution'] = 'FIXED' if hasattr(conn, 'invalid'): params['status'] = 'RESOLVED' params['resolution'] = 'INVALID' if len(params) < 2: raise BugzError('No changes were specified') login(conn) result = conn.call_bz(conn.bz.Bug.update, params) for bug in result['bugs']: changes = bug['changes'] if not len(changes): log_info('Added comment to bug %s' % bug['id']) else: log_info('Modified the following fields in bug %s' % bug['id']) for key in changes: log_info('%-12s: removed %s' % (key, changes[key]['removed'])) log_info('%-12s: added %s' % (key, changes[key]['added']))