U
    %FZh                     @   sb  d Z ddlZddlZddlZddlZddlmZmZmZm	Z	m
Z
 ddlmZ ddlZddlZddlZddlmZmZmZ ddlZejejd eeZdZdZed	 ZG d
d deZG dd deZG dd dZG dd dZG dd dZ G dd dZ!G dd dZ"d eeee#e#f  dddZ$d!eeee#e#f  ee# dddZ%G dd dZ&dS )"zxFirebase Remote Config Module.
This module has required APIs for the clients to use Firebase Remote Config with python.
    N)DictOptionalLiteralUnionAny)Enum)App_http_client_utils)levelZ_remoteconfig
   )defaultremotestaticc                   @   s    e Zd ZdZdZdZdZdZdS )PercentConditionOperatorzFEnum representing the available operators for percent conditions.
    LESS_OR_EQUALGREATER_THANBETWEENUNKNOWNN)__name__
__module____qualname____doc__r   r   r   r    r   r   c/home/aprabhat/apps/x.techxrdev.in/venv/lib/python3.8/site-packages/firebase_admin/remote_config.pyr   '   s
   r   c                   @   sT   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ZdZdS )CustomSignalOperatorzLEnum representing the available operators for custom signal conditions.
    STRING_CONTAINSSTRING_DOES_NOT_CONTAINSTRING_EXACTLY_MATCHESSTRING_CONTAINS_REGEXNUMERIC_LESS_THANNUMERIC_LESS_EQUALNUMERIC_EQUALNUMERIC_NOT_EQUALNUMERIC_GREATER_THANNUMERIC_GREATER_EQUALSEMANTIC_VERSION_LESS_THANSEMANTIC_VERSION_LESS_EQUALSEMANTIC_VERSION_EQUALSEMANTIC_VERSION_NOT_EQUALSEMANTIC_VERSION_GREATER_THANSEMANTIC_VERSION_GREATER_EQUALr   N)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   /   s$   r   c                   @   sT   e Zd ZdZdd Zedd Zedd Zedd	 Zed
