
    =wgY                        d dl mZ d dlZd dlmZ d dlmZ d dlmZ d dlm	Z	 d dlm
Z
  G d d	e      Zdd
ZddZ G d de      Z G d de      Z e       Z e       Z G d de      Z G d de      Z e       Z G d de      Zy)    )divisionN)array)matchingu)TermNotFound)methodcallerc                       e Zd ZdZy)
QueryErrorz-Error encountered while running a query.
    N)__name__
__module____qualname____doc__     I/var/www/horilla/myenv/lib/python3.12/site-packages/whoosh/query/qcore.pyr   r   (   s
    r   r   c                 ,    |
t               }| |_        |S )zReturns the query in the second argument (or a :class:`NullQuery` if the
    second argument is not given) with its ``error`` attribute set to
    ``msg``.
    )
_NullQueryerror)msgqs     r   error_queryr   0   s     	yLAGHr   c                    | j                         r.ddlm} |st        | |      st	        | j                               S yg }| j                         D ]6  }t        ||      }t        |      dk(  r|d   }|s&|j                  |       8 |S )zcReturns the terms in the query tree, with the query hierarchy
    represented as nested lists.
    r   )Phrasephrases   N)
is_leafwhoosh.queryr   
isinstancelisttokenschildrentoken_listslenappend)r   r   r   lsqqts         r   r$   r$   <   s    
 	yy{'*Q/
## 0 **, 	BB0A1v{aD		!	 	r   c                   :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
LowestzSA value that is always compares lower than any other object except
    itself.
    c                 *    |j                   t        u ryy)Nr   )	__class__r+   selfothers     r   __cmp__zLowest.__cmp__W   s    ??f$r   c                 0    | j                   t        |      u S Nr.   typer/   s     r   __eq__zLowest.__eq__\       ~~e,,r   c                 0    t        |      | j                  uS r4   r6   r.   r/   s     r   __lt__zLowest.__lt___   s    E{$..00r   c                 &    | j                  |       S r4   r7   r/   s     r   __ne__zLowest.__ne__b       ;;u%%%r   c                 L    | j                  |      xs | j                  |       S r4   r;   r7   r/   s     r   __gt__zLowest.__gt__e   "    KK&<$++e*<==r   c                 J    | j                  |      xs | j                  |      S r4   r7   r;   r/   s     r   __le__zLowest.__le__h       {{5!7T[[%77r   c                 J    | j                  |      xs | j                  |      S r4   r7   rB   r/   s     r   __ge__zLowest.__ge__k   rG   r   Nr   r   r   r   r2   r7   r;   r>   rB   rF   rJ   r   r   r   r+   r+   R   s*    
-1&>88r   r+   c                   :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
HighestzTA value that is always compares higher than any other object except
    itself.
    c                 *    |j                   t        u ryy)Nr   r   )r.   rM   r/   s     r   r2   zHighest.__cmp__t   s    ??g%r   c                 0    | j                   t        |      u S r4   r5   r/   s     r   r7   zHighest.__eq__y   r8   r   c                 0    t        |      | j                  u S r4   r:   r/   s     r   r;   zHighest.__lt__|   s    E{dnn,,r   c                 &    | j                  |       S r4   r=   r/   s     r   r>   zHighest.__ne__   r?   r   c                 L    | j                  |      xs | j                  |       S r4   rA   r/   s     r   rB   zHighest.__gt__   rC   r   c                 J    | j                  |      xs | j                  |      S r4   rE   r/   s     r   rF   zHighest.__le__   rG   r   c                 J    | j                  |      xs | j                  |      S r4   rI   r/   s     r   rJ   zHighest.__ge__   rG   r   NrK   r   r   r   rM   rM   o   s*    
--&>88r   rM   c                       e Zd ZdZdxZZdZd Zd Zd Z	d Z
d Zd Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd%dZd&dZd%dZd'dZd Zd%dZd(dZd)dZd Zd Z d Z!d Z"d Z#d*d Z$d! Z%d" Z&d# Z'd$ Z(y)+Querya  Abstract base class for all queries.

    Note that this base class implements __or__, __and__, and __sub__ to allow
    slightly more convenient composition of query objects::

        >>> Term("content", u"a") | Term("content", u"b")
        Or([Term("content", u"a"), Term("content", u"b")])

        >>> Term("content", u"a") & Term("content", u"b")
        And([Term("content", u"a"), Term("content", u"b")])

        >>> Term("content", u"a") - Term("content", u"b")
        And([Term("content", u"a"), Not(Term("content", u"b"))])
    Nc                 @    t        | j                  j                        r4   )NotImplementedErrorr.   r   r0   s    r   __unicode__zQuery.__unicode__   s    !$.."9"9::r   c                     t         r4   rX   )r0   items     r   __getitem__zQuery.__getitem__       !!r   c                 >    ddl m}  || |g      j                         S )zWAllows you to use | between query objects to wrap them in an Or
        query.
        r   )Or)r   ra   	normalize)r0   queryra   s      r   __or__zQuery.__or__   s    
 	$4- **,,r   c                 >    ddl m}  || |g      j                         S )zXAllows you to use & between query objects to wrap them in an And
        query.
        r   )And)r   rf   rb   )r0   rc   rf   s      r   __and__zQuery.__and__   s    
 	%D%=!++--r   c                 N    ddl m}m}  ||  ||      g      j                         S )zhAllows you to use - between query objects to add the right-hand
        query as a "NOT" query.
        r   )rf   Not)r   rf   ri   rb   )r0   rc   rf   ri   s       r   __sub__zQuery.__sub__   s$    
 	*D#e*%&0022r   c                     t         r4   r\   rY   s    r   __hash__zQuery.__hash__   r_   r   c                 &    | j                  |       S r4   r=   r/   s     r   r>   zQuery.__ne__   r?   r   c                      y)zoReturns True if this is a leaf node in the query tree, or False if
        this query has sub-queries.
        Tr   rY   s    r   r   zQuery.is_leaf   s    
 r   c                     t        g       S )z>Returns an iterator of the subqueries of this object.
        iterrY   s    r   r#   zQuery.children   s     Bxr   c                      y)zHReturns True if this object searches for values within a range.
        Fr   rY   s    r   is_rangezQuery.is_range   s     r   c                      y)a   Returns True if this specific object represents a search for a
        specific term (as opposed to a pattern, as in Wildcard and Prefix) or
        terms (i.e., whether the ``replace()`` method does something
        meaningful on this instance).
        Fr   rY   s    r   	has_termszQuery.has_terms   s     r   c                 R    | j                         D ]  }|j                         s y y)NTF)r#   needs_spans)r0   childs     r   rw   zQuery.needs_spans   s+    ]]_ 	E  "	 r   c                     | S )a  If this query has children, calls the given function on each child
        and returns a new copy of this node with the new children returned by
        the function. If this is a leaf node, simply returns this object.

        This is useful for writing functions that transform a query tree. For
        example, this function changes all Term objects in a query tree into
        Variations objects::

            def term2var(q):
                if isinstance(q, Term):
                    return Variations(q.fieldname, q.text)
                else:
                    return q.apply(term2var)

            q = And([Term("f", "alfa"),
                     Or([Term("f", "bravo"),
                         Not(Term("f", "charlie"))])])
            q = term2var(q)

        Note that this method does not automatically create copies of nodes.
        To avoid modifying the original tree, your function should call the
        :meth:`Query.copy` method on nodes before changing their attributes.
        r   )r0   fns     r   applyzQuery.apply   s	    2 r   c                 "    fd |       S )a  Applies the given function to this query's subqueries (if any) and
        then to this query itself::

            def boost_phrases(q):
                if isintance(q, Phrase):
                    q.boost *= 2.0
                return q

            myquery = myquery.accept(boost_phrases)

        This method automatically creates copies of the nodes in the original
        tree before passing them to your function, so your function can change
        attributes on nodes without altering the original tree.

        This method is less flexible than using :meth:`Query.apply` (in fact
        it's implemented using that method) but is often more straightforward.
        c                 6    | j                        }  |       S r4   )r{   )r   rz   
