
    jKj C                        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 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mZ d dlmZ d dlZd dlZd dlZ ej0                  d      Zd	e
d
efdZded
efdZd	e
d
e
fdZded
efdZ d Z!d Z"d Z#d Z$d Z%ded
ee   fdZ&d
efdZ' G d de      Z(dZ)dZ*dZ+dZ, G d d       Z- G d! d"      Z. G d# d$      Z/d% Z0d& Z1d' Z2d( Z3d) Z4d* Z5d+ Z6d, Z7d- Z8d
e9eef   fd.Z:y)/    N)defaultdict)asdictis_dataclass)datedatetimetimezone	timedelta)Decimal)AnyOptional)UUIDposthogdtreturnc                 \    | j                   du xs | j                   j                  |       du S )z1Determines if a given datetime.datetime is naive.N)tzinfo	utcoffset)r   s    ^/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/posthog/utils.pyis_naiver      s*    99?		 3 3B 74 ??    deltac                 f    | j                   | j                  | j                  dz  dz  z   dz  z   dz  S )z=Return the total number of seconds contained in the duration.     g    .A)microsecondssecondsdays)r   s    r   total_secondsr      s6     %--%**r/D2H"HC!OOSVVVr   c                    t        |       rt        j                         | z
  }t        |      dk  r<| j	                  t        j                         j                         j                        S | j	                  t        j                        S | S )z:Attempts to convert a naive datetime to an aware datetime.   r   )	r   r   nowr   replace
astimezoner   r   utc)r   r   s     r   guess_timezoner&      sl    | #!# ::X\\^%>%>%@%G%G:HH ::X\\:22Ir   hostc                 2    | j                  d      r| d d S | S )N/)endswith)r'   s    r   remove_trailing_slashr,   /   s    }}SCRyKr   c                    t        | t              rt        |       S t        | t              rt	        |       S t        | t        t
        t        j                  t        t        t        d       f      r| S t        | t        t        t        f      rt        |       S t        |       } t        | t               rt#        |       S t%        |       rt        | t              st'        |       S t)        |       S N)
isinstancer
   floatr   strboolnumbersNumberr   r   typesetlisttuple_clean_list_clean_pydantic_modeldict_clean_dictr   _clean_dataclass_coerce_unicode)items    r   cleanr@   5   s    $ T{$4y$dGNNHdDJOP$dE*+4   &D$4  D*T4"8%%4  r   c                     	 t        | dd       }t        |      r |       S t        | dd       }t        |      r |       S 	 | S # t        $ r#}t        j	                  d|        Y d }~| S d }~ww xY w)N
model_dumpr;   z)Could not serialize Pydantic-like model: )getattrcallable	TypeErrorlogdebug)r?   rB   dict_methodes       r   r:   r:   G   s    
CT<6
J<dFD1K =  ! K  C		=aSABBKCs   A A 	A/A**A/c                 >    | D cg c]  }t        |       c}S c c}w r.   )r@   )list_r?   s     r   r9   r9   W   s    $)*EDE$KE***s   c           
          i }| j                         D ]  \  }}	 t        |      ||<    |S # t        $ r$ t        j	                  d||t        |             Y Ew xY w)NzXDictionary values must be serializeable to JSON "%s" value %s of type %s is unsupported.)itemsr@   rE   rF   warningr5   )dict_datakvs       r   r<   r<   [   sa    D1	AhDG  K  	KKjQ		s   ,*AAc                 2    t        |       }t        |      }|S r.   )r   r<   )
dataclass_rP   s     r   r=   r=   j   s    *DtDKr   cmplxc                 "   d}	 t        | t              r| j                  dd      }|S t        | t              r| }|S # t        $ rI}dj                  t        t        |j                              }t        j                  d|       Y d}~yd}~ww xY w)a  
    In theory, this method is only called
    after many isinstance checks are carried out in `utils.clean`.
    When we supported Python 2 it was safe to call `decode` on a `str`
    but in Python 3 that will throw.
    So, we check if the input is bytes and only call `decode` in that case.

    Previously we would always call `decode` on the input
    That would throw an error.
    Then we would call `decode` on the stringified error
    That would throw an error.
    And then we would return `None`

    To avoid a breaking change, we can maintain the behavior
    that anything which did not have `decode` in Python 2
    returns None.
    Nzutf-8strict:zError decoding: %s)
