o
    }l~iz                     @  s  d Z ddlmZ ddlmZmZmZmZ ddlm	Z	 ddlm
Z
 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 ddlmZ edeeeeejeeed
ZG dd dZG dd de	Z G dd de ee Z!G dd de Z"G dd de"Z#G dd de Z$ede dZ%G dd de$ee% Z&G dd  d e$Z'G d!d" d"e"Z(G d#d$ d$e"Z)G d%d& d&e"Z*G d'd( d(e(Z+G d)d* d*e(Z,G d+d, d,e(Z-G d-d. d.e(Z.G d/d0 d0e(Z/G d1d2 d2e#Z0G d3d4 d4e"Z1dS )5z
.. warning::
    **Preview API**: Firestore Pipelines is currently in preview and is
    subject to potential breaking changes in future releases.
    )annotations)AnyGenericTypeVarSequence)ABC)abstractmethod)EnumNValue)StructuredQuery)Vector)GeoPoint)encode_value)decode_valueCONSTANT_TYPEc                   @  sB   e Zd ZdZG dd deZejfdddZdd	 ZdddZ	dS )Orderingz;Represents the direction for sorting results in a pipeline.c                   @  s   e Zd ZdZdZdS )zOrdering.Direction	ascending
descendingN)__name__
__module____qualname__	ASCENDING
DESCENDING r   r   u/var/www/newdalilibackend/backend/venv/lib/python3.10/site-packages/google/cloud/firestore_v1/pipeline_expressions.py	Direction7   s    r   	order_dirDirection | strc                 C  sB   t |tr|nt|| _t |trtj|  | _	dS || _	dS )aF  
        Initializes an Ordering instance

        Args:
            expr (Expression | str): The expression or field path string to sort by.
                If a string is provided, it's treated as a field path.
            order_dir (Direction | str): The direction to sort in.
                Defaults to ascending
        N)

isinstance
ExpressionFieldofexprstrr   r   upperr   )selfr#   r   r   r   r   __init__;   s   
zOrdering.__init__c                 C  s&   | j tjju r
d}nd}| j| S )Nz.ascending()z.descending())r   r   r   r   r#   )r&   	order_strr   r   r   __repr__L   s   zOrdering.__repr__returnr   c                 C  s$   t dt | jjd| j didS )Nfields)string_value)	direction
expression	map_value)r   r   valuer#   _to_pbr&   r   r   r   r2   S   s   zOrdering._to_pbN)r   r   r*   r   )
r   r   r   __doc__r	   r   r   r'   r)   r2   r   r   r   r   r   4   s    r   c                   @  s  e Zd ZdZdd ZedddZe	ddddZG dd dZ	e	dddZ
e	dddZe	dddZe	dddZe	dddZe	dddZe	dddZe	dd d!Ze	dd"d#Ze	dd$d%Ze	dd'd(Ze	dd)d*Ze	dd,d-Ze	dd.d/Ze	dd0d1Ze	dd4d5Ze	dd6d7Ze	dd9d:Ze	dd;d<Ze	dd=d>Ze	dd?d@Ze	ddAdBZe	ddCdDZ e	ddGdHZ!e	ddJdKZ"e	ddOdPZ#e	ddRdSZ$e	ddUdVZ%e	ddWdXZ&e	ddYdZZ'e	dd[d\Z(e	dd^d_Z)e	dd`daZ*e	ddbdcZ+e	ddddeZ,e	ddgdhZ-e	didj Z.e	ddldmZ/e	ddndoZ0e	ddpdqZ1e	ddrdsZ2e	ddtduZ3e	ddvdwZ4e	ddxdyZ5e	ddzd{Z6e	dd|d}Z7e	dd~dZ8e	dddZ9e	dddZ:e	dddZ;e	dddZ<e	dddZ=e	dddZ>e	dddZ?e	dddZ@e	dddZAe	dddZBe	dddZCe	dddZDe		ddddZEe	dddZFe	dddZGe	dddZHe	dddZIe	dddZJe	dddZKe	dddZLe	dddZMe	dddZNe	dddZOe	dddZPe	dddZQe	dddÄZRe	dddńZSe	dddɄZTe	ddd˄ZUe	dd̈́ ZVe	ddτ ZWddd҄ZXdddԄZYdddلZZdS )r    a  Represents an expression that can be evaluated to a value within the
    execution of a pipeline.

    Expressionessions are the building blocks for creating complex queries and
    transformations in Firestore pipelines. They can represent:

    - **Field references:** Access values from document fields.
    - **Literals:** Represent constant values (strings, numbers, booleans).
    - **FunctionExpression calls:** Apply functions to one or more expressions.
    - **Aggregations:** Calculate aggregate values (e.g., sum, average) over a set of documents.

    The `Expression` class provides a fluent API for building expressions. You can chain
    together method calls to create complex expressions.
    c                 C  s   | j j dS )N())	__class__r   r3   r   r   r   r)   n      zExpression.__repr__r*   r   c                 C     t NNotImplementedErrorr3   r   r   r   r2   q   s   zExpression._to_pbFor   'Expression'c                 C  s\   t | tr| S t | trt| S t | tr*|r&tdd | D r&tt| S t| S t| S )z*Convert arbitrary object to an Expression.c                 S  s   g | ]	}t |ttfqS r   )r   floatint).0ir   r   r   
<listcomp>       zCExpression._cast_to_expr_or_convert_to_constant.<locals>.<listcomp>)	r   r    dictMaplistallConstantr   Array)r=   include_vectorr   r   r   $_cast_to_expr_or_convert_to_constantu   s   


z/Expression._cast_to_expr_or_convert_to_constantc                   @  s(   e Zd ZdZdd Zdd Zdd ZdS )	zExpression.expose_as_staticaG  
        Decorator to mark instance methods to be exposed as static methods as well as instance
        methods.

        When called statically, the first argument is converted to a Field expression if needed.

        Example:
            >>> Field.of("test").add(5)
            >>> FunctionExpression.add("test", 5)
        c                 C  
   || _ d S r:   )instance_func)r&   rN   r   r   r   r'         