fn_wrappers    r   r~   z Query.accept.<locals>.fn_wrapper  s    
#Aa5Lr   r   )r0   rz   r~   s    `@r   acceptzQuery.accept
  s    &	 $r   c                     | j                         rt        j                  |       S | j                  t        d|||            S )zReturns a copy of this query with oldtext replaced by newtext (if
        oldtext was anywhere in this query).

        Note that this returns a *new* query with the given text replaced. It
        *does not* modify the original query "in place".
        replace)r   copyr{   r	   )r0   	fieldnameoldtextnewtexts       r   r   zQuery.replace#  s<     <<>99T?"::l9i+24 5 5r   c                 ,    t        j                  |       S )z0Deprecated, just use ``copy.deepcopy``.
        )r   deepcopyrY   s    r   r   z
Query.copy3  s     }}T""r   c                 8    t        | j                  |            S )zReturns a set of all terms in this query tree.

        This method exists for backwards-compatibility. Use iter_all_terms()
        instead.

        :param phrases: Whether to add words found in Phrase queries.
        :rtype: set
        r   )setiter_all_termsr0   r   s     r   	all_termszQuery.all_terms9  s     4&&w&788r   c                     t        d      S )a   Yields zero or more (fieldname, text) pairs queried by this object.
        You can check whether a query object targets specific terms before you
        call this method using :meth:`Query.has_terms`.

        To get all terms in a query tree, use :meth:`Query.iter_all_terms`.
        r   rp   r   s     r   termszQuery.termsE  s     Bxr   c                 &    | j                  |      S )Nr   )r   )r0   ixreaderr   s      r   expanded_termszQuery.expanded_termsO  s    zz'z**r   c                    |j                   }t               }| j                         D ]  }|r||j                         k7  r|r|j	                  ||      }n|j                  |      }|D ]B  \  }}	||	f|v r||v s||   }
	 |