d Z	edd Z
dS )_ServerTemplateDataz>Parses, validates and encapsulates template data and metadata.c                 C   s   d|kr*|d dk	r |d | _ q0tdni | _ d|krZ|d dk	rP|d | _q`tdng | _d| _d|krx|d | _d| _d|krt|d tr|d | _t|| _	dS )	zInitializes a new ServerTemplateData instance.

        Args:
            template_data: The data to be parsed for getting the parameters and conditions.

        Raises:
            ValueError: If the template data is not valid.
        
parametersNz2Remote Config parameters must be a non-null object
conditionsz2Remote Config conditions must be a non-null object versionetag)
_parameters
ValueError_conditions_version_etag
isinstancestrjsondumps_template_data_json)selftemplate_datar   r   r   __init__F   s"    	



z_ServerTemplateData.__init__c                 C   s   | j S N)r2   r<   r   r   r   r-   i   s    z_ServerTemplateData.parametersc                 C   s   | j S r?   )r6   r@   r   r   r   r1   m   s    z_ServerTemplateData.etagc                 C   s   | j S r?   )r5   r@   r   r   r   r0   q   s    z_ServerTemplateData.versionc                 C   s   | j S r?   )r4   r@   r   r   r   r.   u   s    z_ServerTemplateData.conditionsc                 C   s   | j S r?   )r;   r@   r   r   r   template_data_jsony   s    z&_ServerTemplateData.template_data_jsonN)r   r   r   r   r>   propertyr-   r1   r0   r.   rA   r   r   r   r   r,   D   s   #



r,   c                   @   sr   e Zd ZdZdeeeeef  dddZdd Z	deeee
eef f  dd	d
dZedddZdd ZdS )ServerTemplatezZRepresents a Server Template with implementations for loading and evaluating the template.Nappdefault_configc                 C   sN   t |tt| _d| _i | _t | _	|dk	rJ|D ]}t
|| | j|< q2dS )a  Initializes a ServerTemplate instance.

        Args:
          app: App instance to be used. This is optional and the default app instance will
                be used if not present.
          default_config: The default config to be used in the evaluated config.
        N)r
   Zget_app_service_REMOTE_CONFIG_ATTRIBUTE_RemoteConfigService_rc_service_cache_stringified_default_config	threadingRLock_lockr8   )r<   rE   rF   keyr   r   r   r>      s     
zServerTemplate.__init__c              	      s,   | j  I dH }| j || _W 5 Q R X dS )z0Fetches the server template and caches the data.N)rI   get_server_templaterN   rJ   )r<   Zrc_server_templater   r   r   load   s    zServerTemplate.loadServerConfig)contextreturnc              	   C   s   | j std|pi }i }| j | j j}| j j}W 5 Q R X | jdk	rh| j D ]\}}td|||< qPt||||| _	t
| j	 dS )a"  Evaluates the cached server template to produce a ServerConfig.

        Args:
          context: A dictionary of values to use for evaluating conditions.

        Returns:
          A ServerConfig object.
        Raises:
            ValueError: If the input arguments are invalid.
        zmNo Remote Config Server template in cache.
                            Call load() before calling evaluate().Nr   )config_values)rJ   r3   rN   r.   r-   rK   items_Value_ConditionEvaluatorZ
_evaluatorrR   evaluate)r<   rS   rU   Ztemplate_conditionsZtemplate_parametersrO   valuer   r   r   rY      s     
 zServerTemplate.evaluate)rA   c              	   C   s.   t |}t|}| j || _W 5 Q R X dS )zUpdates the cache to store the given template is of type ServerTemplateData.

        Args:
          template_data_json: A json string representing ServerTemplateData to be cached.
        N)r9   loadsr,   rN   rJ   )r<   rA   Ztemplate_data_mapr=   r   r   r   set   s    
zServerTemplate.setc              	   C   s,   | j std| j | j j}W 5 Q R X |S )zRProvides the server template in a JSON format to be used for initialization later.zkNo Remote Config Server template in cache.
                            Call load() before calling toJSON().)rJ   r3   rN   rA   )r<   Ztemplate_jsonr   r   r   to_json   s
    zServerTemplate.to_json)NN)N)r   r   r   r   r   r   r   r8   r>   rQ   r   intrY   r\   r]   r   r   r   r   rC   ~   s   &rC   c                   @   sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )rR   z.Represents a Remote Config Server Side Config.c                 C   s
   || _ d S r?   )_config_values)r<   rU   r   r   r   r>      s    zServerConfig.__init__c                 C   s   |  | S )Returns the value as a boolean.)
_get_value
as_booleanr<   rO   r   r   r   get_boolean   s    zServerConfig.get_booleanc                 C   s   |  | S )Returns the value as a string.)ra   	as_stringrc   r   r   r   
get_string   s    zServerConfig.get_stringc                 C   s   |  | S )z Returns the value as an integer.)ra   as_intrc   r   r   r   get_int   s    zServerConfig.get_intc                 C   s   |  | S )zReturns the value as a float.)ra   as_floatrc   r   r   r   	get_float   s    zServerConfig.get_floatc                 C   s   |  | S z Returns the source of the value.)ra   
get_sourcerc   r   r   r   get_value_source   s    zServerConfig.get_value_sourcec                 C   s   | j |tdS )Nr   )r_   getrW   rc   r   r   r   ra      s    zServerConfig._get_valueN)r   r   r   r   r>   rd   rg   ri   rk   rn   ra   r   r   r   r   rR      s   rR   c                   @   s:   e Zd ZdZdd Zdd Zdd Zeedd	d
Z	dS )rH   zhInternal class that facilitates sending requests to the Firebase Remote
        Config backend API.
    c                 C   sN   d}|j | _|j }ddtji}|jdt	j
}t	j||||d| _dS )zInitialize a JsonHttpClient with necessary inputs.

        Args:
            app: App instance to be used for fetching app specific details required
                for initializing the http client.
        z+https://firebaseremoteconfig.googleapis.comzX-FIREBASE-CLIENTzfire-admin-python/{0}ZhttpTimeout)
credentialbase_urlheaderstimeoutN)Z
project_id_project_idrp   get_credentialformatfirebase_admin__version__optionsro   r	   ZDEFAULT_TIMEOUT_SECONDSZJsonHttpClient_client)r<   rE   Zremote_config_base_urlZapp_credentialZ
rc_headersrs   r   r   r   r>      s    
 
 z_RemoteConfigService.__init__c              
      sz   z.t  }|d| jjd|  I dH \}}W n0 tjjk
r^ } z| 	|W 5 d}~X Y nX |
d|d< t|S dS )zRequests for a server template and converts the response to an instance of
        ServerTemplateData for storing the template parameters and conditions.Nro   r1   )asyncioZget_event_loopZrun_in_executorrz   Zheaders_and_body_get_urlrequests
exceptionsRequestException_handle_remote_config_errorro   r,   )r<   looprr   r=   errorr   r   r   rP     s     z(_RemoteConfigService.get_server_templatec                 C   s   d | jS )zJReturns project prefix for url, in the format of /v1/projects/${projectId}z>/v1/projects/{0}/namespaces/firebase-server/serverRemoteConfig)rv   rt   r@   r   r   r   r|     s    z_RemoteConfigService._get_url)r   c                 C   s
   t |S )z5Handles errors received from the Cloud Functions API.)r
   Z#handle_platform_error_from_requests)clsr   r   r   r   r     s    z0_RemoteConfigService._handle_remote_config_errorN)
r   r   r   r   r>   rP   r|   classmethodr   r   r   r   r   r   rH      s   rH   c                   @   s   e Zd ZdZdd Zdd Zeeef dddZ	d!e
ed
ddZd"e
ed
ddZd#e
ed
ddZedddZee
dddZedddZedddZedddZedddZedddZd S )$rX   z_Internal class that facilitates sending requests to the Firebase Remote
    Config backend API.c                 C   s   || _ || _|| _|| _d S r?   )_contextr4   r2   r_   )r<   r.   r-   rS   rU   r   r   r   r>   !  s    z_ConditionEvaluator.__init__c           
      C   s   |  | j| j}| jr| j D ]\}}|di }|di }d}|rr| D ] \}}||krP|rP|| } qrqP|r|drtd| q |r|d}	td|	| j	|< q |st
d| q |drtd| q td|d| j	|< q | j	S )	z]Internal function that evaluates the cached server template to produce
        a ServerConfigZconditionalValuesZdefaultValueNZuseInAppDefaultz'Using in-app default value for key '%s'rZ   r   z#No default value found for key '%s')evaluate_conditionsr4   r   r2   rV   ro   loggerinforW   r_   warning)
r<   evaluated_conditionsrO   Z	parameterZconditional_valuesdefault_valueZparameter_value_wrapperZcondition_nameZcondition_evaluationZparameter_valuer   r   r   rY   '  s4    

z_ConditionEvaluator.evaluaterT   c                 C   s.   i }|D ] }|  |d|||d< q|S )a%  Evaluates a list of conditions and returns a dictionary of results.

        Args:
          conditions: A list of NamedCondition objects.
          context: An EvaluationContext object.

        Returns:
          A dictionary that maps condition names to boolean evaluation results.
        	conditionname)evaluate_conditionro   )r<   r.   rS   r   r   r   r   r   r   M  s    
 z'_ConditionEvaluator.evaluate_conditionsr   )nesting_levelrT   c                 C   s   |t krtd dS |ddk	r<| |d||d S |ddk	rb| |d||d S |ddk	rtdS |d	dk	rdS |d
dk	r| |d
|S |ddk	r| |d|S td dS )a  Recursively evaluates a condition.

        Args:
          condition: The condition to evaluate.
          context: An EvaluationContext object.
          nesting_level: The current recursion depth.

        Returns:
          The boolean result of the condition evaluation.
        z+Maximum condition recursion depth exceeded.FZorConditionN   ZandConditiontrueTfalsepercentZcustomSignalz#Unknown condition type encountered.)MAX_CONDITION_RECURSION_DEPTHr   r   ro   evaluate_or_conditionevaluate_and_conditionevaluate_percent_condition evaluate_custom_signal_condition)r<   r   rS   r   r   r   r   r   ^  s.    
  
z&_ConditionEvaluator.evaluate_conditionc                 C   s8   | dpg }|D ] }| |||d }|r dS qdS )a&  Evaluates an OR condition.

        Args:
          or_condition: The OR condition to evaluate.
          context: An EvaluationContext object.
          nesting_level: The current recursion depth.

        Returns:
          True if any of the subconditions are true, False otherwise.
        r.   r   TFro   r   )r<   Zor_conditionrS   r   sub_conditionssub_conditionresultr   r   r   r   ~  s    z)_ConditionEvaluator.evaluate_or_conditionc                 C   s8   | dpg }|D ] }| |||d }|s dS qdS )a(  Evaluates an AND condition.

        Args:
          and_condition: The AND condition to evaluate.
          context: An EvaluationContext object.
          nesting_level: The current recursion depth.

        Returns:
          True if all of the subconditions are met; False otherwise.
        r.   r   FTr   )r<   Zand_conditionrS   r   r   r   r   r   r   r   r     s    z*_ConditionEvaluator.evaluate_and_conditionc                 C   s   | dstd dS | d}| d}| d}| d}|sRtd dS |rt| d	pbd
}| dppd
}nd
}d
}|r|}	nd
}	|r| dnd}
|
 | d }| |}|d }|tjjkr||	kS |tjjkr||	kS |tjjkr||  k o
|kS   S td| dS )zEvaluates a percent condition.

        Args:
          percent_condition: The percent condition to evaluate.
          context: An EvaluationContext object.

        Returns:
          True if the condition is met, False otherwise.
        Zrandomization_idzEMissing randomization_id in context for evaluating percent condition.FseedZpercentOperatorZmicroPercentZmicroPercentRangez/Missing percent operator for percent condition.ZmicroPercentUpperBoundr   ZmicroPercentLowerBound.r/   i zUnknown percent operator: %s)	ro   r   r   hash_seeded_randomization_idr   r   rZ   r   r   )r<   Zpercent_conditionrS   r   Zpercent_operatorZmicro_percentZmicro_percent_rangeZnorm_percent_upper_boundZnorm_percent_lower_boundZnorm_micro_percentZseed_prefixZstring_to_hashhash64Zinstance_micro_percentiler   r   r   r     s<    







z._ConditionEvaluator.evaluate_percent_condition)seeded_randomization_idrT   c                 C   s.   t  }||d | }tt|dS )zHashes a seeded randomization ID.

        Args:
          seeded_randomization_id: The seeded randomization ID to hash.

        Returns:
          The hashed value.
        zutf-8   )hashlibsha256updateencode	hexdigestabsr^   )r<   r   Zhash_objectr   r   r   r   r     s    	z0_ConditionEvaluator.hash_seeded_randomization_idc                 C   s  | dpi }| dpi }| dp(i }t|||gsFtd dS |sNdS | |pZi }|sptd| dS |tjjkr| ||dd S |tj	jkr| ||d	d  S |tj
jkr| ||d
d S |tjjkr| ||tjS |tjjkr| ||d |dd S |tjjkr4| ||d |dd S |tjjkrZ| ||d |dd S |tjjkr| ||d |dd S |tjjkr| ||d |dd S |tjjkr| ||d |dd S |tjjkr| ||d |dd S |tjjkr| ||d |dd S |tjjkr>| ||d |dd S |tjjkrd| ||d |dd S |tjjkr| ||d |dd S |tjjkr| ||d |dd S td| dS )a  Evaluates a custom signal condition.

        Args:
          custom_signal_condition: The custom signal condition to evaluate.
          context: An EvaluationContext object.

        Returns:
          True if the condition is met, False otherwise.
        ZcustomSignalOperatorZcustomSignalKeyZtargetCustomSignalValueszDMissing operator, key, or target values for custom signal condition.Fz,Custom signal value not found in context: %sc                 S   s   | |kS r?   r   targetactualr   r   r   <lambda>       zF_ConditionEvaluator.evaluate_custom_signal_condition.<locals>.<lambda>c                 S   s   | |kS r?   r   r   r   r   r   r     r   c                 S   s   |   |  kS r?   )stripr   r   r   r   r     r   r   c                 S   s   | dk S Nr   r   rr   r   r   r     r   c                 S   s   | dkS r   r   r   r   r   r   r     r   c                 S   s   | dkS r   r   r   r   r   r   r     r   c                 S   s   | dkS r   r   r   r   r   r   r   "  r   c                 S   s   | dkS r   r   r   r   r   r   r   '  r   c                 S   s   | dkS r   r   r   r   r   r   r   ,  r   c                 S   s   | dk S r   r   r   r   r   r   r   3  r   c                 S   s   | dkS r   r   r   r   r   r   r   8  r   c                 S   s   | dkS r   r   r   r   r   r   r   =  r   c                 S   s   | dkS r   r   r   r   r   r   r   B  r   c                 S   s   | dkS r   r   r   r   r   r   r   G  r   c                 S   s   | dkS r   r   r   r   r   r   r   L  r   z"Unknown custom signal operator: %s)ro   allr   r   debugr   r   rZ   _compare_stringsr   r   r   researchr    _compare_numbersr!   r"   r#   r$   r%   r&   _compare_semantic_versionsr'   r(   r)   r*   r+   )r<   Zcustom_signal_conditionrS   Zcustom_signal_operatorcustom_signal_keyZtarget_custom_signal_valuesZactual_custom_signal_valuer   r   r   r     s    
z4_ConditionEvaluator.evaluate_custom_signal_conditionc                 C   s"   |D ]}||t |r dS qdS )aj  Compares the actual string value of a signal against a list of target values.

        Args:
            target_values: A list of target string values.
            actual_value: The actual value to compare, which can be a string or number.
            predicate_fn: A function that takes two string arguments (target and actual)
                            and returns a boolean indicating whether
                            the target matches the actual value.

        Returns:
            bool: True if the predicate function returns True for any target value in the list,
                False otherwise.
        TF)r8   )r<   Ztarget_valuesactual_valuepredicate_fnr   r   r   r   r   P  s    z$_ConditionEvaluator._compare_stringsc                 C   s^   z6t |}t |}||k rdn||kr*dnd}||W S  tk
rX   td| Y dS X d S )Nr   r   z>Invalid numeric value for comparison for custom signal key %s.F)floatr3   r   r   )r<   r   target_valuer   r   r   r   r   r   r   r   r   d  s    
z$_ConditionEvaluator._compare_numbersc                 C   s   |  |t|t||S )a  Compares the actual semantic version value of a signal against a target value.
        Calls the predicate function with -1, 0, 1 if actual is less than, equal to,
        or greater than target.

        Args:
        custom_signal_key: The custom signal for which the evaluation is being performed.
        target_values: A list of target string values.
        actual_value: The actual value to compare, which can be a string or number.
        predicate_fn: A function that takes an integer (-1, 0, or 1) and returns a boolean.

        Returns:
            bool: True if the predicate function returns True for the result of the comparison,
        False otherwise.
        )_compare_versionsr8   )r<   r   r   r   r   r   r   r   r   o  s     z._ConditionEvaluator._compare_semantic_versionsc           
      C   s   zdd | dD }dd | dD }tt|t|}|dg|t|   |dg|t|   t||D ]L\}}	t|dk |	dk frt||	k r|d  W S ||	krv|d  W S qv|dW S  tk
r   td| Y d	S X d
S )a  Compares two semantic version strings.

        Args:
            custom_signal_key: The custom singal for which the evaluation is being performed.
            sem_version_1: The first semantic version string.
            sem_version_2: The second semantic version string.
            predicate_fn: A function that takes an integer and returns a boolean.

        Returns:
            bool: The result of the predicate function.
        c                 S   s   g | ]}t |qS r   r^   .0partr   r   r   
<listcomp>  s     z9_ConditionEvaluator._compare_versions.<locals>.<listcomp>r   c                 S   s   g | ]}t |qS r   r   r   r   r   r   r     s     r   r   r   zHInvalid semantic version format for comparison for custom signal key %s.FN)	splitmaxlenextendzipanyr3   r   r   )
r<   r   Zsem_version_1Zsem_version_2r   Zv1_partsZv2_parts
max_lengthZpart1Zpart2r   r   r   r     s(    
z%_ConditionEvaluator._compare_versionsN)r   )r   )r   )r   r   r   r   r>   rY   r   r8   boolr   r^   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rX     s<   &  "    -orX   rD   c                    s   t | |d}| I dH  |S )a  Initializes a new ServerTemplate instance and fetches the server template.

    Args:
        app: App instance to be used. This is optional and the default app instance will
            be used if not present.
        default_config: The default config to be used in the evaluated config.

    Returns:
        ServerTemplate: An object having the cached server template to be used for evaluation.
    rD   N)init_server_templaterQ   )rE   rF   templater   r   r   rP     s    rP   )rE   rF   rA   c                 C   s"   t | |d}|dk	r|| |S )a  Initializes a new ServerTemplate instance.

    Args:
        app: App instance to be used. This is optional and the default app instance will
            be used if not present.
        default_config: The default config to be used in the evaluated config.
        template_data_json: An optional template data JSON to be set on initialization.

    Returns:
        ServerTemplate: A new ServerTemplate instance initialized with an optional
        template and config.
    rD   N)rC   r\   )rE   rF   rA   r   r   r   r   r     s    
r   c                   @   s   e Zd ZdZdZdZdZdZdddd	d
dgZefe	e
dddZe
dddZedddZedddZedddZe	dddZdS )rW   z3Represents a value fetched from Remote Config.
    Fr/   r   g        1r   tyesyonsourcerZ   c                 C   s   || _ || _dS )a  Initializes a Value instance.

        Args:
          source: The source of the value (e.g., 'default', 'remote', 'static').
          "static" indicates the value was defined by a static constant.
          "default" indicates the value was defined by default config.
          "remote" indicates the value was defined by config produced by evaluating a template.
          value: The string value.
        Nr   )r<   r   rZ   r   r   r   r>     s    
z_Value.__init__r   c                 C   s   | j dkr| jS t| jS )re   r   )r   DEFAULT_VALUE_FOR_STRINGr8   rZ   r@   r   r   r   rf     s    
z_Value.as_stringc                 C   s$   | j dkr| jS t| j | jkS )r`   r   )r   DEFAULT_VALUE_FOR_BOOLEANr8   rZ   lowerBOOLEAN_TRUTHY_VALUESr@   r   r   r   rb     s    
z_Value.as_booleanc                 C   s<   | j dkr| jS zt| jW S  tk
r6   | j Y S X dS zReturns the value as a number.r   N)r   DEFAULT_VALUE_FOR_INTEGERr^   rZ   r3   r@   r   r   r   rh     s    
z_Value.as_intc                 C   s<   | j dkr| jS zt| jW S  tk
r6   | j Y S X dS r   )r   DEFAULT_VALUE_FOR_FLOAT_NUMBERr   rZ   r3   r@   r   r   r   rj     s    
z_Value.as_floatc                 C   s   | j S rl   )r   r@   r   r   r   rm     s    z_Value.get_sourceN)r   r   r   r   r   r   r   r   r   ValueSourcer8   r>   rf   r   rb   r   rh   rj   rm   r   r   r   r   rW     s   		rW   )NN)NNN)'r   r{   r9   loggingrL   typingr   r   r   r   r   enumr   r   r   r}   rw   r   r	   r
   basicConfigINFO	getLoggerr   r   rG   r   r   r   r   r,   rC   rR   rH   rX   r8   rP   r   rW   r   r   r   r   <module>   sB   
:T/   	  