z$Expression.expose_as_static.__init__c                 O  s\   t |ttfstd| jj dt| dt |ts t|n|}| j|g|R i |S )N'zH' must be called on an Expression or a string representing a field. got .)	r   r    r$   	TypeErrorrN   r   typer!   r"   )r&   	first_arg
other_argskwargs
first_exprr   r   r   static_func   s   z'Expression.expose_as_static.static_funcc                 C  s   |d u r| j S | j||S r:   )rX   rN   __get__)r&   instanceownerr   r   r   rY      s   z#Expression.expose_as_static.__get__N)r   r   r   r5   r'   rX   rY   r   r   r   r   expose_as_static   s
    r\   otherExpression | floatc                 C     t d| | |gS )a  Creates an expression that adds this expression to another expression or constant.

        Example:
            >>> # Add the value of the 'quantity' field and the 'reserve' field.
            >>> Field.of("quantity").add(Field.of("reserve"))
            >>> # Add 5 to the value of the 'age' field
            >>> Field.of("age").add(5)

        Args:
            other: The expression or constant value to add to this expression.

        Returns:
            A new `Expression` representing the addition operation.
        addFunctionExpressionrL   r&   r]   r   r   r   r`         zExpression.addc                 C  r_   )a+  Creates an expression that subtracts another expression or constant from this expression.

        Example:
            >>> # Subtract the 'discount' field from the 'price' field
            >>> Field.of("price").subtract(Field.of("discount"))
            >>> # Subtract 20 from the value of the 'total' field
            >>> Field.of("total").subtract(20)

        Args:
            other: The expression or constant value to subtract from this expression.

        Returns:
            A new `Expression` representing the subtraction operation.
        subtractra   rc   r   r   r   re      rd   zExpression.subtractc                 C  r_   )a  Creates an expression that multiplies this expression by another expression or constant.

        Example:
            >>> # Multiply the 'quantity' field by the 'price' field
            >>> Field.of("quantity").multiply(Field.of("price"))
            >>> # Multiply the 'value' field by 2
            >>> Field.of("value").multiply(2)

        Args:
            other: The expression or constant value to multiply by.

        Returns:
            A new `Expression` representing the multiplication operation.
        multiplyra   rc   r   r   r   rf      rd   zExpression.multiplyc                 C  r_   )a  Creates an expression that divides this expression by another expression or constant.

        Example:
            >>> # Divide the 'total' field by the 'count' field
            >>> Field.of("total").divide(Field.of("count"))
            >>> # Divide the 'value' field by 10
            >>> Field.of("value").divide(10)

        Args:
            other: The expression or constant value to divide by.

        Returns:
            A new `Expression` representing the division operation.
        dividera   rc   r   r   r   rg      rd   zExpression.dividec                 C  r_   )a"  Creates an expression that calculates the modulo (remainder) to another expression or constant.

        Example:
            >>> # Calculate the remainder of dividing the 'value' field by field 'divisor'.
            >>> Field.of("value").mod(Field.of("divisor"))
            >>> # Calculate the remainder of dividing the 'value' field by 5.
            >>> Field.of("value").mod(5)

        Args:
            other: The divisor expression or constant.

        Returns:
            A new `Expression` representing the modulo operation.
        modra   rc   r   r   r   rh      rd   zExpression.modc                 C     t d| gS )a"  Creates an expression that calculates the absolute value of this expression.

        Example:
            >>> # Get the absolute value of the 'change' field.
            >>> Field.of("change").abs()

        Returns:
            A new `Expression` representing the absolute value.
        absrb   r3   r   r   r   rj   
     zExpression.absc                 C  ri   )a  Creates an expression that calculates the ceiling of this expression.

        Example:
            >>> # Get the ceiling of the 'value' field.
            >>> Field.of("value").ceil()

        Returns:
            A new `Expression` representing the ceiling value.
        ceilrk   r3   r   r   r   rm     rl   zExpression.ceilc                 C  ri   )a  Creates an expression that computes e to the power of this expression.

        Example:
            >>> # Compute e to the power of the 'value' field
            >>> Field.of("value").exp()

        Returns:
            A new `Expression` representing the exponential value.
        exprk   r3   r   r   r   rn   $  rl   zExpression.expc                 C  ri   )a  Creates an expression that calculates the floor of this expression.

        Example:
            >>> # Get the floor of the 'value' field.
            >>> Field.of("value").floor()

        Returns:
            A new `Expression` representing the floor value.
        floorrk   r3   r   r   r   ro   1  rl   zExpression.floorc                 C  ri   )a(  Creates an expression that calculates the natural logarithm of this expression.

        Example:
            >>> # Get the natural logarithm of the 'value' field.
            >>> Field.of("value").ln()

        Returns:
            A new `Expression` representing the natural logarithm.
        lnrk   r3   r   r   r   rp   >  rl   zExpression.lnbasec                 C  r_   )a  Creates an expression that calculates the logarithm of this expression with a given base.

        Example:
            >>> # Get the logarithm of 'value' with base 2.
            >>> Field.of("value").log(2)
            >>> # Get the logarithm of 'value' with base from 'base_field'.
            >>> Field.of("value").log(Field.of("base_field"))

        Args:
            base: The base of the logarithm.

        Returns:
            A new `Expression` representing the logarithm.
        logra   )r&   rq   r   r   r   rr   K  rd   zExpression.logc                 C  ri   )zCreates an expression that calculates the base 10 logarithm of this expression.

        Example:
            >>> Field.of("value").log10()

        Returns:
            A new `Expression` representing the logarithm.
        log10rk   r3   r   r   r   rs   _  s   
zExpression.log10exponentc                 C  r_   )a  Creates an expression that calculates this expression raised to the power of the exponent.

        Example:
            >>> # Raise 'base_val' to the power of 2.
            >>> Field.of("base_val").pow(2)
            >>> # Raise 'base_val' to the power of 'exponent_val'.
            >>> Field.of("base_val").pow(Field.of("exponent_val"))

        Args:
            exponent: The exponent.

        Returns:
            A new `Expression` representing the power operation.
        powra   )r&   rt   r   r   r   ru   k  rd   zExpression.powc                 C  ri   )a
  Creates an expression that rounds this expression to the nearest integer.

        Example:
            >>> # Round the 'value' field.
            >>> Field.of("value").round()

        Returns:
            A new `Expression` representing the rounded value.
        roundrk   r3   r   r   r   rv     rl   zExpression.roundc                 C  ri   )a  Creates an expression that calculates the square root of this expression.

        Example:
            >>> # Get the square root of the 'area' field.
            >>> Field.of("area").sqrt()

        Returns:
            A new `Expression` representing the square root.
        sqrtrk   r3   r   r   r   rw     rl   zExpression.sqrtothersExpression | CONSTANT_TYPEc                   "   t d g fdd|D  ddS )a=  Creates an expression that returns the larger value between this expression
        and another expression or constant, based on Firestore's value type ordering.

        Firestore's value type ordering is described here:
        https://cloud.google.com/firestore/docs/concepts/data-types#value_type_ordering

        Example:
            >>> # Returns the larger value between the 'discount' field and the 'cap' field.
            >>> Field.of("discount").logical_maximum(Field.of("cap"))
            >>> # Returns the larger value between the 'value' field and some ints
            >>> Field.of("value").logical_maximum(10, 20, 30)

        Args:
            others: The other expression or constant values to compare with.

        Returns:
            A new `Expression` representing the logical maximum operation.
        maximumc                      g | ]}  |qS r   rL   rA   r=   r3   r   r   rC         z.Expression.logical_maximum.<locals>.<listcomp>logical_maximuminfix_name_overriderk   r&   rx   r   r3   r   r     
   zExpression.logical_maximumc                   rz   )aD  Creates an expression that returns the smaller value between this expression
        and another expression or constant, based on Firestore's value type ordering.

        Firestore's value type ordering is described here:
        https://cloud.google.com/firestore/docs/concepts/data-types#value_type_ordering

        Example:
            >>> # Returns the smaller value between the 'discount' field and the 'floor' field.
            >>> Field.of("discount").logical_minimum(Field.of("floor"))
            >>> # Returns the smaller value between the 'value' field and some ints
            >>> Field.of("value").logical_minimum(10, 20, 30)

        Args:
            others: The other expression or constant values to compare with.

        Returns:
            A new `Expression` representing the logical minimum operation.
        minimumc                   r|   r   r}   r~   r3   r   r   rC     r   z.Expression.logical_minimum.<locals>.<listcomp>logical_minimumr   rk   r   r   r3   r   r     r   zExpression.logical_minimum'BooleanExpression'c                 C  r_   )a  Creates an expression that checks if this expression is equal to another
        expression or constant value.

        Example:
            >>> # Check if the 'age' field is equal to 21
            >>> Field.of("age").equal(21)
            >>> # Check if the 'city' field is equal to "London"
            >>> Field.of("city").equal("London")

        Args:
            other: The expression or constant value to compare for equality.

        Returns:
            A new `Expression` representing the equality comparison.
        equalBooleanExpressionrL   rc   r   r   r   r        zExpression.equalc                 C  r_   )aB  Creates an expression that checks if this expression is not equal to another
        expression or constant value.

        Example:
            >>> # Check if the 'status' field is not equal to "completed"
            >>> Field.of("status").not_equal("completed")
            >>> # Check if the 'country' field is not equal to "USA"
            >>> Field.of("country").not_equal("USA")

        Args:
            other: The expression or constant value to compare for inequality.

        Returns:
            A new `Expression` representing the inequality comparison.
        	not_equalr   rc   r   r   r   r     r   zExpression.not_equalc                 C  r_   )aJ  Creates an expression that checks if this expression is greater than another
        expression or constant value.

        Example:
            >>> # Check if the 'age' field is greater than the 'limit' field
            >>> Field.of("age").greater_than(Field.of("limit"))
            >>> # Check if the 'price' field is greater than 100
            >>> Field.of("price").greater_than(100)

        Args:
            other: The expression or constant value to compare for greater than.

        Returns:
            A new `Expression` representing the greater than comparison.
        greater_thanr   rc   r   r   r   r     r   zExpression.greater_thanc                 C  r_   )a  Creates an expression that checks if this expression is greater than or equal
        to another expression or constant value.

        Example:
            >>> # Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1
            >>> Field.of("quantity").greater_than_or_equal(Field.of('requirement').add(1))
            >>> # Check if the 'score' field is greater than or equal to 80
            >>> Field.of("score").greater_than_or_equal(80)

        Args:
            other: The expression or constant value to compare for greater than or equal to.

        Returns:
            A new `Expression` representing the greater than or equal to comparison.
        greater_than_or_equalr   rc   r   r   r   r        z Expression.greater_than_or_equalc                 C  r_   )a)  Creates an expression that checks if this expression is less than another
        expression or constant value.

        Example:
            >>> # Check if the 'age' field is less than 'limit'
            >>> Field.of("age").less_than(Field.of('limit'))
            >>> # Check if the 'price' field is less than 50
            >>> Field.of("price").less_than(50)

        Args:
            other: The expression or constant value to compare for less than.

        Returns:
            A new `Expression` representing the less than comparison.
        	less_thanr   rc   r   r   r   r   $  r   zExpression.less_thanc                 C  r_   )az  Creates an expression that checks if this expression is less than or equal to
        another expression or constant value.

        Example:
            >>> # Check if the 'quantity' field is less than or equal to 20
            >>> Field.of("quantity").less_than_or_equal(Constant.of(20))
            >>> # Check if the 'score' field is less than or equal to 70
            >>> Field.of("score").less_than_or_equal(70)

        Args:
            other: The expression or constant value to compare for less than or equal to.

        Returns:
            A new `Expression` representing the less than or equal to comparison.
        less_than_or_equalr   rc   r   r   r   r   9  r   zExpression.less_than_or_equalarray9Array | Sequence[Expression | CONSTANT_TYPE] | Expressionc                 C  r_   )a  Creates an expression that checks if this expression is equal to any of the
        provided values or expressions.

        Example:
            >>> # Check if the 'category' field is either "Electronics" or value of field 'primaryType'
            >>> Field.of("category").equal_any(["Electronics", Field.of("primaryType")])

        Args:
            array: The values or expressions to check against.

        Returns:
            A new `Expression` representing the 'IN' comparison.
        	equal_anyr   r&   r   r   r   r   r   Q     zExpression.equal_any5Array | list[Expression | CONSTANT_TYPE] | Expressionc                 C  r_   )a  Creates an expression that checks if this expression is not equal to any of the
        provided values or expressions.

        Example:
            >>> # Check if the 'status' field is neither "pending" nor "cancelled"
            >>> Field.of("status").not_equal_any(["pending", "cancelled"])

        Args:
            array: The values or expressions to check against.

        Returns:
            A new `Expression` representing the 'NOT IN' comparison.
        not_equal_anyr   r   r   r   r   r   j  r   zExpression.not_equal_anyoffsetExpression | int'FunctionExpression'c                 C  r_   )a  
        Creates an expression that indexes into an array from the beginning or end and returns the
        element. A negative offset starts from the end.

        Example:
            >>> Array([1,2,3]).array_get(0)

        Args:
            offset: the index of the element to return

        Returns:
            A new `Expression` representing the `array_get` operation.
        	array_getra   )r&   r   r   r   r   r        zExpression.array_getelementc                 C  r_   )aQ  Creates an expression that checks if an array contains a specific element or value.

        Example:
            >>> # Check if the 'sizes' array contains the value from the 'selectedSize' field
            >>> Field.of("sizes").array_contains(Field.of("selectedSize"))
            >>> # Check if the 'colors' array contains "red"
            >>> Field.of("colors").array_contains("red")

        Args:
            element: The element (expression or constant) to search for in the array.

        Returns:
            A new `Expression` representing the 'array_contains' comparison.
        array_containsr   )r&   r   r   r   r   r     s   zExpression.array_containselementsc                 C  r_   )a  Creates an expression that checks if an array contains all the specified elements.

        Example:
            >>> # Check if the 'tags' array contains both "news" and "sports"
            >>> Field.of("tags").array_contains_all(["news", "sports"])
            >>> # Check if the 'tags' array contains both of the values from field 'tag1' and "tag2"
            >>> Field.of("tags").array_contains_all([Field.of("tag1"), "tag2"])

        Args:
            elements: The list of elements (expressions or constants) to check for in the array.

        Returns:
            A new `Expression` representing the 'array_contains_all' comparison.
        array_contains_allr   r&   r   r   r   r   r     s   zExpression.array_contains_allc                 C  r_   )a  Creates an expression that checks if an array contains any of the specified elements.

        Example:
            >>> # Check if the 'categories' array contains either values from field "cate1" or "cate2"
            >>> Field.of("categories").array_contains_any([Field.of("cate1"), Field.of("cate2")])
            >>> # Check if the 'groups' array contains either the value from the 'userGroup' field
            >>> # or the value "guest"
            >>> Field.of("groups").array_contains_any([Field.of("userGroup"), "guest"])

        Args:
            elements: The list of elements (expressions or constants) to check for in the array.

        Returns:
            A new `Expression` representing the 'array_contains_any' comparison.
        array_contains_anyr   r   r   r   r   r     s   zExpression.array_contains_anyc                 C  ri   )a  Creates an expression that calculates the length of an array.

        Example:
            >>> # Get the number of items in the 'cart' array
            >>> Field.of("cart").array_length()

        Returns:
            A new `Expression` representing the length of the array.
        array_lengthrk   r3   r   r   r   r     rl   zExpression.array_lengthc                 C  ri   )a*  Creates an expression that returns the reversed content of an array.

        Example:
            >>> # Get the 'preferences' array in reversed order.
            >>> Field.of("preferences").array_reverse()

        Returns:
            A new `Expression` representing the reversed array.
        array_reverserk   r3   r   r   r   r     rl   zExpression.array_reverseother_arraysc                      t d g fdd|D  S )a  Creates an expression that concatenates an array expression with another array.

        Example:
            >>> # Combine the 'tags' array with a new array and an array field
            >>> Field.of("tags").array_concat(["newTag1", "newTag2", Field.of("otherTag")])

        Args:
            array: The list of constants or expressions to concat with.

        Returns:
            A new `Expression` representing the concatenated array.
        array_concatc                   r|   r   r}   )rA   arrr3   r   r   rC     r   z+Expression.array_concat.<locals>.<listcomp>rk   )r&   r   r   r3   r   r     s   zExpression.array_concatc                   r   )zCreates an expression that concatenates expressions together

        Args:
            *others: The expressions to concatenate.

        Returns:
            A new `Expression` representing the concatenated value.
        concatc                   r|   r   r}   r~   r3   r   r   rC     r   z%Expression.concat.<locals>.<listcomp>rk   r   r   r3   r   r     s   
zExpression.concatc                 C  ri   )aJ  
        Creates an expression that calculates the length of the expression if it is a string, array, map, or blob.

        Example:
            >>> # Get the length of the 'name' field.
            >>> Field.of("name").length()

        Returns:
            A new `Expression` representing the length of the expression.
        lengthrk   r3   r   r   r   r   "     zExpression.lengthc                 C  ri   )a]  Creates an expression that returns true if a value is absent. Otherwise, returns false even if
        the value is null.

        Example:
            >>> # Check if the 'email' field is absent.
            >>> Field.of("email").is_absent()

        Returns:
            A new `BooleanExpressionession` representing the isAbsent operation.
        	is_absentr   r3   r   r   r   r   0  r   zExpression.is_absentdefault_valuec                 C  r_   )a  Creates an expression that returns a default value if an expression evaluates to an absent value.

        Example:
            >>> # Return the value of the 'email' field, or "N/A" if it's absent.
            >>> Field.of("email").if_absent("N/A")

        Args:
            default_value: The expression or constant value to return if this expression is absent.

        Returns:
            A new `Expression` representing the ifAbsent operation.
        	if_absentra   )r&   r   r   r   r   r   >  s   zExpression.if_absentc                 C  ri   )a=  Creates an expression that checks if a given expression produces an error

        Example:
            >>> # Resolves to True if an expression produces an error
            >>> Field.of("value").divide("string").is_error()

        Returns:
            A new `Expression` representing the isError operation.
        is_errorrk   r3   r   r   r   r   Q  rl   zExpression.is_error
then_valuec                 C  r_   )a  Creates an expression that returns ``then_value`` if this expression evaluates to an error.
        Otherwise, returns the value of this expression.

        Example:
            >>> # Resolves to 0 if an expression produces an error
            >>> Field.of("value").divide("string").if_error(0)

        Args:
            then_value: The value to return if this expression evaluates to an error.

        Returns:
            A new `Expression` representing the ifError operation.
        if_errorra   )r&   r   r   r   r   r   ^  r   zExpression.if_errorc                 C  ri   )a*  Creates an expression that checks if a field exists in the document.

        Example:
            >>> # Check if the document has a field named "phoneNumber"
            >>> Field.of("phoneNumber").exists()

        Returns:
            A new `Expression` representing the 'exists' check.
        existsr   r3   r   r   r   r   q  rl   zExpression.existsc                 C  ri   )a[  Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs.

        Example:
            >>> # Calculate the total revenue from a set of orders
            >>> Field.of("orderAmount").sum().as_("totalRevenue")

        Returns:
            A new `AggregateFunction` representing the 'sum' aggregation.
        sumAggregateFunctionr3   r   r   r   r   ~  rl   zExpression.sumc                 C  ri   )aZ  Creates an aggregation that calculates the average (mean) of a numeric field across multiple
        stage inputs.

        Example:
            >>> # Calculate the average age of users
            >>> Field.of("age").average().as_("averageAge")

        Returns:
            A new `AggregateFunction` representing the 'avg' aggregation.
        averager   r3   r   r   r   r     r   zExpression.averagec                 C  ri   )ai  Creates an aggregation that counts the number of stage inputs with valid evaluations of the
        expression or field.

        Example:
            >>> # Count the total number of products
            >>> Field.of("productId").count().as_("totalProducts")

        Returns:
            A new `AggregateFunction` representing the 'count' aggregation.
        countr   r3   r   r   r   r     r   zExpression.countc                 C  ri   )as  Creates an aggregation that counts the number of values of the provided field or expression
        that evaluate to True.

        Example:
            >>> # Count the number of adults
            >>> Field.of("age").greater_than(18).count_if().as_("totalAdults")


        Returns:
            A new `AggregateFunction` representing the 'count_if' aggregation.
        count_ifr   r3   r   r   r   r     s   zExpression.count_ifc                 C  ri   )a|  Creates an aggregation that counts the number of distinct values of the
        provided field or expression.

        Example:
            >>> # Count the total number of countries in the data
            >>> Field.of("country").count_distinct().as_("totalCountries")

        Returns:
            A new `AggregateFunction` representing the 'count_distinct' aggregation.
        count_distinctr   r3   r   r   r   r     r   zExpression.count_distinctc                 C  ri   )aN  Creates an aggregation that finds the minimum value of a field across multiple stage inputs.

        Example:
            >>> # Find the lowest price of all products
            >>> Field.of("price").minimum().as_("lowestPrice")

        Returns:
            A new `AggregateFunction` representing the 'minimum' aggregation.
        r   r   r3   r   r   r   r     rl   zExpression.minimumc                 C  ri   )aQ  Creates an aggregation that finds the maximum value of a field across multiple stage inputs.

        Example:
            >>> # Find the highest score in a leaderboard
            >>> Field.of("score").maximum().as_("highestScore")

        Returns:
            A new `AggregateFunction` representing the 'maximum' aggregation.
        r{   r   r3   r   r   r   r{     rl   zExpression.maximumc                 C  ri   )a(  Creates an expression that calculates the character length of a string.

        Example:
            >>> # Get the character length of the 'name' field
            >>> Field.of("name").char_length()

        Returns:
            A new `Expression` representing the length of the string.
        char_lengthrk   r3   r   r   r   r     rl   zExpression.char_lengthc                 C  ri   )a5  Creates an expression that calculates the byte length of a string in its UTF-8 form.

        Example:
            >>> # Get the byte length of the 'name' field
            >>> Field.of("name").byte_length()

        Returns:
            A new `Expression` representing the byte length of the string.
        byte_lengthrk   r3   r   r   r   r     rl   zExpression.byte_lengthpatternExpression | strc                 C  r_   )a[  Creates an expression that performs a case-sensitive string comparison.

        Example:
            >>> # Check if the 'title' field contains the word "guide" (case-sensitive)
            >>> Field.of("title").like("%guide%")
            >>> # Check if the 'title' field matches the pattern specified in field 'pattern'.
            >>> Field.of("title").like(Field.of("pattern"))

        Args:
            pattern: The pattern (string or expression) to search for. You can use "%" as a wildcard character.

        Returns:
            A new `Expression` representing the 'like' comparison.
        liker   )r&   r   r   r   r   r     rd   zExpression.likeregexc                 C  r_   )a  Creates an expression that checks if a string contains a specified regular expression as a
        substring.

        Example:
            >>> # Check if the 'description' field contains "example" (case-insensitive)
            >>> Field.of("description").regex_contains("(?i)example")
            >>> # Check if the 'description' field contains the regular expression stored in field 'regex'
            >>> Field.of("description").regex_contains(Field.of("regex"))

        Args:
            regex: The regular expression (string or expression) to use for the search.

        Returns:
            A new `Expression` representing the 'contains' comparison.
        regex_containsr   r&   r   r   r   r   r     r   zExpression.regex_containsc                 C  r_   )a  Creates an expression that checks if a string matches a specified regular expression.

        Example:
            >>> # Check if the 'email' field matches a valid email pattern
            >>> Field.of("email").regex_match("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}")
            >>> # Check if the 'email' field matches a regular expression stored in field 'regex'
            >>> Field.of("email").regex_match(Field.of("regex"))

        Args:
            regex: The regular expression (string or expression) to use for the match.

        Returns:
            A new `Expression` representing the regular expression match.
        regex_matchr   r   r   r   r   r   !  rd   zExpression.regex_match	substringc                 C  r_   )af  Creates an expression that checks if this string expression contains a specified substring.

        Example:
            >>> # Check if the 'description' field contains "example".
            >>> Field.of("description").string_contains("example")
            >>> # Check if the 'description' field contains the value of the 'keyword' field.
            >>> Field.of("description").string_contains(Field.of("keyword"))

        Args:
            substring: The substring (string or expression) to use for the search.

        Returns:
            A new `Expression` representing the 'contains' comparison.
        string_containsr   )r&   r   r   r   r   r   5  s   zExpression.string_containsprefixc                 C  r_   )a,  Creates an expression that checks if a string starts with a given prefix.

        Example:
            >>> # Check if the 'name' field starts with "Mr."
            >>> Field.of("name").starts_with("Mr.")
            >>> # Check if the 'fullName' field starts with the value of the 'firstName' field
            >>> Field.of("fullName").starts_with(Field.of("firstName"))

        Args:
            prefix: The prefix (string or expression) to check for.

        Returns:
            A new `Expression` representing the 'starts with' comparison.
        starts_withr   )r&   r   r   r   r   r   J  rd   zExpression.starts_withpostfixc                 C  r_   )a#  Creates an expression that checks if a string ends with a given postfix.

        Example:
            >>> # Check if the 'filename' field ends with ".txt"
            >>> Field.of("filename").ends_with(".txt")
            >>> # Check if the 'url' field ends with the value of the 'extension' field
            >>> Field.of("url").ends_with(Field.of("extension"))

        Args:
            postfix: The postfix (string or expression) to check for.

        Returns:
            A new `Expression` representing the 'ends with' comparison.
        	ends_withr   )r&   r   r   r   r   r   ^  rd   zExpression.ends_withc                   r   )a  Creates an expression that concatenates string expressions, fields or constants together.

        Example:
            >>> # Combine the 'firstName', " ", and 'lastName' fields into a single string
            >>> Field.of("firstName").string_concat(" ", Field.of("lastName"))

        Args:
            *elements: The expressions or constants (typically strings) to concatenate.

        Returns:
            A new `Expression` representing the concatenated string.
        string_concatc                   r|   r   r}   rA   elr3   r   r   rC     r   z,Expression.string_concat.<locals>.<listcomp>rk   r   r   r3   r   r   r  s   zExpression.string_concatc                 C  ri   )a  Creates an expression that converts a string to lowercase.

        Example:
            >>> # Convert the 'name' field to lowercase
            >>> Field.of("name").to_lower()

        Returns:
            A new `Expression` representing the lowercase string.
        to_lowerrk   r3   r   r   r   r     rl   zExpression.to_lowerc                 C  ri   )a  Creates an expression that converts a string to uppercase.

        Example:
            >>> # Convert the 'title' field to uppercase
            >>> Field.of("title").to_upper()

        Returns:
            A new `Expression` representing the uppercase string.
        to_upperrk   r3   r   r   r   r     rl   zExpression.to_upperc                 C  ri   )a(  Creates an expression that removes leading and trailing whitespace from a string.

        Example:
            >>> # Trim whitespace from the 'userInput' field
            >>> Field.of("userInput").trim()

        Returns:
            A new `Expression` representing the trimmed string.
        trimrk   r3   r   r   r   r     rl   zExpression.trimc                 C  ri   )zCreates an expression that reverses a string.

        Example:
            >>> # Reverse the 'userInput' field
            >>> Field.of("userInput").reverse()

        Returns:
            A new `Expression` representing the reversed string.
        string_reverserk   r3   r   r   r   r     rl   zExpression.string_reverseNpositionr   Expression | int | Nonec                 C  s0   | |  |g}|dur||  | td|S )a  Creates an expression that returns a substring of the results of this expression.


        Example:
            >>> Field.of("description").substring(5, 10)
            >>> Field.of("description").substring(5)

        Args:
            position: the index of the first character of the substring.
            length: the length of the substring. If not provided the substring
                will end at the end of the input.

        Returns:
            A new `Expression` representing the extracted substring.
        Nr   )rL   appendrb   )r&   r   r   argsr   r   r   r     s   
zExpression.substring	delimeterc                 C  r_   )a>  Creates an expression that joins the elements of an array into a string


        Example:
            >>> Field.of("tags").join(", ")

        Args:
            delimiter: The delimiter to add between the elements of the array.

        Returns:
            A new `Expression` representing the joined string.
        joinra   )r&   r   r   r   r   r        zExpression.joinkeystr | Constant[str]c                 C  r_   )a|  Accesses a value from the map produced by evaluating this expression.

        Example:
            >>> Map({"city": "London"}).map_get("city")
            >>> Field.of("address").map_get("city")

        Args:
            key: The key to access in the map.

        Returns:
            A new `Expression` representing the value associated with the given key in the map.
        map_getra   r&   r   r   r   r   r     r   zExpression.map_getc                 C  r_   )af  Remove a key from a the map produced by evaluating this expression.

        Example:
            >>> Map({"city": "London"}).map_remove("city")
            >>> Field.of("address").map_remove("city")

        Args:
            key: The key to remove in the map.

        Returns:
            A new `Expression` representing the map_remove operation.
        
map_removera   r   r   r   r   r     r   zExpression.map_remove
other_mapsHMap | dict[str | Constant[str], Expression | CONSTANT_TYPE] | Expressionc                   r   )a  Creates an expression that merges one or more dicts into a single map.

        Example:
            >>> Map({"city": "London"}).map_merge({"country": "UK"}, {"isCapital": True})
            >>> Field.of("settings").map_merge({"enabled":True}, FunctionExpression.conditional(Field.of('isAdmin'), {"admin":True}, {}})

        Args:
            *other_maps: Sequence of maps to merge into the resulting map.

        Returns:
            A new `Expression` representing the value associated with the given key in the map.
        	map_mergec                   r|   r   r}   rA   mr3   r   r   rC     r   z(Expression.map_merge.<locals>.<listcomp>rk   )r&   r   r   r3   r   r     s   zExpression.map_merge!Expression | list[float] | Vectorc                 C     t d| | j|ddgS )a  Calculates the cosine distance between two vectors.

        Example:
            >>> # Calculate the cosine distance between the 'userVector' field and the 'itemVector' field
            >>> Field.of("userVector").cosine_distance(Field.of("itemVector"))
            >>> # Calculate the Cosine distance between the 'location' field and a target location
            >>> Field.of("location").cosine_distance([37.7749, -122.4194])

        Args:
            other: The other vector (represented as an Expression, list of floats, or Vector) to compare against.

        Returns:
            A new `Expression` representing the cosine distance between the two vectors.
        cosine_distanceTrK   ra   rc   r   r   r   r        zExpression.cosine_distancec                 C  r   )a  Calculates the Euclidean distance between two vectors.

        Example:
            >>> # Calculate the Euclidean distance between the 'location' field and a target location
            >>> Field.of("location").euclidean_distance([37.7749, -122.4194])
            >>> # Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB'
            >>> Field.of("pointA").euclidean_distance(Field.of("pointB"))

        Args:
            other: The other vector (represented as an Expression, list of floats, or Vector) to compare against.

        Returns:
            A new `Expression` representing the Euclidean distance between the two vectors.
        euclidean_distanceTr   ra   rc   r   r   r   r   7  s   zExpression.euclidean_distancec                 C  r   )a  Calculates the dot product between two vectors.

        Example:
            >>> # Calculate the dot product between a feature vector and a target vector
            >>> Field.of("features").dot_product([0.5, 0.8, 0.2])
            >>> # Calculate the dot product between two document vectors: 'docVector1' and 'docVector2'
            >>> Field.of("docVector1").dot_product(Field.of("docVector2"))

        Args:
            other: The other vector (represented as an Expression, list of floats, or Vector) to calculate dot product with.

        Returns:
            A new `Expression` representing the dot product between the two vectors.
        dot_productTr   ra   rc   r   r   r   r   Q  r   zExpression.dot_productc                 C  ri   )aJ  Creates an expression that calculates the length (dimension) of a Firestore Vector.

        Example:
            >>> # Get the vector length (dimension) of the field 'embedding'.
            >>> Field.of("embedding").vector_length()

        Returns:
            A new `Expression` representing the length of the vector.
        vector_lengthrk   r3   r   r   r   r   i  rl   zExpression.vector_lengthc                 C  ri   )a  Creates an expression that converts a timestamp to the number of microseconds since the epoch
        (1970-01-01 00:00:00 UTC).

        Truncates higher levels of precision by rounding down to the beginning of the microsecond.

        Example:
            >>> # Convert the 'timestamp' field to microseconds since the epoch.
            >>> Field.of("timestamp").timestamp_to_unix_micros()

        Returns:
            A new `Expression` representing the number of microseconds since the epoch.
        timestamp_to_unix_microsrk   r3   r   r   r   r   v     z#Expression.timestamp_to_unix_microsc                 C  ri   )am  Creates an expression that converts a number of microseconds since the epoch (1970-01-01
        00:00:00 UTC) to a timestamp.

        Example:
            >>> # Convert the 'microseconds' field to a timestamp.
            >>> Field.of("microseconds").unix_micros_to_timestamp()

        Returns:
            A new `Expression` representing the timestamp.
        unix_micros_to_timestamprk   r3   r   r   r   r     r   z#Expression.unix_micros_to_timestampc                 C  ri   )a  Creates an expression that converts a timestamp to the number of milliseconds since the epoch
        (1970-01-01 00:00:00 UTC).

        Truncates higher levels of precision by rounding down to the beginning of the millisecond.

        Example:
            >>> # Convert the 'timestamp' field to milliseconds since the epoch.
            >>> Field.of("timestamp").timestamp_to_unix_millis()

        Returns:
            A new `Expression` representing the number of milliseconds since the epoch.
        timestamp_to_unix_millisrk   r3   r   r   r   r     r   z#Expression.timestamp_to_unix_millisc                 C  ri   )am  Creates an expression that converts a number of milliseconds since the epoch (1970-01-01
        00:00:00 UTC) to a timestamp.

        Example:
            >>> # Convert the 'milliseconds' field to a timestamp.
            >>> Field.of("milliseconds").unix_millis_to_timestamp()

        Returns:
            A new `Expression` representing the timestamp.
        unix_millis_to_timestamprk   r3   r   r   r   r     r   z#Expression.unix_millis_to_timestampc                 C  ri   )a  Creates an expression that converts a timestamp to the number of seconds since the epoch
        (1970-01-01 00:00:00 UTC).

        Truncates higher levels of precision by rounding down to the beginning of the second.

        Example:
            >>> # Convert the 'timestamp' field to seconds since the epoch.
            >>> Field.of("timestamp").timestamp_to_unix_seconds()

        Returns:
            A new `Expression` representing the number of seconds since the epoch.
        timestamp_to_unix_secondsrk   r3   r   r   r   r     r   z$Expression.timestamp_to_unix_secondsc                 C  ri   )a_  Creates an expression that converts a number of seconds since the epoch (1970-01-01 00:00:00
        UTC) to a timestamp.

        Example:
            >>> # Convert the 'seconds' field to a timestamp.
            >>> Field.of("seconds").unix_seconds_to_timestamp()

        Returns:
            A new `Expression` representing the timestamp.
        unix_seconds_to_timestamprk   r3   r   r   r   r     r   z$Expression.unix_seconds_to_timestampunitamountc                 C     t d| | || |gS )a  Creates an expression that adds a specified amount of time to this timestamp expression.

        Example:
            >>> # Add a duration specified by the 'unit' and 'amount' fields to the 'timestamp' field.
            >>> Field.of("timestamp").timestamp_add(Field.of("unit"), Field.of("amount"))
            >>> # Add 1.5 days to the 'timestamp' field.
            >>> Field.of("timestamp").timestamp_add("day", 1.5)

        Args:
            unit: The expression or string evaluating to the unit of time to add, must be one of
                  'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'.
            amount: The expression or float representing the amount of time to add.

        Returns:
            A new `Expression` representing the resulting timestamp.
        timestamp_addra   r&   r   r   r   r   r   r        zExpression.timestamp_addc                 C  r   )aF  Creates an expression that subtracts a specified amount of time from this timestamp expression.

        Example:
            >>> # Subtract a duration specified by the 'unit' and 'amount' fields from the 'timestamp' field.
            >>> Field.of("timestamp").timestamp_subtract(Field.of("unit"), Field.of("amount"))
            >>> # Subtract 2.5 hours from the 'timestamp' field.
            >>> Field.of("timestamp").timestamp_subtract("hour", 2.5)

        Args:
            unit: The expression or string evaluating to the unit of time to subtract, must be one of
                  'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'.
            amount: The expression or float representing the amount of time to subtract.

        Returns:
            A new `Expression` representing the resulting timestamp.
        timestamp_subtractra   r   r   r   r   r     r   zExpression.timestamp_subtractc                 C  ri   )a  Creates an expression that returns the collection ID from a path.

        Example:
            >>> # Get the collection ID from a path.
            >>> Field.of("__name__").collection_id()

        Returns:
            A new `Expression` representing the collection ID.
        collection_idrk   r3   r   r   r   r   
  rl   zExpression.collection_idc                 C  ri   )a  Creates an expression that returns the document ID from a path.

        Example:
            >>> # Get the document ID from a path.
            >>> Field.of("__name__").document_id()

        Returns:
            A new `Expression` representing the document ID.
        document_idrk   r3   r   r   r   r     rl   zExpression.document_idr   c                 C     t | t jjS )aY  Creates an `Ordering` that sorts documents in ascending order based on this expression.

        Example:
            >>> # Sort documents by the 'name' field in ascending order
            >>> client.pipeline().collection("users").sort(Field.of("name").ascending())

        Returns:
            A new `Ordering` for ascending sorting.
        )r   r   r   r3   r   r   r   r   $     
zExpression.ascendingc                 C  r   )ag  Creates an `Ordering` that sorts documents in descending order based on this expression.

        Example:
            >>> # Sort documents by the 'createdAt' field in descending order
            >>> client.pipeline().collection("users").sort(Field.of("createdAt").descending())

        Returns:
            A new `Ordering` for descending sorting.
        )r   r   r   r3   r   r   r   r   0  r   zExpression.descendingaliasr$   'AliasedExpression'c                 C  s
   t | |S )a  Assigns an alias to this expression.

        Aliases are useful for renaming fields in the output of a stage or for giving meaningful
        names to calculated values.

        Example:
            >>> # Calculate the total price and assign it the alias "totalPrice" and add it to the output.
            >>> client.pipeline().collection("items").add_fields(
            ...     Field.of("price").multiply(Field.of("quantity")).as_("totalPrice")
            ... )

        Args:
            alias: The alias to assign to this expression.

        Returns:
            A new `Selectable` (typically an `AliasedExpression`) that wraps this
            expression and associates it with the provided alias.
        )AliasedExpression)r&   r   r   r   r   as_<  s   
zExpression.as_r4   )F)r=   r   r*   r>   )r]   r^   r*   r>   )r*   r>   )rq   r^   r*   r>   )rt   r^   r*   r>   )rx   ry   r*   r>   )r]   ry   r*   r   )r   r   r*   r   )r   r   r*   r   )r   r   r*   r   )r   ry   r*   r   )r   r   r*   r   )r   r   r*   r>   )r*   r   )r   ry   r*   r>   )r   ry   r*   r>   )r   r   r*   r   )r   r   r*   r   )r   r   r*   r   )r   r   r*   r   )r   r   r*   r   )r   ry   r*   r>   r:   )r   r   r   r   r*   r>   )r   r   r*   r>   )r   r   r*   r>   )r   r   r*   r>   )r]   r   r*   r>   )r   r   r   r^   r*   r>   )r*   r   )r   r$   r*   r   )[r   r   r   r5   r)   r   r2   staticmethodrL   r\   r`   re   rf   rg   rh   rj   rm   rn   ro   rp   rr   rs   ru   rv   rw   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r{   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    ^   sR   !




r    c                   @  sJ   e Zd ZdZdddZdd Zedd
dZdd Zdd Z	dddZ
dS )rI   z5Represents a constant literal value in an expression.r1   r   c                 C  rM   r:   r1   )r&   r1   r   r   r   r'   U  rO   zConstant.__init__c                 C  s    t |ts
|| jkS |j| jkS r:   r   rI   r1   rc   r   r   r   __eq__X  s   

