Пример #1
0
    def test_raise(self):
        with pytest.raises(exc.CheckbValueError):
            assert python_utils.iterable([1, 2], 1)

        with pytest.raises(exc.CheckbValueError):
            assert python_utils.iterable([1, 2], 'a')

        with pytest.raises(exc.CheckbValueError):
            assert python_utils.iterable([1, 2], [])

        X = type('X', (object, ), {})
        with pytest.raises(exc.CheckbValueError):
            assert python_utils.iterable([1, 2], X())
Пример #2
0
 def test_iterable(self):
     assert python_utils.iterable([1, 2])
     assert python_utils.iterable(['a', 'b'])
     assert python_utils.iterable(('foo', ))
     assert python_utils.iterable({'foo', 'bar', 'baz'})
     assert python_utils.iterable(set())
     assert python_utils.iterable(())
     assert python_utils.iterable([u'foo', u'bar'])
     assert python_utils.iterable({'a': 1, 'b': 2})
Пример #3
0
    def test_iterable_items(self):
        assert python_utils.iterable([1, 2], int)
        assert not python_utils.iterable([1, 2], float)
        assert not python_utils.iterable([1, 2.2], float)

        assert python_utils.iterable(['a', 'b'], str)
        assert python_utils.iterable(['a', 'b'], basestring)
        try:
            assert not python_utils.iterable(['a', 'b'], unicode)
        except NameError:
            # Python 3 no such thing as unicode, str already tested
            pass
        assert python_utils.iterable([[], []], list)

        # empty classes
        X = type('X', (object, ), {})
        Y = type('Y', (X, ), {})
        assert python_utils.iterable((X(), X()), X)
        assert python_utils.iterable((X(), Y()), X)
        assert not python_utils.iterable((X(), Y()), Y)
Пример #4
0
 def test_not_iterable(self):
     assert not python_utils.iterable('a')
     assert not python_utils.iterable(u'a')
     try:
         assert not python_utils.iterable(unicode('foo'))
     except NameError:
         # Python 3 no such thing as unicode, str already tested
         pass
     assert not python_utils.iterable(3)
     assert not python_utils.iterable(3.14)
     assert not python_utils.iterable(None)
     assert not python_utils.iterable(object())
Пример #5
0
    def build2update(self, builds, strict=False):
        '''Find matching Bodhi updates for provided builds.

        :param builds: builds to search for in N(E)VR format (``foo-1.2-3.fc20``
                       or ``foo-4:1.2-3.fc20``)
        :type builds: iterable of str
        :param bool strict: if ``False``, incomplete Bodhi updates are allowed.
                            If ``True``, every Bodhi update will be compared
                            with the set of provided builds. If there is an
                            Bodhi update which contains builds not provided in
                            ``builds``, that update is marked as incomplete and
                            removed from the result - i.e. all builds from
                            ``builds`` that were part of this incomplete update
                            are placed in the second dictionary of the result
                            tuple.
        :return: a tuple of two dictionaries:

                 * The first dict provides mapping between ``builds`` and their
                   updates where no error occured.

                   ``{build (string): Bodhi update (Munch)}``
                 * The second dict provides mapping between ``builds`` and their
                   updates where some error occured. The value is ``None`` if
                   the matching Bodhi update could not be found (the only
                   possible cause of failure if ``strict=False``). Or the value
                   is a Bodhi update that was incomplete (happens only if
                   ``strict=True``).

                   ``{build (string): Bodhi update (Munch) or None}``
                 * The set of keys in both these dictionaries correspond exactly
                   to ``builds``. For every build provided in ``builds`` you'll
                   get an answer in either the first or the second dictionary,
                   and there will be no extra builds that you haven't specified.
        :raise CheckbValueError: if ``builds`` type is incorrect
        '''
        # validate input params
        if not python_utils.iterable(builds, basestring):
            raise exc.CheckbValueError(
                "Param 'builds' must be an iterable of strings, and yours was: %s"
                % type(builds))

        updates = []
        build2update = {}
        failures = {}
        # Bodhi works with NVR only, but we have to ensure we receive and return
        # even NEVR format. So we need to convert internally.
        builds_nvr = set(
            [rpm_utils.rpmformat(build, 'nvr') for build in builds])
        builds_queue = list(builds_nvr)

        log.info('Querying Bodhi to map %d builds to their updates...',
                 len(builds))

        # retrieve all update data
        while builds_queue:
            builds_chunk = builds_queue[:self._MULTICALL_REQUEST_SIZE]
            builds_chunk = ' '.join(builds_chunk)
            res = self.client.query(builds=builds_chunk)

            updates.extend(res['updates'])
            builds_queue = builds_queue[self._MULTICALL_REQUEST_SIZE:]

            # don't query for builds which were already found
            for update in res['updates']:
                for build in update['builds']:
                    if build['nvr'] in builds_queue:
                        builds_queue.remove(build['nvr'])

            log.info('Bodhi queries done: %d/%d',
                     len(builds_nvr) - len(builds_queue), len(builds_nvr))

        # separate builds into OK and failures
        for update in updates:
            # all builds listed in the update
            bodhi_builds = set([build['nvr'] for build in update['builds']])
            # builds *not* provided in @param builds but part of the update (NVRs)
            missing_builds = bodhi_builds.difference(builds_nvr)
            # builds provided in @param builds and part of the update
            matched_builds = [
                build for build in builds
                if rpm_utils.rpmformat(build, 'nvr') in bodhi_builds
            ]

            # reject incomplete updates when strict
            if missing_builds and strict:
                for build in matched_builds:
                    failures[build] = update
                continue

            # otherwise the update is complete or we don't care
            for build in matched_builds:
                build2update[build] = update

        # mark builds without any associated update as a failure
        for build in builds:
            if build not in build2update and build not in failures:
                failures[build] = None

        diff = set(builds).symmetric_difference(
            set(build2update.keys()).union(set(failures.keys())))
        assert not diff, "Returned NVRs different from input NVRs: %s" % diff

        return (build2update, failures)