r/   bytesdecoder1   	ExceptionjoinmapargsrF   rN   )rU   r?   	exceptions      r   r>   r>   p   s    $ DeU#<<2D K s#D K  xxC01($/s   "< < 	B?B		Bc                 b    	 t        j                  |        y# t         j                  $ r Y yw xY w)NTF)recompileerror)values    r   is_valid_regexre      s,    


588 s    ..c                   (     e Zd Z fdZ fdZ xZS )SizeLimitedDictc                 2    t        |   |i | || _        y r.   )super__init__max_size)selfrk   r^   kwargs	__class__s       r   rj   zSizeLimitedDict.__init__   s    $)&) r   c                 v    t        |       | j                  k\  r| j                          t        |   ||       y r.   )lenrk   clearri   __setitem__)rl   keyrd   rn   s      r   rr   zSizeLimitedDict.__setitem__   s+    t9%JJLC'r   )__name__
__module____qualname__rj   rr   __classcell__)rn   s   @r   rg   rg      s    !( (r   rg   i'  i,  r   zposthog:flags:c                   $    e Zd ZddZd ZefdZy)FlagCacheEntryNc                 Z    || _         || _        |xs t        j                         | _        y r.   )flag_resultflag_definition_versiontime	timestamp)rl   r{   r|   r~   s       r   rj   zFlagCacheEntry.__init__   s$    &'>$"1diikr   c                 P    || j                   z
  |k  }| j                  |k(  }|xr |S r.   )r~   r|   )rl   current_timettlcurrent_flag_version
time_validversion_valids         r   is_validzFlagCacheEntry.is_valid   s1    "T^^3s:
448LL+m+r   c                 &    || j                   z
  |k  S r.   )r~   )rl   r   max_stale_ages      r   is_stale_but_usablez"FlagCacheEntry.is_stale_but_usable   s    t~~->>r   r.   )rt   ru   rv   rj   r   CACHE_STALE_TTLr    r   r   ry   ry      s    2
,
 ?N ?r   ry   c                   J    e Zd ZeefdZd ZddZd Zd Z	d Z
d Zd	 Zd
 Zy)	FlagCachec                 <    i | _         i | _        || _        || _        y r.   )cacheaccess_timesrk   default_ttl)rl   rk   r   s      r   rj   zFlagCache.__init__   s     
 &r   c                     t        j                          }|| j                  vry | j                  |   }||vry ||   }|j                  || j                  |      r|| j                  |<   |j
                  S y r.   )r}   r   r   r   r   r{   )rl   distinct_idflag_keyr   r   
user_flagsentrys          r   get_cached_flagzFlagCache.get_cached_flag   su    yy{djj(ZZ,
:%8$>>,(8(8:NO-9Dk*$$$r   Nc                     |t         }t        j                         }|| j                  vry | j                  |   }||vry ||   }|j                  ||      r|j                  S y r.   )r   r}   r   r   r{   )rl   r   r   r   r   r   r   s          r   get_stale_cached_flagzFlagCache.get_stale_cached_flag   si     +Myy{djj(ZZ,
:%8$$$\=A$$$r   c                 @   t        j                          }|| j                  vr2t        | j                        | j                  k\  r| j	                          || j                  vri | j                  |<   t        ||      }|| j                  |   |<   || j                  |<   y r.   )r}   r   rp   rk   
_evict_lrury   r   )rl   r   r   r{   r|   r   r   s          r   set_cached_flagzFlagCache.set_cached_flag   s     yy{ djj(S_-MOO djj(&(DJJ{# {,CD,1

;))5+&r   c                     | j                   j                         D cg c]  \  }}| j                  ||      r| }}}|D ]  }| j                  |        y c c}}w r.   )r   rM   _remove_flags_with_version_remove_user)rl   old_versionr   r   users_to_removes        r   invalidate_versionzFlagCache.invalidate_version   se     ,0::+;+;+=
+='Z..z;G += 	 
 +Kk* +
s   Ac                     |j                         D cg c]  \  }}|j                  |k(  r| }}}|D ]  }||=  | S c c}}w r.   )rM   r|   )rl   r   r   r   r   flags_to_removes         r   r   z$FlagCache._remove_flags_with_version  sb     $.#3#3#5
#5%,,; #5 	 
 (H8$ ( ~
s   ?c                 t    | j                   j                  |d        | j                  j                  |d        y r.   )r   popr   )rl   r   s     r   r   zFlagCache._remove_user  s*    

