def search(self, **kwargs):
match = False<EOL>r_query = {}<EOL>myself = self.__class__.__name__<EOL>for k, value in six.iteritems(kwargs):<EOL><INDENT>k_pop = query_pop(k, myself)<EOL>if k_pop:<EOL><INDENT>r_query[k_pop] = value<EOL><DEDENT><DEDENT>if not r_query:<EOL><INDENT>return False<EOL><DEDENT>for key in r_query:<EOL><INDENT>if hasattr(self, key):<EOL><INDENT>match |= match_query(getattr(self, key), r_query[key])<EOL><DEDENT><DEDENT>if not match:<EOL><INDENT>for attr in dir(self):<EOL><INDENT>obj = getattr(self, attr)<EOL>if isinstance(obj, JObject):<EOL><INDENT>match |= obj.search(**r_query)<EOL><DEDENT><DEDENT><DEDENT>return match<EOL>
Query this object (and its descendants).

        Parameters
        ----------
        kwargs
            Each `(key, value)` pair encodes a search field in `key`
            and a target value in `value`.

            `key` must be a string, and should correspond to a property in
            the JAMS object hierarchy, e.g., 'Annotation.namespace` or `email`

            `value` must be either an object (tested for equality), a
            string describing a search pattern (regular expression), or a
            lambda function which evaluates to `True` if the candidate
            object matches the search criteria and `False` otherwise.

        Returns
        -------
        match : bool
            `True` if any of the search keys match the specified value,
            `False` otherwise, or if the search keys do not exist
            within the object.

        Examples
        --------
        >>> J = jams.JObject(foo=5, needle='quick brown fox')
        >>> J.search(needle='.*brown.*')
        True
        >>> J.search(needle='.*orange.*')
        False
        >>> J.search(badger='.*brown.*')
        False
        >>> J.search(foo=5)
        True
        >>> J.search(foo=10)
        False
        >>> J.search(foo=lambda x: x < 10)
        True
        >>> J.search(foo=lambda x: x > 10)
        False