
    iVN                    H   d dl Z d dlZd dlZd dlZd dlZd dlmZ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mZ d dlmZmZmZmZ d d	lmZ d d
lmZmZmZmZm Z m!Z!m"Z"m#Z# d dl$m%Z% d dl&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z. d dl/m0Z0m1Z1m2Z2m3Z3 d dl4m5Z5m6Z6 d dl7m8Z8 d dl9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZC d dlDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZP d dlQmRZRmSZSmTZTmUZUmVZVmWZW d dlXmYZY 	 d dlZZZn# e[$ r d dl\ZZY nw xY wdZ]de^e_e`f         fdZad ZbddZc G d ded          Zed ZfdS )    N)datetime	timedelta)AnyDictOptionalUnion)uuid4)tzutc)string_types)Unpack)ID_TYPESExceptionArgOptionalCaptureArgsOptionalSetArgs)Consumer)_get_current_context,get_capture_exception_code_variables_context*get_code_variables_ignore_patterns_context(get_code_variables_mask_patterns_contextget_context_device_idget_context_distinct_idget_context_session_idnew_context)ExceptionCapture)&DEFAULT_CODE_VARIABLES_IGNORE_PATTERNS$DEFAULT_CODE_VARIABLES_MASK_PATTERNSexc_info_from_errorexception_is_already_capturedexceptions_from_error_tuplehandle_in_appmark_exception_as_captured#try_attach_code_variables_to_frames)InconclusiveMatchErrorRequiresServerEvaluationmatch_feature_flag_propertiesresolve_bucketing_value)FlagDefinitionCacheDataFlagDefinitionCacheProvider)Poller)
DEFAULT_HOSTAPIErrorQuotaLimitErrorRequestsConnectionErrorRequestsTimeout
batch_postdetermine_server_hostflagsgetremote_config)FeatureFlagFeatureFlagErrorFeatureFlagResultFlagMetadataFlagsAndPayloadsFlagsResponse	FlagValueSendFeatureFlagsOptionsnormalize_flags_responseto_flags_and_payloadsto_payloads	to_values)	FlagCacheRedisFlagCacheSizeLimitedDictcleanguess_timezonesystem_context)VERSIONiP  returnc                     t          |           }|rt          |          r|dfS t                      }|r|dfS t          t	                                dfS )zMReturns the distinct id to use, and whether this is a personless event or notFT)stringify_idlenr   strr	   )passedstringified
context_ids      A/var/www/icac/venv/lib/python3.11/site-packages/posthog/client.pyget_identity_staterP   ]   sd    v&&K $s;'' $U##(**J #E""LL$    c                    | pi } t                      }|rO|                                }t          |                                          | d<   |                    |            |} d| vrt                      rt                      | d<   | S )Nz$context_tags$session_id)r   collect_tagssetkeysupdater   )
propertiescurrent_contextcontext_tagss      rO   add_context_tagsr[   j   s    !rJ*,,O "&3355&),*;*;*=*=&>&>
?#J'''!
J&&+A+C+C&$:$<$<
=!rQ   c                       fd}|S )a'  
    Decorator to prevent raising exceptions from public API methods.
    Note that this doesn't prevent errors from propagating via `on_error`.
    Exceptions will still be raised if the debug flag is enabled.

    Args:
        default_return: Value to return on exception (default: None)
    c                 D     ddl m}  |            fd            }|S )Nr   )wrapsc                     	  | g|R i |S # t           $ r:}| j        r|| j                            dj         d|            cY d }~S d }~ww xY w)Nz	Error in z: )	Exceptiondebuglog	exception__name__)selfargskwargsedefault_returnfuncs       rO   wrapperz,no_throw.<locals>.decorator.<locals>.wrapper   s    &tD242226222 & & &: G""#Ct}#C#C#C#CDDD%%%%%%%	&s    
A/AAA)	functoolsr^   )rj   r^   rk   ri   s   `  rO   	decoratorzno_throw.<locals>.decorator   sM    ######	t	& 	& 	& 	& 	& 
	& rQ    )ri   rm   s   ` rO   no_throwro   z   s$         rQ   c                   f	   e Zd ZdZ ej        d          Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d\dedee	         de
e         dz  fdZd]dZed             Zej        d             Z	 	 	 	 	 	 d^dee
e                  dee         deeeeef         f         fdZ	 	 	 	 	 	 d^dee
e                  dee         deeef         fdZ	 	 	 	 	 	 d^dee
e                  dee         defdZ	 	 	 	 	 	 	 d_dee         dee         dee
e                  dee         def
dZ e            dedee         dee         fd            Zdefd Z e            dee          dee         fd!            Z! e            dee          dee         fd"            Z" e            	 	 	 	 	 d`d#ed$ed%ee#ee$f                  d&eee%ef                  d'ee         d(ee         dee         dee         fd)            Z& e            	 	 	 dad*edee         fd+            Z'd,ee(         dee         fd-Z)d. Z*d/ Z+d0 Z,d1 Z-	 dbd2e.d3ee         ddfd4Z/d5 Z0d6 Z1d7 Z2dddddd8de3fd9Z4dddddddd:dee         fd;Z5ded<edee6         fd=Z7ddddddddd>d<eded?ee3         dee#eef                  dee         dee6         fd@Z8dddddddd:dee         dee6         fdAZ9dddddddd:dee         dee3         fdBZ:	 dbd<ededeeef         dCeeef         dDeeef         dee         dee3         fdEZ;dddddddddFdGee3         dee         fdHZ<	 dbd<ededeeef         dCeeef         dDeeef         d(ee         dee         de=ee>         ee         ee?         ef         fdIZ@	 dbded<edJee3         dKee         dLede#eef         d(ee         dMee         dNee?         dOee>         dPee         fdQZAd<efdRZBd<edGe3dee         fdSZCddddddddTdee
e                  dee         deeeeeef         f                  fdUZDddddddddTdee
e                  dee         defdVZEddddddWdede#eeee?f         f         dee
e                  dee         de=eef         f
dXZFdY ZGdZ ZHd[ ZIdS )cClienta/  
    This is the SDK reference for the PostHog Python SDK.
    You can learn more about example usage in the [Python SDK documentation](/docs/libraries/python).
    You can also follow [Flask](/docs/libraries/flask) and [Django](/docs/libraries/django)
    guides to integrate PostHog into your project.

    Examples:
        ```python
        from posthog import Posthog
        posthog = Posthog('<ph_project_api_key>', host='<ph_client_api_host>')
        posthog.debug = True
        if settings.TEST:
            posthog.disabled = True
        ```
    posthogNF'  Td         ?            project_api_keyflag_definition_cache_providerin_app_modulesc!                    t          j        |          | _         || _        || _        || _        || _        || _        |pt          | _        t          |          | _
        |	| _        || _        d| _        d| _        d| _        d| _        || _        || _        d| _        t)          t*          t,                    | _        |                     |          | _        d| _        d| _        || _        || _        || _        || _        || _         || _!        || _"        d| _#        || _$        || _%        || _&        ||ntN          | _(        ||ntR          | _*        | | _+        |'	 tY          j-                    }n# t\          $ r d}Y nw xY w|| _/        || _0        |r8tc          j2                     | j3        4                    tb          j5                   n$| j3        4                    tb          j6                   |9to          |          r|| _8        n)| j3        9                    d           d| _8        nd| _8        | j!        rtu          |           | _#        |r	d| _;        dS |rty          j=        | j>                   g | _;        t          |          D ]Z}!t          | j         | j        | j
        ||||	|
||
  
        }"| j;        A                    |"           |r|"B                                 [dS )a  
        Initialize a new PostHog client instance.

        Args:
            project_api_key: The project API key.
            host: The host to use for the client.
            debug: Whether to enable debug mode.

        Examples:
            ```python
            from posthog import Posthog

            posthog = Posthog('<ph_project_api_key>', host='<ph_app_host>')
            ```

        Category:
            Initialization
        Nr   z/before_send is not callable, it will be ignored)hoston_errorflush_atflush_intervalgzipretriestimeouthistorical_migration)CqueueQueueapi_keyr   ra   send	sync_moder*   raw_hostr0   r~   r   r   _feature_flagsfeature_flags_by_keygroup_type_mappingcohortspoll_interval%feature_flags_request_timeout_secondspollerrB   MAX_DICT_SIZErU   #distinct_ids_feature_flags_reported_initialize_flag_cache
flag_cacheflag_definition_version_flags_etag_flag_definition_cache_providerdisableddisable_geoipr   super_propertiesenable_exception_autocapturelog_captured_exceptionsexception_captureprivacy_modeenable_local_evaluation capture_exception_code_variablesr   code_variables_mask_patternsr   code_variables_ignore_patternsr|   osgetcwdr`   project_rootpersonal_api_keyloggingbasicConfigrb   setLevelDEBUGWARNINGcallablebefore_sendwarningr   	consumersatexitregisterjoinranger   appendstart)#re   rz   r~   ra   max_queue_sizer   r   r   r   r   max_retriesr   r   threadr   r   r   r   r   r   r   r   r   r   r   r   flag_fallback_cache_urlr   r{   r   r   r   r|   _consumers#                                      rO   __init__zClient.__init__   s1   j [00
 ' 
	",)$//		"$(!<@15*1 	2 3B=RU3V3V0556MNN'($*./M, *$8! 0,H)'>$!%('>$0P- ,7 )(5 	) .9 +*7 	+
 -$!y{{ $ $ $#$ ) !1 	/ !!!Hgm,,,,Hgo..."$$ (#.    !RSSS#'  #D, 	<%5d%;%;D" 	%!DNNN  +	***DN6]] % %#JL%%#1'#)=   %%h///  %NN$$$#% %s   E0 0E?>E?c                 &    t          |||           S )a+  
        Create a new context for managing shared state. Learn more about [contexts](/docs/libraries/python#contexts).

        Args:
            fresh: Whether to create a fresh context that doesn't inherit from parent.
            capture_exceptions: Whether to automatically capture exceptions in this context.

        Examples:
            ```python
            with posthog.new_context():
                identify_context('<distinct_id>')
                posthog.capture('event_name')
            ```

        Category:
            Contexts
        )freshcapture_exceptionsclient)r   )re   r   r   s      rO   r   zClient.new_contextO  s#    $ ,>t
 
 
 	
rQ   c                     | j         S )z9
        Get the local evaluation feature flags.
        )r   re   s    rO   feature_flagszClient.feature_flagse  s    
 ""rQ   c                 f    |pg | _         d | j         D             | _        | j        
