1# Copyright 2017 Google LLC All rights reserved. 
    2# 
    3# Licensed under the Apache License, Version 2.0 (the "License"); 
    4# you may not use this file except in compliance with the License. 
    5# You may obtain a copy of the License at 
    6# 
    7#     http://www.apache.org/licenses/LICENSE-2.0 
    8# 
    9# Unless required by applicable law or agreed to in writing, software 
    10# distributed under the License is distributed on an "AS IS" BASIS, 
    11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    12# See the License for the specific language governing permissions and 
    13# limitations under the License. 
    14 
    15"""Helpful constants to use for Google Cloud Firestore.""" 
    16 
    17 
    18class Sentinel(object): 
    19    """Sentinel objects used to signal special handling.""" 
    20 
    21    __slots__ = ("description",) 
    22 
    23    def __init__(self, description) -> None: 
    24        self.description = description 
    25 
    26    def __repr__(self): 
    27        return "Sentinel: {}".format(self.description) 
    28 
    29    def __copy__(self): 
    30        # Sentinel identity should be preserved across copies. 
    31        return self 
    32 
    33    def __deepcopy__(self, memo): 
    34        # Sentinel identity should be preserved across deep copies. 
    35        return self 
    36 
    37 
    38DELETE_FIELD = Sentinel("Value used to delete a field in a document.") 
    39 
    40 
    41SERVER_TIMESTAMP = Sentinel( 
    42    "Value used to set a document field to the server timestamp." 
    43) 
    44 
    45 
    46class _ValueList(object): 
    47    """Read-only list of values. 
    48 
    49    Args: 
    50        values (List | Tuple): values held in the helper. 
    51    """ 
    52 
    53    slots = ("_values",) 
    54 
    55    def __init__(self, values) -> None: 
    56        if not isinstance(values, (list, tuple)): 
    57            raise ValueError("'values' must be a list or tuple.") 
    58 
    59        if len(values) == 0: 
    60            raise ValueError("'values' must be non-empty.") 
    61 
    62        self._values = list(values) 
    63 
    64    def __eq__(self, other): 
    65        if not isinstance(other, self.__class__): 
    66            return NotImplemented 
    67        return self._values == other._values 
    68 
    69    @property 
    70    def values(self): 
    71        """Values to append. 
    72 
    73        Returns (List): 
    74            values to be appended by the transform. 
    75        """ 
    76        return self._values 
    77 
    78 
    79class ArrayUnion(_ValueList): 
    80    """Field transform: appends missing values to an array field. 
    81 
    82    See: 
    83    https://cloud.google.com/firestore/docs/reference/rpc/google.firestore.v1#google.firestore.v1.DocumentTransform.FieldTransform.FIELDS.google.firestore.v1.ArrayValue.google.firestore.v1.DocumentTransform.FieldTransform.append_missing_elements 
    84 
    85    Args: 
    86        values (List | Tuple): values to append. 
    87    """ 
    88 
    89 
    90class ArrayRemove(_ValueList): 
    91    """Field transform: remove values from an array field. 
    92 
    93    See: 
    94    https://cloud.google.com/firestore/docs/reference/rpc/google.firestore.v1#google.firestore.v1.DocumentTransform.FieldTransform.FIELDS.google.firestore.v1.ArrayValue.google.firestore.v1.DocumentTransform.FieldTransform.remove_all_from_array 
    95 
    96    Args: 
    97        values (List | Tuple): values to remove. 
    98    """ 
    99 
    100 
    101class _NumericValue(object): 
    102    """Hold a single integer / float value. 
    103 
    104    Args: 
    105        value (float): value held in the helper. 
    106    """ 
    107 
    108    def __init__(self, value) -> None: 
    109        if not isinstance(value, (int, float)): 
    110            raise ValueError("Pass an integer / float value.") 
    111 
    112        self._value = value 
    113 
    114    @property 
    115    def value(self): 
    116        """Value used by the transform. 
    117 
    118        Returns: 
    119            (Lloat) value passed in the constructor. 
    120        """ 
    121        return self._value 
    122 
    123    def __eq__(self, other): 
    124        if not isinstance(other, self.__class__): 
    125            return NotImplemented 
    126        return self._value == other._value 
    127 
    128 
    129class Increment(_NumericValue): 
    130    """Field transform: increment a numeric field with specified value. 
    131 
    132    See: 
    133    https://cloud.google.com/firestore/docs/reference/rpc/google.firestore.v1#google.firestore.v1.DocumentTransform.FieldTransform.FIELDS.google.firestore.v1.ArrayValue.google.firestore.v1.DocumentTransform.FieldTransform.increment 
    134 
    135    Args: 
    136        value (float): value used to increment the field. 
    137    """ 
    138 
    139 
    140class Maximum(_NumericValue): 
    141    """Field transform: bound numeric field with specified value. 
    142 
    143    See: 
    144    https://cloud.google.com/firestore/docs/reference/rpc/google.firestore.v1#google.firestore.v1.DocumentTransform.FieldTransform.FIELDS.google.firestore.v1.ArrayValue.google.firestore.v1.DocumentTransform.FieldTransform.maximum 
    145 
    146    Args: 
    147        value (float): value used to bound the field. 
    148    """ 
    149 
    150 
    151class Minimum(_NumericValue): 
    152    """Field transform: bound numeric field with specified value. 
    153 
    154    See: 
    155    https://cloud.google.com/firestore/docs/reference/rpc/google.firestore.v1#google.firestore.v1.DocumentTransform.FieldTransform.FIELDS.google.firestore.v1.ArrayValue.google.firestore.v1.DocumentTransform.FieldTransform.minimum 
    156 
    157    Args: 
    158        value (float): value used to bound the field. 
    159    """