zConstant.__eq__r*   Constant[CONSTANT_TYPE]c                 C     t | S )z2Creates a constant expression from a Python value.)rI   r  r   r   r   r"   ^  s   zConstant.ofc                 C  s.   t | j}t| jtr|dkrd}d| dS )Nnanzmath.nanzConstant.of())reprr1   r   r?   )r&   	value_strr   r   r   r)   c  s   
zConstant.__repr__c                 C  
   t | jS r:   )hashr1   r3   r   r   r   __hash__i  rO   zConstant.__hash__r   c                 C  r  r:   )r   r1   r3   r   r   r   r2   l  rO   zConstant._to_pbN)r1   r   )r1   r   r*   r  r4   )r   r   r   r5   r'   r  r  r"   r)   r  r2   r   r   r   r   rI   R  s    
rI   c                   @  s:   e Zd ZdZddddddZdd Zdd Zdd ZdS )rb   z;A base class for expressions that represent function calls.TN)use_infix_reprr   namer$   paramsSequence[Expression]r  boolr   
str | Nonec                C  s    || _ t|| _|| _|| _d S r:   )r  rG   r  _use_infix_repr_infix_name_override)r&   r  r  r  r   r   r   r   r'   s  s   

zFunctionExpression.__init__c              
   C  s   | j rN| jp| j}t| jdkr| jd d| dS t| jdkr3| jd d| d| jd dS | jd d| ddd	d
 | jdd D  dS | jj dddd
 | jD  dS )z
        Most FunctionExpressions can be triggered infix. Eg: Field.of('age').greater_than(18).

        Display them this way in the repr string where possible
           r   rQ   r6      (r  z, c                 S     g | ]}t |qS r   r	  rA   pr   r   r   rC         z/FunctionExpression.__repr__.<locals>.<listcomp>Nc                 S  r  r   r  r  r   r   r   rC     r  )r  r  r  lenr  r   r7   r   )r&   