j                  |	      }||f|v s0|j                  ||f       D  |S # t        $ r Y Tw xY w)ay  Returns a set of all byteterms in this query tree that exist in
        the given ixreader.

        :param ixreader: A :class:`whoosh.reading.IndexReader` object.
        :param phrases: Whether to add words found in Phrase queries.
        :param expand: If True, queries that match multiple terms
            will return all matching expansions.
        :rtype: set
        r   )	schemar   leavesfieldr   r   to_bytes
ValueErroradd)r0   r   r   expandr   r   termsetr   r   textr   btexts               r   existing_termszQuery.existing_termsR  s     % 	8AY!'')3((7(C0#( 8	4t$/&"9-E! %t 4 "5)X5Y$678	8.  & ! !s   B33	B?>B?c              #      K   | j                         r|  y| j                         D ]  }|j                         D ]  }|   yw)zaReturns an iterator of all the leaf queries in this query tree as a
        flat series.
        N)r   r#   r   )r0   r   r(   s      r   r   zQuery.leavesy  sE     
 <<>J]]_ ((* BHs   AAc              #      K   | j                         D ].  }|j                         s|j                  |      D ]  }|  0 yw)as  Returns an iterator of (fieldname, text) pairs for all terms in
        this query tree.

        >>> qp = qparser.QueryParser("text", myindex.schema)
        >>> q = myparser.parse("alfa bravo title:charlie")
        >>> # List the terms in a query
        >>> list(q.iter_all_terms())
        [("text", "alfa"), ("text", "bravo"), ("title", "charlie")]
        >>> # Get a set of all terms in the query that don't exist in the index
        >>> r = myindex.reader()
        >>> missing = set(t for t in q.iter_all_terms() if t not in r)
        set([("text", "alfa"), ("title", "charlie")])
        >>> # All terms in the query that occur in fewer than 5 documents in
        >>> # the index
        >>> [t for t in q.iter_all_terms() if r.doc_frequency(t[0], t[1]) < 5]
        [("title", "charlie")]

        :param phrases: Whether to add words found in Phrase queries.
        r   N)r   ru   r   )r0   r   r   r)   s       r   r   zQuery.iter_all_terms  sE     *  	A{{}1 AG	s
   $AAc              #      K   | j                         r| j                  |      D ]  }|  y|t        | d      r| j                  ndz  }| j	                         D ]  }|j                  |      D ]  }|   yw)a  Returns an iterator of :class:`analysis.Token` objects corresponding
        to all terms in this query tree. The Token objects will have the
        ``fieldname``, ``text``, and ``boost`` attributes set. If the query
        was built by the query parser, they Token objects will also have
        ``startchar`` and ``endchar`` attributes indexing into the original
        user query.
        boost      ?N)r   r"   hasattrr   r#   
all_tokens)r0   r   tokenrx   s       r   r   zQuery.all_tokens  s}      <<>U+  74#9TZZsBE  "--e4  EK  s   A9A;c                     t        d      S )a  Yields zero or more :class:`analysis.Token` objects corresponding to
        the terms searched for by this query object. You can check whether a
        query object targets specific terms before you call this method using
        :meth:`Query.has_terms`.

        The Token objects will have the ``fieldname``, ``text``, and ``boost``
        attributes set. If the query was built by the query parser, they Token
        objects will also have ``startchar`` and ``endchar`` attributes
        indexing into the original user query.

        To get all tokens for a query tree, use :meth:`Query.all_tokens`.

        :param exreader: a reader to use to expand multiterm queries such as
            prefixes and wildcards. The default is None meaning do not expand.
        r   rp   )r0   r   exreaders      r   r"   zQuery.tokens  s    " Bxr   c                     t        | g      S )a6  Returns a set of queries that are *known* to be required to match
        for the entire query to match. Note that other queries might also turn
        out to be required but not be determinable by examining the static
        query.

        >>> a = Term("f", u"a")
        >>> b = Term("f", u"b")
        >>> And([a, b]).requires()
        set([Term("f", u"a"), Term("f", u"b")])
        >>> Or([a, b]).requires()
        set([])
        >>> AndMaybe(a, b).requires()
        set([Term("f", u"a")])
        >>> a.requires()
        set([Term("f", u"a")])
        )r   rY   s    r   requireszQuery.requires  s    ( D6{r   c                     | j                   S )zqReturns the field this query matches in, or None if this query does
        not match in a single field.
        )r   rY   s    r   r   zQuery.field  s    
 ~~r   c                 4    | j                         }||_        |S )zReturns a COPY of this query with the boost set to the given value.

        If a query type does not accept a boost itself, it will try to pass the
        boost on to its children, if any.
        )r   r   )r0   r   r   s      r   
