Пример #1
0
    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')
Пример #2
0
    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')
Пример #3
0
    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'
            )
Пример #4
0
    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
Пример #5
0
    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')
Пример #6
0
    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
Пример #7
0
    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!')
Пример #8
0
    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]
Пример #9
0
    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!')
Пример #10
0
    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]