infix_namer   r   r   r)     s   "6&zFunctionExpression.__repr__c                 C  s&   t |tsdS |j| jko|j| jkS NF)r   rb   r  r  rc   r   r   r   r    s   
zFunctionExpression.__eq__c                 C  s   t | jdd | jD ddS )Nc                 S     g | ]}|  qS r   )r2   r  r   r   r   rC     r  z-FunctionExpression._to_pb.<locals>.<listcomp>)r  r   )function_value)r   r  r  r3   r   r   r   r2     s
   zFunctionExpression._to_pb)r  r$   r  r  r  r  r   r  )r   r   r   r5   r'   r)   r  r2   r   r   r   r   rb   p  s    rb   c                   @  s   e Zd ZdZdS )r   zKA base class for aggregation functions that operate across multiple inputs.N)r   r   r   r5   r   r   r   r   r     s    r   c                   @  sB   e Zd ZdZdd ZedddZedd
dZe	dddZ
dS )
SelectablezPBase class for expressions that can be selected or aliased in projection stages.c                 C  s"   t |t| s	dS | |  kS r   )r   rS   _to_maprc   r   r   r   r    s   zSelectable.__eq__r*   tuple[str, Value]c                 C  r9   )zG
        Returns a str: Value representation of the Selectable
        r;   r3   r   r   r   r$    s   zSelectable._to_mapselectablesr   c                 G  s"   t ddd dd |D D idS )zC
        Returns a Value representing a map of Selectables
        r+   c                 S     i | ]	}|d  |d qS r   r  r   r   r   r   r   
