def find_free_prefix(self, auth, vrf, args):

        # input sanity
        if type(args) is not dict:
            raise NipapInputError("invalid input, please provide dict as args")

        # TODO: find good default value for max_num
        # TODO: let max_num be configurable from configuration file
        max_count = 1000
        if 'count' in args:
            if int(args['count']) > max_count:
                raise NipapValueError("count over the maximum result size")
        else:
            args['count'] = 1

        if 'from-pool' in args:
            if 'from-prefix' in args:
                raise NipapInputError("specify 'from-pool' OR 'from-prefix'")
            if 'family' not in args:
                raise NipapMissingInputError("'family' must be specified with 'from-pool' mode")
            try:
                assert int(args['family']) in [ 4, 6 ]
            except (TypeError, AssertionError):
                raise NipapValueError("incorrect family specified, must be 4 or 6")

        elif 'from-prefix' in args:
            if type(args['from-prefix']) is not list:
                raise NipapInputError("from-prefix should be a list")
            if 'from-pool' in args:
                raise NipapInputError("specify 'from-pool' OR 'from-prefix'")
            if 'prefix_length' not in args:
                raise NipapMissingInputError("'prefix_length' must be specified with 'from-prefix'")
            if 'family' in args:
                raise NipapExtraneousInputError("'family' is superfluous when in 'from-prefix' mode")

        # determine prefixes
        prefixes = []
        wpl = 0
        if 'from-pool' in args:
            # extract prefixes from
            pool_result = self.list_pool(auth, args['from-pool'])
            self._logger.debug(args)
            if pool_result == []:
                raise NipapNonExistentError("Non-existent pool specified")
            for p in pool_result[0]['prefixes']:
                if self._get_afi(p) == int(args['family']):
                    prefixes.append(p)
            if len(prefixes) == 0:
                raise NipapInputError('No prefixes of family %s in pool' % str(args['family']))
            if 'prefix_length' not in args:
                if int(args['family']) == 4:
                    wpl = pool_result[0]['ipv4_default_prefix_length']
                else:
                    wpl = pool_result[0]['ipv6_default_prefix_length']

        afi = None
        if 'from-prefix' in args:
            for prefix in args['from-prefix']:
                prefix_afi = self._get_afi(prefix)
                if afi is None:
                    afi = prefix_afi
                elif afi != prefix_afi:
                    raise NipapInputError("mixing of address-family is not allowed for 'from-prefix' arg")
                prefixes.append(prefix)

        if 'prefix_length' in args:
            try:
                wpl = int(args['prefix_length'])
            except ValueError:
                raise NipapValueError("prefix length must be integer")

        # sanity check the wanted prefix length
        if afi == 4:
            if wpl < 0 or wpl > 32:
                raise NipapValueError("the specified wanted prefix length argument must be between 0 and 32 for ipv4")
        elif afi == 6:
            if wpl < 0 or wpl > 128:
                raise NipapValueError("the specified wanted prefix length argument must be between 0 and 128 for ipv6")

        # build SQL
        params = {}
        # TODO: this makes me want to piss my pants
        #       we should really write a patch to psycopg2 or something to
        #       properly adapt an python list of texts with values looking
        #       like prefixes to a postgresql array of inets
        sql_prefix = ' UNION '.join('SELECT %(prefix' + str(prefixes.index(p)) + ')s AS prefix' for p in prefixes)
        for p in prefixes:
            params['prefix' + str(prefixes.index(p))] = str(p)

        damp = 'SELECT array_agg((prefix::text)::inet) FROM (' + sql_prefix + ') AS a'

        sql = """SELECT * FROM find_free_prefix(%(vrf_id)s, (""" + damp + """), %(prefix_length)s, %(max_result)s) AS prefix"""

        v = self._get_vrf(auth, vrf or {}, '')

        params['vrf_id'] = v['id']
        params['prefixes'] = prefixes
        params['prefix_length'] = wpl
        params['max_result'] = args['count']

        self._execute(sql, params)

        res = list()
        for row in self._curs_pg:
            res.append(str(row['prefix']))

        return res
Finds free prefixes in the sources given in `args`.
dataset/ETHPy150Open SpriteLink/NIPAP/nipap/nipap/backend.py/Nipap.find_free_prefix