J d            dS )z9
        Set the local evaluation feature flags.
        c                 J    i | ] }|                     d           |d          |!S keyr2   ).0flags     rO   
<dictcomp>z(Client.feature_flags.<locals>.<dictcomp>r  s8     %
 %
 %
xx* K***rQ   NDfeature_flags_by_key should be initialized when feature_flags is set)r   r   )re   r1   s     rO   r   zClient.feature_flagsl  sV    
 $kr%
 %
+%
 %
 %
!
 (44R 54444rQ   flag_keys_to_evaluate	device_idrG   c           	      \    |                      |||||||          }t          |          pi S )a  
        Get feature flag variants for a user by calling decide.

        Args:
            distinct_id: The distinct ID of the user.
            groups: A dictionary of group information.
            person_properties: A dictionary of person properties.
            group_properties: A dictionary of group properties.
            disable_geoip: Whether to disable GeoIP for this request.
            flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
                only these flags will be evaluated, improving performance.
            device_id: The device ID for this request.

        Category:
            Feature flags
        r   )get_flags_decisionr?   	re   distinct_idgroupsperson_propertiesgroup_propertiesr   r   r   	resp_datas	            rO   get_feature_variantszClient.get_feature_variants{  sH    4 ++! , 
 
	 ##)r)rQ   c           	      \    |                      |||||||          }t          |          pi S )a  
        Get feature flag payloads for a user by calling decide.

        Args:
            distinct_id: The distinct ID of the user.
            groups: A dictionary of group information.
            person_properties: A dictionary of person properties.
            group_properties: A dictionary of group properties.
            disable_geoip: Whether to disable GeoIP for this request.
            flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
                only these flags will be evaluated, improving performance.
            device_id: The device ID for this request.

        Examples:
            ```python
            payloads = posthog.get_feature_payloads('<distinct_id>')
            ```

        Category:
            Feature flags
        r   )r   r>   r   s	            rO   get_feature_payloadszClient.get_feature_payloads  sH    > ++! , 
 
	 9%%++rQ   c           	      X    |                      |||||||          }t          |          S )a!  
        Get feature flags and payloads for a user by calling decide.

        Args:
            distinct_id: The distinct ID of the user.
            groups: A dictionary of group information.
            person_properties: A dictionary of person properties.
            group_properties: A dictionary of group properties.
            disable_geoip: Whether to disable GeoIP for this request.
            flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
                only these flags will be evaluated, improving performance.
            device_id: The device ID for this request.

        Examples:
            ```python
            result = posthog.get_feature_flags_and_payloads('<distinct_id>')
            ```

        Category:
            Feature flags
        r   )r   r=   )	re   r   r   r   r   r   r   r   resps	            rO   get_feature_flags_and_payloadsz%Client.get_feature_flags_and_payloads  sC    > &&! ' 
 
 %T***rQ   r   r   c                     |pi }|pi }|pi }|t                      }|t                      }|| j        }|si }||||||d}|r||d<   t          | j        | j        fd| j        i|}	t          |	          S )a  
        Get feature flags decision.

        Args:
            distinct_id: The distinct ID of the user.
            groups: A dictionary of group information.
            person_properties: A dictionary of person properties.
            group_properties: A dictionary of group properties.
            disable_geoip: Whether to disable GeoIP for this request.
            flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
                only these flags will be evaluated, improving performance.
            device_id: The device ID for this request.

        Examples:
            ```python
            decision = posthog.get_flags_decision('user123')
            ```

        Category:
            Feature flags
        N)r   r   r   r   geoip_disabler   r   r   )r   r   r   r1   r   r~   r   r<   )
re   r   r   r   r   r   r   r   request_datar   s
             rO   r   zClient.get_flags_decision  s    > 2-3+1r133K-//I  .M 	F '!2 0*"
 
 ! 	J4IL01LI
 
 >
 	
 
	 (	222rQ   eventrg   c           
         |                     dd          }|                     dd          }|                     dd          }|                     dd          }|                     dd          }|                     dd          }|                     d	d          }	i |pi t                      }t          |          }|J t          |          \  }}