<dictcomp>  rD   z6Selectable._value_from_selectables.<locals>.<dictcomp>c                 S  r!  r   r$  )rA   sr   r   r   rC     r  z6Selectable._value_from_selectables.<locals>.<listcomp>r/   r
   )clsr&  r   r   r   _value_from_selectables  s   z"Selectable._value_from_selectables
field_listSequence[Selectable]c                 C  s"   t ddd dd | D D idS )Nr+   c                 S  r'  r(  r   r   r   r   r   r)    rD   z(Selectable._to_value.<locals>.<dictcomp>c                 S  r!  r   r*  rA   fr   r   r   rC     r  z(Selectable._to_value.<locals>.<listcomp>r/   r
   )r.  r   r   r   	_to_value  s   zSelectable._to_valueN)r*   r%  )r&  r#  r*   r   )r.  r/  r*   r   )r   r   r   r5   r  r   r$  classmethodr-  r  r2  r   r   r   r   r#    s    
r#  T)boundc                   @  s2   e Zd ZdZdddZdd	 Zd
d Zdd ZdS )r   z"Wraps an expression with an alias.r#   r4  r   r$   c                 C  s   || _ || _d S r:   r#   r   )r&   r#   r   r   r   r   r'     s   
zAliasedExpression.__init__c                 C  s   | j | j fS r:   )r   r#   r2   r3   r   r   r   r$    s   zAliasedExpression._to_mapc                 C  s   | j  d| j dS )Nz.as_('z')r6  r3   r   r   r   r)     s   zAliasedExpression.__repr__c                 C  s   t d| j| j iidS )Nr+   r/   )r   r   r#   r2   r3   r   r   r   r2     s   zAliasedExpression._to_pbN)r#   r4  r   r$   )r   r   r   r5   r'   r$  r)   r2   r   r   r   r   r     s    
r   c                   @  sD   e Zd ZdZdZdddZedddZd	d
 Zdd Z	dd Z