{D)k40r   c                 "   | j                   sy t        | j                   j                         d       }t        dt	        |      dz        }|d | D ]<  \  }}|| j
                  v r| j
                  |= || j                   v s0| j                   |= > y )Nc                     | d   S )N   r   )xs    r   <lambda>z&FlagCache._evict_lru.<locals>.<lambda>  s    qtr   )rs   r   r    )r   sortedrM   maxrp   r   )rl   sorted_users	to_remover   _s        r   r   zFlagCache._evict_lru  s       d//557^L3|,12	*:I6NKdjj(JJ{+d///%%k2	 7r   c                 l    | j                   j                          | j                  j                          y r.   )r   rq   r   )rl   s    r   rq   zFlagCache.clear!  s$    

!r   r.   )rt   ru   rv   CACHE_MAX_SIZE	CACHE_TTLrj   r   r   r   r   r   r   r   rq   r   r   r   r   r      s4     .I '"&6$	+13"r   r   c                   f    e Zd ZeeefdZd ZddZd Z	d Z
ddZd Zd	 Zd
 Zd Zd Zd Zd Zy)RedisFlagCachec                 P    || _         || _        || _        || _        | d| _        y )Nversion)redisr   	stale_ttl
key_prefixversion_key)rl   redis_clientr   r   r   s        r   rj   zRedisFlagCache.__init__'  s0     "
&"$(\1r   c                 (    | j                    | d| S )NrX   )r   )rl   r   r   s      r   _get_cache_keyzRedisFlagCache._get_cache_key4  s    //";-q
;;r   Nc                 z    |t        j                          }t        |      }|||d}t        j                  |      S )N)r{   flag_versionr~   )r}   r@   jsondumps)rl   r{   r|   r~   serialized_resultr   s         r   _serialize_entryzRedisFlagCache._serialize_entry7  sC    		I "+. -3"

 zz%  r   c                     	 t        j                  |      }|d   }t        ||d   |d         S # t         j                  t        t
        f$ r Y y w xY w)Nr{   r   r~   )r{   r|   r~   )r   loadsry   JSONDecodeErrorKeyError