Пример #6
0
    def process(self, params, arg_data):
        if ('package' not in params and 'nvr' not in params) or 'path' not in params \
            or 'target_dir' not in params:
            detected_args = ', '.join(params.keys())
            raise exc.CheckbDirectiveError(
                "The distgit directive requires 'package' (or 'nvr') and 'path' and 'target_dir' arguments."
                "Detected arguments: %s" % detected_args)

        package = None
        gitref = None
        namespace = None

        if 'nvr' in params:
            nvr = params['nvr']
            package = rpm_utils.rpmformat(nvr, fmt='n')
            gitref = rpm_utils.get_dist_tag(nvr).replace('c', '')
            rawhide_tag = yumrepoinfo.YumRepoInfo(resolve_baseurl=False).get(
                'rawhide', 'tag')
            if gitref == rawhide_tag:
                gitref = 'master'
            namespace = 'rpms'

        # Assign defaults
        package = params.get('package', package)
        gitref = params.get('gitref', gitref or 'master')
        namespace = params.get('namespace', namespace or 'rpms')
        baseurl = params.get('baseurl', BASEURL)
        target_dir = params['target_dir']
        ignore_missing = params.get('ignore_missing', False)

        if not python_utils.iterable(params['path']):
            raise exc.CheckbValueError(
                "Incorrect value type of the 'path' argument: "
                "%s" % type(params['path']))

        target_path = params['path']
        output_data = {}

        if 'localpath' in params:
            if not python_utils.iterable(params['localpath']):
                raise exc.CheckbValueError(
                    "Incorrect value type of the 'localpath' argument: "
                    "%s" % type(params['path']))

            if not len(params['path']) == len(params['localpath']):
                raise exc.CheckbValueError(
                    'path and localpath lists must be of the same '
                    'length.')

            target_path = params['localpath']

        format_fields = {
            'package': package,
            'gitref': gitref,
            'namespace': namespace,
            'baseurl': baseurl,
        }
        output_data['downloaded_files'] = []
        for path, localpath in zip(params['path'], target_path):
            localpath = os.path.join(target_dir, localpath)
            file_utils.makedirs(os.path.dirname(localpath))
            url = URL_FMT.format(path=path, **format_fields)
            try:
                output_data['downloaded_files'].append(
                    file_utils.download(url, '.', localpath))
            except exc.CheckbRemoteError as e:
                if e.errno == 404 and ignore_missing:
                    log.debug('File not found, ignoring: %s', url)
                else:
                    raise e

        return output_data