|
r	d
|vrd|d
<   |||||d}|r||d<   i }i }|                     |          }|d         r	 |d         du r1|                     ||pi |d         |d         |	d|d                   }n|d         du r.|                     |||d         |d         |	|d                   }ne| j        r1|                     ||pi |d         |d         |	d|d                   }n-|                     |||d         |d         |	|d                   }n4# t          $ r'}| j	        
                    d|            Y d}~nd}~ww xY w|pi                                 D ]\  }}||d| <   d |pi                                 D             }|r||d<   |ri ||}||d<   |                     ||	          S )a  
        Captures an event manually. [Learn about capture best practices](https://posthog.com/docs/product-analytics/capture-events)

        Args:
            event: The event name to capture.
            distinct_id: The distinct ID of the user.
            properties: A dictionary of properties to include with the event.
            timestamp: The timestamp of the event.
            uuid: A unique identifier for the event.
            groups: A dictionary of group information.
            send_feature_flags: Whether to send feature flags with the event.
            disable_geoip: Whether to disable GeoIP for this event.

        Examples:
            ```python
            # Anonymous event
            posthog.capture('some-anon-event')
            ```
            ```python
            # Context usage
            from posthog import identify_context, new_context
            with new_context():
                identify_context('distinct_id_of_the_user')
                posthog.capture('user_signed_up')
                posthog.capture('user_logged_in')
                posthog.capture('some-custom-action', distinct_id='distinct_id_of_the_user')
            ```
            ```python
            # Set event properties
            posthog.capture(
                "user_signed_up",
                distinct_id="distinct_id_of_the_user",
                properties={
                    "login_type": "email",
                    "is_free_trial": "true"
                }
            )
            ```
            ```python
            # Page view event
            posthog.capture('$pageview', distinct_id="distinct_id_of_the_user", properties={'$current_url': 'https://example.com'})
            ```

        Category:
            Capture
        r   NrX   	timestampuuidr   send_feature_flagsFr   z$process_person_profile)rX   r   r   r   r   z$groupsshould_sendonly_evaluate_locallyTr   r   flag_keys_filter)r   r   r   r   r   r   )r   r   r   r   z0[FEATURE FLAGS] Unable to get feature variants: 	$feature/c                      g | ]\  }}|d u	|S )Frn   )r   r   values      rO   
<listcomp>z"Client.capture.<locals>.<listcomp>  s1      
  
  
eE!! !!!rQ   z$active_feature_flags)r2   rE   r[   rP   _parse_send_feature_flagsget_all_flagsr   r   r`   rb   rc   items_enqueue)re   r   rg   r   rX   r   r   r   r   r   
personlessmsgextra_propertiesfeature_variantsflag_optionsrh   featurevariantactive_feature_flagss                      rO   capturezClient.capture8  s   d jj55ZZd33
JJ{D11	zz&$''Hd++#ZZ(<eDD

?D99?)r?n.>.>?
%j11
%%%$6{$C$C!j 	:3:EE49J01 %"&
 
  	+$*Jy!+-BD 556HII& /	. 78D@@'+'9'9# &"*67J*K)56H)I&3.2.:;M.N (: ( ($$ ""9:eCC'+'@'@#*67J*K)56H)I&3.:;M.N (A ( ($$ ' '+'9'9# &"*67J*K)56H)I&3.2.:;M.N (: ( ($$ (,'@'@#*67J*K)56H)I&3.:;M.N (A ( ($    ""JqJJ       
 "2!7R > > @ @ 	> 	>GW6=22233 
  
!1!7R > > @ @ 
  
  

   	M8L45 	+;,;
;J *C}}S-000s   CG* *
H4HHc                 N   t          |t                    rTd|                    d          |                    d          |                    d          |                    d          dS t          |t                    r|dddddS t	          dt          |           d	          )
a  
        Parse and normalize send_feature_flags parameter into a standard format.

        Args:
            send_feature_flags: Either bool or SendFeatureFlagsOptions dict

        Returns:
            SendFeatureFlagsOptions: Normalized options with keys: should_send, only_evaluate_locally,
                  person_properties, group_properties, flag_keys_filter

        Raises:
            TypeError: If send_feature_flags is not bool or dict
        Tr   r   r   r   )r   r   r   r   r   Nz%Invalid type for send_feature_flags: z. Expected bool or dict.)
isinstancedictr2   bool	TypeErrortype)re   r   s     rO   r   z Client._parse_send_feature_flags  s     ($// 	#);)?)?+* * &8%;%;<O%P%P$6$:$:;M$N$N$6$:$:;M$N$N   *D11 	1)-%)$($(   *=O8P8P * * *  rQ   c                 p   |                     dd          }|                     dd          }|                     dd          }|                     dd          }|                     dd          }|pi }t          |          }t          |          \  }}|s|sdS |||d|d}|                     ||          S )	a  
        Set properties on a person profile.

        Args:
            distinct_id: The distinct ID of the user.
            properties: A dictionary of properties to set.
            timestamp: The timestamp of the event.
            uuid: A unique identifier for the event.
            disable_geoip: Whether to disable GeoIP for this event.

        Examples:
            ```python
            # Set with distinct id
            posthog.set(distinct_id='user123', properties={'name': 'Max Hedgehog'})
            ```

        Category:
            Identification

        Note: This method will not raise exceptions. Errors are logged.
        r   NrX   r   r   r   $set)r   r   r  r   r   r2   r[   rP   r   	re   rg   r   rX   r   r   r   r   r   s	            rO   rU   z
Client.set  s    . jj55ZZd33
JJ{D11	zz&$''

?D99%2
%j11
$6{$C$C!j 	Z 	4 #&
 
 }}S-000rQ   c                 p   |                     dd          }|                     dd          }|                     dd          }|                     dd          }|                     dd          }|pi }t          |          }t          |          \  }}|s|sdS |||d|d}|                     ||          S )	a  
        Set properties on a person profile only if they haven't been set before.

        Args:
            distinct_id: The distinct ID of the user.
            properties: A dictionary of properties to set once.
            timestamp: The timestamp of the event.
            uuid: A unique identifier for the event.
            disable_geoip: Whether to disable GeoIP for this event.

        Examples:
            ```python
            posthog.set_once(distinct_id='user123', properties={'initial_signup_date': '2024-01-01'})
            ```

        Category:
            Identification

        Note: This method will not raise exceptions. Errors are logged.
        r   NrX   r   r   r   	$set_once)r   r   r  r   r   r  r  s	            rO   set_oncezClient.set_once%  s    , jj55ZZd33
JJ{D11	zz&$''

?D99%2
%j11
$6{$C$C!j 	Z 	4 #&# 
 
 }}S-000rQ   
group_type	group_keyrX   r   r   r   c                     |pi }t          |          d         }d|||d|||d}t                      r$t          t                                |d         d<   |                     ||          S )aZ  
        Identify a group and set its properties.

        Args:
            group_type: The type of group (e.g., 'company', 'team').
            group_key: The unique identifier for the group.
            properties: A dictionary of properties to set on the group.
            timestamp: The timestamp of the event.
            uuid: A unique identifier for the event.
            disable_geoip: Whether to disable GeoIP for this event.
            distinct_id: The distinct ID of the user performing the action.

        Examples:
            ```python
            posthog.group_identify('company', 'company_id_in_your_db', {
                'name': 'Awesome Inc.',
                'employees': 11
            })
            ```

        Category:
            Identification

        Note: This method will not raise exceptions. Errors are logged.
        r   z$groupidentify)z$group_type
$group_keyz
$group_set)r   rX   r   r   r   rX   rS   rP   r   rK   r   )	re   r	  r
  rX   r   r   r   r   r   s	            rO   group_identifyzClient.group_identifyS  s    H  %2
 )55a8 &)'( 
 '"

 

 "## 	M/23I3K3K/L/LCm,}}S-000rQ   previous_idc                     t          |          \  }}|rdS ||d|d||d}t                      r$t          t                                |d         d<   |                     ||          S )a`  
        Create an alias between two distinct IDs.

        Args:
            previous_id: The previous distinct ID.
            distinct_id: The new distinct ID to alias to.
            timestamp: The timestamp of the event.
            uuid: A unique identifier for the event.
            disable_geoip: Whether to disable GeoIP for this event.

        Examples:
            ```python
            posthog.alias(previous_id='distinct_id', distinct_id='alias_id')
            ```

        Category:
            Identification

        Note: This method will not raise exceptions. Errors are logged.
        N)r   aliasz$create_alias)rX   r   r   r   r   rX   rS   r  )re   r  r   r   r   r   r   r   s           rO   r  zClient.alias  s    : %7{$C$C!j 	4  +$  #$&	
 	
 "## 	M/23I3K3K/L/LCm,}}S-000rQ   rc   c           
         |                     dd          }|                     dd          }|                     dd          }|                     dd          }	 |pi }|+t          |          r| j                            d           dS |t	          |          }nt          j                    }||dk    r| j                            d	           dS t          |          }t          d