ValueError)rl   rP   r   r{   s       r   _deserialize_entryz!RedisFlagCache._deserialize_entryE  s`    
	JJt$E.K!'(-n(=, 
 $$h
; 		s   -0 AAc                    	 | j                  ||      }| j                  j                  |      }|rN| j                  |      }|r;|j	                  t        j
                         | j                  |      r|j                  S y # t        $ r Y y w xY wr.   )	r   r   getr   r   r}   r   r{   r[   )rl   r   r   r   	cache_keyrP   r   s          r   r   zRedisFlagCache.get_cached_flagR  s    	++KBI::>>),D//5U^^IIK!1!13G !,,, 		s   A<B   	BBc                 $   	 || j                   }| j                  ||      }| j                  j                  |      }|rC| j	                  |      }|r0|j                  t        j                         |      r|j                  S y # t        $ r Y y w xY wr.   )	r   r   r   r   r   r   r}   r{   r[   )rl   r   r   r   r   rP   r   s          r   r   z$RedisFlagCache.get_stale_cached_flagc  s    	$ $++KBI::>>),D//5U66tyy{MR ,,, 		s   A?B 	BBc                    	 | j                  ||      }| j                  ||      }| j                  j                  || j                  |       | j                  j                  | j                  |       y # t        $ r Y y w xY wr.   )r   r   r   setexr   r6   r   r[   )rl   r   r   r{   r|   r   serialized_entrys          r   r   zRedisFlagCache.set_cached_flagu  sz    	++KBI#444 
 JJY8HI JJNN4++-DE 		s   A1A4 4	B ?B c                     	 d}| j                    d}	 | j                  j                  ||d      \  }}| j                  ||       |dk(  ry :# t        $ r Y y w xY wNr   *d   )matchcount)r   r   scan_delete_keys_with_versionr[   )rl   r   cursorpatternkeyss        r   r   z!RedisFlagCache.invalidate_version  sq    	 F)+G#zzvWCP..t[AQ;   		s   A
A A 	AAc                    |D ]B  }| j                  |      r	 | j                  ||      r| j                  j                  |       D y # t        j
                  t        f$ r | j                  j                  |       Y |w xY wr.   )_is_version_key_key_has_versionr   deleter   r   r   )rl   r   r   rs   s       r   r   z(RedisFlagCache._delete_keys_with_version  ss    C##C('((k:JJ%%c*  (((3 '

!!#&'s   -A		4B ?B c                 >    | j                  |      | j                  k(  S r.   )_redis_key_to_stringr   rl   rs   s     r   r   zRedisFlagCache._is_version_key  s    ((-1A1AAAr   c                 F    t        |t              r|j                         S |S r.   )r/   rY   rZ   r   s     r   r   z#RedisFlagCache._redis_key_to_string  s    c5!::<
r   c                     | j                   j                  |      }|syt        j                  |      j                  d      |k(  S )NFr   )r   r   r   r   )rl   rs   r   rP   s       r   r   zRedisFlagCache._key_has_version  s9    zz~~c"zz$##N3{BBr   c                     	 d}| j                    d}	 | j                  j                  ||d      \  }}|r | j                  j                  |  |dk(  ry C# t        $ r Y y w xY wr   )r   r   r   r   r[   )rl   r   r   r   s       r   rq   zRedisFlagCache.clear  sv    	F)+G#zzvWCP%DJJ%%t,Q;   		s   AA A 	A#"A#r.   )rt   ru   rv   r   r   CACHE_KEY_PREFIXrj   r   r   r   r   r   r   r   r   r   r   r   rq   r   r   r   r   r   &  sP     !#2<!"$&$	'B
Cr   r   c                 ^    | j                    | j                  t        j                        } | S )Nr!   )r   r#   r   r%   )date_objs    r   convert_to_datetime_awarer     s(    ##8<<#8Or   c                 f    t        |      j                         t        |       j                         v S )a  
    Check if a string contains another string, ignoring case.

    Args:
        source: The string to search within
        search: The substring to search for

    Returns:
        bool: True if search is a substring of source (case-insensitive), False otherwise

    Examples:
        >>> str_icontains("Hello World", "WORLD")
        True
        >>> str_icontains("Hello World", "python")
        False
    r1   casefold)sourcesearchs     r   str_icontainsr     s)    " v;!S[%9%9%;;;r   c                 h    t        |       j                         t        |      j                         k(  S )a  
    Check if a string equals another string, ignoring case.

    Args:
        value: The string to compare
        comparand: The string to compare with

    Returns:
        bool: True if value and comparand are equal (case-insensitive), False otherwise

    Examples:
        >>> str_iequals("Hello World", "hello world")
        True
        >>> str_iequals("Hello World", "hello")
        False
    r   )rd   	comparands     r   str_iequalsr     s)    " u: C	N$;$;$===r   c                  J    t        t        dd       } t        |       r |        S y)Nrelease rC   platformrD   )r   s    r   _platform_releaser     s#    h	40Gyr   c                  ^    t        t        dd       } t        |       rd |        d   xs ddfS y)N	win32_verWindowsr   r   )r   r   r   r   )r   s    r   _get_windows_os_infor     s3    +t4I	)+a..B22r   c                  ^    t        t        dd       } t        |       rd |        d   xs ddfS y)Nmac_verMac OS Xr   r   )r   r   r   r   )r   s    r   _get_macos_infor      s3    h	40G79Q<-2r11r   c                  n    t        j                         } d| d   xs dt        j                         xs dfS )NLinuxr   r   )distroinfoname)
linux_infos    r   _get_linux_os_infor    s/    JJy)/R1D"DDr   c                     | j                  d      r
t               S | dk(  r
t               S | j                  d      r
t               S | j                  d      rdt	               dfS | t	               dfS )NwindarwinlinuxfreebsdFreeBSDr   )
startswithr   r   r  r   )platform_names    r   _get_platform_os_infor    sq    &#%%   (!##	*+-r11+-r11r   c                  X    t        t        j                        \  } }}| |d}|r||d<   |S )z
    Returns standardized OS name, version and distro (in case of Linux) information.
    Similar to how user agent parsing works in JS.
    )z$osz$os_versionz
$os_distro)r  sysr   )os_name
os_version	os_distror  s       r   get_os_infor    s<    
 &;3<<%H"GZ !D &\Kr   c                  l    t        j                         dt        j                  d d z  dt	               S )Nz%s.%s.%s   )z$python_runtimez$python_version)r   python_implementationr  version_infor  r   r   r   system_contextr  )  s9    #99;%)9)9"1)=> - r   );r   loggingr3   ra   r}   collectionsr   dataclassesr   r   r   r   r   r	   decimalr
   typingr   r   uuidr   r  r   r  	getLoggerrF   r2   r   r0   r   r&   r1   r,   r@   r:   r9   r<   r=   r>   re   rg   r   r   r   r   ry   r   r   r   r   r   r   r   r   r  r  r  r;   r  r   r   r   <module>r#     s\      	  # , 8 8     
  g	"@ @d @
W Wu Wx H "  !$ +3 8C= @T 	(k 	( 	# ? ?j" j"Z[ [|<(>(E
	2"S#X r   