def search_prefix(self, auth, query, search_options=None):
if search_options is None:<EOL><INDENT>search_options = {}<EOL><DEDENT>if '<STR_LIT>' not in search_options:<EOL><INDENT>search_options['<STR_LIT>'] = False<EOL><DEDENT>else:<EOL><INDENT>if search_options['<STR_LIT>'] not in (True, False):<EOL><INDENT>raise NipapValueError('<STR_LIT>' +<EOL>"<STR_LIT>" % unicode(search_options['<STR_LIT>']))<EOL><DEDENT><DEDENT>if '<STR_LIT>' not in search_options:<EOL><INDENT>search_options['<STR_LIT>'] = False<EOL><DEDENT>else:<EOL><INDENT>if search_options['<STR_LIT>'] not in (True, False):<EOL><INDENT>raise NipapValueError('<STR_LIT>' +<EOL>"<STR_LIT>" % unicode(search_options['<STR_LIT>']))<EOL><DEDENT><DEDENT>if '<STR_LIT>' not in search_options:<EOL><INDENT>search_options['<STR_LIT>'] = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>search_options['<STR_LIT>'] = int(search_options['<STR_LIT>'])<EOL><DEDENT>except (ValueError, TypeError):<EOL><INDENT>raise NipapValueError('<STR_LIT>' +<EOL>'''<STR_LIT>''')<EOL><DEDENT><DEDENT>if '<STR_LIT>' not in search_options:<EOL><INDENT>search_options['<STR_LIT>'] = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>search_options['<STR_LIT>'] = int(search_options['<STR_LIT>'])<EOL><DEDENT>except (ValueError, TypeError):<EOL><INDENT>raise NipapValueError('<STR_LIT>' +<EOL>'''<STR_LIT>''')<EOL><DEDENT><DEDENT>if '<STR_LIT>' not in search_options:<EOL><INDENT>search_options['<STR_LIT>'] = False<EOL><DEDENT>else:<EOL><INDENT>if search_options['<STR_LIT>'] not in (True, False):<EOL><INDENT>raise NipapValueError('<STR_LIT>' +<EOL>"<STR_LIT>" % unicode(search_options['<STR_LIT>']))<EOL><DEDENT><DEDENT>if '<STR_LIT>' not in search_options:<EOL><INDENT>search_options['<STR_LIT>'] = <NUM_LIT:50><EOL><DEDENT>else:<EOL><INDENT>if search_options['<STR_LIT>'] in (False, None):<EOL><INDENT>search_options['<STR_LIT>'] = None<EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>search_options['<STR_LIT>'] = int(search_options['<STR_LIT>'])<EOL><DEDENT>except (ValueError, TypeError):<EOL><INDENT>raise NipapValueError('<STR_LIT>' +<EOL>'''<STR_LIT>''')<EOL><DEDENT><DEDENT><DEDENT>if '<STR_LIT>' not in search_options:<EOL><INDENT>search_options['<STR_LIT>'] = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>search_options['<STR_LIT>'] = int(search_options['<STR_LIT>'])<EOL><DEDENT>except (ValueError, TypeError):<EOL><INDENT>raise NipapValueError('<STR_LIT>' +<EOL>'''<STR_LIT>''')<EOL><DEDENT><DEDENT>if ('<STR_LIT>' not in search_options or<EOL>search_options['<STR_LIT>'] is None):<EOL><INDENT>search_options['<STR_LIT>'] = None<EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>_ = int(search_options['<STR_LIT>'])<EOL><DEDENT>except ValueError:<EOL><INDENT>raise NipapValueError(<EOL>"<STR_LIT>"<EOL>% search_options['<STR_LIT>'])<EOL><DEDENT>try:<EOL><INDENT>parent_prefix = self.list_prefix(auth, { '<STR_LIT:id>': search_options['<STR_LIT>'] })[<NUM_LIT:0>]<EOL><DEDENT>except IndexError:<EOL><INDENT>raise NipapNonExistentError("<STR_LIT>" % search_options['<STR_LIT>'])<EOL><DEDENT><DEDENT>self._logger.debug('<STR_LIT>' % unicode(search_options))<EOL>if search_options['<STR_LIT>'] or search_options['<STR_LIT>'] == -<NUM_LIT:1>:<EOL><INDENT>where_parents = '<STR_LIT>'<EOL><DEDENT>elif search_options['<STR_LIT>'] >= <NUM_LIT:0>:<EOL><INDENT>where_parents = '<STR_LIT>' % search_options['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>raise NipapValueError("<STR_LIT>")<EOL><DEDENT>if search_options['<STR_LIT>'] or search_options['<STR_LIT>'] == -<NUM_LIT:1>:<EOL><INDENT>where_children = '<STR_LIT>'<EOL><DEDENT>elif search_options['<STR_LIT>'] >= <NUM_LIT:0>:<EOL><INDENT>where_children = '<STR_LIT>' % search_options['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>raise NipapValueError("<STR_LIT>")<EOL><DEDENT>if search_options['<STR_LIT>']:<EOL><INDENT>include_neighbors = '<STR_LIT:true>'<EOL><DEDENT>else:<EOL><INDENT>include_neighbors = '<STR_LIT:false>'<EOL><DEDENT>if search_options['<STR_LIT>']:<EOL><INDENT>vrf_id = <NUM_LIT:0><EOL>if parent_prefix['<STR_LIT>']:<EOL><INDENT>vrf_id = parent_prefix['<STR_LIT>']<EOL><DEDENT>where_parent_prefix = "<STR_LIT>" % (vrf_id, parent_prefix['<STR_LIT>'], parent_prefix['<STR_LIT>'] + <NUM_LIT:1>)<EOL>left_join = '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>where_parent_prefix = '<STR_LIT>'<EOL>left_join = '<STR_LIT>'<EOL><DEDENT>if search_options['<STR_LIT>'] is None:<EOL><INDENT>limit_string = "<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>limit_string = "<STR_LIT>" % (search_options['<STR_LIT>'] + search_options['<STR_LIT>'])<EOL><DEDENT>display = '<STR_LIT>' % (where_parents, where_children)<EOL>where, opt = self._expand_prefix_query(query)<EOL>sql = """<STR_LIT>""" + display + """<STR_LIT>""" + left_join + """<STR_LIT>""" + where_parents + """<STR_LIT>""" + where_children + """<STR_LIT>""" + include_neighbors + """<STR_LIT>""" + where + """<STR_LIT>""" + limit_string + """<STR_LIT>""" + where_parent_prefix + """<STR_LIT>"""  + unicode(search_options['<STR_LIT>']) + "<STR_LIT>"<EOL>self._execute(sql, opt)<EOL>result = list()<EOL>for row in self._curs_pg:<EOL><INDENT>result.append(dict(row))<EOL>if search_options['<STR_LIT>'] not in (False, None):<EOL><INDENT>if len(result) >= int(search_options['<STR_LIT>']):<EOL><INDENT>break<EOL><DEDENT><DEDENT><DEDENT>return { '<STR_LIT>': search_options, '<STR_LIT:result>': result }<EOL>
Search prefix list for prefixes matching `query`.

            * `auth` [BaseAuth]
                AAA options.
            * `query` [dict_to_sql]
                How the search should be performed.
            * `search_options` [options_dict]
                Search options, see below.

            Returns a list of dicts.

            The `query` argument passed to this function is designed to be
            able to express quite advanced search filters. It is internally
            expanded to an SQL WHERE-clause.

            The `query` is a dict with three elements, where one specifies the
            operation to perform and the two other specifies its arguments. The
            arguments can themselves be `query` dicts, i.e. nested, to build
            more complex queries.

            The :attr:`operator` key specifies what operator should be used for the
            comparison. Currently the following operators are supported:

            * :data:`and` - Logical AND
            * :data:`or` - Logical OR
            * :data:`equals_any` - Equality of any element in array
            * :data:`equals` - Equality; =
            * :data:`not_equals` - Inequality; !=
            * :data:`less` - Less than; <
            * :data:`less_or_equal` - Less than or equal to; <=
            * :data:`greater` - Greater than; >
            * :data:`greater_or_equal` - Greater than or equal to; >=
            * :data:`like` - SQL LIKE
            * :data:`regex_match` - Regular expression match
            * :data:`regex_not_match` - Regular expression not match
            * :data:`contains` - IP prefix contains
            * :data:`contains_equals` - IP prefix contains or is equal to
            * :data:`contained_within` - IP prefix is contained within
            * :data:`contained_within_equals` - IP prefix is contained within or equals

            The :attr:`val1` and :attr:`val2` keys specifies the values which
            are subjected to the comparison. :attr:`val1` can be either any
            prefix attribute or a query dict. :attr:`val2` can be either the
            value you want to compare the prefix attribute to, or a `query`
            dict.

            Example 1 - Find the prefixes which contains 192.0.2.0/24::

                query = {
                    'operator': 'contains',
                    'val1': 'prefix',
                    'val2': '192.0.2.0/24'
                }

            This will be expanded to the pseudo-SQL query::

                SELECT * FROM prefix WHERE prefix contains '192.0.2.0/24'

            Example 2 - Find for all assignments in prefix 192.0.2.0/24::

                query = {
                    'operator': 'and',
                    'val1': {
                        'operator': 'equals',
                        'val1': 'type',
                        'val2': 'assignment'
                    },
                    'val2': {
                        'operator': 'contained_within',
                        'val1': 'prefix',
                        'val2': '192.0.2.0/24'
                    }
                }

            This will be expanded to the pseudo-SQL query::

                SELECT * FROM prefix WHERE (type == 'assignment') AND (prefix contained within '192.0.2.0/24')

            If you want to combine more than two expressions together with a
            boolean expression you need to nest them. For example, to match on
            three values, in this case the tag 'foobar' and a prefix-length
            between /10 and /24, the following could be used::

                query = {
                    'operator': 'and',
                    'val1': {
                        'operator': 'and',
                        'val1': {
                            'operator': 'greater',
                            'val1': 'prefix_length',
                            'val2': 9
                        },
                        'val2': {
                            'operator': 'less_or_equal',
                            'val1': 'prefix_length',
                            'val2': 24
                        }
                    },
                    'val2': {
                        'operator': 'equals_any',
                        'val1': 'tags',
                        'val2': 'foobar'
                    }
                }


            The `options` argument provides a way to alter the search result to
            assist in client implementations. Most options regard parent and
            children prefixes, that is the prefixes which contain the prefix(es)
            matching the search terms (parents) or the prefixes which are
            contained by the prefix(es) matching the search terms. The search
            options can also be used to limit the number of rows returned.

            The following options are available:
                * :attr:`parents_depth` - How many levels of parents to return. Set to :data:`-1` to include all parents.
                * :attr:`children_depth` - How many levels of children to return. Set to :data:`-1` to include all children.
                * :attr:`include_all_parents` - Include all parents, no matter what depth is specified.
                * :attr:`include_all_children` - Include all children, no matter what depth is specified.
                * :attr:`max_result` - The maximum number of prefixes to return (default :data:`50`).
                * :attr:`offset` - Offset the result list this many prefixes (default :data:`0`).

            The options above gives the possibility to specify how many levels
            of parent and child prefixes to return in addition to the prefixes
            that actually matched the search terms. This is done by setting the
            :attr:`parents_depth` and :attr:`children depth` keys in the
            `search_options` dict to an integer value.  In addition to this it
            is possible to get all all parents and/or children included in the
            result set even though they are outside the limits set with
            :attr:`*_depth`.  The extra prefixes included will have the
            attribute :attr:`display` set to :data:`false` while the other ones
            (the actual search result togther with the ones included due to
            given depth) :attr:`display` set to :data:`true`. This feature is
            usable obtain search results with some context given around them,
            useful for example when displaying prefixes in a tree without the
            need to implement client side IP address logic.

            This is the documentation of the internal backend function. It's
            exposed over XML-RPC, please also see the XML-RPC documentation for
            :py:func:`nipap.xmlrpc.NipapXMLRPC.search_prefix` for full
            understanding.