with_boostzQuery.with_boost  s     IIKr   c                     t         )a
  Returns an estimate of how many documents this query could
        potentially match (for example, the estimated size of a simple term
        query is the document frequency of the term). It is permissible to
        overestimate, but not to underestimate.
        r\   r0   r   s     r   estimate_sizezQuery.estimate_size  s
     "!r   c                 $    | j                  |      S )zkReturns an estimate of the minimum number of documents this query
        could potentially match.
        )r   r   s     r   estimate_min_sizezQuery.estimate_min_size  s    
 !!(++r   c                     t         )zReturns a :class:`~whoosh.matching.Matcher` object you can use to
        retrieve documents and scores matching this query.

        :rtype: :class:`whoosh.matching.Matcher`
        r\   r0   searchercontexts      r   matcherzQuery.matcher  s
     "!r   c                     	 |j                         }| j                  ||      j                         S # t        $ r t	        g       cY S w xY w)zReturns an iterator of docnums matching this query.

        >>> with my_index.searcher() as searcher:
        ...     list(my_query.docs(searcher))
        [10, 34, 78, 103]

        :param searcher: A :class:`whoosh.searching.Searcher` object.
        )boolean_contextr   all_idsr   rq   r   s      r   docsz
Query.docs  sG    	..0G<<'2::<< 	8O	s   /2 A	A	c                 $    | j                  |      S )a  Returns an iterator of docnums matching this query for the purpose
        of deletion. The :meth:`~whoosh.writing.IndexWriter.delete_by_query`
        method will use this method when deciding what documents to delete,
        allowing special queries (e.g. nested queries) to override what
        documents are deleted. The default implementation just forwards to
        :meth:`Query.docs`.
        )r   r0   r   s     r   deletion_docszQuery.deletion_docs  s     yy""r   c                     | S )a  Returns a recursively "normalized" form of this query. The
        normalized form removes redundancy and empty queries. This is called
        automatically on query trees created by the query parser, but you may
        want to call it yourself if you're writing your own parser or building
        your own queries.

        >>> q = And([And([Term("f", u"a"),
        ...               Term("f", u"b")]),
        ...               Term("f", u"c"), Or([])])
        >>> q.normalize()
        And([Term("f", u"a"), Term("f", u"b"), Term("f", u"c")])

        Note that this returns a *new, normalized* query. It *does not* modify
        the original query "in place".
        r   rY   s    r   rb   zQuery.normalize  s	      r   c                     | S )zReturns a recursively simplified form of this query, where
        "second-order" queries (such as Prefix and Variations) are re-written
        into lower-level queries (such as Term and Or).
        r   r   s     r   simplifyzQuery.simplify1  s	    
 r   T)F)TFN)r   )r   Nr4   ))r   r   r   r   	startcharendcharr   rZ   r^   rd   rg   rj   rl   r>   r   r#   rs   ru   rw   r{   r   r   r   r   r   r   r   r   r   r   r"   r   r   r   r   r   r   r   r   rb   r   r   r   r   rV   rV      s    " I E;"-.3"&6 25 #