dS )r!   z4Represents a reference to a field within a document.r   pathr$   c                 C  s
   || _ dS )zInitializes a Field reference.

        Args:
            path: The dot-separated path to the field (e.g., "address.city").
                  Use Field.DOCUMENT_ID for the document ID.
        Nr7  )r&   r7  r   r   r   r'     s   
zField.__init__c                 C  r  )zCreates a Field reference.

        Args:
            path: The dot-separated path to the field (e.g., "address.city").
                  Use Field.DOCUMENT_ID for the document ID.

        Returns:
            A new Field instance.
        )r!   r8  r   r   r   r"     s   zField.ofc                 C  s   | j |  fS r:   )r7  r2   r3   r   r   r   r$    r8   zField._to_mapc                 C  s   d| j dS )Nz	Field.of(r  r8  r3   r   r   r   r)     r8   zField.__repr__c                 C  s   t | jdS )N)field_reference_value)r   r7  r3   r   r   r   r2     s   zField._to_pbN)r7  r$   )r   r   r   r5   DOCUMENT_IDr'   r  r"   r$  r)   r2   r   r   r   r   r!     s    
	r!   c                   @  s   e Zd ZdZedd ZdS )r   z#Filters the given data in some way.c                   s  t | tjr0 fdd| jD }| jtjjjkrt| S | jtjjjkr(t	| S t