d|ii| j
        | j                  }	|	d
         d         }
d|
i|}t                      }t                      }t                      }||n| j        }||n| j        }||n| j        }|rt%          |
|||           | j        r| j                            ||           |                     dd          }|                     dd          }|                     dd          }|                     d|||||||          }||t-          ||           |S # t.          $ r(}| j                            d|            Y d}~dS d}~ww xY w)a  
        Capture an exception for error tracking.

        Args:
            exception: The exception to capture.
            distinct_id: The distinct ID of the user.
            properties: A dictionary of additional properties.
            send_feature_flags: Whether to send feature flags with the exception.
            disable_geoip: Whether to disable GeoIP for this event.

        Examples:
            ```python
            try:
                # Some code that might fail
                pass
            except Exception as e:
                posthog.capture_exception(e, 'user_distinct_id', properties=additional_properties)
            ```

        Category:
            Error Tracking
        r   NrX   r   Fr   z$Exception already captured, skippingNNNz"No exception information availablerc   values)in_app_includer   z$exception_list)mask_patternsignore_patterns)extrar   r   r   z
$exception)r   rX   r   r   r   r   r   zFailed to capture exception: )r2   r   rb   ra   r   sysexc_infor   r   r    r|   r   r   r   r   r   r   r   r"   r   rc   r   r!   r`   )re   rc   rg   r   rX   r   r   r  all_exceptions_with_tracer   $all_exceptions_with_trace_and_in_appcontext_enabledcontext_maskcontext_ignoreenabledr  r  r   r   r   resrh   s                         rO   capture_exceptionzClient.capture_exception  s   6 jj55ZZd33
#ZZ(<eDD

?D99X	D#)rJ $)Fy)Q)Q$EFFFt$.y99<>>8/A#A#A  !EFFFt )DH(M(M% " ";"
  $2!.  E 493Eh3O0 "#GJ
 KLLOCEELGIIN #.  :   + 6  "- 8   38"/$3	    + <""9F";;;

;55I::fd++DZZ$//F,,'%##5+  	 	C $*9c:::J 	D 	D 	DHBqBBCCCCCCCCC	Ds&   /H AH D:H 
IH<<Ic                 X   | j         rdS |d         }|!t          j        t                                }t	          |          }|                                |d<   d|v r)|                    d          }|rt          |          |d<   d|vrt          t                                |d<   |d         }|	                    d          si |d<   d|d         d<   t          |d         d<   || j        }|rd	|d         d
<   | j        ri |d         | j        |d<   t          |	                    dd                    |d<   t          |          }| j        rk	 |                     |          }|| j                            d           dS |}n4# t"          $ r'}| j                            d|            Y d}~nd}~ww xY w| j                            d|           | j        s|S | j        rR| j                            d|d                    t+          | j        | j        | j        | j        |g| j                   |S 	 | j                            |d           | j                            d|d                    |S # t6          j        $ r | j                            d           Y dS w xY w)z8Push a new `msg` onto the queue, return `(success, msg)`Nr   tzr   rX   zposthog-pythonz$libz$lib_versionTz$geoip_disabler   z%Event dropped by before_send callbackzError in before_send callback: zqueueing: %szenqueued with blocking %s.r   )r   r   batchr   F)blockzenqueued %s.zanalytics-python queue is full)r   r   nowr
   rD   	isoformatpoprI   r	   r2   rF   r   r   rC   r   rb   ra   r`   rc   r   r   r/   r   r~   r   r   r   r   putFullr   )re   r   r   r   r   	sent_uuidmodified_msgrh   s           rO   r   zClient._enqueue;  s    = 	4$	 000I #9--	$..00KS==776??D 1*400F&uww//CKK	ww|$$ 	# "C$4L&!,3L.)  .M 	726C./  	O N3|#4 N8M NC)#''-*F*FGGMCjj 	JJ#//44'HNN#JKKK4" J J J""#HQ#H#HIIIIIIIIJ 	~s+++ y 	> 	HNN7WFFF	Ye%)%>    	JNN3eN,,,HNN>3w<888z 	 	 	H=>>>44	s0   1F F 
F<F77F<=>I< <)J)(J)c                     | j         } |j                    } |j                     | j                            d|           dS )a  
        Force a flush from the internal queue to the server. Do not use directly, call `shutdown()` instead.

        Examples:
            ```python
            posthog.capture('event_name')
            posthog.flush()  # Ensures the event is sent immediately
            ```
        z$successfully flushed about %s items.N)r   qsizer   rb   ra   )re   r   sizes      rO   flushzClient.flush  sB     
u{}}
=tDDDDDrQ   c                    | j         rC| j         D ];}|                                 	 |                                 ,# t          $ r Y 8w xY w| j        r| j                                         | j        rQ	 | j                                         dS # t          $ r(}| j	        
                    d|            Y d}~dS d}~ww xY wdS )z
        End the consumer thread once the queue is empty. Do not use directly, call `shutdown()` instead.

        Examples:
            ```python
            posthog.join()
            ```
        z/[FEATURE FLAGS] Cache provider shutdown error: N)r   pauser   RuntimeErrorr   stopr   shutdownr`   rb   error)re   r   rh   s      rO   r   zClient.join  s    > 	 N     MMOOOO#   D ; 	K / 	VV4==????? V V VTQRTTUUUUUUUUUV	V 	Vs'   ;