9+%N
4 $&,	"," 	#$r   rV   c                   p    e Zd ZdZdZd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd ZddZy)r   z-Represents a query that won't match anything.r   c                     d | _         y r4   )r   rY   s    r   __init__z_NullQuery.__init__@  s	    
r   c                     t        d      S )Nz<_NullQuery>r   rY   s    r   rZ   z_NullQuery.__unicode__C  s      r   c                     | S r4   r   rY   s    r   __call__z_NullQuery.__call__F      r   c                 4    d| j                   j                  z  S )Nz<%s>)r.   r   rY   s    r   __repr__z_NullQuery.__repr__I  s    0011r   c                 "    t        |t              S r4   )r    r   r/   s     r   r7   z_NullQuery.__eq__L  s    %,,r   c                 &    | j                  |       S r4   r=   r/   s     r   r>   z_NullQuery.__ne__O  r?   r   c                     t        |       S r4   )idrY   s    r   rl   z_NullQuery.__hash__R  s    $xr   c                     | S r4   r   rY   s    r   __copy__z_NullQuery.__copy__U  r   r   c                     | S r4   r   )r0   memos     r   __deepcopy__z_NullQuery.__deepcopy__X  r   r   c                      y r4   r   rY   s    r   r   z_NullQuery.field[  s    r   c                      y)Nr   r   r   s     r   r   z_NullQuery.estimate_size^  s    r   c                     | S r4   r   rY   s    r   rb   z_NullQuery.normalizea  r   r   c                     | S r4   r   r   s     r   r   z_NullQuery.simplifyd  r   r   c                     g S r4   r   r   s     r   r   z_NullQuery.docsg  s    	r   Nc                 *    t        j                         S r4   )r   NullMatcherr   s      r   r   z_NullQuery.matcherj  s    ##%%r   r4   )r   r   r   r   r   r   rZ   r   r   r7   r>   rl   r   r   r   r   rb   r   r   r   r   r   r   r   r   ;  sU    3E!2-&&r   r   c                   B    e Zd ZdZd
dZd Zd Zd ZeZd Z	d Z
dd	Zy)Everya  A query that matches every document containing any term in a given
    field. If you don't specify a field, the query matches every document.

    >>> # Match any documents with something in the "path" field
    >>> q = Every("path")
    >>> # Matcher every document
    >>> q = Every()

    The unfielded form (matching every document) is efficient.

    The fielded is more efficient than a prefix query with an empty prefix or a
    '*' wildcard, but it can still be very slow on large indexes. It requires
    the searcher to read the full posting list of every term in the given
    field.

    Instead of using this query it is much more efficient when you create the
    index to include a single term that appears in all documents that have the
    field you want to match.

    For example, instead of this::

        # Match all documents that have something in the "path" field
        q = Every("path")

    Do this when indexing::

        # Add an extra field that indicates whether a document has a path
        schema = fields.Schema(path=fields.ID, has_path=fields.ID)

        # When indexing, set the "has_path" field based on whether the document
        # has anything in the "path" field
        writer.add_document(text=text_value1)
        writer.add_document(text=text_value2, path=path_value2, has_path="t")

    Then to find all documents with a path::

        q = Term("has_path", "t")
    Nc                 2    |r|dk(  rd}|| _         || _        y)z|
        :param fieldname: the name of the field to match, or ``None`` or ``*``
            to match all documents.
        *N)r   r   )r0   r   r   s      r   r   zEvery.__init__  s!     I,I"
r   c                 h    | j                   j                  d| j                  d| j                  dS )N(z, boost=))r.   r   r   r   rY   s    r   r   zEvery.__repr__  s&    %)^^%<%<dnn%)ZZ1 	1r   c                     |xrN | j                   |j                   u xr4 | j                  |j                  k(  xr | j                  |j                  k(  S r4   )r.   r   r   r/   s     r   r7   zEvery.__eq__  sH     .$..EOO; .NNeoo5.JJ%++-	/r   c                 2    t        d      | j                  z  S )Nz%s:*)r   r   rY   s    r   rZ   zEvery.__unicode__  s    y4>>))r   c                 ,    t        | j                        S r4   )hashr   rY   s    r   rl   zEvery.__hash__  s    DNN##r   c                 "    |j                         S r4   )	doc_countr   s     r   r   zEvery.estimate_size  s    !!##r   c                 r   | j                   }|j                         }|dv rt        d|j                               }n\t	               }|j                  |      D ]3  }|j                  ||      }|j                  |j                                5 t        |      }t        j                  || j                        S )N)N r   I)all_weights)r   readerr   all_doc_idsr   lexiconpostingsupdater   sortedr   ListMatcherr   )r0   r   r   r   r   doclistr   prs           r   r   zEvery.matcher  s    NN	"'C!3!3!56G
 eG ((3 -&&y$7rzz|,- WoG##GDDr   )Nr   r4   )r   r   r   r   r   r   r7   rZ   __str__rl   r   r   r   r   r   r   r   s  s3    %N	1/
* G$$Er   r   r4   r   )
__future__r   r   r   whooshr   whoosh.compatr   whoosh.readingr   r	   	Exceptionr   r   r$   objectr+   rM   rV   r   	NullQueryr   r   r   r   <module>r      s   8       ' &
	 		,8V 8:8f 8: 

)
dF dR0& 0&f L	
XEE XEr   