def update_bug(self, bugid, callback=None, callback_param=None, whiteboard_add=None, whiteboard_remove=None, **kwargs): ''' Updates bugzilla. ''' self.load_update_form(bugid) changes = False # Do not add ourselves to CC when setting whiteboard if ((whiteboard_add is not None or whiteboard_remove is not None) and 'addselfcc' not in kwargs): kwargs['addselfcc'] = [] # Set parameters for k in kwargs: val = kwargs[k] if isinstance(val, unicode): val = val.encode('utf-8') try: self.browser[k] = val except ControlNotFoundError: if k not in IGNORABLE_FIELDS: raise changes = True # Callback can adjust data on fly if callback is not None: changes |= callback(self.browser, callback_param) # Whiteboard manipulations if whiteboard_add is not None or whiteboard_remove is not None: changes |= self._update_bug_whiteboard(whiteboard_remove, whiteboard_add) # Retrun on no changes if not changes or self.force_readonly: return # Submit response = self.submit() data = webscraper_safely(response.read) if 'Mid-air collision!' in data: raise BugzillaUpdateError('Mid-air collision!') if 'reason=invalid_token' in data: raise BugzillaUpdateError('Suspicious Action') if 'Changes submitted for' not in data: raise BugzillaUpdateError('Unknown error while submitting form')
def update_bug(self, bugid, callback=None, callback_param=None, whiteboard_add=None, whiteboard_remove=None, **kwargs): ''' Updates bugzilla. ''' self.load_update_form(bugid) changes = False # Do not add ourselves to CC when setting whiteboard if ((whiteboard_add is not None or whiteboard_remove is not None) and 'addselfcc' not in kwargs): kwargs['addselfcc'] = [] # Set parameters for k in kwargs: val = kwargs[k] if isinstance(val, unicode): val = val.encode('utf-8') try: self.browser[k] = val except ControlNotFoundError: if k not in IGNORABLE_FIELDS: raise changes = True # Callback can adjust data on fly if callback is not None: changes |= callback(self.browser, callback_param) # Whiteboard manipulations if whiteboard_add is not None or whiteboard_remove is not None: changes |= self._update_bug_whiteboard( whiteboard_remove, whiteboard_add ) # Retrun on no changes if not changes: return # Submit response = self.submit() data = webscraper_safely(response.read) if 'Mid-air collision!' in data: raise BugzillaUpdateError('Mid-air collision!') if 'reason=invalid_token' in data: raise BugzillaUpdateError('Suspicious Action') if 'Changes submitted for' not in data: raise BugzillaUpdateError('Unknown error while submitting form')
def login(self, force=False): ''' Login to Bugzilla using Access Manager. ''' if self.check_login(): return try: # Submit fake javascript form # pylint: disable=E1102 self.browser.select_form(nr=0) response = self.submit() # Find the login form # pylint: disable=E1102 self.browser.select_form(nr=0) self.browser['Ecom_User_ID'] = self.user self.browser['Ecom_Password'] = self.password except (FormNotFoundError, ControlNotFoundError): raise BugzillaLoginFailed('Failed to parse HTML for login!') self.logger.info('Doing login') response = self.submit() text = webscraper_safely(response.read) # Check for error messages soup = BeautifulSoup(text, "lxml") for para in soup.find_all('p'): if 'error' in para['class']: raise BugzillaLoginFailed(para.text) # Emulate javascript redirect for script in soup.findAll('script'): for line in script.text.splitlines(): line = line.strip() if line.startswith('top.location.href='): path = line.split("'")[1] newpath = urlparse.urljoin( response.geturl(), path ) response = self.request(newpath) if not self.check_login(): raise BugzillaLoginFailed( 'Failed to verify login after successful login' )
def get_bugs(self, ids, retry=True, permissive=False, store_errors=False): ''' Returns Bug objects based on data received from bugzilla for each bug ID. Returns empty list in case of some problems. ''' # Generate request query req = [('id', bugid) for bugid in ids if bugid is not None] req += [('ctype', 'xml'), ('excludefield', 'attachmentdata')] # Download data response = self.request('show_bug', paramlist=req) data = webscraper_safely(response.read) # Fixup XML errors bugzilla produces data = escape_xml_text(data) # Parse XML try: response_et = ElementTree.fromstring(data) except SyntaxError: self._handle_parse_error( ','.join([str(bugid) for bugid in ids]), data ) return [] try: bugs = [] for bug in response_et.findall('bug'): try: bugs.append(Bug(bug, self.anonymous)) except BugzillaError as exc: if store_errors: bugs.append(exc) if permissive: self.logger.error(exc) else: raise exc return bugs except BugzillaNotPermitted as exc: if retry and not self.anonymous: self.logger.error("%s - login and retry", exc) self.login() return self.get_bugs(ids, False, permissive) raise exc
def login(self, force=False): ''' Login to Bugzilla using Access Manager. ''' if self.check_login(): return try: # Submit fake javascript form # pylint: disable=E1102 self.browser.select_form(nr=0) response = self.submit() # Find the login form # pylint: disable=E1102 self.browser.select_form(nr=0) self.browser['Ecom_User_ID'] = self.user self.browser['Ecom_Password'] = self.password except (FormNotFoundError, ControlNotFoundError): raise BugzillaLoginFailed('Failed to parse HTML for login!') self.logger.info('Doing login') response = self.submit() text = webscraper_safely(response.read) # Check for error messages soup = BeautifulSoup(text, "lxml") for para in soup.find_all('p'): if 'error' in para['class']: raise BugzillaLoginFailed(para.text) # Emulate javascript redirect for script in soup.findAll('script'): for line in script.text.splitlines(): line = line.strip() if line.startswith('top.location.href='): path = line.split("'")[1] newpath = urlparse.urljoin(response.geturl(), path) response = self.request(newpath) if not self.check_login(): raise BugzillaLoginFailed( 'Failed to verify login after successful login')
def get_bugs(self, ids, retry=True, permissive=False, store_errors=False): ''' Returns Bug objects based on data received from bugzilla for each bug ID. Returns empty list in case of some problems. ''' # Generate request query req = [('id', bugid) for bugid in ids if bugid is not None] req += [('ctype', 'xml'), ('excludefield', 'attachmentdata')] # Download data response = self.request('show_bug', paramlist=req) data = webscraper_safely(response.read) # Fixup XML errors bugzilla produces data = escape_xml_text(data) # Parse XML try: response_et = ElementTree.fromstring(data) except SyntaxError: self._handle_parse_error(','.join([str(bugid) for bugid in ids]), data) return [] try: bugs = [] for bug in response_et.findall('bug'): try: bugs.append(Bug(bug, self.anonymous)) except BugzillaError as exc: if store_errors: bugs.append(exc) if permissive: self.logger.error(exc) else: raise exc return bugs except BugzillaNotPermitted as exc: if retry and not self.anonymous: self.logger.error("%s - login and retry", exc) self.login() return self.get_bugs(ids, False, permissive) raise exc
def load_update_form(self, bugid): """ Selects form for bug update. """ if self.anonymous: raise BugzillaUpdateError('No updates in anonymous mode!') # Load the form self.logger.info('Loading bug form for %d', bugid) response = self.request('show_bug', id=bugid) data = webscraper_safely(response.read) if 'You are not authorized to access bug' in data: raise BugzillaNotPermitted( 'You are not authorized to access bug #%d.' % bugid) self.check_viewing_html() # Find the form try: # pylint: disable=E1102 self.browser.select_form(name="changeform") except FormNotFoundError: raise BugzillaUpdateError('Failed to parse HTML to update bug!')
def do_search(self, params): ''' Performs search and returns list of IDs. ''' req = [('ctype', 'atom')] + params self.logger.info('Doing bugzilla search: %s', req) response = self.request('buglist', paramlist=req) data = webscraper_safely(response.read) data = escape_xml_text(data) try: response_et = ElementTree.fromstring(data) except SyntaxError: self._handle_parse_error('recent', data) return [] id_query = '{http://www.w3.org/2005/Atom}id' entry_query = '{http://www.w3.org/2005/Atom}entry' bugs = [ bug.find(id_query).text for bug in response_et.findall(entry_query) ] # Strip http://bugzilla.novell.com/show_bug.cgi?id= return [int(bugid[bugid.find("?id=") + 4:]) for bugid in bugs]
def load_update_form(self, bugid): """ Selects form for bug update. """ if self.anonymous: raise BugzillaUpdateError('No updates in anonymous mode!') # Load the form self.logger.info('Loading bug form for %d', bugid) response = self.request('show_bug', id=bugid) data = webscraper_safely(response.read) if 'You are not authorized to access bug' in data: raise BugzillaNotPermitted( 'You are not authorized to access bug #%d.' % bugid ) self.check_viewing_html() # Find the form try: # pylint: disable=E1102 self.browser.select_form(name="changeform") except FormNotFoundError: raise BugzillaUpdateError('Failed to parse HTML to update bug!')