AA3B 
C B;;C c                     |                                   |                                  | j        r| j                                         dS dS )z
        Flush all messages and cleanly shutdown the client. Call this before the process ends in serverless environments to avoid data loss.

        Examples:
            ```python
            posthog.shutdown()
            ```
        N)r2  r   r   closer   s    rO   r7  zClient.shutdown  sN     	

		! 	+"((*****	+ 	+rQ   dataold_flags_by_keyc                     |d         | _         |d         | _        |d         | _        | j        rB|B|| j        pi k    r7| j        }| xj        dz  c_        | j                            |           dS dS dS dS )zVUpdate internal flag state from cache data and invalidate evaluation cache if changed.r1   r   r   Nrx   )r   r   r   r   r   r   invalidate_version)re   r;  r<  old_versions       rO   _update_flag_statezClient._update_flag_state  s     "']"&';"<I O	< , T%>%D"EE6K((A-((O..{;;;;;	< 	<,,EErQ   c                    d}| j         rQ	 | j                                         }n6# t          $ r)}| j                            d|            d}Y d }~nd }~ww xY w|s| j         r	 | j                                         }|r`| j                            d           |                     || j        pi            t          j
        t                                | _        d S | j        s| j                            d           d}n6# t          $ r)}| j                            d|            d}Y d }~nd }~ww xY w|r|                                  d S d S )NTz3[FEATURE FLAGS] Cache provider should_fetch error: zA[FEATURE FLAGS] Using cached flag definitions from external cacher<  r$  zJ[FEATURE FLAGS] Cache empty and no flags loaded, falling back to API fetchz*[FEATURE FLAGS] Cache provider get error: )r   should_fetch_flag_definitionsr`   rb   r8  get_flag_definitionsra   r@  r   r   r(  r
   _last_feature_flag_pollr   _fetch_feature_flags_from_api)re   should_fetchrh   cached_datas       rO   _load_feature_flagszClient._load_feature_flags  s   / 
	$	$8VVXX   $ $ $M!MM    $$  	$ D 	$$8MMOO   ,HNN[   ++#d6O6USU ,    4<<5773K3K3KD0F  - ,h   (, $ $ $OAOOPPP#$
  	1..00000	1 	1s3   % 
AAA%A9D  #D 
D7D22D7c                    	 | j         pi }t          | j        d| j         d| j        d| j                  }|j        | _        |j        rB| j        	                    d           t          j        t                                | _        dS |j        | j                            d           dS |                     |j        |	           | j        ri	 | j                            | j        pg | j        pi | j        pi d
           n4# t,          $ r'}| j                            d|            Y d}~nd}~ww xY wni# t.          $ r}|j        dk    rh| j                            d           g | _        i | _        i | _        | j        r| j                                         | j	        rt/          dd          n|j        dk    rh| j                            d           g | _        i | _        i | _        | j        r| j                                         | j	        rt/          dd          n| j                            d|            Y d}~nVd}~wt,          $ rF}| j                            d| j        z             | j                            |           Y d}~nd}~ww xY wt          j        t                                | _        dS )z)Fetch feature flags from the PostHog API.z*/api/feature_flag/local_evaluation/?token=z&send_cohorts
   )r   etagz;[FEATURE FLAGS] Flags not modified (304), using cached datar$  NzB[FEATURE FLAGS] Unexpected empty response data in non-304 responserB  )r1   r   r   z,[FEATURE FLAGS] Cache provider store error: i  z[FEATURE FLAGS] Error loading feature flags: To use feature flags, please set a valid personal_api_key. More information: https://posthog.com/docs/api/overviewzYou are using a write-only key with feature flags. To use feature flags, please set a personal_api_key More information: https://posthog.com/docs/api/overview)statusmessagei  z[FEATURE FLAGS] PostHog feature flags quota limited, resetting feature flag data.  Learn more about billing limits at https://posthog.com/docs/billing/limits-alertsz#PostHog feature flags quota limitedz-[FEATURE FLAGS] Error loading feature flags: z`[FEATURE FLAGS] Fetching feature flags failed with following error. We will retry in %s seconds.)r   r2   r   r   r~   r   rL  not_modifiedrb   ra   r   r(  r
   rE  r;  r8  r@  r   on_flag_definitions_receivedr   r   r   r`   r+   rM  r   clearr   r   )re   r<  responserh   s       rO   rF  z$Client._fetch_feature_flags_from_api  s   Y	 040I0OR%XT\XXX	%  H  (}D $ Q   08|uww/G/G/G,}$X   ##HMDT#UUU 3 
W	W8UU%)%7%=2262I2OR'+|'9r     ! W W WHNN#URS#U#UVVVVVVVVW  &	T &	T &	Tx3 v   &("*,'!? ,O))+++: ""!R    S   {   &("*,'! ? ,O))+++: "" E    RqRRSSS 	  	  	 Hr$%   HQ	  (0|uww'?'?'?$$$s[   BD= !D= /#D= 3D D= 
D8D3.D= 3D88D= =J#DIJ#<JJ#c                 f   | j         s#| j                            d           g | _        dS |                                  | j        ri| j        r| j                                        sKt          t          | j
                  | j                  | _        | j                                         dS dS dS )z
        Load feature flags for local evaluation.

        Examples:
            ```python
            posthog.load_feature_flags()
            ```

        Category:
            Feature flags
        zL[FEATURE FLAGS] You have to specify a personal_api_key to use feature flags.N)seconds)intervalexecute)r   rb   r   r   rI  r   r   is_aliver)   r   r   r   r   s    rO   load_feature_flagszClient.load_feature_flagsf  s     $ 	H^   "$DF  """ ' 	 K	  K0022	  !"4+=>>>0  DK K	  	  	  	 rQ   r   r   r   warn_on_unknown_groupsr   c          
      L   |pi }|pi }|pi }i }|                     dd          rt          d          |                     d          sdS |                     d          pi }	|	                     d          }
|
| j        pi }|                     t          |
                    }|s5| j                            d|
 d|d	                     t          d
          ||vrM|r%| j                            d|d	          d           n$| j                            d|d	          d           dS ||vrt          d| d          ||         }||         }t          |||| j        | j	        |||          S t          |||          }t          |||| j        | j	        |||          S )Nensure_experience_continuityFz&Flag has experience continuity enabledactivefiltersaggregation_group_type_indexz)[FEATURE FLAGS] Unknown group type index z for feature flag r   z!Flag has unknown group type indexz2[FEATURE FLAGS] Can't compute group feature flag: z without group names passed inz(Flag has no group properties for group '')cohort_propertiesflags_by_keyevaluation_cacher   bucketing_value)r2   r#   r   rK   rb   r   ra   r%   r   r   r&   )re   feature_flagr   r   r   r   rZ  r   rc  flag_filtersr_  r   
group_namefocused_group_propertiesr
  rd  s                   rO   _compute_flag_locallyzClient._compute_flag_locally  s    2-3+1r <>:EBB 	S()QRRR)) 	5#''	228b'3'7'78V'W'W$'3!%!8!>B+//4P0Q0QRRJ R   F@\  F  Fp|  ~C  qD  F  F   --PQQQ'' * H$$ A\Z_M`  A  A  A    HNN A\Z_M`  A  A  A   u!111,LzLLL   (8
'C$z*I0("&,!6!1# )	 	 	 	 6k9 O 1!"&,!6!1# /	 	 	 	rQ   r   r   r   r   send_feature_flag_eventsr   r   c                d    |                      |||||||||		  	        }
|
dS t          |
          S )a3  
        Check if a feature flag is enabled for a user.

        Args:
            key: The feature flag key.
            distinct_id: The distinct ID of the user.
            groups: A dictionary of group information.
            person_properties: A dictionary of person properties.
            group_properties: A dictionary of group properties.
            only_evaluate_locally: Whether to only evaluate locally.
            send_feature_flag_events: Whether to send feature flag events.
            disable_geoip: Whether to disable GeoIP for this request.
            device_id: The device ID for this request.

        Examples:
            ```python
            is_my_flag_enabled = posthog.feature_enabled('flag-key', 'distinct_id_of_your_user')
            if is_my_flag_enabled:
                # Do something differently for this user
                # Optional: fetch the payload
                matched_flag_payload = posthog.get_feature_flag_payload('flag-key', 'distinct_id_of_your_user')
            ```

        Category:
            Feature flags
        rj  N)get_feature_flagr   )re   r   r   r   r   r   r   rk  r   r   rR  s              rO   feature_enabledzClient.feature_enabled  sS    N ((/-"7%=' ) 

 

 4H~~rQ   r   c                     | j         r<| j                             ||          }|r| j                            d|            |S dS )z?Returns a stale cached flag value if available, otherwise None.z2[FEATURE FLAGS] Using stale cached value for flag N)r   get_stale_cached_flagrb   info)re   r   r   stale_results       rO   _get_stale_flag_fallbackzClient._get_stale_flag_fallback  s]     ? 	$?@@cRRL $NNN   $#trQ   override_match_valuer   r   r   r   rk  r   r   ru  c                   | j         rd S |                     ||pi |pi |pi           \  }}|pi }|pi }|pi }d }d }d }d }d }|
t                      }
|                     ||||||
          }|d u}|ra|p|}||                     ||          nd }t          j        |||          }| j        r$|r"| j                            |||| j	                   n|r#| j
        | j                            d           n	 |                     ||||||	|
          \  }}}}g }|r|                    t          j                   ||                    t          j                   |rd                    |          }t          j        ||          }| j        r$|r"| j                            |||| j	                   | j                            d| d|            n# t*          $ rJ}| j                            d|            t          j        }|                     ||          }Y d }~nZd }~wt0          $ rJ}| j                            d|            t          j        }|                     ||          }Y d }~nd }~wt4          $ rI}| j                            d|            t          j        }|                     ||          }Y d }~nd }~wt8          $ rV}| j                            d	|            t          j        |j                  }|                     ||          }Y d }~nYd }~wt>          $ rI}| j                             d
|            t          j!        }|                     ||          }Y d }~nd }~ww xY w|r>| "                    |||r|#                                nd |r|j$        nd |||	||||           |S )Nz[FEATURE FLAGS] Local evaluation called but feature flag definitions are not loaded yet. Returning None. You can call load_feature_flags() to load flags explicitly.r   ,z&Successfully computed flag remotely: #z -> #z&[FEATURE FLAGS] Quota limit exceeded: z#[FEATURE FLAGS] Request timed out: z"[FEATURE FLAGS] Connection error: z[FEATURE FLAGS] API error: z-[FEATURE FLAGS] Unable to get flag remotely: )%r   &_add_local_person_and_group_propertiesr   _locally_evaluate_flag_compute_payload_locallyr6   from_value_and_payloadr   set_cached_flagr   r   rb   r   %_get_feature_flag_details_from_serverr   r5   ERRORS_WHILE_COMPUTINGFLAG_MISSINGr   from_flag_detailsra   r,   QUOTA_LIMITEDrs  r.   TIMEOUTr-   CONNECTION_ERRORr+   	api_errorrM  r`   rc   UNKNOWN_ERROR_capture_feature_flag_called	get_valuepayload)re   r   r   ru  r   r   r   r   rk  r   r   flag_resultflag_details
request_idevaluated_atfeature_flag_error
flag_valueflag_was_locally_evaluatedlookup_match_valuer  errors_while_computingerrorsrh   s                          rO   _get_feature_flag_resultzClient._get_feature_flag_result  s    = 	4 77"!'R &B	  	,+ 2-3+1r
,0 -//I00f&79I9
 

 &0t%;"% K	N!5!C &1 --c3EFFF 
 ,B' K
  ; //k43O   # ;	N!)  b  