d| j t | tjrt| jj}| jtjjjkrQt	| |tdS | jtjjjkrgt	| t|tdS | jtjjjkryt	| |d S | jtjjjkrt	| t|d S t
d| j t | tjrkt| jj}t| j }| jtjjjkrt	| ||S | jtjjjkrt	| ||S | jtjjjkrt	| | |S | jtjjj!krt	| |"|S | jtjjj#krt	| ||S | jtjjj$krt	| |%|S | jtjjj&kr*t	| |'|S | jtjjj(kr=t	| |)|S | jtjjj*krPt	| |+|S | jtjjj,krct	| |-|S t
d| j t | tj.r| j/p|| j0p|| j1}t23| S t
dt4|  )Nc                   s   g | ]}t | qS r   )r   _from_query_filter_pbr0  clientr   r   rC     s    
z;BooleanExpression._from_query_filter_pb.<locals>.<listcomp>z*Unexpected CompositeFilter operator type: r  z&Unexpected UnaryFilter operator type: z&Unexpected FieldFilter operator type: zUnexpected filter type: )5r   Query_pbCompositeFilterfiltersopOperatorOROrANDAndrR   UnaryFilterr!   r"   field
field_pathIS_NANr   r   r?   
IS_NOT_NANNotIS_NULLIS_NOT_NULLFieldFilterr   r1   	LESS_THANr   LESS_THAN_OR_EQUALr   GREATER_THANr   GREATER_THAN_OR_EQUALr   EQUAL	NOT_EQUALr   ARRAY_CONTAINSr   ARRAY_CONTAINS_ANYr   INr   NOT_INr   Filtercomposite_filterfield_filterunary_filterr   r;  rS   )	filter_pbr=  sub_filtersrH  r1   r1  r   r<  r   r;    sl   

