o
    Rh                     @   s"  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
 d dlmZ d dlmZmZ d dlmZ d dlZd dlmZmZ e d	Zd
d Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdedee  fddZ!de"fddZ#G d d! d!eZ$d"d# Z%d$d% Z&d&d' Z'dS )(    N)defaultdict)asdictis_dataclass)datedatetimetimezone)Decimal)AnyOptional)UUID)tzlocaltzutcposthogc                 C   s   | j du p| j | du S )z1Determines if a given datetime.datetime is naive.N)tzinfo	utcoffset)dt r   O/home/air/sanwanet/backup_V2/venv/lib/python3.10/site-packages/posthog/utils.pyis_naive   s   r   c                 C   s"   | j | j| jd d  d  d S )z2Determines total seconds with python < 2.7 compat.   i  g    .A)microsecondssecondsdays)deltar   r   r   total_seconds   s   "r   c                 C   s@   t | rt |  }t|dk r| jt dS | jt dS | S )z:Attempts to convert a naive datetime to an aware datetime.   r   )r   r   nowr   replacer   r   )r   r   r   r   r   guess_timezone   s   r   c                 C   s   |  dr| d d S | S )N/)endswith)hostr   r   r   remove_trailing_slash-   s   
r$   c              
   C   s  t | tr	t| S t | trt| S t | tjttj	t
ttd fr#| S t | tttfr/t| S zt| dr?t| jr?|  } nt| drMt| jrM|  } W n tyh } ztd|  W Y d }~nd }~ww t | trrt| S t| rt | tst| S t| S )N
model_dumpdictz)Could not serialize Pydantic-like model: )
isinstancer   floatr   strsixstring_typesboolnumbersNumberr   r   typesetlisttuple_clean_listhasattrcallabler%   r&   	TypeErrorlogdebug_clean_dictr   _clean_dataclass_coerce_unicode)itemer   r   r   clean3   s4   



r>   c                 C   s   dd | D S )Nc                 S   s   g | ]}t |qS r   )r>   ).0r<   r   r   r   
<listcomp>Q   s    z_clean_list.<locals>.<listcomp>r   )list_r   r   r   r3   P   s   r3   c                 C   sR   i }t | D ]\}}zt|||< W q ty&   td||t| Y qw |S )NzXDictionary values must be serializeable to JSON "%s" value %s of type %s is unsupported.)r*   	iteritemsr>   r6   r7   warningr/   )dict_datakvr   r   r   r9   T   s   r9   c                 C   s   t | }t|}|S N)r   r9   )
dataclass_rE   r   r   r   r:   c   s   r:   cmplxreturnc              
   C   s   d}zt | tr| dd}W |S t | tr| }W |S W |S  ty? } zdtt|j}t	d| W Y d}~dS d}~w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decoder)   	Exceptionjoinmapargsr7   rC   )rJ   r<   	exceptionr   r   r   r;   i   s    

r;   c                 C   s(   zt |  W dS  t jy   Y dS w )NTF)recompileerror)valuer   r   r   is_valid_regex   s   
rY   c                       s(   e Zd Z fddZ fddZ  ZS )SizeLimitedDictc                    s   t  j|i | || _d S rH   )super__init__max_size)selfr]   rS   kwargs	__class__r   r   r\      s   
zSizeLimitedDict.__init__c                    s(   t | | jkr|   t || d S rH   )lenr]   clearr[   __setitem__)r^   keyrX   r`   r   r   rd      s   zSizeLimitedDict.__setitem__)__name__
__module____qualname__r\   rd   __classcell__r   r   r`   r   rZ      s    rZ   c                 C   s   | j d u r| jtjd} | S )Nr   )r   r   r   utc)date_objr   r   r   convert_to_datetime_aware   s   
rl   c                 C   s   t | t |  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
    r)   casefold)sourcesearchr   r   r   str_icontains      rq   c                 C   s   t |  t | 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
    rm   )rX   	comparandr   r   r   str_iequals   rr   rt   )(loggingr-   rU   collectionsr   dataclassesr   r   r   r   r   decimalr   typingr	   r
   uuidr   r*   dateutil.tzr   r   	getLoggerr7   r   r   r   r$   r>   r3   r9   r:   r)   r;   r,   rY   rZ   rl   rq   rt   r   r   r   r   <module>   s4    
 