4N>>#)(%"+ ?   Oj,8N ) KMM"2"IJJJ'MM"2"?@@@ :),&)9)9&/A "6 
 ? { O33#S+t7S   TSTT{TT    # N N N  !M!!M!MNNN%5%C"";;KMM" N N N  !Jq!J!JKKK%5%="";;KMM* N N N  !Ia!I!IJJJ%5%F"";;KMM N N N  !Bq!B!BCCC%5%?%I%I"";;KMM N N N""#VST#V#VWWW%5%C"";;KMMN
 $ 	--+6@%%'''D'2<##*"   sJ   8CG 
M< ?H%%M<2?I77M<?KM<AL&&M<3?M77M<c                >    |                      |||||||||		  	        S )a{  
        Get a FeatureFlagResult object which contains the flag result and payload for a key by evaluating locally or remotely
        depending on whether local evaluation is enabled and the flag can be locally evaluated.
        This also captures the `$feature_flag_called` event unless `send_feature_flag_events` is `False`.

        Examples:
            ```python
            flag_result = posthog.get_feature_flag_result('flag-key', 'distinct_id_of_your_user')
            if flag_result and flag_result.get_value() == 'variant-key':
                # Do something differently for this user
                # Optional: fetch the payload
                matched_flag_payload = flag_result.payload
            ```

        Args:
            key: The feature flag key.
            distinct_id: The distinct ID of the user.
            groups: A dictionary of group information.
            person_properties: A dictionary of person properties.
            group_properties: A dictionary of group properties.
            only_evaluate_locally: Whether to only evaluate locally.
            send_feature_flag_events: Whether to send feature flag events.
            disable_geoip: Whether to disable GeoIP for this request.
            device_id: The device ID for this request.

        Returns:
            Optional[FeatureFlagResult]: The feature flag result or None if disabled/not found.
        rj  )r  )
re   r   r   r   r   r   r   rk  r   r   s
             rO   get_feature_flag_resultzClient.get_feature_flag_result  s=    R ,,/-"7%=' - 

 

 
	
rQ   c                n    |                      |||||||||		  	        }
|
r|
                                ndS )au  
        Get multivariate feature flag value for a user.

        Args:
            key: The feature flag key.
            distinct_id: The distinct ID of the user.
            groups: A dictionary of group information.
            person_properties: A dictionary of person properties.
            group_properties: A dictionary of group properties.
            only_evaluate_locally: Whether to only evaluate locally.
            send_feature_flag_events: Whether to send feature flag events.
            disable_geoip: Whether to disable GeoIP for this request.
            device_id: The device ID for this request.

        Examples:
            ```python
            enabled_variant = posthog.get_feature_flag('flag-key', 'distinct_id_of_your_user')
            if enabled_variant == 'variant-key': # replace 'variant-key' with the key of your variant
                # Do something differently for this user
                # Optional: fetch the payload
                matched_flag_payload = posthog.get_feature_flag_payload('flag-key', 'distinct_id_of_your_user')
            ```

        Category:
            Feature flags
        rj  N)r  r  )re   r   r   r   r   r   r   rk  r   r   feature_flag_results              rO   rm  zClient.get_feature_flag  s[    N #::/-"7%=' ; 

 

 3FO",,...4OrQ   r   r   c                 
   | j         | j        r|                                  d }| j         r| j        
J d            | j                            |          }|r	 |                     ||||||          }| j                            d| d|            nm# t          t          f$ r*}	| j                            d| d|	            Y d }	~	n7d }	~	wt          $ r'}	| j                            d|	            Y d }	~	nd }	~	ww xY w|S )Nr   )r   r   r   r   z$Successfully computed flag locally: z -> zFailed to compute flag z
 locally: z7[FEATURE FLAGS] Error while computing variant locally: )r   r   rX  r   r2   ri  rb   ra   r$   r#   r`   rc   )
re   r   r   r   r   r   r   rR  r   rh   s
             rO   ry  zClient._locally_evaluate_flag  s    %$*?%##%%% 	,88V 988 ,0055D #99#%*;)9"+  :    H HNNRsRRRR    12HI Q Q QHNN#OS#O#OA#O#OPPPPPPPP    H&&URSUU        s$   ;B D ' CD C;;D )match_valuer   r   r   r   rk  r   r   r  c                    |rt          j        dt          d           |                     |||||||||	|

  
        }|r|j        ndS )a  
        Get the payload for a feature flag.

        Args:
            key: The feature flag key.
            distinct_id: The distinct ID of the user.
            match_value: The specific flag value to get payload for.
            groups: A dictionary of group information.
            person_properties: A dictionary of person properties.
            group_properties: A dictionary of group properties.
            only_evaluate_locally: Whether to only evaluate locally.
            send_feature_flag_events: Deprecated. Use get_feature_flag() instead if you need events.
            disable_geoip: Whether to disable GeoIP for this request.
            device_id: The device ID for this request.

        Examples:
            ```python
            is_my_flag_enabled = posthog.feature_enabled('flag-key', 'distinct_id_of_your_user')

            if is_my_flag_enabled:
                # Do something differently for this user
                # Optional: fetch the payload
                matched_flag_payload = posthog.get_feature_flag_payload('flag-key', 'distinct_id_of_your_user')
            ```

        Category:
            Feature flags
        zsend_feature_flag_events is deprecated in get_feature_flag_payload() and will be removed in a future version. Use get_feature_flag() if you want to send $feature_flag_called events.   )
stacklevelrt  N)warningswarnDeprecationWarningr  r  )re   r   r   r  r   r   r   r   rk  r   r   r  s               rO   get_feature_flag_payloadzClient.get_feature_flag_payload6  s    T $ 	Mo"	    #;;!,/-"7%=' < 
 
 /BK"**tKrQ   c           	         |                      ||||||g|          }|                    d          }	|                    d          }
|                    dd          }|                    d          }|r |j        |          nd}||	|
|fS )z
        Calls /flags and returns the flag details, request id, evaluated at timestamp,
        and whether there were errors while computing flags.
        )r   r   	requestIdevaluatedAterrorsWhileComputingFlagsFr1   N)r   r2   )re   r   r   r   r   r   r   r   r   r  r  r  r1   r  s                 rO   r}  z,Client._get_feature_flag_details_from_serverv  s     ++#&% , 
 
	 ]];//
 }}]33!*/JE!R!Rg&&).8yuy~~~DZ7MMMrQ   rR  r  r  r  r  r  r  c                 h   | d|dnt          |           }| j                            |          }|t                      }|| j        |<   ||vrd|d|d|d| |i}|||d<   |r||d<   |	r|	|d	<   t	          |
t
                    rr|
j        r|
j        j        r|
j        j        |d
<   t	          |
j        t                    r6|
j        j
        r|
j        j
        |d<   |
j        j        r|
j        j        |d<   |r||d<   |                     d||||           |                    |           d S d S )Nr   z::null::z$feature_flagz$feature_flag_responselocally_evaluatedr   z$feature_flag_payloadz$feature_flag_request_idz$feature_flag_evaluated_atz$feature_flag_reasonz$feature_flag_versionz$feature_flag_idz$feature_flag_errorz$feature_flag_called)r   rX   r   r   )rK   r   r2   rU   r   r4   reasondescriptionmetadatar7   versionidr   add)re   r   r   rR  r  r  r   r   r  r  r  r  feature_flag_reported_keyreported_flagsrX   s                  rO   r  z#Client._capture_feature_flag_called  s    HH8#3ZZXHH 	" AEEkRR! UUNDRD4[A$N::((#%?!C!!8	*J "6=
23 D9C
56 H;G
78,44 	R& Y<+>+J Y9E9L9XJ56l3\BB R#,4 (19 ##:; $,/ R9E9N9Q
#56! G4F
01LL&'%+     899999I ;:rQ   c                    | j         rd S | j        | j                            d           d S 	 t	          | j        | j        | j        || j                  S # t          $ r(}| j        	                    d|            Y d }~d S d }~ww xY w)Nz`[FEATURE FLAGS] You have to specify a personal_api_key to fetch decrypted feature flag payloads.)r   z>[FEATURE FLAGS] Unable to get decrypted feature flag payload: )
r   r   rb   r   r3   r   r~   r   r`   rc   )re   r   rh   s      rO   get_remote_config_payloadz Client.get_remote_config_payload  s    = 	4 (Hr   4	 %	B     	 	 	HTQRTT        	s   'A 
B BBc                 ,   d }| j         |S | j                             |          }|rl|                    d          pi }|                    d          pi }t          |t                    r|rdnt	          |          }|                    |d           }|S )Nr^  payloadstrue)r   r2   r   r   rK   )re   r   r  r  flag_definitionrf  flag_payloadslookup_values           rO   rz  zClient._compute_payload_locally  s     $,N377<< 
	<*..y99?RL(,,Z88>BM
 k400&5@&%% 
 $''d;;GrQ   r   r   r   r   r   r   r   c          
      L    |                      ||||||||          }	|	d         S )a<  
        Get all feature flags for a user.

        Args:
            distinct_id: The distinct ID of the user.
            groups: A dictionary of group information.
            person_properties: A dictionary of person properties.
            group_properties: A dictionary of group properties.
            only_evaluate_locally: Whether to only evaluate locally.
            disable_geoip: Whether to disable GeoIP for this request.
            flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
                only these flags will be evaluated, improving performance.
            device_id: The device ID for this request.

        Examples:
            ```python
            posthog.get_all_flags('distinct_id_of_your_user')
            ```

        Category:
            Feature flags
        r  featureFlags)get_all_flags_and_payloads)
re   r   r   r   r   r   r   r   r   rR  s
             rO   r   zClient.get_all_flags  sD    D 22/-"7'"7 3 	
 	
 ''rQ   c          	      x   | j         rdddS |                     ||||          \  }}|t                      }|                     ||||||          \  }	}
|
rb|s`	 |                     |||||||          }t          |          S # t          $ r'}| j                            d|            Y d}~nd}~ww xY w|	S )a\  
        Get all feature flags and their payloads for a user.

        Args:
            distinct_id: The distinct ID of the user.
            groups: A dictionary of group information.
            person_properties: A dictionary of person properties.
            group_properties: A dictionary of group properties.
            only_evaluate_locally: Whether to only evaluate locally.
            disable_geoip: Whether to disable GeoIP for this request.
            flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
                only these flags will be evaluated, improving performance.
            device_id: The device ID for this request.

        Examples:
            ```python
            posthog.get_all_flags_and_payloads('distinct_id_of_your_user')
            ```

        Category:
            Feature flags
        Nr  featureFlagPayloads)r   r   r   r   r   )r   r   r   r   r   r   z:[FEATURE FLAGS] Unable to get feature flags and payloads: )	r   rx  r   #_get_all_flags_and_payloads_locallyr   r=   r`   rb   rc   )re   r   r   r   r   r   r   r   r   rR  fallback_to_flagsdecide_responserh   s                rO   r  z!Client.get_all_flags_and_payloads-  sJ   D = 	G$(FFF 77V%68H  	,+ -//I&*&N&N/-"7 'O '
 '
##  	%: 	"&"9"9!&7%5"/*?' #: # # -_===   ""TQRTT       
 s   *B 
B7B22B7)r   r   rZ  r   r   c          
      "   |pi }|pi }| j         | j        r|                                  i }i }	d}
| j         r| j         }|r"t          |          fd| j         D             }|D ]}	 |                     |||||||          ||d         <   |                     |d         ||d                            }|||	|d         <   ^# t          $ r d}
Y lt          $ r)}| j        	                    d|            d}
Y d }~d }~ww xY wnd}
||	d|
fS )NFc                 (    g | ]}|d          v |S r   rn   )r   r   flag_keys_sets     rO   r   z>Client._get_all_flags_and_payloads_locally.<locals>.<listcomp>  s.     $ $ $!4;-;W;WD;W;W;WrQ   rY  r   Tz;[FEATURE FLAGS] Error while computing variant and payload: r  )
r   r   rX  rU   ri  rz  r#   r`   rb   rc   )re   r   r   r   r   rZ  r   r   r1   r  r  flags_to_processr   matched_payloadrh   r  s                  @rO   r  z*Client._get_all_flags_and_payloads_locallyx  s    .3+1r%$*?%##%%%&(#%! "	%#1$  #$9 : :$ $ $ $%)%7$ $ $  ) - --)-)C)C#%*;)9/E"+ *D * *E$u+& '+&C&CUU4;%7' 'O '20?e-- - - -(,%%%  - - -H&&YVWYY   )-%%%%%%	-'-2 !% "#+
 
  	s   )ACD	DC??Dc                    |sdS 	 ddl m}m} n# t          $ r ddlm}m} Y nw xY w	  ||          }|j                                        } ||j                  }t          |                    ddg          d                   }|dk    r:t          |                    ddg          d                   }t          ||          S |d	k    r	 ddl
}	|j         d
}
|j        s|j        r|
|j        pd d|j        pd dz  }
|
|j        pd d|j        pd z  }
|j        r
|
|j        z  }
|	                    |
          }|                                 t%          ||          S # t          $ r | j                            d           Y dS t*          $ r)}| j                            d| d           Y d}~dS d}~ww xY wt-          d| d          # t*          $ r+}| j                            d| d|            Y d}~dS d}~ww xY w)a9  Initialize feature flag cache for graceful degradation during service outages.

        When enabled, the cache stores flag evaluation results and serves them as fallback
        when the PostHog API is unavailable. This ensures your application continues to
        receive flag values even during outages.

        Args:
            cache_url: Cache configuration URL. Examples:
                - None: Disable caching
                - "memory://local/?ttl=300&size=10000": Memory cache with TTL and size
                - "redis://localhost:6379/0/?ttl=300": Redis cache with TTL
                - "redis://username:password@host:port/?ttl=300": Redis with auth

        Example usage:
            # Memory cache
            client = Client(
                "your-api-key",
                flag_fallback_cache_url="memory://local/?ttl=300&size=10000"
            )

            # Redis cache
            client = Client(
                "your-api-key",
                flag_fallback_cache_url="redis://localhost:6379/0/?ttl=300"
            )

            # Normal evaluation - cache is populated
            flag_value = client.get_feature_flag("my-flag", "user123")

            # During API outage - returns cached value instead of None
            flag_value = client.get_feature_flag("my-flag", "user123")  # Uses cache
        Nr   )parse_qsurlparsettli,  memoryr1  rs   redisz:// :@	localhosti  )default_ttlz:[FEATURE FLAGS] Redis not available, flag caching disabledz)[FEATURE FLAGS] Redis connection failed: z, flag caching disabledzUnknown cache URL scheme: z". Supported schemes: memory, redisz+[FEATURE FLAGS] Failed to parse cache URL 'z': )urllib.parser  r  ImportErrorschemelowerqueryintr2   r@   r  usernamepasswordhostnameportpathfrom_urlpingrA   rb   r   r`   
ValueError)re   	cache_urlr  r  parsedr  query_paramsr  r1  r  	redis_urlr   rh   s                rO   r   zClient._initialize_flag_cache  s   B  	4	4777777777 	4 	4 	43333333333	42	Xi((F]((**F#8FL11Ll&&use44Q788C!!<++FUG<<Q?@@ s+++7""  LLL#)= 5 5 5I Y&/ Y!(=2%X%X@USU%X%X%XX	!?9kQQFK<O4QQI { 1!V[0	"^^I66F KKMMM)&cBBBB"      H$$T    44       H$$^A^^^    44444	  ![[[[    	 	 	HOiOOAOO   44444		s[    $$BG G BE% %$F>	G 	F>F93G 9F>>G 
H	 HH	c                     | j         S N)r   r   s    rO   feature_flag_definitionszClient.feature_flag_definitions	  s    !!rQ   c                 x    d|i|pi }i }|r+|D ](}d||         i|pi                      |          pi ||<   )||fS )Nr   r  r   )re   r   r   r   r   all_person_propertiesall_group_propertiesrg  s           rO   rx  z-Client._add_local_person_and_group_properties	  s     ;!
 &B!

  " 	$  
 &"44(.B33J??E24$Z00
 %&:::rQ   )NFrs   TNrt   ru   Frv   Frw   rx   ry   NFTFrv   NFFNFNNTNFNNN)FT)NNNNNN)NNNNNNN)NNNNNr  r  )Jrd   
__module____qualname____doc__r   	getLoggerrb   rK   r   r(   listr   r   propertyr   setterr   r   r   r   r   r8   r   r   r9   r   ro   r   r   r   r;   r   r   rU   r  r   r   r   r  r  r   r"  r   r2  r   r7  r'   r@  rI  rF  rX  r:   ri  rn  r6   rs  r  r  rm  ry  r  tupler4   r  r}  r  r  rz  r   r  r  r   r  rx  rn   rQ   rO   rq   rq      s          '
I
&
&C
 "./%* % $ $PT).%)'++/Cd% d%d%: )11L(M;d%B S	D(Cd% d% d% d%L
 
 
 
, # # X# 
 
 
" 59#'#* #*  (S	2#* C=#* 
c5s##	$#* #* #* #*P 59#'(, (,  (S	2(, C=(, 
c3h(, (, (, (,Z 59#'(+ (+  (S	2(+ C=(+ 
(+ (+ (+ (+X +/!%59#'B3 B3h'B3 B3  (S	2B3 C=B3 
B3 B3 B3 B3H XZZT1T1$*+>$?T1	#T1 T1 T1 ZT1l$?V $ $ $ $L XZZ-1F?3 -1 -1 -1 -1 Z-1^ XZZ+1!8 +1Xc] +1 +1 +1 Z+1Z XZZ
 0448"(,*.81 8181 81 T#s(^,	81
 E(C-0181 sm81  ~81 h'81 
#81 81 81 Z81t XZZ
 /1 /1/1 c]/1 /1 /1 Z/1byDL)yD ,-yD yD yD yDvP P PdE E E V V V8+ + +  QU< <+<?G~<	< < < <$+1 +1 +1Z]@ ]@ ]@~     H #O O O 
O O O Ol #!%#'5 5 5 C=5 5 5 5n#*-	#	$   $ 59+/#!%#'I I II I
 'y1I c3h(I C=I 
#	$I I I I` #!%#'3
 3
 3
 C=3
 
#	$3
 3
 3
 3
t #!%#'2P 2P 2P C=2P 
)	2P 2P 2P 2Pv $(& && & S#X	&
  S>& sCx.& C=& 
)	& & & &Z ,0#!&#'>L >L >L
 i(>L C=>L >L >L >LP $(N NN N S#X	N
  S>N sCx.N  ~N C=N 
x$hsmXc]DH	IN N N NT -1;: ;:;: ;: 9%	;:
 #;: %);: S#X;:  ~;: SM;: sm;: {+;: %SM;: ;: ;: ;:zS    .%.	#   4 #59#'-( -( -(  (S	2-( C=-( 
$sE$),,-	.-( -( -( -(f #59#'I I I  (S	2I C=I 
I I I I` $59#'< < << S%S/)*	<  (S	2< C=< 
%	&< < < <|[ [ [z" " "; ; ; ; ;rQ   rq   c                 V    | d S t          | t                    r| S t          |           S r  )r   r   rK   )vals    rO   rI   rI   )	  s.    
{t#|$$ 
s88OrQ   r  )gr   r   r   r  r  r   r   typingr   r   r   r   r   r	   dateutil.tzr
   sixr   typing_extensionsr   posthog.argsr   r   r   r   posthog.consumerr   posthog.contextsr   r   r   r   r   r   r   r   posthog.exception_capturer   posthog.exception_utilsr   r   r   r   r   r    r!   r"   posthog.feature_flagsr#   r$   r%   r&   posthog.flag_definition_cacher'   r(   posthog.pollerr)   posthog.requestr*   r+   r,   r-   r.   r/   r0   r1   r2   r3   posthog.typesr4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   posthog.utilsr@   rA   rB   rC   rD   rE   posthog.versionrF   r   r  r   r   r  rK   r   rP   r[   ro   objectrq   rI   rn   rQ   rO   <module>r     s     				 



  ( ( ( ( ( ( ( ( - - - - - - - - - - - -                   $ $ $ $ $ $ U U U U U U U U U U U U % % % % % %	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 7 6 6 6 6 6	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	                   " ! ! ! ! !                                                                  $ # # # # #LLLL    
 %T	"2 
  
  
  
       8P"; P"; P"; P"; P";V P"; P"; P";fD    s   &C+ +	C76C7