z'BooleanExpression._from_query_filter_pbN)r   r   r   r5   r  r;  r   r   r   r   r      s    r   c                      *   e Zd ZdZd fddZdd Z  ZS )	rJ   z
    Creates an expression that creates a Firestore array value from an input list.

    Example:
        >>> Array(["bar", Field.of("baz")])

    Args:
        elements: The input list to evaluate in the expression
    r    list[Expression | CONSTANT_TYPE]c                   s6   t |ts	td fdd|D }t d| d S )Nz%Array must be constructed with a listc                   r|   r   r}   r   r3   r   r   rC   Q  s    
z"Array.__init__.<locals>.<listcomp>r   )r   rG   rR   superr'   )r&   r   converted_elementsr7   r3   r   r'   N  s   

zArray.__init__c                 C  s   d| j  dS )NzArray(r  )r  r3   r   r   r   r)   V  r8   zArray.__repr__)r   ra  r   r   r   r5   r'   r)   __classcell__r   r   rd  r   rJ   C  s    
rJ   c                      r`  )	rF   z
    Creates an expression that creates a Firestore map value from an input dict.

    Example:
        >>> Expression.map({"foo": "bar", "baz": Field.of("baz")})

    Args:
        elements: The input dict to evaluate in the expression
    r   5dict[str | Constant[str], Expression | CONSTANT_TYPE]c                   sH   g }|  D ]\}}|| | || | qt d| d S )Nmap)itemsr   rL   rb  r'   )r&   r   element_listkvrd  r   r   r'   e  s
   zMap.__init__c                 C  sD   dd | j D }dd t|d d d |dd d D }d| dS )	Nc                 S  s    g | ]}t |tr|jn|qS r   r  )rA   ar   r   r   rC   m  s    z Map.__repr__.<locals>.<listcomp>c                 S  s   i | ]\}}||qS r   r   )rA   rm  br   r   r   r)  p  r   z Map.__repr__.<locals>.<dictcomp>r  r  zMap(r  )r  zip)r&   formatted_paramsdr   r   r   r)   l  s
   (zMap.__repr__)r   rg  re  r   r   rd  r   rF   Z  s    
rF   c                      "   e Zd ZdZd fddZ  ZS )rF  a  
    Represents an expression that performs a logical 'AND' operation on multiple filter conditions.

    Example:
        >>> # Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND
        >>> # the 'status' field is "active"
        >>> And(Field.of("age").greater_than(18), Field.of("city").equal("London"), Field.of("status").equal("active"))

    Args:
        *conditions: The filter conditions to 'AND' together.
    
conditionsr   c                      t  jd|dd d S )NandFr  rb  r'   r&   rs  rd  r   r   r'        zAnd.__init__rs  r   r   r   r   r5   r'   rf  r   r   rd  r   rF  t      rF  c                      rr  )rL  a  
    Represents an expression that negates a filter condition.

    Example:
        >>> # Find documents where the 'completed' field is NOT true
        >>> Not(Field.of("completed").equal(True))

    Args:
        condition: The filter condition to negate.
    	conditionr   c                   s   t  jd|gdd d S )NnotFrv  rw  )r&   r}  rd  r   r   r'     s   zNot.__init__)r}  r   r{  r   r   rd  r   rL    s    rL  c                      rr  )rD  a  
    Represents expression that performs a logical 'OR' operation on multiple filter conditions.

    Example:
       >>> # Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR
       >>> # the 'status' field is "active"
       >>> Or(Field.of("age").greater_than(18), Field.of("city").equal("London"), Field.of("status").equal("active"))

    Args:
        *conditions: The filter conditions to 'OR' together.
    rs  r   c                   rt  )NorFrv  rw  rx  rd  r   r   r'     ry  zOr.__init__rz  r{  r   r   rd  r   rD    r|  rD  c                      rr  )Xora  
    Represents an expression that performs a logical 'XOR' (exclusive OR) operation on multiple filter conditions.

    Example:
       >>> # Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London",
       >>> # or 'status' is "active".
       >>> Xor(Field.of("age").greater_than(18), Field.of("city").equal("London"), Field.of("status").equal("active"))

    Args:
        *conditions: The filter conditions to 'XOR' together.
    rs  Sequence['BooleanExpression']c                   rt  )NxorFrv  rw  rx  rd  r   r   r'     ry  zXor.__init__)rs  r  r{  r   r   rd  r   r    r|  r  c                      s"   e Zd ZdZd	 fddZ  ZS )
Conditionala2  
    Represents a conditional expression that evaluates to a 'then' expression if a condition is true
    and an 'else' expression if the condition is false.

    Example:
        >>> # If 'age' is greater than 18, return "Adult"; otherwise, return "Minor".
        >>> Conditional(Field.of("age").greater_than(18), Constant.of("Adult"), Constant.of("Minor"));

    Args:
        condition: The condition to evaluate.
        then_expr: The expression to return if the condition is true.
        else_expr: The expression to return if the condition is false
    r}  r   	then_exprr    	else_exprc                   s   t  jd|||gdd d S )NconditionalFrv  rw  )r&   r}  r  r  rd  r   r   r'     s   
zConditional.__init__)r}  r   r  r    r  r    r{  r   r   rd  r   r    s    r  c                      s$   e Zd ZdZdd fddZ  ZS )	Counta  
    Represents an aggregation that counts the number of stage inputs with valid evaluations of the
    expression or field.

    Example:
        >>> # Count the total number of products
        >>> Field.of("productId").count().as_("totalProducts")
        >>> Count(Field.of("productId"))
        >>> Count().as_("count")

    Args:
        expression: The expression or field to count. If None, counts all stage inputs.
    Nr.   Expression | Nonec                   s(   |r|gng }t  jd|t|d d S )Nr   rv  )rb  r'   r  )r&   r.   expression_listrd  r   r   r'     s   zCount.__init__r:   )r.   r  r{  r   r   rd  r   r    s    r  c                      s    e Zd ZdZ fddZ  ZS )CurrentTimestampzCreates an expression that returns the current timestamp

    Returns:
        A new `Expression` representing the current timestamp.
    c                   s   t  jdg dd d S )Ncurrent_timestampFrv  rw  r3   rd  r   r   r'     ry  zCurrentTimestamp.__init__r{  r   r   rd  r   r    s    r  )2r5   
__future__r   typingr   r   r   r   abcr   r   enumr	   datetime(google.cloud.firestore_v1.types.documentr   %google.cloud.firestore_v1.types.queryr   r>   google.cloud.firestore_v1.vectorr   "google.cloud.firestore_v1._helpersr   r   r   r$   r@   r?   r  bytesr   r   r    rI   rb   r   r#  r4  r   r!   r   rJ   rF   rF  rL  rD  r  r  r  r  r   r   r   r   <module>   sn   *           /$%C